国内还有能打的吗
GPT绝对是出道即巅峰
相较之下
百度文心一言不幸沦为背景板
发布会直接翻车
其实不是百度的问题
毕竟在大语言模型的AI领域
百度已经是最强的一个了
奈何对方太强
无论是投入成本还是效果
差距太大了
当天股票暴跌10%
不过还好后劲缓了过来
第二天涨了16%
投资者体验了一把过山车的感觉
不过东西再好,毕竟在老美手里
在信创自主可控的大环境下
对产品有更多的安全方面的要求
毕竟,科学无国界
但科学家有国界
继续学习密码学
在之前的文章里
我们介绍了密码学的发展和演变
从古代的“阴符”、“阴书”
到现代计算机技术的百花齐放
目前主流的对称、非对称、摘要加密算法
大部分都是国外的标准和算法
随着信创产业的发展
自助可控就成了硬性要求
国内也产生了相应的技术
我们称之为“国密算法”
国密算法
国密由国家密码管理局认定
主要用于商用领域
大部分国密算法都叫做 SM-N 的格式
比如 SM1,SM3等等
还有一些是具有民族历史特点的
比如 ZUC 祖冲之算法等
今天先介绍 SM 算法家族的几个常见示例
SM 1 2 3 4
准备工作
创建一个maven项目
pom.xml 引用hutool和bcprov库
代码语言:javascript复制 <dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.5</version>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15to18</artifactId>
<version>1.69</version>
</dependency>
SM1
SM1对于大部分软件工程师来说都很陌生
因为它属于硬件加密
一般是用在 IC卡,智能芯片,加密机,警务通等领域
它是一种对称算法
对标AES,算法不公开
如果不是从事涉密行业的同学
可能一辈子都接触不到
SM2
SM2是非对称算法的一种
有公钥和私钥
对标国际的RSA
SM2的数学原理基于ECC椭圆曲线密码机制
具体过程很复杂
大家主要需要知道如何使用就行
首先通过工具生成秘钥对
代码语言:javascript复制public class TestSM2 {
@Test
void test() {
SM2 sm2=SmUtil.sm2();
System.out.println("PublicKey: " sm2.getPublicKeyBase64());
System.out.println("PrivateKey: " sm2.getPrivateKeyBase64());
}
}
输出结果为:
代码语言:javascript复制 PublicKey: MFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAEPLJZNooUGYoWA eBPmIhEr7mspmcy8r8b5xWfqQYvGVCe32rMNR5bITvt7hdbiKjbZu0gRxLmZ6D64toLYharw==
PrivateKey: MIGTAgEAMBMGByqGSM49AgEGCCqBHM9VAYItBHkwdwIBAQQg585PmCpcH0c6X3GnnrAWyZobwotFG5yVWFvXIw1CUqygCgYIKoEcz1UBgi2hRANCAAQ8slk2ihQZihYD54E YiESvuaymZzLyvxvnFZ pBi8ZUJ7fasw1HlshO 3uF1uIqNtm7SBHEuZnoPri2gtiFqv
这个秘钥对是随机生成的
我们把它存下来
下次使用的时候
直接用两个参数初始化
代码语言:javascript复制public class TestSM2 {
private String publicKey="MFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAEPLJZNooUGYoWA eBPmIhEr7mspmcy8r8b5xWfqQYvGVCe32rMNR5bITvt7hdbiKjbZu0gRxLmZ6D64toLYharw==";
private String privateKey="MIGTAgEAMBMGByqGSM49AgEGCCqBHM9VAYItBHkwdwIBAQQg585PmCpcH0c6X3GnnrAWyZobwotFG5yVWFvXIw1CUqygCgYIKoEcz1UBgi2hRANCAAQ8slk2ihQZihYD54E YiESvuaymZzLyvxvnFZ pBi8ZUJ7fasw1HlshO 3uF1uIqNtm7SBHEuZnoPri2gtiFqv";
@Test
void test() {
// SM2 sm2=SmUtil.sm2();
SM2 sm2 = SmUtil.sm2(privateKey, publicKey);
}
}
然后演示 公钥加密,私钥解密
代码语言:javascript复制public class TestSM2 {
private String publicKey="MFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAEPLJZNooUGYoWA eBPmIhEr7mspmcy8r8b5xWfqQYvGVCe32rMNR5bITvt7hdbiKjbZu0gRxLmZ6D64toLYharw==";
private String privateKey="MIGTAgEAMBMGByqGSM49AgEGCCqBHM9VAYItBHkwdwIBAQQg585PmCpcH0c6X3GnnrAWyZobwotFG5yVWFvXIw1CUqygCgYIKoEcz1UBgi2hRANCAAQ8slk2ihQZihYD54E YiESvuaymZzLyvxvnFZ pBi8ZUJ7fasw1HlshO 3uF1uIqNtm7SBHEuZnoPri2gtiFqv";
@Test
void test() {
SM2 sm2 = SmUtil.sm2(privateKey, publicKey);
String data="小面同学我爱你";
String secretText=sm2.encryptHex(data, KeyType.PublicKey);
System.out.println(secretText);
}
}
输出结果为:
~~ 04e53728b5377786dbb8bf3d2dc3803602855cbaf7d287cc647e2f5ff83cbeb28e6be013fa9010763d59dfae0c76e77dc9826420a1c51f360603a9281c31b71873f2c128e7204177a6b2d5ba4f8691b8328c2746a7dd20b890d706174a0754a629e53d3fe9cb8cee30b2e79db692ea39eab7a4c262fb
~~
这就是加密后的话
然后用私钥解密试试
代码语言:javascript复制public class TestSM2 {
private String publicKey="MFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAEPLJZNooUGYoWA eBPmIhEr7mspmcy8r8b5xWfqQYvGVCe32rMNR5bITvt7hdbiKjbZu0gRxLmZ6D64toLYharw==";
private String privateKey="MIGTAgEAMBMGByqGSM49AgEGCCqBHM9VAYItBHkwdwIBAQQg585PmCpcH0c6X3GnnrAWyZobwotFG5yVWFvXIw1CUqygCgYIKoEcz1UBgi2hRANCAAQ8slk2ihQZihYD54E YiESvuaymZzLyvxvnFZ pBi8ZUJ7fasw1HlshO 3uF1uIqNtm7SBHEuZnoPri2gtiFqv";
@Test
void test() {
SM2 sm2 = SmUtil.sm2(privateKey, publicKey);
String secretText="04e53728b5377786dbb8bf3d2dc3803602855cbaf7d287cc647e2f5ff83cbeb28e6be013fa9010763d59dfae0c76e77dc9826420a1c51f360603a9281c31b71873f2c128e7204177a6b2d5ba4f8691b8328c2746a7dd20b890d706174a0754a629e53d3fe9cb8cee30b2e79db692ea39eab7a4c262fb";
String data=sm2.decryptStr(secretText, KeyType.PrivateKey);
System.out.println(data);
}
}
输出结果为:
代码语言:javascript复制小面同学我爱你
个别场合可能加解密会遇到编码转换问题
建议使用 utf-8 编码转换
用法是 String s = StrUtil.utf8Str(s);
对称加密强调数据的加密与复原
并且公钥可以公开
在信息鉴别和秘钥交换方面用处很大
SM3
SM3是一种摘要算法
类似 MD5、SHA-256等
他具有单向加密的特点
无法逆推
主要用于数字签名、完整性效验、认证等功能
SM3 是在SMA-256基础上改进的一种算法
但复杂度远远提高
在防范碰撞攻击方面更具有优势
SM3使用更加简单
因为根本没有秘钥
代码语言:javascript复制public class TestSM3 {
@Test
void test() {
String data="小面同学我爱你";
System.out.println(SmUtil.sm3(data));
}
}
直接一步就行
输出结果为:
代码语言:javascript复制c6ff5d9098ab6b4b69a306e54ac6eb0ed90656dd9c8ae02d814cccdf202946a3
这里是采用默认的加密方法
可以选择 “加盐” 提高安全性
调整如下:
代码语言:javascript复制public class TestSM3 {
@Test
void test() {
String data="小面同学我爱你";
SM3 sm3 = SmUtil.sm3();
sm3.setSalt("xiaomian".getBytes());
String secretText=sm3.digestHex(data);
System.out.println(secretText);
}
}
输出结果为:
代码语言:javascript复制e545d9646cd702e93b654aee70f7b9c59af50dcc888e94bfca52ca13afc3134
加盐的目的是增加干扰因素
摘要算法是不可逆的
通常仅用于验证结果
最常见的例如数字签名、密码加密存储等方面使用
SM4
SM4是一种对称加密算法
对标国外的DES算法
使用一个秘钥
可以加密和解密
而且要兼顾复杂度和性能
通常用于内容加密和解密
对称算法只有一个秘钥
首先通过工具生成
代码语言:javascript复制SM4 sm4 = SmUtil.sm4();
byte[] key=sm4.getSecretKey().getEncoded();
由于工具生成的key是字节,无法阅读和保存
所以我们通常可以自己建key
长度必须128位,一个char是8位
所以文字的密码必须16个英文字长
代码语言:javascript复制String key="ILoveXiaoMian456";
SM4 sm4 = SmUtil.sm4(key.getBytes());
加密:
代码语言:javascript复制public class TestSM4 {
@Test
void test() {
String key="ILoveXiaoMian456";
SM4 sm4 = SmUtil.sm4(key.getBytes());
String data="我爱小面,小面爱我";
System.out.println(sm4.encryptHex(data));
}
}
加密成功,输出结果为:
代码语言:javascript复制382eeef6fd65b154f1f157eadd78c840a5fe1a460aeb478598b3ed2ae137e4a5
解密:
代码语言:javascript复制public class TestSM4 {
@Test
void test() {
String key="ILoveXiaoMian456";
SM4 sm4 = SmUtil.sm4(key.getBytes());
String secretText="382eeef6fd65b154f1f157eadd78c840a5fe1a460aeb478598b3ed2ae137e4a5";
System.out.println(sm4.decryptStr(secretText));
}
}
输出结果为:
代码语言:javascript复制我爱小面,小面爱我
总结
加密算法多种多样
主要考虑应用场景
除了以上的SM1234
还有 SM7、SM9等等
大家可以自己研究