链接:
目录
国产加密算法,通常也称为国密算法或商用密码算法,是由中国国家密码管理局制定的一系列加密标准。这些算法旨在提供与国际通用的加密算法相同的功能,同时确保中国的信息化系统能够拥有自主可控的安全保障。
一、对称加密算法
- SM1 算法:由国家密码管理局编制的一种商用密码分组标准对称算法,其分组长度和密钥长度均为 128 位。该算法的安全保密强度及相关软硬件实现性能与 AES 算法相当。值得注意的是,SM1 算法尚未公开,仅以 IP 核的形式存在于芯片中,广泛应用于电子政务、电子商务及国民经济的各个应用领域。
- SM4 算法:我国自主研发的分组对称密码算法,用于数据的加密和解密运算。它的分组长度和密钥长度同样为 128 比特,并具有较高的安全性和计算效率。加密算法与密钥扩展算法都采用 32 轮非线性迭代结构。解密算法与加密算法结构相同,只是轮密钥的使用顺序相反。
- SM7 算法:一种分组密码算法,分组长度为 128 比特,密钥长度也是 128 比特。它特别适用于非接 IC 卡的应用场景,包括身份识别类应用、票务类应用、支付与通卡类应用等。
- 祖冲之密码算法(ZUC):中国自主研究的流密码算法,是运用于移动通信 4G 网络中的国际标准密码算法。该算法体系包含了祖冲之算法、加密算法和完整性算法三个部分,确保了通信过程中的数据安全性和完整性。
二、非对称加密算法
- SM2 算法:基于椭圆曲线密码学(ECC)的非对称密钥算法,其加密强度为 256 位。SM2 包含椭圆曲线数字签名算法、密钥交换协议和公钥加密算法,分别用于实现数字签名、密钥协商和数据加密等功能。相比于 RSA1024,SM2 在安全性方面具有明显优势,同时在签名速度与密钥生成速度上也更快。
- SM9 算法:这是一种基于标识的密码算法,类似于 SM2,但包含总则、数字签名算法、密钥交换协议以及密钥封装机制和公钥加密算法。SM9 实现了一种基于身份的密码体制,其中公钥直接与用户的身份信息即标识相关联,因此省去了证书管理的需求,非常适合互联网应用的各种新兴应用场景,提供了更便捷的安全保障。
三、杂凑(哈希)算法
- SM3算法:SM3是中国商用密码标准中指定的密码杂凑算法,它是一个基于Merkle-Damgard结构的迭代型算法,能够将输入的消息处理成一个256位的固定长度摘要。该算法可替代 MD5/SHA - 1/SHA - 2 等国际算法,能满足电子认证服务系统等应用需求。
四、各种算法对比一览表
类别 | 算法名称 | 概述 | 特点 | 应用场景 |
对称加密算法 | SM1 算法 | 由国家密码管理局编制的一种商用密码分组标准对称算法,分组长度和密钥长度均为 128 位。 | 安全保密强度与 AES 算法相当,尚未公开,仅以 IP 核形式存在于芯片中。 | 广泛应用于电子政务、电子商务及国民经济的各个应用领域。 |
SM4 算法 | 我国自主研发的分组对称密码算法,用于实现数据的加密和解密运算。 | 分组长度和密钥长度均为 128 比特,采用 32 轮非线性迭代结构,具有较高的安全性和计算效率。 | 适用于需要高效加密的各种场景,如电子政务、电子商务等。 | |
SM7 算法 | 一种分组密码算法,专为非接 IC 卡应用设计。 | 分组长度为 128 比特,密钥长度也为 128 比特,适合资源受限的环境。 | 包括身份识别类应用、票务类应用、支付与通卡类应用等。 | |
祖冲之密码算法(ZUC) | 中国自主研究的流密码算法,是移动通信 4G 网络中的国际标准密码算法。 | 包含祖冲之算法、加密算法和完整性算法三个部分,确保通信过程中的数据安全性和完整性。 | 主要用于移动通信领域,保障数据传输的安全。 | |
非对称加密算法 | SM2 算法 | 基于椭圆曲线密码学(ECC)的非对称密钥算法,提供数字签名、密钥交换和公钥加密功能。 | 加密强度为 256 位,相比 RSA1024 在安全性方面具有明显优势,且签名速度与密钥生成速度更快。 | 适用于高安全需求的场合,如电子签章、网络认证等。 |
SM9 算法 | 基于标识的密码算法,允许直接使用用户的身份信息作为公钥。 | 省去了证书管理的需求,提供了更便捷的安全保障机制。 | 特别适合互联网应用的各种新兴场景,如云服务、物联网等,其中需要简便且高效的安全措施。 | |
杂凑(哈希)算法 | SM3算法 | 密码杂凑算法,能够将输入的消息处理成一个256位的固定长度摘要。 | 具有256位固定长度输出,通过多轮迭代和复杂的压缩函数确保高安全性,能有效抵抗碰撞攻击和原像攻击 | 适用于数字签名、消息认证码、数据完整性校验、密码存储、区块链等场景。 |
五、如何应用
1. BouncyCastle库
BouncyCastle是一个开源的加密库,支持多种加密算法,包括SM2/SM4。支持Java、C#等编程语言
下载地址:Bouncy Castle open-source cryptographic APIs
2. Gmssl库
一个支持国密算法的库,支持Java、Python、go、php、js等语言。
GitHub地址:https://github.com/guanzhi/GmSSL
五、C#中应用国产加密算法
准备工作
1.通过 NuGet 安装 Bouncy Castle 库。
Install-Package Portable.BouncyCastle
2. 在代码中引入必要的命名空间:
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Math;
using System.Text;
代码示例
1. SM4 加密与解密示例
SM4 是一种分组对称加密算法,分组长度为 128 比特(16 字节),支持 CBC 模式。
using System;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Modes;
using Org.BouncyCastle.Crypto.Parameters;
public class SM4Example
{
public static void Main(string[] args)
{
byte[] key = HexToBytes("0123456789ABCDEFFEDCBA9876543210"); // 16字节密钥
byte[] iv = HexToBytes("1234567890ABCDEF1234567890ABCDEF"); // 16字节IV
string plainText = "Hello, SM4!";
// 加密
byte[] encrypted = SM4Encrypt(key, iv, Encoding.UTF8.GetBytes(plainText));
Console.WriteLine("加密结果: " + BytesToHex(encrypted));
// 解密
byte[] decrypted = SM4Decrypt(key, iv, encrypted);
Console.WriteLine("解密结果: " + Encoding.UTF8.GetString(decrypted));
}
public static byte[] SM4Encrypt(byte[] key, byte[] iv, byte[] data)
{
var cipher = new CbcBlockCipher(new SM4Engine());
var parameters = new ParametersWithIV(new KeyParameter(key), iv);
cipher.Init(true, parameters);
byte[] output = new byte[cipher.GetOutputSize(data.Length)];
int length = cipher.ProcessBytes(data, 0, data.Length, output, 0);
cipher.DoFinal(output, length);
return output;
}
public static byte[] SM4Decrypt(byte[] key, byte[] iv, byte[] data)
{
var cipher = new CbcBlockCipher(new SM4Engine());
var parameters = new ParametersWithIV(new KeyParameter(key), iv);
cipher.Init(false, parameters);
byte[] output = new byte[cipher.GetOutputSize(data.Length)];
int length = cipher.ProcessBytes(data, 0, data.Length, output, 0);
cipher.DoFinal(output, length);
return output;
}
private static byte[] HexToBytes(string hex)
{
return Enumerable.Range(0, hex.Length)
.Where(x => x % 2 == 0)
.Select(x => Convert.ToByte(hex.Substring(x, 2), 16))
.ToArray();
}
private static string BytesToHex(byte[] bytes)
{
StringBuilder sb = new StringBuilder();
foreach (byte b in bytes)
sb.Append(b.ToString("X2"));
return sb.ToString();
}
}
2. SM2 签名与验签示例
SM2 是一种基于椭圆曲线密码学(ECC)的非对称加密算法,常用于数字签名。
using System;
using Org.BouncyCastle.Asn1.GM;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Generators;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Security;
public class SM2Example
{
public static void Main(string[] args)
{
// 生成SM2密钥对
AsymmetricCipherKeyPair keyPair = GenerateSM2KeyPair();
ECPublicKeyParameters publicKey = (ECPublicKeyParameters)keyPair.Public;
ECPrivateKeyParameters privateKey = (ECPrivateKeyParameters)keyPair.Private;
string message = "Hello, SM2!";
byte[] messageBytes = Encoding.UTF8.GetBytes(message);
// 签名
byte[] signature = Sign(privateKey, messageBytes);
Console.WriteLine("签名结果: " + BytesToHex(signature));
// 验签
bool isValid = Verify(publicKey, messageBytes, signature);
Console.WriteLine("验签结果: " + isValid);
}
public static AsymmetricCipherKeyPair GenerateSM2KeyPair()
{
var keyGen = new ECKeyPairGenerator();
var keyGenParams = new ECKeyGenerationParameters(GMObjectIdentifiers.sm2p256v1, new SecureRandom());
keyGen.Init(keyGenParams);
return keyGen.GenerateKeyPair();
}
public static byte[] Sign(ECPrivateKeyParameters privateKey, byte[] data)
{
ISigner signer = SignerUtilities.GetSigner("SM3withSM2");
signer.Init(true, privateKey);
signer.BlockUpdate(data, 0, data.Length);
return signer.GenerateSignature();
}
public static bool Verify(ECPublicKeyParameters publicKey, byte[] data, byte[] signature)
{
ISigner signer = SignerUtilities.GetSigner("SM3withSM2");
signer.Init(false, publicKey);
signer.BlockUpdate(data, 0, data.Length);
return signer.VerifySignature(signature);
}
private static string BytesToHex(byte[] bytes)
{
StringBuilder sb = new StringBuilder();
foreach (byte b in bytes)
sb.Append(b.ToString("X2"));
return sb.ToString();
}
}
3. SM3 哈希计算示例
SM3 是一种哈希算法,输出为 256 位(32 字节)。
using System;
using Org.BouncyCastle.Crypto.Digests;
public class SM3Example
{
public static void Main(string[] args)
{
string input = "Hello, SM3!";
byte[] hash = ComputeSM3(Encoding.UTF8.GetBytes(input));
Console.WriteLine("SM3 哈希值: " + BytesToHex(hash));
}
public static byte[] ComputeSM3(byte[] data)
{
var digest = new SM3Digest();
digest.BlockUpdate(data, 0, data.Length);
byte[] result = new byte[digest.GetDigestSize()];
digest.DoFinal(result, 0);
return result;
}
private static string BytesToHex(byte[] bytes)
{
StringBuilder sb = new StringBuilder();
foreach (byte b in bytes)
sb.Append(b.ToString("X2"));
return sb.ToString();
}
}
六、Java中应用国产加密算法
准备工作
1. 安装 Bouncy Castle for Java:
在 Maven 项目中添加依赖:
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>1.70</version> <!-- 使用最新版本 -->
</dependency>
2.引入命名空间
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>1.70</version> <!-- 使用最新版本 -->
</dependency>
代码示例
1. SM4 加密与解密示例
SM4 是一种分组对称加密算法,支持 CBC 模式。
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.Security;
import java.util.Base64;
public class SM4Example {
public static void main(String[] args) throws Exception {
Security.addProvider(new BouncyCastleProvider());
String keyHex = "0123456789ABCDEFFEDCBA9876543210"; // 16字节密钥
String ivHex = "1234567890ABCDEF1234567890ABCDEF"; // 16字节IV
String plainText = "Hello, SM4!";
byte[] key = hexToBytes(keyHex);
byte[] iv = hexToBytes(ivHex);
// 加密
byte[] encrypted = sm4Encrypt(key, iv, plainText.getBytes());
System.out.println("加密结果: " + Base64.getEncoder().encodeToString(encrypted));
// 解密
byte[] decrypted = sm4Decrypt(key, iv, encrypted);
System.out.println("解密结果: " + new String(decrypted));
}
public static byte[] sm4Encrypt(byte[] key, byte[] iv, byte[] data) throws Exception {
Cipher cipher = Cipher.getInstance("SM4/CBC/PKCS5Padding", "BC");
SecretKeySpec keySpec = new SecretKeySpec(key, "SM4");
IvParameterSpec ivSpec = new IvParameterSpec(iv);
cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec);
return cipher.doFinal(data);
}
public static byte[] sm4Decrypt(byte[] key, byte[] iv, byte[] data) throws Exception {
Cipher cipher = Cipher.getInstance("SM4/CBC/PKCS5Padding", "BC");
SecretKeySpec keySpec = new SecretKeySpec(key, "SM4");
IvParameterSpec ivSpec = new IvParameterSpec(iv);
cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
return cipher.doFinal(data);
}
private static byte[] hexToBytes(String hex) {
int len = hex.length();
byte[] data = new byte[len / 2];
for (int i = 0; i < len; i += 2) {
data[i / 2] = (byte) ((Character.digit(hex.charAt(i), 16) << 4)
+ Character.digit(hex.charAt(i + 1), 16));
}
return data;
}
}
2. SM2 签名与验签示例
SM2 是一种基于椭圆曲线密码学(ECC)的非对称加密算法。
import org.bouncycastle.asn1.gm.GMObjectIdentifiers;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.jce.ECNamedCurveTable;
import org.bouncycastle.jce.spec.ECParameterSpec;
import org.bouncycastle.jce.spec.ECPrivateKeySpec;
import org.bouncycastle.jce.spec.ECPublicKeySpec;
import java.math.BigInteger;
import java.security.*;
import java.security.spec.ECGenParameterSpec;
import java.util.Base64;
public class SM2Example {
public static void main(String[] args) throws Exception {
Security.addProvider(new BouncyCastleProvider());
String message = "Hello, SM2!";
KeyPair keyPair = generateSM2KeyPair();
// 签名
byte[] signature = sign((PrivateKey) keyPair.getPrivate(), message.getBytes());
System.out.println("签名结果: " + Base64.getEncoder().encodeToString(signature));
// 验签
boolean isValid = verify((PublicKey) keyPair.getPublic(), message.getBytes(), signature);
System.out.println("验签结果: " + isValid);
}
public static KeyPair generateSM2KeyPair() throws Exception {
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("EC", "BC");
ECGenParameterSpec ecSpec = new ECGenParameterSpec("sm2p256v1");
keyGen.initialize(ecSpec, new SecureRandom());
return keyGen.generateKeyPair();
}
public static byte[] sign(PrivateKey privateKey, byte[] data) throws Exception {
Signature signer = Signature.getInstance("SM3withSM2", "BC");
signer.initSign(privateKey);
signer.update(data);
return signer.sign();
}
public static boolean verify(PublicKey publicKey, byte[] data, byte[] signature) throws Exception {
Signature verifier = Signature.getInstance("SM3withSM2", "BC");
verifier.initVerify(publicKey);
verifier.update(data);
return verifier.verify(signature);
}
}
3. SM3 哈希计算示例
SM3 是一种哈希算法,输出为 256 位(32 字节)。
import org.bouncycastle.crypto.digests.SM3Digest;
import java.util.Base64;
public class SM3Example {
public static void main(String[] args) {
String input = "Hello, SM3!";
byte[] hash = computeSM3(input.getBytes());
System.out.println("SM3 哈希值: " + Base64.getEncoder().encodeToString(hash));
}
public static byte[] computeSM3(byte[] data) {
SM3Digest digest = new SM3Digest();
digest.update(data, 0, data.length);
byte[] result = new byte[digest.getDigestSize()];
digest.doFinal(result, 0);
return result;
}
}