【发布时间】:2011-07-12 13:57:54
【问题描述】:
我想知道对于素数域上的每种曲线类型(192, 224、256、384 和 521)。
【问题讨论】:
标签: cryptography digital-signature dsa elliptic-curve diffie-hellman
我想知道对于素数域上的每种曲线类型(192, 224、256、384 和 521)。
【问题讨论】:
标签: cryptography digital-signature dsa elliptic-curve diffie-hellman
如果您使用“命名曲线”之一,则公钥大小是固定的,并取决于基础曲线的“字段大小”。
公钥大小进一步取决于是使用“未压缩”表示还是“压缩”表示。在未压缩形式中,公钥大小等于字段大小(以字节为单位)+ 1 的两倍,在压缩形式中,它是字段大小 + 1。因此,如果您的曲线是在 secp256r1 (also called NIST P-256 or X9.62 prime256v1) 上定义的,那么字段大小是 256 位或 32 字节。因此,公钥在未压缩形式下正好是 65 字节 (32*2 +1) 长,在压缩形式下正好是 33 字节 (32 +1) 长。
未压缩的形式由 0x04(类似于 DER OCTET STRING tag)加上 x 坐标的大端二进制表示加上公共点的 y 坐标的二进制表示的串联组成。
如果基础字段是 GF(p),其中 p 是一个大素数(在 P-256 的情况下,是一个 256 位素数),那么 x 和 y 可以被认为是 [0, p- 1]。它们以通常的方式编码为 ((log2(p)+1)/8) 字节整数,如果需要,MSB 用零填充。
对于 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");
【讨论】: