给出公钥,找到点和椭圆曲线

时间:2015-06-04 09:37:56

标签: cryptography public-key elliptic-curve

我正在尝试解决此问题。知道公钥后,我想知道用哪个点和椭圆曲线生成该公钥。

例如,给定此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公钥?

2 个答案:

答案 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 = 0x02tag = 0x03see section 2.2)表示

现在,示例公钥可以写成:

  

04
  6bfbeec69de72c66a668ece1aaf1a264a3c9b288fb32d059e92c3e5d5bd4d7b5014878f4479c13c883d054555cd90ecd
  136ec4cc346489cdd64e6943f333864ab9dfe442dcbf8f69c19e71d035ff317fc032fc2155caeaa65b493d191d399ac0

每个坐标的长度为48个字节或384位。所以它似乎'示例公钥来自 EC P-384 曲线。

enter image description here

答案 1 :(得分:1)

您应该按概率顺序检查每条已知(命名)曲线。概率当然取决于具体情况,我不知道你从哪里找到了这个点。

所以你要做到以下几点:

  1. 遍历您可以找到的所有命名曲线;
  2. 检查曲线上的点是否有效而不是无穷大。
  3. 现在,如果你这样做,你会发现这是一条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 - 这个我提供了对曲线的更多控制。