我正在尝试解决此问题。知道公钥后,我想知道用哪个点和椭圆曲线生成该公钥。
例如,给定此ECC公钥:
04 6b fb ee c6 9d e7 2c 66 a6 68 ec e1 aa f1 a2 64 a3 c9 b2 88 fb 32 d0 59 e9 2c 3e 5d 5b d4 d7 b5 01 48 78 f4 47 9c 13 c8 83 d0 54 55 5c d9 0e cd 13 6e c4 cc 34 64 89 cd d6 4e 69 43 f3 33 86 4a b9 df e4 42 dc bf 8f 69 c1 9e 71 d0 35 ff 31 7f c0 32 fc 21 55 ca ea a6 5b 49 3d 19 1d 39 9a c0
如何知道哪个点和椭圆曲线用于生成ECC公钥?
答案 0 :(得分:3)
如果椭圆曲线是recommended elliptic curves for Federal Government use之一,您可以轻松找到其中(p,a,b,G,n,h)
为G
的域参数base point
和公钥的位长会告诉你曲线名称。
EC公钥是曲线上的一个点,如下所示:y^2 = x^3 + ax + b (mod p)
其中p
是素数模数。
根据ANSI X9.62,该点表示为压缩或未压缩形式的八位字符串。
因此,您提到的示例公钥包含x坐标和y坐标:
Public Key = tag + x co-ordinate + y co-ordinate
未压缩的表单由tag = 0x04
表示,压缩的表单由tag = 0x02
或tag = 0x03
(see section 2.2)表示
现在,示例公钥可以写成:
04
6bfbeec69de72c66a668ece1aaf1a264a3c9b288fb32d059e92c3e5d5bd4d7b5014878f4479c13c883d054555cd90ecd
136ec4cc346489cdd64e6943f333864ab9dfe442dcbf8f69c19e71d035ff317fc032fc2155caeaa65b493d191d399ac0
每个坐标的长度为48个字节或384位。所以它似乎'示例公钥来自 EC P-384 曲线。
答案 1 :(得分:1)
您应该按概率顺序检查每条已知(命名)曲线。概率当然取决于具体情况,我不知道你从哪里找到了这个点。
所以你要做到以下几点:
现在,如果你这样做,你会发现这是一条BrainpoolP384r1曲线,而不是NIST曲线。
好的,因为否则这个Java代码会腐烂:
import java.util.Enumeration;
import java.util.LinkedList;
import java.util.List;
import org.bouncycastle.asn1.nist.NISTNamedCurves;
import org.bouncycastle.asn1.sec.SECNamedCurves;
import org.bouncycastle.asn1.teletrust.TeleTrusTNamedCurves;
import org.bouncycastle.asn1.x9.X962NamedCurves;
import org.bouncycastle.asn1.x9.X9ECParameters;
import org.bouncycastle.math.ec.ECPoint;
import org.bouncycastle.util.encoders.Hex;
public class CurveFinder {
interface CurveRetriever {
X9ECParameters getByName(String name);
Enumeration<String> getNames();
}
public static void main(String[] args) {
byte[] wd = Hex.decode("04 6b fb ee c6 9d e7 2c 66 a6 68 ec e1 aa f1 a2 64 a3 c9 b2 88 fb 32 d0 59 e9 2c 3e 5d 5b d4 d7 b5 01 48 78 f4 47 9c 13 c8 83 d0 54 55 5c d9 0e cd 13 6e c4 cc 34 64 89 cd d6 4e 69 43 f3 33 86 4a b9 df e4 42 dc bf 8f 69 c1 9e 71 d0 35 ff 31 7f c0 32 fc 21 55 ca ea a6 5b 49 3d 19 1d 39 9a c0".replaceAll("\\s+", ""));
String name = findCurveName(wd);
if (name == null) {
System.out.println("Curve not found");
} else {
System.out.println("Curve: " + name);
}
}
private static String findCurveName(byte[] wd) {
List<CurveRetriever> retrievers = new LinkedList<>();
retrievers.add(new CurveRetriever() {
@Override
public X9ECParameters getByName(String name) {
return SECNamedCurves.getByName(name);
}
@Override
public Enumeration<String> getNames() {
return SECNamedCurves.getNames();
}
});
retrievers.add(new CurveRetriever() {
@Override
public X9ECParameters getByName(String name) {
return TeleTrusTNamedCurves.getByName(name);
}
@Override
public Enumeration<String> getNames() {
return TeleTrusTNamedCurves.getNames();
}
});
retrievers.add(new CurveRetriever() {
@Override
public X9ECParameters getByName(String name) {
return NISTNamedCurves.getByName(name);
}
@Override
public Enumeration<String> getNames() {
return NISTNamedCurves.getNames();
}
});
retrievers.add(new CurveRetriever() {
@Override
public X9ECParameters getByName(String name) {
return X962NamedCurves.getByName(name);
}
@Override
public Enumeration<String> getNames() {
return X962NamedCurves.getNames();
}
});
for (CurveRetriever curveRetriever : retrievers) {
String name = retrieveAndValidate(wd, curveRetriever);
if (name != null) {
return name;
}
}
return null;
}
private static String retrieveAndValidate(byte[] wd,
CurveRetriever retriever) {
ECPoint decodedPoint = null;
Enumeration<String> names = retriever.getNames();
while (names.hasMoreElements()) {
String name = names.nextElement();
X9ECParameters curveParams = retriever.getByName(name);
try {
decodedPoint = curveParams.getCurve().decodePoint(wd);
} catch (IllegalArgumentException e) {
continue;
}
if (decodedPoint.isInfinity() || !decodedPoint.isValid()) {
continue;
}
return name;
}
return null;
}
}
显然,这段代码需要Bouncy Castle的轻量级API。我不知道为什么我没有使用Bouncy Castle提供商代替JCE - 这个我提供了对曲线的更多控制。