2023/05/02更新说明
1、修复明文中包含中文或者标点符号等特殊字符时,摘要计算结果不一致的问题,修复方法是先加明文做base64处理,因为base64的结果都是一致的。具体看下方注释和新增代码。
前言
不知不觉已经2023年了,最近工作比较忙,各种问题和项目改造,这篇博客就一直拖延到现在,希望各位读者见谅。
闲话就说到这,让我们一起回顾下之前两期的内容,第一期博主主要演示了java、C#、nodejs、golang4种开发语言的sm2密钥对生成的代码,传送门:java国密 C#国密 golang国密 NodeJS国密汇总(一),第二期博主主要演示了java、C#、nodejs、golang4种开发语言的sm2加签验签、加密解密的代码,传送门:java国密 C#国密 golang国密 NodeJS国密汇总(二)。回顾完后博主就开始本期的内容演示,本期主要把四种开发语言的SM3杂凑算法整上,希望对各位观众大佬有所帮助。
4、SM3计算摘要
由于sm3比较简单,所以这边也不做过多篇幅说明,~~**但是中文需要转码才可以,并且对特殊字符无法处理 **,这两个注意点在演示代码中的注释里有说明。
(1)java
代码示例(中文或者特殊字符遗留问题已解决):
package sm3;
import org.bouncycastle.crypto.digests.SM3Digest;
import org.bouncycastle.util.encoders.Hex;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
/**
* @Author: 系统异常
* @CreateTime: 2022/12/26 14:45
* @Description: sm3测试类
* @Version: 1.0
*/
public class SM3Test {
public static void main(String[] args) throws UnsupportedEncodingException {
// 定义数组
byte[] sm3Byte = new byte[32];
// 初始化sm3
SM3Digest sm3 = new SM3Digest();
// 待摘要字符串、数字
String unSm3Str = "12345678";
sm3.update(unSm3Str.getBytes(StandardCharsets.UTF_8), 0, unSm3Str.length());
sm3.doFinal(sm3Byte, 0);
String sm3StrHex = new String(Hex.encode(sm3Byte));
System.out.println("java sm3StrHex 数字 -->" + sm3StrHex);
// 待摘要字符串、字母
unSm3Str = "abcdefg";
sm3.update(unSm3Str.getBytes(StandardCharsets.UTF_8), 0, unSm3Str.length());
sm3.doFinal(sm3Byte, 0);
sm3StrHex = new String(Hex.encode(sm3Byte));
System.out.println("java sm3StrHex 字母 -->" + sm3StrHex);
// 2023/05/02 修复明文中包含中文或者标点符号等特殊字符时,摘要计算结果不一致的问题,修复方法是先加明文做base64处理,因为base64的结果都是一致的。
// 待摘要字符串、中文
unSm3Str = "你好,世界";
String changeCodeStr = Base64.toBase64String(unSm3Str.getBytes(StandardCharsets.UTF_8));
System.out.println("java 中文base64后 -->" + changeCodeStr);
sm3.update(changeCodeStr.getBytes(StandardCharsets.UTF_8), 0, changeCodeStr.length());
sm3.doFinal(sm3Byte, 0);
sm3StrHex = new String(Hex.encode(sm3Byte));
System.out.println("java sm3StrHex 中文 -->" + sm3StrHex);
// 特殊字符、
unSm3Str = ",./;'<>?:\"!@#$%^&*()_+-=`";
changeCodeStr = Base64.toBase64String(unSm3Str.getBytes(StandardCharsets.UTF_8));
System.out.println("java 特殊字符base64后 -->" + changeCodeStr);
sm3.update(changeCodeStr.getBytes(StandardCharsets.UTF_8), 0, changeCodeStr.length());
sm3.doFinal(sm3Byte, 0);
sm3StrHex = new String(Hex.encode(sm3Byte));
System.out.println("java sm3StrHex 特殊字符 -->" + sm3StrHex);
}
}
演示结果(各种语言的结果中特殊字符不一致、暂未解决,其他情况均测试一致 ):
java sm3StrHex 数字 -->0fffff81e971fa3f09107abf77931463fc0710bfb8962efeae3d5654b073bb0c
java sm3StrHex 字母 -->08b7ee8f741bfb63907fcd0029ae3fd6403e6927b50ed9f04665b22eab81e9b7
java 中文base64后 -->5L2g5aW977yM5LiW55WM
java sm3StrHex 中文 -->3d22faa1b58113903211b22bfd7c119f9b70d9993abb8239ac382b41a315ce3a
java 特殊字符base64后 -->LC4vOyc8Pj86IiFAIyQlXiYqKClfKy09YA==
java sm3StrHex 特殊字符 -->95cbbf02e028fbe9e4514e60c321a0329559e60c2e1b6ddc52124706b2147e90
(2)c#
代码示例(中文或者特殊字符遗留问题已解决):
using Org.BouncyCastle.Crypto.Digests;
using Org.BouncyCastle.Utilities.Encoders;
using System;
using System.Collections.Generic;
using System.Text;
/// <summary>
/// 九二战歌
/// sm3摘要计算演示
/// </summary>
namespace sm
{
class Sm3Test
{
public void Sm3Calculate()
{
// 定义数组
byte[] sm3Byte = new byte[32];
// 初始化sm3
SM3Digest sm3 = new SM3Digest();
// 待摘要字符串、数字
string unSm3Str = "12345678";
sm3.BlockUpdate(Encoding.UTF8.GetBytes(unSm3Str), 0, unSm3Str.Length);
sm3.DoFinal(sm3Byte, 0);
String sm3StrHex = new String(Hex.ToHexString(sm3Byte));
Console.WriteLine("csharp sm3StrHex 数字 -->" + sm3StrHex);
// 待摘要字符串、字母
unSm3Str = "abcdefg";
sm3.BlockUpdate(Encoding.UTF8.GetBytes(unSm3Str), 0, unSm3Str.Length);
sm3.DoFinal(sm3Byte, 0);
sm3StrHex = new String(Hex.ToHexString(sm3Byte));
Console.WriteLine("csharp sm3StrHex 字母 -->" + sm3StrHex);
// 2023/05/02 修复明文中包含中文或者标点符号等特殊字符时,摘要计算结果不一致的问题,修复方法是先加明文做base64处理,因为base64的结果都是一致的。
// 待摘要字符串、中文
unSm3Str = "你好,世界";
String changeCodeStr = Base64.ToBase64String(Encoding.UTF8.GetBytes(unSm3Str));
Console.WriteLine("csharp 中文base64后 -->" + changeCodeStr);
sm3.BlockUpdate(Encoding.UTF8.GetBytes(changeCodeStr), 0, changeCodeStr.Length);
sm3.DoFinal(sm3Byte, 0);
sm3StrHex = new String(Hex.ToHexString(sm3Byte));
Console.WriteLine("csharp sm3StrHex 中文 -->" + sm3StrHex);
// 待摘要字符串、特殊字符
unSm3Str = ",./;'<>?:\"!@#$%^&*()_+-=`";
changeCodeStr = Base64.ToBase64String(Encoding.UTF8.GetBytes(unSm3Str));
Console.WriteLine("csharp 特殊字符base64后 -->" + changeCodeStr);
sm3.BlockUpdate(Encoding.UTF8.GetBytes(changeCodeStr), 0, changeCodeStr.Length);
sm3.DoFinal(sm3Byte, 0);
sm3StrHex = new String(Hex.ToHexString(sm3Byte));
Console.WriteLine("csharp sm3StrHex 特殊字符 -->" + sm3StrHex);
}
}
}
演示结果(各种语言的结果中特殊字符不一致、暂未解决,其他情况均测试一致 ):
csharp sm3StrHex 数字 -->0fffff81e971fa3f09107abf77931463fc0710bfb8962efeae3d5654b073bb0c
csharp sm3StrHex 字母 -->08b7ee8f741bfb63907fcd0029ae3fd6403e6927b50ed9f04665b22eab81e9b7
csharp 中文base64后 -->5L2g5aW977yM5LiW55WM
csharp sm3StrHex 中文 -->3d22faa1b58113903211b22bfd7c119f9b70d9993abb8239ac382b41a315ce3a
csharp 特殊字符base64后 -->LC4vOyc8Pj86IiFAIyQlXiYqKClfKy09YA==
csharp sm3StrHex 特殊字符 -->95cbbf02e028fbe9e4514e60c321a0329559e60c2e1b6ddc52124706b2147e90
(3)nodejs
代码示例:
const sm3 = require('sm-crypto').sm3;
function sm3Test() {
// 待摘要字符串、数字
let unSm3Str = "12345678";
let sm3StrHex = sm3(unSm3Str);
console.log("nodejs sm3StrHex 数字 -->" + sm3StrHex);
// 待摘要字符串、字母
unSm3Str = "abcdefg";
sm3StrHex = sm3(unSm3Str);
console.log("nodejs sm3StrHex 字母 -->" + sm3StrHex);
// 2023/05/02 修复明文中包含中文或者标点符号等特殊字符时,摘要计算结果不一致的问题,修复方法是先加明文做base64处理,因为base64的结果都是一致的。
// 待摘要字符串、中文
unSm3Str = "你好,世界";
let changeCodeStr = Buffer.from(unSm3Str).toString('base64');
console.log("nodejs 中文base64后 -->" + changeCodeStr);
sm3StrHex = sm3(changeCodeStr);
console.log("nodejs sm3StrHex 中文 -->" + sm3StrHex);
// 特殊字符
unSm3Str = ",./;'<>?:\"!@#$%^&*()_+-=`";
changeCodeStr = Buffer.from(unSm3Str).toString('base64');
console.log("nodejs 特殊字符base64后 -->" + changeCodeStr);
sm3StrHex = sm3(changeCodeStr);
console.log("nodejs sm3StrHex 特殊字符 -->" + sm3StrHex);
}
sm3Test()
演示结果(各种语言的结果中特殊字符不一致、暂未解决,其他情况均测试一致 ):
nodejs sm3StrHex 数字 -->0fffff81e971fa3f09107abf77931463fc0710bfb8962efeae3d5654b073bb0c
nodejs sm3StrHex 字母 -->08b7ee8f741bfb63907fcd0029ae3fd6403e6927b50ed9f04665b22eab81e9b7
nodejs 中文base64后 -->5L2g5aW977yM5LiW55WM
nodejs sm3StrHex 中文 -->3d22faa1b58113903211b22bfd7c119f9b70d9993abb8239ac382b41a315ce3a
nodejs 特殊字符base64后 -->LC4vOyc8Pj86IiFAIyQlXiYqKClfKy09YA==
nodejs sm3StrHex 特殊字符 -->95cbbf02e028fbe9e4514e60c321a0329559e60c2e1b6ddc52124706b2147e90
(4)golang
代码示例:
package test
import (
"encoding/hex"
"fmt"
"github.com/tjfoc/gmsm/sm3"
"net/url"
"testing"
)
func TestSm3(t *testing.T) {
// 待摘要字符串、数字
unsignStr := "12345678"
sm3Byte := sm3.Sm3Sum([]byte(unsignStr))
sm3StrHex := hex.EncodeToString(sm3Byte)
fmt.Println("golang sm3StrHex 数字 -->" + sm3StrHex)
// 待摘要字符串、字母
unsignStr = "abcdefg"
sm3Byte = sm3.Sm3Sum([]byte(unsignStr))
sm3StrHex = hex.EncodeToString(sm3Byte)
fmt.Println("golang sm3StrHex 字母 -->", sm3StrHex)
// 2023/05/02 修复明文中包含中文或者标点符号等特殊字符时,摘要计算结果不一致的问题,修复方法是先加明文做base64处理,因为base64的结果都是一致的。
// 待摘要字符串、中文
unsignStr = "你好,世界"
encodedStr := base64.StdEncoding.EncodeToString([]byte(unsignStr))
fmt.Println("golang 中文base64后 -->", encodedStr)
sm3Byte = sm3.Sm3Sum([]byte(encodedStr))
sm3StrHex = hex.EncodeToString(sm3Byte)
fmt.Println("golang sm3StrHex 中文 -->", sm3StrHex)
// 待摘要字符串、特殊字符、
unsignStr = ",./;'<>?:\"!@#$%^&*()_+-=`"
encodedStr = base64.StdEncoding.EncodeToString([]byte(unsignStr))
fmt.Println("golang 特殊字符base64后 -->", encodedStr)
sm3Byte = sm3.Sm3Sum([]byte(encodedStr))
sm3StrHex = hex.EncodeToString(sm3Byte)
fmt.Println("golang sm3StrHex 特殊字符 -->", sm3StrHex)
}
演示结果(各种语言的结果中特殊字符不一致、暂未解决,其他情况均测试一致 ):
golang sm3StrHex 数字 -->0fffff81e971fa3f09107abf77931463fc0710bfb8962efeae3d5654b073bb0c
golang sm3StrHex 字母 -->08b7ee8f741bfb63907fcd0029ae3fd6403e6927b50ed9f04665b22eab81e9b7
golang 中文base64后 -->5L2g5aW977yM5LiW55WM
golang sm3StrHex 中文 -->3d22faa1b58113903211b22bfd7c119f9b70d9993abb8239ac382b41a315ce3a
golang 特殊字符base64后 -->LC4vOyc8Pj86IiFAIyQlXiYqKClfKy09YA==
golang sm3StrHex 特殊字符 -->95cbbf02e028fbe9e4514e60c321a0329559e60c2e1b6ddc52124706b2147e90
总结
以上就是博主对四种语言的SM3杂凑算法的演示,这篇博客拖了很久,其一是最近工作比较忙,其二是特殊字符的问题研究了很久一直找不到有效的解决办法,如果有哪位大佬知道特殊字符的解决方案,可以联系我活着在评论区发表,由衷感谢 ,其二的问题已经在五一节中解决,各位可放心参考,最好是给博主一键三连。