【问题标题】:Find point and elliptic curve given the public key给定公钥找到点和椭圆曲线
【发布时间】:2015-08-18 20:31:37
【问题描述】:

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

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

【问题讨论】:

  • 你应该问这个问题@@crypto。恕我直言,如果您只知道公钥,那么就没有简单有效的方法。
  • @Qiu 另一方面,在加密 avm_69 上不会得到代码:P
  • 请不要删除您问题的内容。要将问题标记为已解决,mark the answer that helped you most as accepted。还要对所有对您有帮助的答案投赞成票。

标签: cryptography public-key elliptic-curve


【解决方案1】:

如果椭圆曲线是recommended elliptic curves for Federal Government use 之一,您可以轻松找出域参数(p,a,b,G,n,h),其中Gbase point,公钥的位长会告诉您曲线名称。

EC 公钥是曲线上的一个点,如下所示:y^2 = x^3 + ax + b (mod p) 其中p 是质数模数。

根据ANSI X9.62,该点以压缩或未压缩形式表示为八位字节字符串。

所以您提到的示例公钥由 x 坐标和 y 坐标组成:

公钥=标签+x坐标+y坐标

未压缩的形式用tag = 0x04表示,压缩的形式用tag = 0x02tag = 0x03see section 2.2)表示

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

04
6bfbeec69de72c66a668ece1aaf1a264a3c9b288fb32d059e92c3e5d5bd4d7b5014878f4479c13c883d054555cd90ecd
136ec4cc346489cdd64e6943f333864ab9dfe442dcbf8f69c19e71d035ff317fc032fc2155caeaa65b493d191d399ac0

每个坐标的长度为 48 字节或 384 位。因此,示例公钥“似乎”来自 EC P-384 曲线。

【讨论】:

  • 请仅对代码使用代码格式,不要对随机单词使用。
  • @Gilles,罗杰,先生。
  • 这个答案设置和描述性很好。验证它是否不正确也很容易。使用的曲线是 Brainpool 曲线,而不是 NIST 曲线。
  • 亲爱的@MaartenBodewes 先生,我只是想说 OP 一种方法,如何找到 NIST 推荐的曲线名称。这就是为什么我的答案以“如果”开头。不过,如果您要求,我可以删除我的答案。
  • 我可以编辑答案以表明它也可能是另一条曲线(即 Brainpool 曲线)。我不是在十字军东征或任何事情上,只是错就是错。剩下的答案很好,我们应该保留它:)
【解决方案2】:

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

所以你执行以下操作:

  1. 遍历所有你能找到的命名曲线;
  2. 检查该点在曲线上是否有效,而不是无穷大。

现在,如果您这样做,您会发现这是 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。我不知道为什么我没有为 JCE 使用 Bouncy Castle 提供程序——我猜这个提供了对曲线的更多控制。

【讨论】:

  • 公钥是从这个网站bsi.bund.de/SharedDocs/Downloads/EN/BSI/CSCA/…获取的,你可以在这里找到更多信息bsi.bund.de/EN/Topics/ElectrIDDocuments/CSCAcertGermany/…考虑到它是一个Brainpool曲线,怎么可能知道哪个是使用的点?
  • 链接证书要么明确指定参数,要么从前一个证书“借用”参数(第一个证书必须包含参数。公共点本身当然是包含在证书中,它是与私有值 $s$ 一起生成的,它在某个 HSM 中。生成器 g,也是一个点,是参数的一部分。
  • 所以,它是一条脑池曲线,点是公钥减去标签 0x04 给出的 x,y 坐标?
  • 是的,就是这样。当然,您仍然需要将 x、y 坐标解释为一组固定大小的大端整数,以便它们在实际计算中可用。请注意,链接证书仅包含需要更改的参数(这是允许的)。
猜你喜欢
  • 1970-01-01
  • 2020-03-08
  • 1970-01-01
  • 2020-03-04
  • 2013-11-09
  • 1970-01-01
  • 2021-10-10
  • 2015-02-03
  • 1970-01-01
相关资源
最近更新 更多