最近和外部系统对接,使用了国密算法,且我们这边是c#,对方是Java,折腾了一番后,把踩过的坑记录下来,有需要的可以参考。
一、密钥生成
我们这边生成密钥是用的bouncycastle.crypto库,一开始对方是用Java自带的加密库生成的密钥,结果是双方都使用不了对方的密钥,后来我们两边都统一使用bouncycastle.crypto库来生成密钥,问题解决。
二、密文格式
c#这边默认的密文格式是C1C2C3,而Java那边使用格式一开始是C1C3C2,导致加解密、加验签不成功,后来两边统一使用C1C2C3,问题解决。
总结:c#和Java国密互通,两边的密钥生成以及加解密、加验签都要统一使用bouncycastle.crypto库,密文格式也最好统一,如果不统一,需要C1C2C3和C1C2C3进行转换。
附加解密、加验签的代码
加密
cs
public string EncryptM2(string message, string key)
{
X9ECParameters curve = ECNamedCurveTable.GetByName("sm2p256v1");
ECPoint q = curve.Curve.DecodePoint(Base64.Decode(key));
ECDomainParameters domain = new ECDomainParameters(curve);
ECPublicKeyParameters pubk = new ECPublicKeyParameters("EC", q, domain);
// 创建SM2加密器
SM2Engine sm2Engine = new SM2Engine();
sm2Engine.Init(true, new ParametersWithRandom(pubk, new SecureRandom()));
byte[] dataBytes = Encoding.UTF8.GetBytes(message);
byte[] encryptedData = sm2Engine.ProcessBlock(dataBytes, 0, dataBytes.Length);
return Base64.ToBase64String(encryptedData);
}
解密
cs
public string DecryptM2(string message, string key)
{
X9ECParameters curve = ECNamedCurveTable.GetByName("sm2p256v1");
ECDomainParameters domain = new ECDomainParameters(curve);
BigInteger d = new BigInteger(1, Base64.Decode(key));
ECPrivateKeyParameters prik = new ECPrivateKeyParameters(d, domain);
// 创建SM2加密器
SM2Engine sm2Engine = new SM2Engine();
sm2Engine.Init(false, prik);
byte[] encryptedData = Base64.Decode(message);
byte[] decryptedData = sm2Engine.ProcessBlock(encryptedData, 0, encryptedData.Length);
return Encoding.UTF8.GetString(decryptedData);
}
加签
cs
public string SignM2(string strPrivateKey, string strData)
{
byte[] messageBytes = System.Text.Encoding.UTF8.GetBytes(strData);
X9ECParameters curve1 = ECNamedCurveTable.GetByName("sm2p256v1");
ECDomainParameters domain1 = new ECDomainParameters(curve1);
BigInteger d = new BigInteger(1, Base64.Decode(strPrivateKey));
ECPrivateKeyParameters privKey = new ECPrivateKeyParameters(d, domain1);
ISigner signer = SignerUtilities.GetSigner("SM3withSM2");
signer.Init(true, new ParametersWithRandom(privKey, new SecureRandom()));
signer.BlockUpdate(messageBytes, 0, messageBytes.Length);
byte[] signature = signer.GenerateSignature();
return Base64.ToBase64String(signature);
}
验签
cs
public bool verifySignM2(string strPublickey, string strData, string strSign)
{
byte[] messageBytes = System.Text.Encoding.UTF8.GetBytes(strData);
byte[] signature = Base64.Decode(strSign);
X9ECParameters curve = ECNamedCurveTable.GetByName("sm2p256v1");
ECPoint q = curve.Curve.DecodePoint(Base64.Decode(strPublickey));
ECDomainParameters domain = new ECDomainParameters(curve);
ECPublicKeyParameters pubk = new ECPublicKeyParameters("EC", q, domain);
ISigner signer = SignerUtilities.GetSigner("SM3withSM2");
signer.Init(false, pubk);
signer.BlockUpdate(messageBytes, 0, messageBytes.Length);
bool isVerified = signer.VerifySignature(signature);
return isVerified;
}