鼠鼠昨晚闲着无聊逛了一下大学生创业大赛,看到了一个名为《基于国密算法和区块链的党建信信息安全防护系统》的项目,鼠鼠最近沉迷于搭建安全性极高的聊天平台,于是就了解了一下国密算法,并且写下了这篇文章

国密算法概述及与国际算法对比

一、SM2 – 椭圆曲线公钥密码算法

作用

  • 数字签名:提供数据完整性和不可否认性。
  • 密钥交换:支持双方安全地协商共享密钥。
  • 公钥加密:用于保护信息的机密性。

对比国际算法

  • RSA:广泛应用于公钥加密和数字签名,但随着密钥长度增加,计算复杂度大幅上升。
  • ECC (椭圆曲线密码):SM2 基于 ECC,具有更短的密钥长度却提供相同的安全级别。例如,256位的 SM2 提供了相当于 3072 位 RSA 的安全性。

二、SM3 – 密码杂凑算法

作用

  • 数据完整性验证:通过生成输入数据的消息摘要来确保数据未被篡改。
  • 消息认证:结合对称或非对称加密技术,实现消息来源的身份验证。

对比国际算法

  • SHA-256:是目前广泛使用的哈希函数之一。SM3 和 SHA-256 在设计上有相似之处,但 SM3 针对中国市场需求进行了优化,理论上具备更高的抗攻击能力。

三、SM4 – 对称分组密码算法

作用

  • 数据加密:用于保护存储和传输中的敏感信息。
  • 密钥管理:配合其他算法使用时,可作为基础的加密层保障密钥的安全传输。

对比国际算法

  • AES (高级加密标准):AES 是全球范围内最流行的对称加密算法之一,支持128、192和256位密钥长度。SM4 只支持128位密钥长度,但在性能和安全性方面与 AES 相当。

Java实践

pom文件

 复制代码 隐藏代码
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.xiaoz</groupId>
    <artifactId>Safety</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>21</maven.compiler.source>
        <maven.compiler.target>21</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.8.26</version>
        </dependency>
        <dependency>
            <groupId>org.bouncycastle</groupId>
            <artifactId>bcprov-jdk15on</artifactId>
            <version>1.70</version>
        </dependency>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>1.5.18</version>
        </dependency>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-core</artifactId>
            <version>1.5.18</version>
        </dependency>
    </dependencies>

</project>

Java代码

 复制代码 隐藏代码
import cn.hutool.core.codec.Base64;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.asymmetric.KeyType;
import cn.hutool.crypto.asymmetric.SM2;
import cn.hutool.crypto.digest.SM3;
import cn.hutool.crypto.symmetric.SM4;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.crypto.KeyAgreement;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.security.spec.ECGenParameterSpec;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionException;

public class NationalEncryption {

    static {
        SecureUtil.addProvider(new BouncyCastleProvider());
    }

    private static final Logger log = LoggerFactory.getLogger("国密算法");
    private final static String key = "这是一个测试";
    //模拟RSA
    public void mrsa(){
        SM2 sm2 = new SM2();
        //生成密钥对
        String privatekey = sm2.getPrivateKeyBase64();
        String publickey = sm2.getPublicKeyBase64();
        log.info("私钥:{}",privatekey);
        log.info("公钥:{}",publickey);
        //公钥加密
        byte[] encryptData = sm2.encrypt(key.getBytes(StandardCharsets.UTF_8), KeyType.PublicKey);
        log.info("加密后的数据为:{}", Base64.encode(encryptData));
    }

    //密钥交换
    public void change() throws Exception {
       //初始化密钥对生成器
        KeyPairGenerator kPG = KeyPairGenerator.getInstance("ECDH", "BC");
        ECGenParameterSpec sm2p256v1 = new ECGenParameterSpec("sm2p256v1");
        kPG.initialize(sm2p256v1,new SecureRandom());

        //用户A
        KeyPair AkeyPair = kPG.generateKeyPair();//获取密钥对
        PublicKey aPublic = AkeyPair.getPublic();
        PrivateKey aPrivate = AkeyPair.getPrivate();
        //用户B
        KeyPair bkeyPair = kPG.generateKeyPair();
        PublicKey bPublic = bkeyPair.getPublic();
        PrivateKey bPrivate = bkeyPair.getPrivate();

        //交换密钥
        //(以A为第一视角交换B)
        KeyAgreement Aagreement = KeyAgreement.getInstance("ECDH", "BC");
        Aagreement.init(aPrivate);
        Aagreement.doPhase(bPublic,true);
        byte[] ABgenerateSecret = Aagreement.generateSecret();
        //(以B为第一视角交换A)
        KeyAgreement Bagreement = KeyAgreement.getInstance("ECDH", "BC");
        Bagreement.init(bPrivate);
        Bagreement.doPhase(aPublic,true);
        byte[] BgenerateSecret = Bagreement.generateSecret();

        //输出测试
        log.info("A计算出的密钥为:{}", Base64.encode(ABgenerateSecret));
        log.info("B计算出的密钥为:{}",Base64.encode(BgenerateSecret));

        //使用sm3算法获取信息摘要
        SM3 sm3 = new SM3();
        byte[] sourkey = sm3.digest(ABgenerateSecret);
        log.info("协商密钥的信息摘要为:{}",Base64.encode(key));
        byte[] endkey = CompletableFuture.supplyAsync( ()->{
            byte[] bytes = new byte[16];
            int jsq = 0;
            for (byte k : sourkey){
                if (jsq >= 16) break;
                bytes[jsq] = k;
                jsq = jsq+1;
            }
            return bytes;
        }  ).join();
        log.info("m4算法使用的密钥为:{}",Base64.encode(endkey));
        //使用sm4加密字符串(需要密钥为16字节)
        SM4 sm4 = new SM4(endkey);
        String s = sm4.encryptBase64(key);
        log.info("sm4加密后的信息为:{}",s);
    }

}

关于代码的解释

介绍

此文档提供了一个基于 Hutool 库实现的 Java 示例,展示了如何使用国家密码局标准的 SM2, SM3 和 SM4 算法进行加密操作。这些算法分别用于非对称加密(SM2)、消息摘要生成(SM3)和对称加密(SM4)。此外,还展示了如何利用 ECDH 协议完成密钥交换。

主要类和方法

NationalEncryption 类

mrsa 方法

模拟 RSA 加密过程,实际上使用的是 SM2 算法:

  • 功能:生成密钥对,并用公钥加密指定的信息。
  • 步骤
    1. 创建 SM2 实例并生成密钥对。
    2. 打印私钥和公钥。
    3. 使用公钥加密信息,并打印加密后的数据。
change 方法

实现了密钥协商与信息加密:

  • 功能:通过 ECDH 协议进行密钥交换,然后使用 SM3 生成摘要,并最终使用 SM4 对信息进行加密。
  • 步骤
    1. 初始化密钥对生成器,使用 "sm2p256v1" 曲线参数。
    2. 分别为用户 A 和 B 生成密钥对。
    3. 使用 ECDH 协议计算共享密钥。
    4. 使用 SM3 计算共享密钥的消息摘要。
    5. 截取前 16 字节作为 SM4 的密钥。
    6. 使用 SM4 加密信息并打印结果。

参数解释

KeyType.PublicKey

  • 作用:指定使用公钥进行加密或解密操作。

Base64.encode()

  • 作用:将字节数组编码为 Base64 字符串,便于存储或传输。

SecureRandom

  • 作用:提供一个强随机数生成器,用于初始化密钥对生成器。

KeyAgreement.getInstance("ECDH", "BC")

  • 作用:获取一个 ECDH 密钥协商协议的实例,"BC" 指定使用 BouncyCastle 提供者。

Aagreement.init(aPrivate) 和 Bagreement.init(bPrivate)

  • 作用:初始化密钥协商协议,使用各自的私钥。

Aagreement.doPhase(bPublic,true) 和 Bagreement.doPhase(aPublic,true)

  • 作用:执行密钥协商的一个阶段,传入对方的公钥。

ABgenerateSecret 和 BgenerateSecret

  • 作用:存储通过密钥协商得到的共享密钥。

SM3 sm3 = new SM3()

  • 作用:创建 SM3 实例用于生成消息摘要。

CompletableFuture.supplyAsync()

  • 作用:异步地截取共享密钥的消息摘要的前 16 字节,虽然在这个场景下并不需要异步处理,但这里展示了如何结合异步编程来实现特定逻辑。

SM4 sm4 = new SM4(endkey)

  • 作用:创建 SM4 实例,使用之前生成的 16 字节密钥进行信息加密。

执行结果预览

 复制代码 隐藏代码
20:25:29.321 [main] INFO 国密算法 -- A计算出的密钥为:YI7H7nOPvfmy/9lynC9PArzlq0yIx1g8TWVtOyB3iQY=
20:25:29.329 [main] INFO 国密算法 -- B计算出的密钥为:YI7H7nOPvfmy/9lynC9PArzlq0yIx1g8TWVtOyB3iQY=
20:25:29.344 [main] INFO 国密算法 -- 协商密钥的信息摘要为:44GT44KM44Gv44OG44K544OI44Gn44GZ
20:25:29.347 [main] INFO 国密算法 -- m4算法使用的密钥为:IsjicN+tpI1AxFvF8J2E8w==
20:25:29.368 [main] INFO 国密算法 -- sm4加密后的信息为:6AinKttABwlMPUAx/CBndz8ivoiZoEGUHb4e4MzqM+E=

扫码免费获取资源: