///
/// 國密SM2算法(ECC算法)加密器
/// 簽名部分采用SM3算法進行摘要計算
///
public class Sm2Encryptor
{
///
/// SM2算法默認用戶ID,目前開放平台不會使用非默認用戶ID
///
public const string DefaultUserId = "1234567812345678";
public string GetAsymmetricType()
{
return "SM2";
}
public (string privatePem, string publicPem) DoKeyPairGenerator()
{
var SM2_ECC_P = new BigInteger("FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF", 16);
var SM2_ECC_A = new BigInteger("FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC", 16);
var SM2_ECC_B = new BigInteger("28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93", 16);
var SM2_ECC_N = new BigInteger("FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123", 16);
var SM2_ECC_H = BigInteger.One;
var SM2_ECC_GX = new BigInteger("32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7", 16);
var SM2_ECC_GY = new BigInteger("BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0", 16);
var SM2_ECC_Random = new SecureRandom();
ECCurve curve = new FpCurve(SM2_ECC_P, SM2_ECC_A, SM2_ECC_B, SM2_ECC_N, SM2_ECC_H);
var g = curve.CreatePoint(SM2_ECC_GX, SM2_ECC_GY);
var domainParams = new ECDomainParameters(curve, g, SM2_ECC_N);
var keyPairGenerator = new ECKeyPairGenerator();
var aKeyGenParams = new ECKeyGenerationParameters(domainParams, SM2_ECC_Random);
keyPairGenerator.Init(aKeyGenParams);
var aKp = keyPairGenerator.GenerateKeyPair();
var aPub = (ECPublicKeyParameters) aKp.Public;
var aPriv = (ECPrivateKeyParameters) aKp.Private;
var pkinfoPri = PrivateKeyInfoFactory.CreatePrivateKeyInfo(aPriv);
var priPem = Convert.ToBase64String(pkinfoPri.GetDerEncoded());
var pkinfoPub = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(aPub);
var pubPem = Convert.ToBase64String(pkinfoPub.GetDerEncoded());
return (priPem, pubPem);
}
public string DoDecrypt(string cipherTextBase64, string charset, string privateKey)
{
//加載私鑰參數
var cipherParams = BuildPrivateKeyParams(privateKey).Parameters;
//初始化SM2算法引擎
var sm2Engine = new SM2Engine();
sm2Engine.Init(false, cipherParams);
//對輸入密文進行解密
var input = Convert.FromBase64String(cipherTextBase64);
var output = sm2Engine.ProcessBlock(input, 0, input.Length);
//將解密后的明文按指定字符集編碼后返回
return Encoding.GetEncoding(charset).GetString(output);
}
public string DoEncrypt(string plainText, string charset, string publicKey)
{
//加載公鑰參數
var cipherParams = BuildPublicKeyParams(publicKey).Parameters;
var parametersWithRandom = new ParametersWithRandom(cipherParams);
//初始化SM2算法引擎
var sm2Engine = new SM2Engine();
sm2Engine.Init(true, parametersWithRandom);
//對輸入明文進行加密
var input = Encoding.GetEncoding(charset).GetBytes(plainText);
var output = sm2Engine.ProcessBlock(input, 0, input.Length);
//將密文Base64編碼后返回
return Convert.ToBase64String(output);
}
public string DoSign(string content, string charset, string privateKey)
{
//加載私鑰參數
var parametersWithId = BuildPrivateKeyParams(privateKey);
//加載簽名器
var signer = new SM2Signer();
signer.Init(true, parametersWithId);
//向簽名器中輸入原文
var input = Encoding.GetEncoding(charset).GetBytes(content);
signer.BlockUpdate(input, 0, input.Length);
//將簽名結果轉換為Base64
return Convert.ToBase64String(signer.GenerateSignature());
}
public bool DoVerify(string content, string charset, string publicKey, string sign)
{
//加載公鑰參數
var parametersWithId = BuildPublicKeyParams(publicKey);
//加載簽名器
var signer = new SM2Signer();
signer.Init(false, parametersWithId);
//向簽名器中輸入原文
var input = Encoding.GetEncoding(charset).GetBytes(content);
signer.BlockUpdate(input, 0, input.Length);
//傳入指定簽名串進行驗簽並返回結果
return signer.VerifySignature(Convert.FromBase64String(sign));
}
private ParametersWithID BuildPrivateKeyParams(string privateKey)
{
var key = PrivateKeyFactory.CreateKey(Convert.FromBase64String(privateKey));
var parametersWithId = new ParametersWithID(key, Encoding.UTF8.GetBytes(DefaultUserId));
return parametersWithId;
}
private static ParametersWithID BuildPublicKeyParams(string publicKey)
{
var key = PublicKeyFactory.CreateKey(Convert.FromBase64String(publicKey));
var parametersWithId = new ParametersWithID(key, Encoding.UTF8.GetBytes(DefaultUserId));
return parametersWithId;
}
}
//推薦參數http://www.oscca.gov.cn/sca/xxgk/2010-12/17/content_1002386.shtml
//參考:https://github.com/alipay/alipay-sdk-net-all
//參考:https://github.com/Arthurvdmerwe/AS2805.6.5.3/blob/6ee870947c0504da427734604aa79503d8ee3607/Crypto/test/src/crypto/test/SM2EngineTest.cs