我想知道是否有(我希望有)ECDH(椭圆曲线 Diffie-Hellman)和 ECDSA(椭圆曲线数字签名算法)的公钥大小标准,适用于素数字段(192、224、256)上的每种曲线类型, 384 和 521)。
2 回答
如果您使用“命名曲线”之一,则公钥大小是固定的,并取决于基础曲线的“字段大小”。
压缩与未压缩表示
公钥大小进一步取决于是使用“未压缩”表示还是“压缩”表示。在未压缩形式中,公钥大小等于字段大小(以字节为单位)+ 1 的两倍,在压缩形式中,它是字段大小 + 1。因此,如果您的曲线定义在secp256r1
(也称为NIST P-256
or X9.62 prime256v1
)上,那么字段大小为 256 位或 32 字节。因此,公钥在未压缩形式下正好是 65 字节 (32*2 +1) 长,在压缩形式下正好是 33 字节 (32 +1) 长。
未压缩的形式由 0x04(类似于DER OCTET STRING 标签)加上 x 坐标的大端二进制表示加上公共点的 y 坐标的二进制表示的串联组成。
GF(p) 案例
如果基础字段是 GF(p),其中 p 是一个大素数(在 P-256 的情况下,是一个 256 位素数),那么 x 和 y 可以被认为是来自 [0, p-1] 的元素。它们以通常的方式编码为 ((log2(p)+1)/8) 字节整数,如果需要,MSB 用零填充。
GF(2^m) 案例
对于 GF(2^m),x 和 y 可以被认为是多项式 a_0 + a_1x + a_2x^2 + ... + a_{m-1}x^{m-1},系数 a_i 等于 0 或 1 . 它们的二进制表示只是系数的串联。
进一步阅读
确切的细节可以在SEC1v2中找到。(特别是第10 页和第 11 页的第2.3.3 节椭圆曲线点到八位字节串的转换。)
我一直在寻找答案,并想用 Java 分享我的答案。我的任务是从 X509Certificate 获取密钥大小(网站是正确的)
方法#1 - 实际计算:
ECPublicKeyImpl ecPublicKey = (ECPublicKeyImpl) certificate.getPublicKey();
int publicKeyLength = (ecPublicKey.getEncodedPublicValue().length - 1) / 2 * 8;
(可能会添加第一个字节是否为 0x04 的验证)
方法#2 - 从一些“内部”中提取:
ECParameterSpec spec = ecPublicKey.getParams();
AlgorithmParameters algorithmParameters = AlgorithmParameters.getInstance("EC");
algorithmParameters.init(spec);
Provider provider = algorithmParameters.getProvider();
provider.get("KeyPairGenerator.EC KeySize");