跨语言国密SM4加解密实战:Java与Golang无缝对接

news/2024/12/2 15:34:53/文章来源:https://www.cnblogs.com/exmyth/p/18581992

概述

本文详细介绍了如何在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. 1. SM4加解密使用CBC模式,测试通过

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/845458.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2099年:IDEA 2024.3 安装激活使用教程

IntelliJ IDEA简介 IntelliJ IDEA是一款非常强大的Java集成开发环境(IDE),由JetBrains公司开发。它提供了丰富的功能和工具,帮助开发者更高效地编写、调试和部署代码。 要求 在开始之前,请确保您的计算机满足以下系统要求:操作系统:Windows、macOS或Linux 处理器:至少1 GH…

creo分割面

分割一个面成两个面.el-image-viewer__wrapper { position: fixed; top: 0; right: 0; bottom: 0; left: 0; z-index: 2147483647 !important } .el-image-viewer__btn { position: absolute; z-index: 1; display: flex; align-items: center; justify-content: center; borde…

记录Vue3中使用pinia可能遇到的问题及解决方法

1.在安装依赖时容易停留pinia,附带持久化插件使用的地址 https://prazdevs.github.io/pinia-plugin-persistedstate/zh/guide/ 方法:请按照以下步骤: 删除 C:\Users账户中的 .npmrc 文件在命令提示符里执行 npm cache verify在命令提示符里执行 npm config set registry htt…

git报错403怎么解决

Git报错403及解决询问AI主要有以下可能原因:创建SSH:(不要用中文,管理员权限打开PowerShell运行下面的命令,地址可以自定义)ssh-keygen -t rsa -b 4096 -C "2919356315@qq.com" -f "C:/Users/lzh/.ssh/id_rsa"查看SSH:cat C:/Users/lzh/.ssh/id_rsa.p…

fetch call web api upload or update picture

昨天C# + html + fetch + API + javascript https://www.cnblogs.com/insus/p/18579193 其中有一个图片相关的功能,现把它解说一下。html页面上,简单的input和button,无需何附加<form action="/action_page_binary.asp" method="post" enctype="…

长期主义下的一本经济账:卷价格更要卷性能

「 不做陪跑者,要做支撑者。企业成长的每个关键时刻,在背后默默发力。」今年以来,云的价格战似乎更猛烈了一些。 事实上,云服务降价在规模与创新两重推动力下早就是一种常态。作为云的鼻祖,亚马逊云经常是一年连续降价十几次甚至几十次。这种理性降价,是将规模红利与创新…

“天翼云息壤杯”高校AI大赛福建赛区启动!

11月20日,2024首届全国“天翼云息壤杯”高校AI 大赛(福建赛区)正式启动。中国电信福建公司携手华为公司、福建省计算机学会、福建省自动化学会,正式启动天翼云科技有限公司承办的“天翼云息壤杯”高校AI大赛(福建赛区)赛事。该赛事是中国电信搭建的进一步挖掘培养AI人才、…

从挑战到突破:HBlock定义智算存储新范式!

近日,由DOIT传媒主办,中国计算机学会信息存储专委会、武汉光电国家研究中心、百易存储研究院支持的2024中国数据与存储峰会在北京召开。此次峰会以“智数据 AI未来”为主题,天翼云科技有限公司国际业务事业部存储产品线专家肖夏敏代表参会,并发表“轻量级存储集群控制器HBl…

html2canvas 解决某些站点截图空白问题

业务场景介绍 点击浏览器右上角已安装的chrome插件图标,这个时候会出现一个界面,我们称这个界面为popup,界面上有个"从页面获取产品信息"按钮,单机它会对当前标签页面内容进行截图,最后将截图的图片转成base64发送至xx接口 部分核心代码解读:截取当前可视区域的…

领歌看板助力电商大促筹备

每年的“双11”“双12”“618”等大型电商促销活动是各企业的年度重头戏,但涉及环节众多、协作复杂,稍有疏漏就可能影响活动效果。领歌看板为您提供了一种高效、直观的任务管理方式,确保每一步都尽在掌握。 1. 全面覆盖任务场景,理清活动脉络 利用领歌看板,您可以将大促活…

.NET开发WinForm(C/S)项目整合三种SOA服务访问(直连、WCF、WebAPI)模式

在软件开发领域,尤其是企业级应用开发中,灵活性、开放性、可扩展性往往是项目成功的关键因素。对于C/S项目,如何高效地与后端数据库进行交互,以及如何提供多样化的服务访问方式,是开发者需要深入考虑的问题。目前主流的方式就三种:数据库直连、WCF模式、WebAPI模式。RDIF…