java sm3&sm4国密算法

java sm3&sm4国密算法

CreationTime--2018年7月5日09点20分

Author:Marydon

1.实现方式

  借助bcprov-jdk15on-1.59.jar实现

2.sm3哈希算法

  导包

import org.bouncycastle.crypto.digests.SM3Digest;
import org.bouncycastle.crypto.macs.HMac;
import org.bouncycastle.crypto.params.KeyParameter;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.pqc.math.linearalgebra.ByteUtils;
import java.security.Security;
import java.util.Arrays;

  代码实现 

 1 /**
 2  * sm3加密算法工具类
 3  * @explain 加密与加密结果验证
 4  * @author Marydon
 5  * @creationTime 2018年7月5日上午10:01:24
 6  * @version 1.0
 7  * @since
 8  * @email [email protected]
 9  */
10 public class Sm3Util {
11     static {
12         Security.addProvider(new BouncyCastleProvider());
13     }
14 
15     /**
16      * 将字符串使用sm3算法进行加密
17      * @explain 
18      * @param paramStr 带加密字符串
19      * @return 返回加密后,长度=32的16进制字符串
20      */
21     public static String encrypt(String paramStr) {
22         // 将字符串转换成byte数组
23         byte[] srcData = paramStr.getBytes();
24         // 调用hash()
25         byte[] resultHash = hash(srcData);
26         // 将返回的hash值转换成16进制字符串
27         String resultHexString = ByteUtils.toHexString(resultHash);
28         return resultHexString;
29     }
30     
31     /**
32      * 返回长度=32的byte数组
33      * @explain 生成对应的hash值
34      * @param srcData
35      * @return
36      */
37     public static byte[] hash(byte[] srcData) {
38         SM3Digest digest = new SM3Digest();
39         digest.update(srcData, 0, srcData.length);
40         byte[] hash = new byte[digest.getDigestSize()];
41         digest.doFinal(hash, 0);
42         return hash;
43     }
44 
45     /**
46      * 判断源数据是否一致
47      * @explain 通过验证原数组和生成的hash数组是否为同一数组,验证2者是否为同一数据
48      * @param srcData
49      *            原数组
50      * @param sm3Hash
51      *            hash值数组
52      * @return
53      */
54     public static boolean verify(byte[] srcData, byte[] sm3Hash) {
55         byte[] newHash = hash(srcData);
56         if (Arrays.equals(newHash, sm3Hash))
57             return true;
58         else
59             return false;
60     }
61 
62     /**
63      * 通过密钥进行加密
64      * @explain 指定密钥进行加密
65      * @param key
66      *            密钥
67      * @param srcData
68      *            被加密的byte数组
69      * @return
70      */
71     public static byte[] hmac(byte[] key, byte[] srcData) {
72         KeyParameter keyParameter = new KeyParameter(key);
73         SM3Digest digest = new SM3Digest();
74         HMac mac = new HMac(digest);
75         mac.init(keyParameter);
76         mac.update(srcData, 0, srcData.length);
77         byte[] result = new byte[mac.getMacSize()];
78         mac.doFinal(result, 0);
79         return result;
80     }
81 
82     public static void main(String[] args) {
83         // SM3加密结果展示
84         // 测试二:json
85         String json = "{\"name\":\"Marydon\",\"website\":\"http://www.cnblogs.com/Marydon20170307\"}";
86         // 0b0880f6f2ccd817809a432420e42b66d3772dc18d80789049d0f9654efeae5c
87         System.out.println(Sm3Util.encrypt(json));
88         // 测试三:中文
89         String str = "迪士尼真人版《花木兰》终于定下男主角,但并非此前大众猜测的国内男星,来自新西兰的华裔演员安佑森(Yoson An)将饰演本片男主角陈宏辉。安佑森此前曾在《卧虎藏龙Ⅱ青冥宝剑》中出演角色,还曾主演新西兰出品的恐怖片《幽灵新娘》。据悉,安佑森出演的这版陈宏辉是一名自信且雄心勃勃的新兵,随着剧情发展,他将成为木兰的朋友和恋人。据此前美国媒体的报道,真人版《花木兰》已经定下由刘亦菲饰演花木兰,李连杰饰演皇帝,巩俐饰演大反派女巫,甄子丹饰演木兰导师Tung,迪士尼为本片投入的预算高达2.9亿美元,本片的导演妮基·卡罗曾执导《鲸骑士》。据悉,《花木兰》将于今年8月在中国以及新西兰开拍,将于2020年3月27日在北美上映。";
90         String result = Sm3Util.encrypt(str);
91         // 455c383de153ee7b82dab05e91e92d3ac16163f270ca317854c23fad2d807222
92         System.out.println(result);
93         
94         // 验证加密后的16进制字符串与加密前的字符串是否相同
95         boolean flag = Sm3Util.verify(str.getBytes(), ByteUtils.fromHexString(result));
96         System.out.println(flag);// true
97 
98     }
99 }

3.sm4哈希算法

  导包

import java.security.InvalidKeyException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.SecureRandom;
import java.security.Security;
import java.util.Arrays;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.SecretKeySpec;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.pqc.math.linearalgebra.ByteUtils;

  代码实现  

  1 public class Sm4Util {
  2     static {
  3         Security.addProvider(new BouncyCastleProvider());
  4     }
  5 
  6     public static final String ALGORITHM_NAME = "SM4";
  7     // 加密算法/分组加密模式/分组填充方式
  8     // PKCS5Padding-以8个字节为一组进行分组加密
  9     // 定义分组加密模式使用:PKCS5Padding
 10     public static final String ALGORITHM_NAME_ECB_PADDING = "SM4/ECB/PKCS5Padding";
 11     // 128-32位16进制;256-64位16进制
 12     public static final int DEFAULT_KEY_SIZE = 128;
 13 
 14     /**
 15      * 自动生成密钥
 16      * @explain
 17      * @return
 18      * @throws NoSuchAlgorithmException
 19      * @throws NoSuchProviderException
 20      */
 21     public static byte[] generateKey() throws NoSuchAlgorithmException, NoSuchProviderException {
 22         return generateKey(DEFAULT_KEY_SIZE);
 23     }
 24 
 25     /**
 26      * @explain
 27      * @param keySize
 28      * @return
 29      * @throws NoSuchAlgorithmException
 30      * @throws NoSuchProviderException
 31      */
 32     public static byte[] generateKey(int keySize) throws NoSuchAlgorithmException, NoSuchProviderException {
 33         KeyGenerator kg = KeyGenerator.getInstance(ALGORITHM_NAME, BouncyCastleProvider.PROVIDER_NAME);
 34         kg.init(keySize, new SecureRandom());
 35         return kg.generateKey().getEncoded();
 36     }
 37 
 38     /**
 39      * 将字符串使用sm4算法进行加密
 40      * @explain 加密模式采用ECB
 41      * @param paramStr 带加密字符串
 42      * @return 返回16进制的key和16进制的加密字符串
 43      */
 44     public static String[] encryptEcb(String paramStr) {
 45         // 返回16进制的key和16进制的加密字符串
 46         String resultHexStringArray[] = new String[2];
 47         try {
 48             // 生成key
 49             byte[] keyData = generateKey();
 50             // 将字符串转换成byte数组
 51             byte[] srcData = paramStr.getBytes();
 52             // 加密后的数组
 53             byte[] cipherArray = encrypt_Ecb_Padding(keyData, srcData);
 54             // 将返回的数组转换成16进制字符串
 55             String cipherHexString = ByteUtils.toHexString(cipherArray);
 56             // 将key值转换成16进制字符串
 57             String keyHexString = ByteUtils.toHexString(keyData);
 58             // 16进制key 
 59             resultHexStringArray[0] = keyHexString;
 60             // 16进制加密字符串
 61             resultHexStringArray[1] = cipherHexString;
 62         } catch (Exception e) {
 63             e.printStackTrace();
 64         }
 65         return resultHexStringArray;
 66     }
 67     
 68     /**
 69      * 使用sm4算法对加密后的字符串进行解密    
 70      * @explain 解密模式采用ECB
 71      *  特殊字符串转换成String可能出现误差,比如解密后的\\所代表的byte转成String时,只返回一个\
 72      * @param hexKey 16进制密钥
 73      * @param cipherText 16进制加密字符串
 74      * @return 解密后的字符串
 75      */
 76     public static String decryptEcb(String hexKey, String cipherText) {
 77         // 用于接收解密后的字符串
 78         String decryptStr = "";
 79         try {
 80             // 将16进制key转换成数组
 81             byte[] keyData = ByteUtils.fromHexString(hexKey);
 82             // 将16进制字符串转换成数组
 83             byte[] cipherData = ByteUtils.fromHexString(cipherText);
 84             // 解密
 85             byte[] srcData = decrypt_Ecb_Padding(keyData, cipherData);
 86             // 将byte[]转换成String
 87             decryptStr = new String(srcData);
 88         } catch (Exception e) {
 89             e.printStackTrace();
 90         }
 91         return decryptStr;
 92     }
 93     
 94     /**
 95      * 校验加密前后的字符串是否为同一数据
 96      * @explain 
 97      * @param hexKey 16进制密钥
 98      * @param cipherText 16进制加密后的字符串
 99      * @param paramStr 加密前的字符串
100      * @return 是否为同一数据
101      */
102     public static boolean verifyEcb(String hexKey, String cipherText, String paramStr) {
103         // 用于接收校验结果
104         boolean flag = false;
105         try {
106             // 将16进制key转换成数组
107             byte[] keyData = ByteUtils.fromHexString(hexKey);
108             // 将16进制字符串转换成数组
109             byte[] cipherData = ByteUtils.fromHexString(cipherText);
110             // 解密
111             byte[] decryptData = decrypt_Ecb_Padding(keyData, cipherData);
112             // 将原字符串转换成byte[]
113             byte[] srcData = paramStr.getBytes("utf-8");
114             // 判断2个数组是否一致
115             flag = Arrays.equals(decryptData, srcData);
116         } catch (Exception e) {
117             e.printStackTrace();
118         }
119         return flag;
120     }
121     
122     /**
123      * 加密模式之Ecb
124      * @explain
125      * @param key
126      * @param data
127      * @return
128      * @throws InvalidKeyException
129      * @throws NoSuchAlgorithmException
130      * @throws NoSuchProviderException
131      * @throws NoSuchPaddingException
132      * @throws IllegalBlockSizeException
133      * @throws BadPaddingException
134      */
135     public static byte[] encrypt_Ecb_Padding(byte[] key, byte[] data)
136             throws InvalidKeyException, NoSuchAlgorithmException, NoSuchProviderException, NoSuchPaddingException,
137             IllegalBlockSizeException, BadPaddingException {
138         Cipher cipher = generateEcbCipher(ALGORITHM_NAME_ECB_PADDING, Cipher.ENCRYPT_MODE, key);
139         return cipher.doFinal(data);
140     }
141 
142     /**
143      * 解密
144      * @explain
145      * @param key
146      * @param cipherText
147      * @return
148      * @throws IllegalBlockSizeException
149      * @throws BadPaddingException
150      * @throws InvalidKeyException
151      * @throws NoSuchAlgorithmException
152      * @throws NoSuchProviderException
153      * @throws NoSuchPaddingException
154      */
155     public static byte[] decrypt_Ecb_Padding(byte[] key, byte[] cipherText)
156             throws IllegalBlockSizeException, BadPaddingException, InvalidKeyException, NoSuchAlgorithmException,
157             NoSuchProviderException, NoSuchPaddingException {
158         Cipher cipher = generateEcbCipher(ALGORITHM_NAME_ECB_PADDING, Cipher.DECRYPT_MODE, key);
159         return cipher.doFinal(cipherText);
160     }
161 
162     /**
163      * 生成ECB暗号
164      * @explain ECB模式(电子密码本模式:Electronic codebook)
165      * @param algorithmName
166      *            算法名称
167      * @param mode
168      *            模式
169      * @param key
170      * @return
171      * @throws NoSuchAlgorithmException
172      * @throws NoSuchProviderException
173      * @throws NoSuchPaddingException
174      * @throws InvalidKeyException
175      */
176     private static Cipher generateEcbCipher(String algorithmName, int mode, byte[] key)
177             throws NoSuchAlgorithmException, NoSuchProviderException, NoSuchPaddingException, InvalidKeyException {
178         Cipher cipher = Cipher.getInstance(algorithmName, BouncyCastleProvider.PROVIDER_NAME);
179         Key sm4Key = new SecretKeySpec(key, ALGORITHM_NAME);
180         cipher.init(mode, sm4Key);
181         return cipher;
182     }
183     
184     public static void main(String[] args) {
185         String str = "迪士尼真人版《花木兰》终于定下男主角,但并非此前大众猜测的国内男星,来自新西兰的华裔演员安佑森(Yoson An)将饰演本片男主角陈宏辉。安佑森此前曾在《卧虎藏龙Ⅱ青冥宝剑》中出演角色,还曾主演新西兰出品的恐怖片《幽灵新娘》。据悉,安佑森出演的这版陈宏辉是一名自信且雄心勃勃的新兵,随着剧情发展,他将成为木兰的朋友和恋人。据此前美国媒体的报道,真人版《花木兰》已经定下由刘亦菲饰演花木兰,李连杰饰演皇帝,巩俐饰演大反派女巫,甄子丹饰演木兰导师Tung,迪士尼为本片投入的预算高达2.9亿美元,本片的导演妮基·卡罗曾执导《鲸骑士》/\\、,。据悉,《花木兰》将于今年8月在中国以及新西兰开拍,将于2020年3月27日在北美上映。";
186         // 加密
187         String[] encrytData = Sm4Util.encryptEcb(str);
188         // 密钥
189         String hexKey = encrytData[0];
190         // 密文
191         String cipherText = encrytData[1];
192         // 解密后的字符串,少了一个\
193         System.out.println(Sm4Util.decryptEcb(hexKey, cipherText));
194         // 判断是否为加密前后,数据是否一致
195         System.out.println(Sm4Util.verifyEcb(hexKey, cipherText, str));// true
196     }
197 }

  

 相关推荐:

猜你喜欢

转载自www.cnblogs.com/Marydon20170307/p/9266946.html