吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 1017|回复: 18
收起左侧

[Java 转载] 国密SM4算法应用分享

[复制链接]
johnz521 发表于 2025-3-16 21:00
本帖最后由 johnz521 于 2025-3-21 08:41 编辑

一、什么是SM4
– SM4算法介绍
SM4 算法是一种分组密码算法。其分组长度为 128bit,密钥长度也为 128bit。
加密算法与密钥扩展算法均采用 32 轮非线性迭代结构,以字(32 位)为单位进
行加密运算,每一次迭代运算均为一轮变换函数 F。SM4 算法加/解密算法的结构
相同,只是使用轮密钥相反,其中解密轮密钥是加密轮密钥的逆序。

二、java使用步骤
1.引入maven依赖
pom文件中增加BC库:


[XML] 纯文本查看 复制代码
1
2
3
4
5
6
<!-- https://mvnrepository.com/artifact/org.bouncycastle/bcprov-jdk18on -->
<dependency>
    <groupId>org.bouncycastle</groupId>
    <artifactId>bcprov-jdk18on</artifactId>
    <version>1.78</version>
</dependency>



2.java代码
代码如下:
[Java] 纯文本查看 复制代码
001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
054
055
056
057
058
059
060
061
062
063
064
065
066
067
068
069
070
071
072
073
074
075
076
077
078
079
080
081
082
083
084
085
086
087
088
089
090
091
092
093
094
095
096
097
098
099
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
/*
 
    * SM4算法名称
 
    * */
 
    private static final String ALGORITHM_NAME = "SM4";
 
 
 
    /**
 
    *  加密模式和填充
 
    * */
 
    public static final String CIPHER_ALGORITHM_ECB_WITH_PKCS5PADDING = "SM4/ECB/PKCS5Padding";
 
 
 
    public static final String CIPHER_ALGORITHM_CBC_WITH_PKCS5PADDING = "SM4/CBC/PKCS5Padding";
 
 
 
    public static final String CIPHER_ALGORITHM_ECB_WITH_PKCS7PADDING = "SM4/ECB/PKCS7Padding";
 
 
 
    public static final String CIPHER_ALGORITHM_CBC_WITH_PKCS7PADDING = "SM4/CBC/PKCS7Padding";
 
 
 
    public static final String CIPHER_ALGORITHM_CBC_WITH_NOPADDING = "SM4/CBC/NOPadding";
 
 
 
    public static final String CIPHER_ALGORITHM_ECB_WITH_NOPADDING = "SM4/ECB/NOPadding";
 
 
 
     /**
 
     * 默认密钥长度 只有126bit
 
     */
 
    private static final int DEFAULT_KEY_SIZE = 128;
 
    
 
    /**
 
     * 默认向量 要求16字节
 
     */
 
    private static final byte[] DEFAULT_IV = HexUtil.decodeHex("设置默认向量 需要改动");
 
 
 
    static {
 
        if (Security.getProvider(BouncyCastleProvider.PROVIDER_NAME) == null) {
 
            Security.addProvider(new BouncyCastleProvider());
 
        }
 
    }
 
        /**
 
     * 创建密钥
 
     *
 
     *
 
     * @Return base64格式的密钥
 
     * @throws Exception 创建密钥异常
 
     */
 
    public static String generateKey() throws Exception {
 
        KeyGenerator keyGenerator = KeyGenerator.getInstance(ALGORITHM_NAME, BouncyCastleProvider.PROVIDER_NAME);
 
        keyGenerator.init(DEFAULT_KEY_SIZE, new SecureRandom());
 
        return Base64.getEncoder().encodeToString(keyGenerator.generateKey().getEncoded());
 
    }
 
    /**
 
     * 加密
 
     *
 
     * @Param data 要加密的明文
 
     * @param padding 填充方式
 
     * @param iv 如果是cbc 则需要iv
 
     * @return 加密后的密文
 
     * @throws Exception 加密异常
 
     */
 
    public static String encrypt(String data,String key,String padding,String iv) throws Exception {
 
        return sm4(data, key, Cipher.ENCRYPT_MODE,padding,iv);
 
    }
 
 
 
    /**
 
     * 解密
 
     *
 
     * @param data 要解密的密文
 
     * @param padding 填充方式
 
     * @param iv 如果是cbc 则需要iv
 
     * @return 解密后的明文
 
     * @throws Exception 解密异常
 
     */
 
    public static String decrypt(String data,String key,String padding,String iv) throws Exception {
 
        return sm4(data, key , Cipher.DECRYPT_MODE,padding,iv);
 
    }
 
 
 
    /**
 
     * 加解密核心方法
 
     *
 
     * @param input 明文(加密模式)或密文(解密模式)
 
     * @param key   密钥
 
     * @param mode  1-加密 2-解密
 
     * @param padding 填充方式
 
     * @param iv 向量 如传则使用传的 不传则使用默认的
 
     * @return 密文(加密模式)或明文(解密模式)
 
     * @throws Exception 加解密异常
 
     */
 
    private static String sm4(String input,String key, int mode,String padding,String iv)
 
            throws Exception {
 
        SecretKeySpec secretKeySpec = new SecretKeySpec(Base64.getDecoder().decode(key), ALGORITHM_NAME);
 
        Cipher cipher = Cipher
 
                .getInstance(padding, BouncyCastleProvider.PROVIDER_NAME);
 
        if (StringUtils.containsIgnoreCase(padding,"CBC")){
 
            cipher.init(mode, secretKeySpec,new IvParameterSpec(StringUtils.isBlank(iv) ? DEFAULT_IV : Base64.getDecoder().decode(iv)));
 
        }else {
 
            cipher.init(mode, secretKeySpec);
 
        }
 
        return Base64.getEncoder().encodeToString(cipher.doFinal(Base64.getDecoder().decode(input)));
 
    }
 
 
 
        /**
 
     * 测试 判断最后是否输出true
 
     */
 
        public static void main(String[] args) throws Exception {
 
 
 
 
 
        String s = generateKey();
 
        String padding = CIPHER_ALGORITHM_CBC_WITH_PKCS7PADDING;
 
        String data = "hello world!!";
 
        String iv = Base64.getEncoder().encodeToString("testivtestivtest".getBytes(StandardCharsets.UTF_8));
 
        String encryptStr = encrypt(Base64.getEncoder().encodeToString(data.getBytes(StandardCharsets.UTF_8)), s, padding, iv);
 
        String decryptStr = decrypt(encryptStr, s, padding, iv);
 
        System.out.println(data.equals(new String(Base64.getDecoder().decode(decryptStr))));
 
         
 
   }



3.openssl验证
第二步已经在java中进行密钥生成、加密、解密操作,证明逻辑在java中没有问题,现在进行openssl和java对接
方式:使用同一把密钥,在openssl中加密、在java中解密 判断是否正确

# -sm4-ecb 指模式,和java中加密模式和填充对应,-e代表加密 -d代表解密 -K表示指定密钥
# 157307f646eb47c3b9c3bf9ef1a2090b为java中生成的密钥的16进制形式
openssl enc -in text.bin -sm4-ecb -e -K 157307f646eb47c3b9c3bf9ef1a2090b -out b.txt

已经在openssl中进行加密,现在在java中对密文b.txt进行解密

[Java] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
public static void main(String[] args) throws Exception {
 
    String de = Base64.getEncoder().encodeToString(Files.readAllBytes(new File("/b.txt").toPath()));
 
    System.out.println(de);
 
    String decryptStr = decrypt(de, key, padding, "");
 
    System.out.println(new String(Base64.getDecoder().decode(decryptStr)));
 
 
 
}


免费评分

参与人数 5吾爱币 +2 热心值 +5 收起 理由
zp89060778 + 1 + 1 热心回复!
langyoChina + 1 我很赞同!
wantall + 1 谢谢@Thanks!
pingyian + 1 我很赞同!
yinxingyouhua + 1 + 1 用心讨论,共获提升!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

 楼主| johnz521 发表于 2025-3-20 14:13
绕天涯 发表于 2025-3-17 10:19
有没有python的实现方法呀

Python实现国密SM4加密和解密,GmSSL是由北京大学自主开发的国产商用密码开源库,实现了对国密算法、标准和安全通信协议的全面功能覆盖,包括SM3、SM4等国密算法,参考代码如下
[Python] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# -*- coding: utf-8 -*-
 
from gmssl.sm4 import CryptSM4, SM4_ENCRYPT, SM4_DECRYPT
import binascii
import os
 
def str_to_hexStr(hex_str):
    """
    字符串转hex
    :param hex_str: 字符串
    :return: hex
    """
    hex_data = hex_str.encode('utf-8')
    str_bin = binascii.unhexlify(hex_data)
    return str_bin.decode('utf-8')
 
def encrypt(crypt_sm4,encrypt_key, value):
    """
    国密sm4加密
    :param encrypt_key: sm4加密key
    :param value: 待加密的字符串
    :return: sm4加密后的hex值
    """
    crypt_sm4.set_key(encrypt_key, SM4_ENCRYPT)
    encrypt_value = crypt_sm4.crypt_ecb(value)  # bytes类型
    return encrypt_value.hex()
 
def decrypt(crypt_sm4,decrypt_key, encrypt_value):
    """
    国密sm4解密
    :param decrypt_key:sm4加密key
    :param encrypt_value: 待解密的hex值
    :return: 原字符串
    """
    crypt_sm4.set_key(decrypt_key, SM4_DECRYPT)
    decrypt_value = crypt_sm4.crypt_ecb(bytes.fromhex(encrypt_value))  # bytes类型
    return str_to_hexStr(decrypt_value.hex())
 
 
key = os.urandom(16)
value = b'Hello@2023' #  bytes类型
crypt_sm4 = CryptSM4()
 
# 加密
enc_value = encrypt(crypt_sm4,key,value)
 
#解密
dec_value = encrypt(crypt_sm4,key,enc_value)
 楼主| johnz521 发表于 2025-3-20 14:07
AliaoJO 发表于 2025-3-17 11:59
感谢大佬分享,又认识到一个新的加密算法库,但我更想了解一下这个算法有什么特点?

SM4是一种对称加密算法,算法是公开的,类似AES算法。SM4密码算法作为国密算法之一,是一种我国自主设计的分组对称密码算法,用于实现数据的加密/解密运算,以保证数据和信息的机密性。

在具体实现上,SM4将明文分成多个固定长度的数据块,每个数据块通过一系列的置换和变换进行加密,最终生成密文。解密过程则是逆向操作,通过相同的置换和变换还原出原始明文。

该算法的分组长度为128比特,密钥长度为128比特(明文和密钥等长)。
加密算法与密钥扩展算法都采用32轮非线性迭代结构。
密钥扩展算法:将加密密钥变换为轮密钥的运算单元。
数据解密和数据加密的算法结构相同,只是轮密钥的使用顺序相反,解密轮密钥是加密轮密钥的逆序。
lccpstb 发表于 2025-3-17 09:20
nzkboy 发表于 2025-3-17 09:29
学习了学习了学习了
wolfstudio 发表于 2025-3-17 09:32
都是拿着加密库在那搞几下,没意思
COMPUTERCD 发表于 2025-3-17 09:43
wolfstudio 发表于 2025-3-17 09:32
都是拿着加密库在那搞几下,没意思

我也搞搞
131486352 发表于 2025-3-17 09:56
国密加密研究下,谢谢大佬
pingyian 发表于 2025-3-17 10:05
收藏了,后面可能会用到
sming2018 发表于 2025-3-17 10:13
谢谢,有没有硬算法?
绕天涯 发表于 2025-3-17 10:19
有没有python的实现方法呀
PKzengwei200808 发表于 2025-3-17 10:20
感谢大佬,新手学习中
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2025-5-20 21:36

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表