目录  前言 国密算法 SM1对称加密算法 SM1算法的基本原理 SM1算法的应用场景 SM1算法的优势 代码示例 SM2非对称加密算法 SM2算法的基本原理 SM2算法的应用场景 SM2算法的优势 代码示例   SM3杂凑算法 SM4分组密码算法 SM3、SM4工具类示例     
 
目前形式国内都在推行国产化,例如:国产化数据库,国产化服务器等。 我上家公司其中一条产品线是做电网项目的,其中加密的方式就要求使用国密加密算法,SM3和SM4,所以说国产化应该是一个趋势。 国密即国家密码局认定的国产密码算法。主要有SM1,SM2,SM3,SM4。密钥长度和分组长度均为128位。 国密算法,全称为中国密码算法国家标准,是由中国国家密码管理局主导制定的一套密码算法标准。 国密算法包括以下四种: SM1对称加密算法 SM2非对称加密算法 SM3杂凑算法 SM4分组密码算法  国密算法在国家信息安全领域得到了广泛应用,被用于政务通信、金融支付、电子商务、云计算等领域。 其目的是为了保护国家信息安全和个人隐私,增强国内密码产品和系统的自主可控能力。 SM1对称加密算法是一种高效的分组密码算法,适用于对称加密和消息认证码,其安全性与国际上的AES算法相近。 SM1算法是一种分组密码,采用对称密钥方式,将明文按照固定长度分组,然后对每个分组进行加密和解密。 该算法的关键在于密钥的生成和密钥的长度。 SM1算法的密钥长度为128位,密钥生成过程中采用了多种随机数生成器,保证了密钥的随机性和安全性。 电子政务:SM1算法可以用于电子政务中的公文传输、公文存储和电子签章等场景,保证数据的机密性和完整性。 金融行业:SM1算法可以用于金融行业中的网上银行、移动支付和电子钱包等场景,保护用户的个人信息和资金安全。 医疗卫生:SM1算法可以用于医疗卫生中的电子病历、远程医疗和医疗数据存储等场景,确保医疗信息的机密性和完整性。 物联网:SM1算法可以用于物联网中的传感器网络、智能家居和智能交通等场景,保障物联网设备的通信安全和数据隐私。 云计算:SM1算法可以用于云计算中的数据加密、云存储和虚拟化等场景,保证云服务的安全性和可靠性。 高安全性:SM1算法的密钥长度为128位,相比其他对称加密算法具有更高的安全性。此外,该算法的密钥生成过程中采用了多种随机数生成器,保证了密钥的随机性和安全性。 高效性:SM1算法的加解密速度较快,适用于大规模的数据加解密和安全通信同。时,该算法的软硬件实现成本较低,方便在各种设备上应用。 广泛适用性:SM1算法适用于各种不同的应用场景,包括电子政务、金融行业、医疗卫生、物联网和云计算等。该算法的应用范围广泛,可以满足不同领域的安全需求。 国家标准:SM1算法是中国的国家密码标准之一,被广泛应用于国家重要信息系统的数据加密和安全通信领域。该算法得到了国家的支持和认可,具有较高的可靠性和安全性。 import  javax. crypto.  Cipher ;   
import  javax. crypto. spec.  SecretKeySpec ;   
import  java. nio. charset.  StandardCharsets ;   
import  java. util.  Base64 ;   public  class  AESUtil  {   private  static  final  String  ALGORITHM  =  "AES" ;   private  static  final  String  TRANSFORMATION  =  "AES/ECB/PKCS5Padding" ;  public  static  String  encrypt ( String  key,  String  value)  throws  Exception  {   SecretKeySpec  secretKeySpec =  new  SecretKeySpec ( key. getBytes ( StandardCharsets . UTF_8 ) ,  ALGORITHM ) ;   Cipher  cipher =  Cipher . getInstance ( TRANSFORMATION ) ;   cipher. init ( Cipher . ENCRYPT_MODE ,  secretKeySpec) ;   byte [ ]  encrypted =  cipher. doFinal ( value. getBytes ( StandardCharsets . UTF_8 ) ) ;   return  Base64 . getEncoder ( ) . encodeToString ( encrypted) ;   }   public  static  String  decrypt ( String  key,  String  encrypted)  throws  Exception  {   SecretKeySpec  secretKeySpec =  new  SecretKeySpec ( key. getBytes ( StandardCharsets . UTF_8 ) ,  ALGORITHM ) ;   Cipher  cipher =  Cipher . getInstance ( TRANSFORMATION ) ;   cipher. init ( Cipher . DECRYPT_MODE ,  secretKeySpec) ;   byte [ ]  original =  cipher. doFinal ( Base64 . getDecoder ( ) . decode ( encrypted) ) ;   return  new  String ( original,  StandardCharsets . UTF_8 ) ;   }   public  static  void  main ( String [ ]  args)  throws  Exception  {   String  key =  "your_16_byte_key_here_for_aes" ;  String  value =  "Hello, World!" ;   String  encrypted =  encrypt ( key,  value) ;   System . out. println ( "Encrypted: "  +  encrypted) ;   String  decrypted =  decrypt ( key,  encrypted) ;   System . out. println ( "Decrypted: "  +  decrypted) ;   }   
} 
SM2非对称加密算法是基于椭圆曲线密码体制的数字签名算法和密钥交换协议,安全性较高。 SM2使用非对称密钥加密体制,包括公钥和私钥。 公钥用于加密数据和验证数字签名,私钥用于解密数据和生成数字签名。 数据加密: SM2算法可用于加密和解密数据,保障数据传输的安全性。它利用公钥进行加密,私钥进行解密,确保数据在传输过程中的机密性。 在网络安全领域,SM2算法常被用于保护敏感信息的传输,如电子邮件加密、文件传输加密等。  数字签名: SM2算法可用于生成数字签名,验证文档或数据的完整性和真实性。通过私钥对消息进行签名,利用公钥进行验证,确保数据在传输过程中未被篡改,并验证发送方的身份。 数字签名在电子认证、电子合同、电子票据等领域具有广泛应用,如网上银行交易、电子政务等。  身份认证: SM2算法可用于身份认证,验证用户的身份信息。通过公钥和私钥的配对使用,可以确保用户身份的真实性和可信度。 在网络安全领域,SM2算法常被用于用户登录、权限管理等场景,保障系统的安全性和可信度。  密钥交换: SM2算法支持密钥交换功能,通过公钥和私钥的配对使用,可以安全地协商出共享密钥,用于后续的对称加密通信。 密钥交换在网络安全通信中具有重要意义,可以确保通信双方之间密钥的安全传输和共享。  国家安全领域: 作为中国国家密码管理局颁布的国家标准,SM2算法在中国国内得到广泛应用,特别是在政府机构和企业的信息安全领域。 它符合国家密码管理政策,有利于保障国家信息安全,防止外部攻击和数据泄露。  国际认可: 虽然SM2是中国的国家标准,但它在一定程度上也获得了国际认可。部分国际组织和标准化机构也开始考虑将其作为一种可选的加密算法。  安全性高: SM2算法基于椭圆曲线离散对数难题,这一数学问题的复杂性保证了算法的安全性。 与RSA算法相比,SM2算法在同等安全水平下,所需的密钥长度和签名长度更短,从而降低了被破解的风险。 SM2算法被认为在经典计算机和量子计算机的攻击下都是安全的。  效率高: SM2算法具有较高的运算效率,特别是在加密、解密和数字签名方面,性能优于RSA算法。 它适合高并发场景,满足大量数据加密、解密和数字签名的需求。 SM2算法的CPU占用少、内容使用少、网络消耗低,特别适用于移动设备和资源受限的环境。  灵活性好: SM2算法支持多种密钥长度,可以根据实际需求灵活选择密钥长度,适用于不同的应用场景。  自主创新: 它符合国家密码管理政策,有利于保障国家关键信息系统的信息安全。  技术特点: SM2算法基于椭圆曲线密码学,具备ECC算法的性能特点并实现优化改进。 它采用了一系列安全性增强措施,如密钥派生函数和随机数生成算法,以防止各种攻击。  < dependency> < groupId> </ groupId> < artifactId> </ artifactId> < version> </ version> </ dependency> import  org. bouncycastle. crypto.  CipherParameters ;   
import  org. bouncycastle. crypto. engines.  SM2Engine ;   
import  org. bouncycastle. crypto. params.  ECPublicKeyParameters ;   
import  org. bouncycastle. crypto. params.  ECPrivateKeyParameters ;   
import  org. bouncycastle. crypto. params.  SM2PrivateKeyParameters ;   
import  org. bouncycastle. crypto. params.  SM2PublicKeyParameters ;   
import  org. bouncycastle. jce.  ECNamedCurveGenParameterSpec ;   
import  org. bouncycastle. jce.  ECNamedCurveTable ;   
import  org. bouncycastle. jce. provider.  BouncyCastleProvider ;   
import  org. bouncycastle. jce. spec.  ECParameterSpec ;   import  java. security.  KeyPair ;   
import  java. security.  KeyPairGenerator ;   
import  java. security.  PrivateKey ;   
import  java. security.  PublicKey ;   
import  java. security.  Security ;   public  class  SM2Utils  {   static  {   Security . addProvider ( new  BouncyCastleProvider ( ) ) ;   }   public  static  KeyPair  generateKeyPair ( )  throws  Exception  {   KeyPairGenerator  keyGen =  KeyPairGenerator . getInstance ( "EC" ,  "BC" ) ;   ECParameterSpec  ecSpec =  ECNamedCurveTable . getParameterSpec ( "sm2p256v1" ) ;   keyGen. initialize ( new  ECNamedCurveGenParameterSpec ( "sm2p256v1" ) ,  new  java. security.  SecureRandom( ) ) ;   return  keyGen. generateKeyPair ( ) ;   }   public  static  byte [ ]  encrypt ( PublicKey  publicKey,  byte [ ]  data)  throws  Exception  {   return  null ;  }   public  static  byte [ ]  decrypt ( PrivateKey  privateKey,  byte [ ]  cipherText)  throws  Exception  {   return  null ;  }   public  static  byte [ ]  sign ( PrivateKey  privateKey,  byte [ ]  data)  throws  Exception  {   return  null ;  }   public  static  boolean  verify ( PublicKey  publicKey,  byte [ ]  data,  byte [ ]  signature)  throws  Exception  {   return  false ;  }   
} 
SM3 消息摘要。可以用MD5作为对比理解。该算法已公开。校验结果为256位。 SM3杂凑算法是一种散列算法,用于将输入的数据转化为固定长度的摘要,具有抗碰撞、抗第二原像和抗预像等特性。 SM3杂凑算法是我国自主设计的密码杂凑算法,适用于商用密码应用中的数字签名和验证消息认证码的生成与验证以及随机数的生成,可满足多种密码应用的安全需求。 为了保证杂凑算法的安全性,其产生的杂凑值的长度不应太短,例如MD5输出128比特杂凑值,输出长度太短,影响其安全性SHA-1算法的输出长度为160比特,SM3算法的输出长度为256比特,因此SM3算法的安全性要高于MD5算法和SHA-1算法。 SM4 无线局域网标准的分组数据算法。对称加密,密钥长度和分组长度均为128位。 SM4分组密码算法是我国自主设计的分组对称密码算法,用于实现数据的加密/解密运算,以保证数据和信息的机密性。 要保证一个对称密码算法的安全性的基本条件是其具备足够的密钥长度,SM4算法与AES算法具有相同的密钥长度分组长度128比特,因此在安全性上高于3DES算法。 < dependency> < groupId> </ groupId> < artifactId> </ artifactId> < version> </ version> </ dependency> package  com. mkj. publicservice. utils. smalgorithm ; import  org. bouncycastle. crypto. digests.  SM3Digest ; 
import  org. bouncycastle. crypto. macs.  HMac ; 
import  org. bouncycastle. crypto. params.  KeyParameter ; 
import  org. bouncycastle. pqc. math. linearalgebra.  ByteUtils ; import  java. io.  UnsupportedEncodingException ; 
public  class  Sm3Util  { public  static  String   Sm3EncryptText ( String  content)  throws  UnsupportedEncodingException  { byte [ ]  bytes =  content. getBytes ( ) ; byte [ ]  hash =  hash ( bytes) ; String  sm3 =  ByteUtils . toHexString ( hash) ; System . out. println ( "[Sm3EncryptText]sm3 hex:"  +  sm3) ; return  sm3; } public  static  byte [ ]  hash ( byte [ ]  srcData) { SM3Digest  digest= new  SM3Digest ( ) ; digest. update ( srcData, 0 , srcData. length) ; byte [ ]  bytes =  new  byte [ digest. getDigestSize ( ) ] ; digest. doFinal ( bytes, 0 ) ; return  bytes; } public  static  String  encryptByKey ( String  keyText,  String  plainText)  { return  ByteUtils . toHexString ( encryptByKey ( keyText. getBytes ( ) ,  plainText. getBytes ( ) ) ) ; } public  static  byte [ ]  encryptByKey ( byte [ ]  keyByte,  byte [ ]  plainByte)  { KeyParameter  keyParameter =  new  KeyParameter ( keyByte) ; SM3Digest  sm3Digest =  new  SM3Digest ( ) ; HMac  hMac =  new  HMac ( sm3Digest) ; hMac. init ( keyParameter) ; hMac. update ( plainByte,  0 ,  plainByte. length) ; byte [ ]  result =  new  byte [ hMac. getMacSize ( ) ] ; hMac. doFinal ( result,  0 ) ; return  result; } public  static  void  main ( String [ ]  args)  throws  UnsupportedEncodingException  { Sm3EncryptText ( "ceshi001" ) ; System . out. println ( encryptByKey ( "key001" , "abc" ) ) ; } } 
SM4两种算法,基于ECB和CBC。示例中key都使用了16进制的字符串,有的项目没有需求可以自行去除。看实际情况。 package  com. mkj. publicservice. utils. smalgorithm ; import  org. bouncycastle. jce. provider.  BouncyCastleProvider ; 
import  org. bouncycastle. pqc. math. linearalgebra.  ByteUtils ; 
import  javax. crypto.  Cipher ; 
import  javax. crypto.  KeyGenerator ; 
import  javax. crypto. spec.  IvParameterSpec ; 
import  javax. crypto. spec.  SecretKeySpec ; 
import  java. security.  AlgorithmParameters ; 
import  java. security.  Key ; 
import  java. security.  SecureRandom ; 
import  java. security.  Security ; 
import  java. util.  Arrays ; 
public  class  Sm4CbcUtils  { static  { Security . addProvider ( new  BouncyCastleProvider ( ) ) ; } private  static  final  String  ENCODING  =  "UTF-8" ; public  static  final  String  ALGORITHM_NAME  =  "SM4" ; public  static  final  String  ALGORITHM_NAME_CBC_PADDING  =  "SM4/CBC/PKCS5Padding" ; public  static  final  int  DEFAULT_KEY_SIZE  =  128 ; public  static  byte [ ]  generateKey ( )  throws  Exception  { return  generateKey ( DEFAULT_KEY_SIZE ) ; } public  static  String  generateKeyString ( )  throws  Exception  { return  ByteUtils . toHexString ( generateKey ( ) ) ; } public  static  byte [ ]  generateKey ( int  keySize)  throws  Exception  { KeyGenerator  kg =  KeyGenerator . getInstance ( ALGORITHM_NAME ,  BouncyCastleProvider . PROVIDER_NAME ) ; kg. init ( keySize,  new  SecureRandom ( ) ) ; return  kg. generateKey ( ) . getEncoded ( ) ; } public  static  String  encrypt ( String  hexKey,  String  paramStr)  throws  Exception  { String  result =  "" ; byte [ ]  keyData =  ByteUtils . fromHexString ( hexKey) ; byte [ ]  srcData =  paramStr. getBytes ( ENCODING ) ; byte [ ]  cipherArray =  encryptCbcPadding ( keyData,  srcData) ; result =  ByteUtils . toHexString ( cipherArray) ; return  result; } public  static  byte [ ]  encryptCbcPadding ( byte [ ]  key,  byte [ ]  data)  throws  Exception  { Cipher  cipher =  generateCbcCipher ( ALGORITHM_NAME_CBC_PADDING ,  Cipher . ENCRYPT_MODE ,  key) ; return  cipher. doFinal ( data) ; } private  static  Cipher  generateCbcCipher ( String  algorithmName,  int  mode,  byte [ ]  key)  throws  Exception  { Cipher  cipher =  Cipher . getInstance ( algorithmName,  BouncyCastleProvider . PROVIDER_NAME ) ; Key  sm4Key =  new  SecretKeySpec ( key,  ALGORITHM_NAME ) ; cipher. init ( mode,  sm4Key,  generateIV ( ) ) ; return  cipher; } public  static  AlgorithmParameters  generateIV ( )  throws  Exception  { byte [ ]  iv =  new  byte [ 16 ] ; Arrays . fill ( iv,  ( byte )  0x00 ) ; AlgorithmParameters  params =  AlgorithmParameters . getInstance ( ALGORITHM_NAME ) ; params. init ( new  IvParameterSpec ( iv) ) ; return  params; } public  static  String  decrypt ( String  hexKey,  String  text)  throws  Exception  { String  result =  "" ; byte [ ]  keyData =  ByteUtils . fromHexString ( hexKey) ; byte [ ]  resultData =  ByteUtils . fromHexString ( text) ; byte [ ]  srcData =  decryptCbcPadding ( keyData,  resultData) ; result =  new  String ( srcData,  ENCODING ) ; return  result; } public  static  byte [ ]  decryptCbcPadding ( byte [ ]  key,  byte [ ]  cipherText)  throws  Exception  { Cipher  cipher =  generateCbcCipher ( ALGORITHM_NAME_CBC_PADDING ,  Cipher . DECRYPT_MODE ,  key) ; return  cipher. doFinal ( cipherText) ; } public  static  void  main ( String [ ]  args)  throws  Exception  { String  str =  "Hello, world"  ; System . out. println ( "==========生成密钥==========" ) ; String  generateKey =  generateKeyString ( ) ; System . out. println ( generateKey) ; System . out. println ( "==========加密==========" ) ; String  encrypt =  encrypt ( generateKey,  str) ; System . out. println ( encrypt) ; System . out. println ( "==========解密==========" ) ; String  decrypt =  decrypt ( generateKey,  encrypt) ; System . out. println ( decrypt) ; } 
} 
package  com. mkj. publicservice. utils. smalgorithm ; import  cn. hutool. crypto.  SmUtil ; 
import  cn. hutool. crypto. symmetric.  SM4 ; 
import  org. bouncycastle. jce. provider.  BouncyCastleProvider ; 
import  org. bouncycastle. pqc. math. linearalgebra.  ByteUtils ; 
import  org. bouncycastle. util. encoders.  Hex ; import  javax. crypto.  Cipher ; 
import  javax. crypto.  KeyGenerator ; 
import  javax. crypto. spec.  SecretKeySpec ; 
import  java. nio. charset.  StandardCharsets ; 
import  java. security.  Key ; 
import  java. security.  SecureRandom ; 
import  java. security.  Security ; 
import  java. util.  Arrays ; 
public  class  Sm4EcbUtils  { static  { Security . addProvider ( new  BouncyCastleProvider ( ) ) ; } private  static  final  String  ENCODING  =  "UTF-8" ; public  static  final  String  ALGORITHM_NAME  =  "SM4" ; public  static  final  String  ALGORITHM_NAME_ECB_PADDING  =  "SM4/ECB/PKCS5Padding" ; public  static  final  int  DEFAULT_KEY_SIZE  =  128 ; public  static  String  generateKey ( )  throws  Exception  { return  new  String ( Hex . encode ( generateKey ( DEFAULT_KEY_SIZE ) ) ) ; } public  static  byte [ ]  generateKey ( int  keySize)  throws  Exception  { KeyGenerator  kg =  KeyGenerator . getInstance ( ALGORITHM_NAME ,  BouncyCastleProvider . PROVIDER_NAME ) ; kg. init ( keySize,  new  SecureRandom ( ) ) ; return  kg. generateKey ( ) . getEncoded ( ) ; } private  static  Cipher  generateEcbCipher ( String  algorithmName,  int  mode,  byte [ ]  key)  throws  Exception  { Cipher  cipher =  Cipher . getInstance ( algorithmName,  BouncyCastleProvider . PROVIDER_NAME ) ; Key  sm4Key =  new  SecretKeySpec ( key,  ALGORITHM_NAME ) ; cipher. init ( mode,  sm4Key) ; return  cipher; } public  static  String  encryptEcb ( String  hexKey,  String  paramStr)  { try  { String  cipherText =  "" ; byte [ ]  keyData =  ByteUtils . fromHexString ( hexKey) ; byte [ ]  srcData =  paramStr. getBytes ( ENCODING ) ; byte [ ]  cipherArray =  encryptEcbPadding ( keyData,  srcData) ; cipherText =  ByteUtils . toHexString ( cipherArray) ; return  cipherText; }  catch  ( Exception  e)  { return  paramStr; } } public  static  byte [ ]  encryptEcbPadding ( byte [ ]  key,  byte [ ]  data)  throws  Exception  { Cipher  cipher =  generateEcbCipher ( ALGORITHM_NAME_ECB_PADDING ,  Cipher . ENCRYPT_MODE ,  key) ; return  cipher. doFinal ( data) ; } public  static  String  decryptEcb ( String  hexKey,  String  cipherText)  { String  decryptStr =  "" ; byte [ ]  keyData =  ByteUtils . fromHexString ( hexKey) ; byte [ ]  cipherData =  ByteUtils . fromHexString ( cipherText) ; byte [ ]  srcData =  new  byte [ 0 ] ; try  { srcData =  decryptEcbPadding ( keyData,  cipherData) ; decryptStr =  new  String ( srcData,  ENCODING ) ; }  catch  ( Exception  e)  { e. printStackTrace ( ) ; } return  decryptStr; } public  static  byte [ ]  decryptEcbPadding ( byte [ ]  key,  byte [ ]  cipherText)  throws  Exception  { Cipher  cipher =  generateEcbCipher ( ALGORITHM_NAME_ECB_PADDING ,  Cipher . DECRYPT_MODE ,  key) ; return  cipher. doFinal ( cipherText) ; } public  static  boolean  verifyEcb ( String  hexKey,  String  cipherText,  String  paramStr)  throws  Exception  { boolean  flag =  false ; byte [ ]  keyData =  ByteUtils . fromHexString ( hexKey) ; byte [ ]  cipherData =  ByteUtils . fromHexString ( cipherText) ; byte [ ]  decryptData =  decryptEcbPadding ( keyData,  cipherData) ; byte [ ]  srcData =  paramStr. getBytes ( ENCODING ) ; flag =  Arrays . equals ( decryptData,  srcData) ; return  flag; } public  static  void  main ( String [ ]  args)  { try  { String  paramStr =  "Hello, world" ; System . out. println ( "==========加密前源数据==========" ) ; System . out. println ( paramStr) ; String  key =  generateKey ( ) ; System . out. println ( "==========生成key==========" ) ; System . out. println ( key) ; String  cipher =  encryptEcb ( key,  paramStr) ; System . out. println ( "==========加密串==========" ) ; System . out. println ( cipher) ; System . out. println ( "==========是否为同一数据==========" ) ; System . out. println ( verifyEcb ( key,  cipher,  paramStr) ) ; paramStr =  decryptEcb ( key,  cipher) ; System . out. println ( "==========解密后数据==========" ) ; System . out. println ( paramStr) ; }  catch  ( Exception  e)  { e. printStackTrace ( ) ; } } 
}