跨语言国密SM4加解密实战:Java与Golang无缝对接
概述
本文详细介绍了如何在Java和Golang中使用SM4算法进行对称加密和解密操作。通过使用CBC模式和PKCS5填充,成功实现了跨语言的数据加密和解密。无论是Java加密后在Golang解密,还是Golang加密后在Java解密,均通过了测试验证,保证了两种语言在处理国密SM4算法时的兼容性和一致性。
前期准备
Java 国密库
<!-- https://mvnrepository.com/artifact/org.bouncycastle/bcprov-jdk15on -->
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>1.70</version>
</dependency>
Golang 国密库
<!--https://github.com/Hyperledger-TWGC/ccs-gm-->
go get github.com/Hyperledger-TWGC/ccs-gm
国密SM4对称加解密
Java 加密 Golang 解密
Java 加密
/**
* 生成SM4密钥和密文 必须使用CBC模式
*
* @param data 需要加密的数据
*/
publicstaticvoidgenerateKeyAndCiphertext(byte[] data){
// 生成SM4密钥
KeyGeneratorkeyGen=null;
try{
// 生成SM4密钥
keyGen =KeyGenerator.getInstance("SM4","BC");
keyGen.init(128);// SM4使用128位密钥
SecretKeysecretKey= keyGen.generateKey();
byte[] key = secretKey.getEncoded();
// 生成随机的IV向量
byte[] iv =newbyte[16];
SecureRandomrandom=newSecureRandom();
random.nextBytes(iv);
IvParameterSpecivSpec=newIvParameterSpec(iv);
// 使用SM4进行加密
Ciphercipher=Cipher.getInstance("SM4/CBC/PKCS5Padding","BC");
cipher.init(Cipher.ENCRYPT_MODE,newSecretKeySpec(key,"SM4"), ivSpec);
byte[] encrypted = cipher.doFinal(data);
// 编码密钥、IV和密文为Base64
StringkeyBase64=Base64.toBase64String(key);
StringivBase64=Base64.toBase64String(iv);
StringencryptedBase64=Base64.toBase64String(encrypted);
// 输出Base64编码的密钥、IV和密文
System.out.println("Key (Base64): "+ keyBase64);
System.out.println("IV (Base64): "+ ivBase64);
System.out.println("Encrypted Data (Base64): "+ encryptedBase64);
}catch(Exception e){
thrownewRuntimeException(e);
}
}
Golang 解密
/**
* SM4解密
* @param keyBase64 密钥Base64编码
* @param encryptedBase64 密文Base64编码
*/
func DecodeCiphertext(keyBase64, ivBase64, encryptedBase64 string)[]byte{
// 解码Base64编码的密钥、IV和密文
key, err := base64.StdEncoding.DecodeString(keyBase64)
if err !=nil{
log.Fatalf("Failed to decode key: %v", err)
}
iv, err := base64.StdEncoding.DecodeString(ivBase64)
if err !=nil{
log.Fatalf("Failed to decode IV: %v", err)
}
encryptedData, err := base64.StdEncoding.DecodeString(encryptedBase64)
if err !=nil{
log.Fatalf("Failed to decode encrypted data: %v", err)
}
// 创建SM4解密器
block, err := sm4.NewCipher(key)
if err !=nil{
log.Fatalf("Failed to create SM4 cipher: %v", err)
}
// 创建CBC解密模式
mode := cipher.NewCBCDecrypter(block, iv)
// 解密数据
decryptedData :=make([]byte,len(encryptedData))
mode.CryptBlocks(decryptedData, encryptedData)
// 移除PKCS5填充
decryptedData, err =RemovePKCS5Padding(decryptedData)
if err !=nil{
log.Fatalf("Failed to remove padding: %v", err)
}
fmt.Printf("Decrypted Data: %s\n",string(decryptedData))
return decryptedData
}
结果对比
Java
sm.generateKeyAndCiphertext("hello world".getBytes(StandardCharsets.UTF_8));
Key (Base64): 7TD7k33kyXB4d8VWK/HcDQ==
IV (Base64): x2MZrm+WXlZSSoyoqf/e6A==
Encrypted Data (Base64): GmZPfuyGYJAGWKpIQdeTpQ==
golang
func TestDecodeCiphertext(t *testing.T) {
keyBase64 := "7TD7k33kyXB4d8VWK/HcDQ=="
encryptedBase64 := "GmZPfuyGYJAGWKpIQdeTpQ=="
t.Log(DecodeCiphertext(keyBase64, "x2MZrm+WXlZSSoyoqf/e6A==", encryptedBase64))
}
=== RUN TestDecodeCiphertext
DecryptedData: hello world
sm_test.go:25:[10410110810811132119111114108100]
--- PASS:TestDecodeCiphertext(0.00s)
PASS
Golang 加密 Java 解密
Golang 加密
/**
* SM4加密
* @param data 待加密数据
* @return keyBase64 密钥Base64编码
*/
func EncodeChainText(data []byte)(keyBase64, ivBase64, encryptedBase64 string){
// 生成SM4密钥
key :=make([]byte,16)
if _, err := io.ReadFull(rand.Reader, key); err !=nil{
log.Fatalf("Failed to generate key: %v", err)
}
// 生成随机的IV向量
iv :=make([]byte,16)
if _, err := io.ReadFull(rand.Reader, iv); err !=nil{
log.Fatalf("Failed to generate IV: %v", err)
}
// 创建SM4加密器
block, err := sm4.NewCipher(key)
if err !=nil{
log.Fatalf("Failed to create SM4 cipher: %v", err)
}
// 使用CBC模式加密
mode := cipher.NewCBCEncrypter(block, iv)
// 添加PKCS5填充
paddedData := PKCS5Padding(data, block.BlockSize())
// 加密数据
encryptedData :=make([]byte,len(paddedData))
mode.CryptBlocks(encryptedData, paddedData)
// 编码密钥、IV和密文为Base64
keyBase64 = base64.StdEncoding.EncodeToString(key)
ivBase64 = base64.StdEncoding.EncodeToString(iv)
encryptedBase64 = base64.StdEncoding.EncodeToString(encryptedData)
// 输出Base64编码的密钥、IV和密文
fmt.Println("Key (Base64):", keyBase64)
fmt.Println("IV (Base64):", ivBase64)
fmt.Println("Encrypted Data (Base64):", encryptedBase64)
return keyBase64, ivBase64, encryptedBase64
}
Java 解密
/**
* SM4 解密
*
* @param keyBase64 key
* @param ivBase64 iv
* @param encryptedBase64 密文
*/
publicstaticvoidDecodeCipertext(String keyBase64, String ivBase64, String encryptedBase64){
// 解码Base64编码的密钥、IV和密文
byte[] key =Base64.decode(keyBase64);
byte[] iv =Base64.decode(ivBase64);
byte[] encryptedData =Base64.decode(encryptedBase64);
// 使用SM4进行解密
Ciphercipher=null;
try{
cipher =Cipher.getInstance("SM4/CBC/PKCS5Padding","BC");
cipher.init(Cipher.DECRYPT_MODE,newSecretKeySpec(key,"SM4"),newIvParameterSpec(iv));
byte[] decryptedData = cipher.doFinal(encryptedData);
// 输出解密后的数据
System.out.println("Decrypted Data: "+newString(decryptedData,"UTF-8"));
}catch(Exception e){
thrownewRuntimeException(e);
}
}
结果对比
golang
func TestEncodeChainText(t *testing.T) {
EncodeChainText([]byte("hello go"))
}
=== RUN TestEncodeChainText
Key (Base64): SxxgXVsnCpwak5go/wTqMg==
IV (Base64): xenl6HJR+yvvfMonpjYYug==
Encrypted Data (Base64): XgiZU0fklp+Asc0kJBfYqg==
--- PASS: TestEncodeChainText (0.00s)
PASS
java
sm.DecodeCipertext("SxxgXVsnCpwak5go/wTqMg==", "xenl6HJR+yvvfMonpjYYug==", "XgiZU0fklp+Asc0kJBfYqg==");
Decrypted Data: hello go
Process finished with exit code 0
总结
1. SM4加解密使用CBC模式,测试通过
跨语言国密SM4加解密实战:Java与Golang无缝对接的更多相关文章
- .NET Core加解密实战系列之——消息摘要与数字签名算法
目录 简介 功能依赖 消息摘要算法 MD算法 家族发展史 应用场景 代码实现 MD5 示例代码 SHA算法 应用场景 代码实现 SHA1 SHA256 示例代码 MAC算法 HMAC算法的典型应用 H ...
- .NET Core加解密实战系列之——对称加密算法
简介 加解密现状,编写此系列文章的背景: 需要考虑系统环境兼容性问题(Linux.Windows) 语言互通问题(如C#.Java等)(加解密本质上没有语言之分,所以原则上不存在互通性问题) 网上资料 ...
- .NET Core加解密实战系列之——使用BouncyCastle制作p12(.pfx)数字证书
简介 加解密现状,编写此系列文章的背景: 需要考虑系统环境兼容性问题(Linux.Windows) 语言互通问题(如C#.Java等)(加解密本质上没有语言之分,所以原则上不存在互通性问题) 网上资料 ...
- 国密SM4对称算法实现说明(原SMS4无线局域网算法标准)
国密SM4对称算法实现说明(原SMS4无线局域网算法标准) SM4分组密码算法,原名SMS4,国家密码管理局于2012年3月21日发布:http://www.oscca.gov.cn/News/201 ...
- 一个关于国密SM4的故事
一个关于国密SM4的故事 我的名字叫SM4,我还有三位兄长,分别是大哥SM1, 二哥SM2, 和三哥SM3.说起我的名字,故事要回到2006年的时候,我出生的时候并不是叫SM4的,而是叫做SMS4.只 ...
- [转帖]一个关于国密SM4的故事
一个关于国密SM4的故事 https://www.cnblogs.com/ouyida3/p/10053862.html SM1 硬件SM2 非对称加密SM3 hash算法SM4 对称加密 一个关于国 ...
- Atitit.跨语言反射api 兼容性提升与增强 java c#。Net php js
Atitit.跨语言反射api 兼容性提升与增强 java c#.Net php js 1. 什么是反射1 1.1. 反射提供的主要功能:1 1.2. 实现反射的过程:1 ...
- AES加解密异常java.security.InvalidKeyException: Illegal key size
AES加解密异常 Java后台AES解密,抛出异常如下:java.security.InvalidKeyException: Illegal key size Illegal key size or ...
- .NET Core加解密实战系列之——RSA非对称加密算法
目录 简介 功能依赖 生成RSA秘钥 PKCS1格式 PKCS8格式 私钥操作 PKCS1与PKCS8格式互转 PKCS1与PKCS8私钥中提取公钥 PEM操作 PEM格式密钥读取 PEM格式密钥写入 ...
- openssl在多平台和多语言之间进行RSA加解密注意事项
首先说一下平台和语言: 系统平台为CentOS6.3,RSA加解密时使用NOPADDING进行填充 1)使用C/C++调用系统自带的openssl 2)Android4.2模拟器,第三方openssl ...
随机推荐
- 数据库周刊29│2020数据库研究报告;Oracle取消今年技术大会;腾讯云DBbridge发布支持一键迁库;饿了么迁至阿里云;PG数组查询;Oracle被比特币勒索;DM8 安全管理…
摘要:墨天轮数据库周刊第29期发布啦,每周1次推送本周数据库相关热门资讯.精选文章.干货文档. 热门资讯 1.快讯:2020年Oracle OOW大会因疫情取消 系近20年首度[摘要]Oracle ...
- iOS中在导航条设置搜索框使用小结
最近在项目开发中用到了搜索框,一般是设置在列表顶部或者导航条上.下面说一下在导航条上使用搜索框的思路,刚开始是直接将CCSearchBar添加到导航条,在viewWillDisappear设置隐藏,在 ...
- Notepad--特色功能:拷贝另存为
Notepad--特色功能:拷贝另存为 你是否纠结如下的使用场景: 正在编辑的文件,还没有想好,保存担心把原文件给覆盖了. 使用"另存为"后当前编辑界面的文档又变成新的文件了,可是 ...
- Whizard:跨越 Thanos 从开源项目到生产就绪的鸿沟
此文是根据 KubeSphere 在 KubeCon China 2024 上的演讲分享整理而成. 议题简介 作为最受欢迎和强大的 Prometheus 长期存储项目之一,Thanos 被社区广泛采用 ...
- 在 Debian 12 上安装 KubeSphere 实战入门
老 Z,运维架构师,云原生爱好者,目前专注于云原生运维,云原生领域技术栈涉及 Kubernetes.KubeSphere.DevOps.OpenStack.Ansible 等. 前言 知识点 定级:入 ...
- dirseach目录扫描工具-安装详细教程
安装: 1.github源码下载解压 使用 git 安装: 推荐git clone https://github.com/maurosoria/dirsearch.git --depth 1 zip文 ...
- Python实现回数
题目:回数是指从左向右读和从右向左读都是一样的数,例如 12321,909.请利用 filter()滤掉非回数: 思路:要实现回数判断,主要是将输入的数找到其各个位置的值,然后判断前后相对应的位置是否 ...
- 蚂蚁KAG框架核心功能研读
作者介绍: 薛明:拥有近10年在医疗和零售领域应用机器学习和人工智能的经验.曾就职于通用电气.复星医药等企业.长期专注于医学图像.自然语言处理以及数据科学的研发工作,如训练/推理框架.数据挖掘与分析等 ...
- Sqlsugar调用Oracle的存储过程
前段时间在搬迁项目的时候,遇到一个问题,就是用sqlsugar调用oracle的存储过程的时候调用不了: 当时卡了一整天,现在有空了把这个问题记录分享一下. 先去nuget上安装一下sqlsugar的 ...
- C# Modbus 之 EasyModbus
直接上代码 public int EasyModbusReadInputRegisters() { ModbusClient modbusClient = new ModbusClient(_spHe ...