lpilp / phpsm2sm3sm4

php版本,支持国密SM2的签名算法,非对称加解密,SM3的hash, SM4的对称加解密
320 stars 74 forks source link

sm2加密公钥 #50

Closed m-finder closed 1 year ago

m-finder commented 1 year ago

在跟银行做对接时,对方提供的 sm2 加密公钥长度为 66 位,03 开头。

查了下资料说是公钥分 x、y 两部分,x 为 02 开头,y 为 03 开头,04 表示完整公钥未压缩。

想问下大佬有方法将 x 或 y 还原成完整的公钥吗?或者是 sm2 支持下压缩密钥的加解密?

lpilp commented 1 year ago

02, 03 开头的没有什么区别呢,y是偶数就是02,y是奇数就是03, 公钥的确是x,y 两部分,通过x可以算出y,

lpilp commented 1 year ago
function decompressPublicKey($compressedKey) {
  // 获取压缩标志和X坐标
  $flag = substr($compressedKey, 0, 2);
  $x = substr($compressedKey, 2);

  // 将16进制字符串转换为大整数
  $p = gmp_init('FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF', 16);
  $a = gmp_init('FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC', 16);
  $b = gmp_init('28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93', 16);
  $gx = gmp_init('32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1711D7AFB1B8B4E16', 16);
  $gy = gmp_init('BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0', 16);
  $n = gmp_init('FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123', 16);

  // 计算Y坐标
  $x = gmp_init($x, 16);
  $alpha = gmp_powm($x, 3, $p);
  $beta = gmp_add(gmp_mod(gmp_mul($a, $x), $p), $b);
  $y2 = gmp_mod(gmp_add($alpha, $beta), $p);
  $y = gmp_powm($y2, gmp_div_q(gmp_add($p, 1), 4), $p);

  if ($flag == "02") {
    // 如果压缩标志为“02”,则Y坐标为偶数
    if (gmp_strval(gmp_mod($y, 2)) == "0") {
      return "04" . gmp_strval($x, 16) . str_pad(gmp_strval($y, 16), 64, "0", STR_PAD_LEFT);
    } else {
      $y = gmp_sub($p, $y);
      return "04" . gmp_strval($x, 16) . str_pad(gmp_strval($y, 16), 64, "0", STR_PAD_LEFT);
    }
  } elseif ($flag == "03") {
    // 如果压缩标志为“03”,则Y坐标为奇数
    if (gmp_strval(gmp_mod($y, 2)) == "1") {
      return "04" . gmp_strval($x, 16) . str_pad(gmp_strval($y, 16), 64, "0", STR_PAD_LEFT);
    } else {
      $y = gmp_sub($p, $y);
      return "04" . gmp_strval($x, 16) . str_pad(gmp_strval($y, 16), 64, "0", STR_PAD_LEFT);
    }
  } else {
    return null;
  }
}
m-finder commented 1 year ago

完美,感谢大佬🙏