
SM4是我们国家密码管理局发布的一种对称分组加密算法,也称为国密算法。与AES类似,都是基于分组的对称加密,但其结构和加密流程有自己独特的设计。SM4算法在无线局域网设备的安全认证和数据加密中应用广泛......
SM4是我们国家密码管理局发布的一种对称分组加密算法,也称为国密算法。与AES类似,都是基于分组的对称加密,但其结构和加密流程有自己独特的设计。
SM4算法在无线局域网设备的安全认证和数据加密中应用广泛,尤其适用于对数据安全性要求较高的应用场景。
这是之前在公司对接的一家资金方就是使用的SM4加密,但在开发demo时,加密时出现错误,随手记录了下来,现整理发出希望帮到更多的网友。
问题描述使用SM4加密算法运行一直报错Nosuchalgorithm:SM4/ECB/PKCS7Padding。
本次加密用到的第三方库是BouncyCastle,提供对SM4算法的支持,该组件是由bcprov-jdkxx提供。
网上有各种解决办法,有修改jre下文件的。
但本次问题较简单,解决相关jar包问题即可。
问题探索并解决经查发现加密用的jar包是:bcprov-jdk16:1.64:
而配置的依赖明明是:bcprov-jdk15on:1.60:
/groupIdartifactIdbcprov-jdk15on//version/depency
是不是这个原因?新建一个项目直接添加bcprov-jdk15on:1.60依赖,运行后加密成功,那应该就是这个版本问题。
pom文件中并没有显示添加bcprov-jdk16:1.64这个依赖,那应该是其它的组件里的,经查发现是公司的一个加密组件里的,尴尬。。。将这个版本排除掉,使用bcprov-jdk15on:1.60依赖:
/groupIdartifactIdbcprov-jdk15on//version//groupIdartifactIdsecurity///groupIdartifactIdbcprov-jdk16/artifactId/exclusion/exclusions/depency
经测试公司的加密组件功能不受影响。
下面提供SM4加密解密的工具类以及一个测试方法。
SM4加解密工具;;;;;;;;;;;;;/***SM4加密*@authorwankun*@date2021/10/29.*/@Slf4j@EnableApolloConfigpublicclassSM4Utils{privatestaticfinalStringENCODING=_8.toString();publicstaticfinalStringALGORIGTHM_NAME="SM4";publicstaticfinalStringALGORITHM_NAME_ECB_PADDING="SM4/ECB/PKCS7Padding";publicstaticfinalintDEFAULT_KEY_SIZE=128;publicSM4Utils(){}static{(newBouncyCastleProvider());}/***生成ecb暗号*@paramalgorithmName*@parammode*@paramkey*@returnecb暗号*@throwsException*/privatestaticCiphergenerateEcbCipher(StringalgorithmName,intmode,byte[]key)throwsException{Ciphercipher=(algorithmName,_NAME);Keysm4Key=newSecretKeySpec(key,ALGORIGTHM_NAME);(mode,sm4Key);returncipher;}/***自动生成密钥*@return密钥*@throwsException*/publicstaticbyte[]generateKey()throwsException{returngenerateKey(DEFAULT_KEY_SIZE);}/***自动生成密钥*@paramkeySize*@return密钥*@throwsException*/publicstaticbyte[]generateKey(intkeySize)throwsException{KeyGeneratorkg=(ALGORIGTHM_NAME,_NAME);(keySize,newSecureRandom());().getEncoded();}/***加密*@paramhexKey私钥*@paramparamStr明文*@return密文*@throwsException*/publicstaticStringencrypt(StringhexKey,StringparamStr)throwsException{returnencryptEcb(hexKey,paramStr,ENCODING);}/***加密*@paramhexKey私钥*@paramparamStr明文*@paramcharset编码*@return密文*@throwsException*/publicstaticStringencryptEcb(StringhexKey,StringparamStr,Stringcharset)throwsException{StringcipherText="";if(null!=paramStr!"".equals(paramStr)){byte[]keyData=(hexKey);charset=();if(()=0){charset=ENCODING;}byte[]srcData=(charset);byte[]cipherArray=encrypt_Ecb_Padding(keyData,srcData);cipherText=(cipherArray);}returncipherText;}/***加密模式之ecb*@paramkey*@paramdata*@return*@throwsException*/publicstaticbyte[]encrypt_Ecb_Padding(byte[]key,byte[]data)throwsException{Ciphercipher=generateEcbCipher(ALGORITHM_NAME_ECB_PADDING,_MODE,key);(data);}/***解密*@paramhexKey私钥*@paramcipherText密文*@paramcharset编码*@return明文*@throwsException*/publicstaticStringdecryptEcb(StringhexKey,StringcipherText,Stringcharset)throwsException{StringdecryptStr="";byte[]keyData=(hexKey);byte[]cipherData=(cipherText);byte[]srcData=decrypt_Ecb_Padding(keyData,cipherData);charset=();if(()=0){charset=ENCODING;}decryptStr=newString(srcData,charset);returndecryptStr;}/***解密*@paramkey*@paramcipherText*@return*@throwsException*/publicstaticbyte[]decrypt_Ecb_Padding(byte[]key,byte[]cipherText)throwsException{Ciphercipher=generateEcbCipher(ALGORITHM_NAME_ECB_PADDING,_MODE,key);(cipherText);}/***密码校验*@paramhexKey私钥*@paramcipherText密文*@paramparamStr明文*@return校验结果*@throwsException*/publicstaticbooleanverifyEcb(StringhexKey,StringcipherText,StringparamStr)throwsException{booleanflag=false;byte[]keyData=(hexKey);byte[]cipherData=(cipherText);byte[]decryptData=decrypt_Ecb_Padding(keyData,cipherData);byte[]srcData=(ENCODING);flag=(decryptData,srcData);returnflag;}}测试代码:
publicstaticvoidmain(String[]args){try{Stringkey="564e351eae88ebbddc28c5709cd286a6";Stringstr="110101197408070619";//密钥(564e351eae88ebbddc28c5709cd286a6)加密(110101197408070619)=9dd25f18ebef6938d4eaaf465a389836eb62ddb02ab6456aa0c3da3437f20532Stringcipher=(key,str);(cipher);((key,cipher,str));str=(key,cipher,ENCODING);(str);}catch(Exceptione){();}}