当前位置:   article > 正文

C#使用ECC椭圆曲线算法实现加密与解密&签名与验签,有完整代码_ecdomainparameters

ecdomainparameters

        在C#、Java、Android中都使用BouncyCastle,以此实现多种环境之间的互通,比如在Java中生成的公私钥,在C#或Android中使用……

        为了在几种环境中得到一致结果,实现时做了一些退化。比如公钥、私钥转为字符串时,直接读取了公私钥的参数,而不是转为PKCS8(java中默认);还比如,C#中找不到ECIES,所以java与C#中都使用SM2实现加解密,等等。

        网上难以搜索到相关实现,所以贴上完整代码。有些地方还不确定是否符号标准,比如公私钥转为字符串时,直接使用其中D、Q值,不确定这种实现在未来版本中是否会变得不适用。如果哪位安全专家看到这篇文章,希望能够批评指正。在Java、C#中测试,两边可以互通。相反,如果在Java中使用Key的getEncoded得到的公私钥,在C#中不能使用;反之亦然,在C#中转为PKCS8,在Java中不能用。

        以下是几个主要函数的说明:

  1. genKeyPair产生公私钥对,密钥长度是256位,据说强度与RSA 3072相当;
  2. sign使用私钥签名,verify使用公钥验签;
  3. encrypt使用公钥加密,decrypt使用私钥解密;
  4. privateKey2Str将私钥转为base64字符串,publicKey2Str将公钥转为base64字符串,对应有str2PublicKey、str2PrivateKey进行逆向转变,此功能用在与js的交互中。

        以上列举的这些功能在至简网格中用到,至简网格是为中小企业信息化准备的,它是一套分布式、服务化、端云结合的开发框架。它可以多实例跨机房、跨城市部署,也可以部署到一部旧手机中。提供的服务都是开源、免费的,以此为中小企业节省成本。其中用到多种技术,对这些技术点的摸索,都记录在CSDN至简网格专栏中,便于自己查找,也希望能帮到需要的人。

  1. using Org.BouncyCastle.Asn1;
  2. using Org.BouncyCastle.Asn1.X9;
  3. using Org.BouncyCastle.Crypto;
  4. using Org.BouncyCastle.Crypto.EC;
  5. using Org.BouncyCastle.Crypto.Engines;
  6. using Org.BouncyCastle.Crypto.Generators;
  7. using Org.BouncyCastle.Crypto.Parameters;
  8. using Org.BouncyCastle.Math;
  9. using Org.BouncyCastle.Math.EC;
  10. using Org.BouncyCastle.Security;
  11. using System;
  12. namespace MeshClient.util {
  13. public class Ecc {
  14. private const string SIGN_ALGORITHM = "SHA256withECDSA"; //"SM3withSM2";
  15. private static readonly SecureRandom random = new SecureRandom();
  16. private static readonly ECDomainParameters domainParameters;
  17. private readonly ECPrivateKeyParameters privateKey;
  18. private readonly ECPublicKeyParameters publicKey;
  19. static Ecc() {
  20. DerObjectIdentifier oid = X9ObjectIdentifiers.Prime256v1;
  21. X9ECParameters ecps = CustomNamedCurves.GetByOid(oid);
  22. domainParameters = new ECDomainParameters(ecps.Curve, ecps.G, ecps.N, ecps.H, ecps.GetSeed());
  23. }
  24. private Ecc(ECPrivateKeyParameters privateKey, ECPublicKeyParameters publicKey) {
  25. this.privateKey = privateKey;
  26. this.publicKey = publicKey;
  27. }
  28. public static Ecc instance(AsymmetricCipherKeyPair keyPair) {
  29. return new Ecc((ECPrivateKeyParameters)keyPair.Private, (ECPublicKeyParameters)keyPair.Public);
  30. }
  31. public static Ecc instance() {
  32. AsymmetricCipherKeyPair keyPair = genKeyPair();
  33. return new Ecc((ECPrivateKeyParameters)keyPair.Private, (ECPublicKeyParameters)keyPair.Public);
  34. }
  35. //产生EC公私钥对
  36. public static AsymmetricCipherKeyPair genKeyPair() {
  37. ECKeyGenerationParameters ecKeyGenerationParameters = new ECKeyGenerationParameters(domainParameters, random);
  38. ECKeyPairGenerator gen = new ECKeyPairGenerator();
  39. gen.Init(ecKeyGenerationParameters);
  40. return gen.GenerateKeyPair();
  41. }
  42. /// <summary>
  43. /// 签名
  44. /// </summary>
  45. /// <param name="content">待签名内容</param>
  46. /// <param name="privateKey">EC私钥</param>
  47. /// <returns></returns>
  48. public static byte[] sign(byte[] content, ECPrivateKeyParameters privateKey) {
  49. ISigner signer = SignerUtilities.GetSigner(SIGN_ALGORITHM);
  50. signer.Init(true, new ParametersWithRandom(privateKey, random));
  51. signer.BlockUpdate(content, 0, content.Length);
  52. return signer.GenerateSignature();
  53. }
  54. /// <summary>
  55. /// 验签
  56. /// </summary>
  57. /// <param name="content">待验签内容</param>
  58. /// <param name="signature">待比较的签名结果</param>
  59. /// <param name="publicKey">EC公钥</param>
  60. /// <returns></returns>
  61. public static bool verify(byte[] content, byte[] signature, ECPublicKeyParameters publicKey) {
  62. ISigner signer = SignerUtilities.GetSigner(SIGN_ALGORITHM);
  63. signer.Init(false, publicKey);
  64. signer.BlockUpdate(content, 0, content.Length);
  65. return signer.VerifySignature(signature);
  66. }
  67. //使用SM2(国密2)算法解密数据
  68. public static byte[] decrypt(byte[] cipherText, ECPrivateKeyParameters privateKey) {
  69. SM2Engine sm2Engine = new SM2Engine();
  70. sm2Engine.Init(false, privateKey);
  71. return sm2Engine.ProcessBlock(cipherText, 0, cipherText.Length);
  72. }
  73. //使用SM2(国密2)算法加密数据
  74. public static byte[] encrypt(byte[] plainText, ECPublicKeyParameters publicKey) {
  75. SM2Engine sm2Engine = new SM2Engine();
  76. sm2Engine.Init(true, new ParametersWithRandom(publicKey, random));
  77. return sm2Engine.ProcessBlock(plainText, 0, plainText.Length);
  78. }
  79. /**
  80. * convert a privateKey to string
  81. * @param privateKey 私钥
  82. * @return 私钥字符串,以base64编码
  83. */
  84. public static string privateKey2Str(ECPrivateKeyParameters privateKey) {
  85. return Convert.ToBase64String(privateKey2Bytes(privateKey));
  86. }
  87. public static byte[] privateKey2Bytes(ECPrivateKeyParameters privateKey) {
  88. return privateKey.D.ToByteArray();
  89. }
  90. /**
  91. * convert the privateKey to string
  92. * @return 私钥字符串,以base64编码
  93. */
  94. public string privateKey2Str() {
  95. return privateKey2Str(this.privateKey);
  96. }
  97. /**
  98. * 将私钥从字符串转为私钥对象
  99. * @param content 私钥字符串,标准base64格式
  100. * @return 私钥
  101. */
  102. public static ECPrivateKeyParameters str2PrivateKey(string privateKey) {
  103. byte[] publicKeyBytes = Convert.FromBase64String(privateKey);
  104. return bytes2PrivateKey(publicKeyBytes);
  105. }
  106. public static ECPrivateKeyParameters bytes2PrivateKey(byte[] privateKey) {
  107. BigInteger D = new BigInteger(1, privateKey);
  108. return new ECPrivateKeyParameters(D, domainParameters);
  109. }
  110. /**
  111. * convert a publicKey to string
  112. * @param publicKey 公钥
  113. * @return 公钥字符串,以base64格式返回
  114. */
  115. public static string publicKey2Str(ECPublicKeyParameters publicKey) {
  116. BigInteger x = publicKey.Q.AffineXCoord.ToBigInteger();
  117. BigInteger y = publicKey.Q.AffineYCoord.ToBigInteger();
  118. byte[] bX = x.ToByteArray();
  119. byte[] bY = y.ToByteArray();
  120. int xLen = bX.Length;
  121. byte[] key = new byte[1 + xLen + bY.Length];
  122. key[0] = (byte)xLen; //EC256的情况为32
  123. Array.Copy(bX, 0, key, 1, xLen);
  124. Array.Copy(bY, 0, key, 1 + xLen, bY.Length);
  125. return Convert.ToBase64String(key);
  126. }
  127. public string publicKey2Str() {
  128. return publicKey2Str(this.publicKey);
  129. }
  130. /**
  131. * 将公钥从字符串转为私钥对象
  132. * @param content 公钥字符串,标准base64格式
  133. * @return 公钥
  134. */
  135. public static ECPublicKeyParameters str2PublicKey(string publicKey) {
  136. byte[] key = Convert.FromBase64String(publicKey);
  137. return bytes2PublicKey(key);
  138. }
  139. public static ECPublicKeyParameters bytes2PublicKey(byte[] key) {
  140. int xLen = (key[0]) & 0xff;
  141. if (xLen >= key.Length) {
  142. throw new ArgumentException("Invalid key data");
  143. }
  144. byte[] x = new byte[xLen];
  145. Array.Copy(key, 1, x, 0, xLen);
  146. byte[] y = new byte[key.Length - 1 - xLen];
  147. Array.Copy(key, 1 + xLen, y, 0, y.Length);
  148. ECPoint Q = domainParameters.Curve.ValidatePoint(new BigInteger(1, x), new BigInteger(1, y));
  149. return new ECPublicKeyParameters(Q, domainParameters);
  150. }
  151. }
  152. }

        

        

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/你好赵伟/article/detail/731279
推荐阅读
相关标签
  

闽ICP备14008679号