一. 概述

国产密码算法(国密算法)是指国家密码局认定的国产商用密码算法,目前主要使用公开的SM2SM3SM4三类算法,分别是非对称算法哈希算法对称算法

SM3算法:SM3杂凑算法是我国自主设计的密码杂凑算法,适用于商用密码应用中的数字签名和验证消息认证码的生成与验证以及随机数的生成,可满足多种密码应用的安全需求。为了保证杂凑算法的安全性,其产生的杂凑值的长度不应太短,例如MD5输出128比特杂凑值,输出长度太短,影响其安全性SHA-1算法的输出长度为160比特,SM3算法的输出长度为256比特,因此SM3算法的安全性要高于MD5算法和SHA-1算法。

SM4算法:SM4分组密码算法是我国自主设计的分组对称密码算法,用于实现数据的加密/解密运算,以保证数据和信息的机密性。要保证一个对称密码算法的安全性的基本条件是其具备足够的密钥长度,SM4算法与AES算法具有相同的密钥长度分组长度128比特,因此在安全性上高于3DES算法。

二. 实现

(1) SM3

参数为要加密的内容和秘钥;

import java.io.UnsupportedEncodingException;import org.bouncycastle.crypto.digests.SM3Digest;import org.bouncycastle.crypto.macs.HMac;import org.bouncycastle.crypto.params.KeyParameter;import sun.misc.BASE64Encoder;public class SM3Util {/*** * @param message 需要进行签名的内容* @param secret hmac秘钥* @return*/public static String getSignatureBySM3(String message, String secret) {String signature = null;KeyParameter keyParameter;try {keyParameter = new KeyParameter(secret.getBytes("UTF-8"));SM3Digest digest = new SM3Digest();HMac mac = new HMac(digest);mac.init(keyParameter);mac.update(message.getBytes("UTF-8"), 0, message.length());byte[] byteSM3 = new byte[mac.getMacSize()];mac.doFinal(byteSM3, 0);signature = new BASE64Encoder().encode(byteSM3);} catch (UnsupportedEncodingException e) {System.out.println("getSignatureBySM3 error :");e.printStackTrace();}return signature;}}

(2) SM4

import java.security.Security;import javax.crypto.Cipher;import javax.crypto.SecretKey;import javax.crypto.SecretKeyFactory;import org.apache.commons.codec.binary.Hex;import com.huawei.crypto.provider.SMS4KeySpec;import sun.misc.BASE64Decoder;/** * sm4工具类 * 秘钥不得小于16位 * @author hWX588043 * */public class SM4Util {static {Security.addProvider(new com.huawei.crypto.provider.HWJCE());}public static String decode(String encrypted, String secretKey) throws Exception {// 加密结果转码byte[] data = Hex.decodeHex(encrypted.toCharArray());// 用户密钥处理SecretKey key = getKey(secretKey);// 解密Cipher cipher = Cipher.getInstance("SMS4");cipher.init(Cipher.DECRYPT_MODE, key);byte[] reclaimedBytes = cipher.doFinal(data);// 将解密结果输出return new String(reclaimedBytes, "utf-8");}/** * @param source待加密字符串 * @param secretKey 加密秘钥 * @return 加密结果 */public static String encode(String source, String secretKey)throws Exception {// 字符串转byte[]byte[] data = source.getBytes("utf-8");// 密钥处理SecretKey key = getKey(secretKey);// 加密Cipher cipher = Cipher.getInstance("SMS4");cipher.init(Cipher.ENCRYPT_MODE, key);byte[] encryptedBytes = cipher.doFinal(data);// 将加密结果转16进制输出return Hex.encodeHexString(encryptedBytes);}/** * 对secretKey进行加密 * * @param secretKey 密钥 * @throws Exception */private static SecretKey getKey(String secretKey) throws Exception {byte[] keyBytes = new BASE64Decoder().decodeBuffer(secretKey);SMS4KeySpec sms4KeySpec = new SMS4KeySpec(keyBytes);SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("SMS4");return keyFactory.generateSecret(sms4KeySpec);}}