<< 新闻中心

国产化椭圆曲线ECC加密算法源码-国密SM2


——基于椭圆曲线非对称加密算法SM2

2021-05-06 17:06:02 作者 书写人生

椭圆曲线密码利用了上述“运算”中的“椭圆曲线上的离散对数问题”的复杂度,就像RSA利用了“大数质因数分解”的复杂度,以及EIGamal密码的Diffie-Hellman密钥交换利用了“有限域上的离散对数问题”的复杂度一样。

椭圆曲线上的离散对数问题:

已知

椭圆曲线E

椭圆曲线E上一点G(基点)

椭圆曲线E上的一点xGx倍的G

求解

x

这个问题的难度保证了椭圆曲线密码的安全性。

ECC公钥和私钥

在椭圆曲线加密中,给定椭圆曲线E,基点G和点xG,我们称xG为公钥,x值为私钥。由椭圆曲线性质可知,已知私钥求公钥很简单,而已知公钥求私钥几乎是不可能的事情。

ECC应用

因为在安全性、加解密性能、网络消耗方面有较大优势,ECC加密算法大有取代RSA成为下一代主流加密算法的趋势。如今ECC应用范围很广,在TLS、区块链(比特币、以太坊等等)、SM2国密算法、证书、银行政府机构等许多方面都有大量应用

核心代码

 

/**

 * 私钥解密

 *

 * @param encryptData

 *            密文数据字节数组

 * @param privateKey

 *            解密私钥

 * @return

 */

public String decrypt(byte[] encryptData, BigInteger privateKey) {

   if (debug) {

      System.out.println("encryptData length: " + encryptData.length);

      }

      byte[] C1Byte = new byte[65];

      System.arraycopy(encryptData, 0, C1Byte, 0,C1Byte.length);

      ECPoint C1 = curve.decodePoint(C1Byte).normalize();

      /*

       * 计算椭圆曲线点 S = [h]C1 是否为无穷点

       */

      BigInteger h = ecc_bc_spec.getH();

      if (h != null) {

         ECPoint S = C1.multiply(h);

         if (S.isInfinity()) {

            throw new IllegalStateException();

         }

      }

      /* 计算[dB]C1 = (x2, y2) */

      ECPoint dBC1 = C1.multiply(privateKey).normalize();

      /* 计算t = KDF(x2 || y2, klen) */

      byte[] dBC1Bytes = dBC1.getEncoded(false);

      int klen = encryptData.length - 65 - DIGEST_LENGTH;

      byte[] t = KDF(dBC1Bytes, klen);

      if (allZero(t)) {

         System.err.println("all zero");

         throw new IllegalStateException();

      }

      /* 5 计算M'=C2^t */

      byte[] M = new byte[klen];

      for (int i = 0; i < M.length; i++) {

         M[i] = (byte) (encryptData[C1Byte.length + i] ^ t[i]);

      }

      if (debug) {

         printHexString(M);

      }

      /* 6 计算 u = Hash(x2 || M' || y2) 判断 u == C3是否成立 */

      byte[] C3 = new byte[DIGEST_LENGTH];

      if (debug) {

         try {

            System.out.println("M = " + new String(M, "UTF8"));

         } catch (UnsupportedEncodingException e1) {

            e1.printStackTrace();

         }

      }

      System.arraycopy(encryptData, encryptData.length - DIGEST_LENGTH, C3, 0, DIGEST_LENGTH);

      byte[] u = sm3hash(dBC1.getXCoord().toBigInteger().toByteArray(), M,

            dBC1.getYCoord().toBigInteger().toByteArray());

      if (Arrays.equals(u, C3)) {

         if (debug) {

            System.out.println("解密成功");

         }

         try {

            return new String(M, "UTF8");

         } catch (UnsupportedEncodingException e) {

            e.printStackTrace();

         }

         return null;

      } else {

         if (debug) {

            System.out.print("u = ");

            printHexString(u);

            System.out.print("C3 = ");

            printHexString(C3);

            System.err.println("解密验证失败");

         }

         return null;

      }

   }

 

/**

* SM2秘钥对bean

*/

public class SM2KeyPair {

   private final ECPoint    publicKey;

   private final BigInteger privateKey;

   public SM2KeyPair(ECPoint publicKey, BigInteger privateKey)

   {

      this.publicKey = publicKey;

      this.privateKey = privateKey;

   }

   public ECPoint getPublicKey() {

      return publicKey;

   }

   public BigInteger getPrivateKey() {

      return privateKey;

   }

}

测试用例

// 生成秘钥对

SM2KeyPair keys = encrypt.generateKeyPair();

ECPoint publicKey = keys.getPublicKey();

BigInteger privateKey = keys.getPrivateKey();

GlobalFunction gb = GlobalFunction.getSingleton();

// 将公钥转换为String(十六进制)

String publicKeyHex = gb.convertByte2Hex(publicKey.getEncoded(false));

System.out.println("公钥(十六进制):" + publicKeyHex);

encrypt.setPassword(publicKeyHex);

byte[] encodeData = encrypt.encode("测试加密aaaaaaaaaaa123aabb");

String encodeDataHex =gb.convertByte2Hex(encodeData);

System.out.println("密文:" + encodeDataHex);

// 将私钥转换为String(十六进制)

String privateKeyHex = privateKey.toString(16);

System.out.println("私钥(十六进制):" + privateKeyHex);

encrypt.setPassword(privateKeyHex);

byte[] encodeDataByte = gb.convertHex2Byte(encodeDataHex);

byte[] decodeData = encrypt.decode(encodeDataByte);

System.out.println("明文:" + new String(decodeData, "UTF-8"));

ECC国密SM2 非对称加密Java源代码下载:

undefined

         具体更多实现细节,因涉及商业技术秘密,不在此详述。欢迎致电我司技术研发,为您提供更完整的解决方案。

         公司名称:四川书写人生科技有限公司

         通信地址:成都市金牛区兴盛西路2号固特大厦3A405A

         公司座机:028-83410634

         微信电话:191-8044-7517

         联系邮件:admin@skycto.com

         我们承诺:邮件8小时回,微信1小时回复,电话3分钟回复,欢迎致电联系。



推荐阅读

首页 分享微博 分享微信 回到顶部