我有一个使用此代码生成的公共私有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中的压缩格式将公钥信息编码为字节数组?
答案 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。