在Java中获取压缩的X9.62编码的EC公钥

时间:2015-10-03 20:33:46

标签: java

我有一个使用此代码生成的公共私有KeyPair:

KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("EC");
SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
keyPairGenerator.initialize(256, secureRandom);
KeyPair pair = keyPairGenerator.generateKeyPair();

我想获得一个代表公钥的字节数组,使用X9.62 编码点压缩编码:

  

ANSI X9.62为压缩,未压缩或混合形式的椭圆点定义了强制八位字符串表示

我对点压缩的基本理解是,它允许另一端从公钥所代表的点找出(使用曲线)Y坐标,只给出X坐标和LSB。 Y在起始字节(0x02或0x03)中进行坐标。我可以得到两个BigInteger X和Y值,如下所示:

ECPoint point = ((ECPublicKey) pk.getPublic()).getW();
BigInteger y = point.getAffineY();
BigInteger x = point.getAffineX();

如何使用Java中的压缩格式将公钥信息编码为字节数组?

1 个答案:

答案 0 :(得分:1)

http://www.secg.org的SEC1中更方便地指定X9.62压缩和非压缩(但不是混合)形式 并且在https://security.stackexchange.com/questions/63876/can-any-ecc-field-element-be-safely-serialized-as-compressed-and-then-restored处有一个(nonJava)示例。

如果您希望几乎任何其他软件(包括标准Java加密)读取此编码的公钥, 您不仅需要X9.62 / SEC1编码,而且该编码包含在完整的 X.509证书中, 或者至少是X.509定义的SubjectPublicKeyInfo (SPKI) 结构。 SPKI包装依赖于算法的密钥数据 (对于ECC X9.62,对于其他算法的其他算法)在具有AlgorithmIdentifier的ASN.1 SEQUENCE中 识别算法(足够简单)加上适用的参数,ECC为曲线, 几乎总是以“命名”形式使用标识曲线的(标准化)ASN.1 OID。 任何包含PublicKey.getEncoded()的Java ECPublicKey都会返回, 并且所有KeyFactory.generatePublic()接受,编码Java名称“X.509”实际上是SPKI。

OpenSSL可以使用SPKI(它在API上调用PUBKEY,在PEM分隔符中调用PUBLIC KEY)或证书。 许多其他软件只接受证书,或者将证书与私钥组合在一起的PKCS#12又名PFX。 SSH,包括我相信OpenSSH 我还没有足够新的版本来测试,只接受带有XDRish字符串的SEC1 / X9.62来识别算法和曲线。

来自EC生成器的KeyPair使用整数大小初始化,就像实际使用命名曲线一样 但ECParameterSpec返回的EC{Public,Private}Key.getParams() API无法获取其OID。 您可以获得基础字段,系数,基点等,并以显式形式进行编码,但(1)浪费了大量空间,比 通过压缩publickey点来保存,以及(2)其他软件可能不接受/支持它。 你应该

  • 使用ECPublicKey.getEncoded()获取包含AlgId的SPKI,从算法相关部分解析点(这是微不足道的), 重新编码点,重建结构;或

  • 通过.initialize ECGenParameterSpec(name)在指定的曲线上生成一个键来转向另一个方向 然后使用生成的公共点对已知曲线(和固定算法)进行编码。

无论哪种方式,请参阅http://tools.ietf.org/html/rfc5480以及您是否喜欢之前的http://tools.ietf.org/html/rfc3279.html关于ECC的SPKI。