当前位置: 首页 > 面试题库 >

从私钥派生ECDSA公钥

罗飞宇
2023-03-14
问题内容

我试图从私钥生成公共ECDSA密钥,但是在Internet上如何进行此操作方面,我还没有找到太多帮助。几乎所有内容都是根据公共密钥规范生成公共密钥的,我不知道该如何获得。到目前为止,这是我汇总的内容:

public void setPublic() throws GeneralSecurityException {
    ECNamedCurveParameterSpec params = ECNamedCurveTable.getParameterSpec("secp256k1");
    KeyFactory fact = KeyFactory.getInstance("ECDSA", "BC");
    ECCurve curve = params.getCurve();
    java.security.spec.EllipticCurve ellipticCurve = EC5Util.convertCurve(curve, params.getSeed());
    java.security.spec.ECPoint point = ECPointUtil.decodePoint(ellipticCurve, this.privateKey.getEncoded());
    java.security.spec.ECParameterSpec params2=EC5Util.convertSpec(ellipticCurve, params);
    java.security.spec.ECPublicKeySpec keySpec = new java.security.spec.ECPublicKeySpec(point,params2);
    this.publicKey = fact.generatePublic(keySpec);
}

但是,在运行时,出现以下错误:

Exception in thread "main" java.lang.IllegalArgumentException: Invalid point encoding 0x30
at org.bouncycastle.math.ec.ECCurve.decodePoint(Unknown Source)
at org.bouncycastle.jce.ECPointUtil.decodePoint(Unknown Source)
at Wallet.Wallet.setPublic(Wallet.java:125)

我究竟做错了什么?有没有更好/更简便的方法可以做到这一点?

编辑:我设法获得一些代码进行编译,但不能正常工作:

public void setPublic() throws GeneralSecurityException {
    BigInteger privKey = new BigInteger(getHex(privateKey.getEncoded()),16);
    X9ECParameters ecp = SECNamedCurves.getByName("secp256k1");
    ECPoint curvePt = ecp.getG().multiply(privKey);
    BigInteger x = curvePt.getX().toBigInteger();
    BigInteger y = curvePt.getY().toBigInteger();
    byte[] xBytes = removeSignByte(x.toByteArray());
    byte[] yBytes = removeSignByte(y.toByteArray());
    byte[] pubKeyBytes = new byte[65];
    pubKeyBytes[0] = new Byte("04");
    System.arraycopy(xBytes, 0, pubKeyBytes, 1, xBytes.length);
    System.arraycopy(yBytes, 0, pubKeyBytes, 33, xBytes.length);




    ECNamedCurveParameterSpec params = ECNamedCurveTable.getParameterSpec("secp256k1");
    KeyFactory fact = KeyFactory.getInstance("ECDSA", "BC");
    ECCurve curve = params.getCurve();
    java.security.spec.EllipticCurve ellipticCurve = EC5Util.convertCurve(curve, params.getSeed());
    java.security.spec.ECPoint point = ECPointUtil.decodePoint(ellipticCurve, pubKeyBytes);
    java.security.spec.ECParameterSpec params2 = EC5Util.convertSpec(ellipticCurve, params);
    java.security.spec.ECPublicKeySpec keySpec = new java.security.spec.ECPublicKeySpec(point,params2);
    this.publicKey = fact.generatePublic(keySpec);
}

private byte[] removeSignByte(byte[] arr)
{
    if(arr.length==33)
    {
        byte[] newArr = new byte[32];
        System.arraycopy(arr, 1, newArr, 0, newArr.length);
        return newArr;
    }
    return arr;
}

当我运行它时,它会生成一个publicKey,但是它与私钥对应的不是同一个。


问题答案:

因此,过了一会儿,我想出了一个解决方案,并决定将其发布,以防其他人遇到与我相同的问题:

KeyFactory keyFactory = KeyFactory.getInstance("ECDSA", "BC");
    ECParameterSpec ecSpec = ECNamedCurveTable.getParameterSpec("secp256k1");

    ECPoint Q = ecSpec.getG().multiply(((org.bouncycastle.jce.interfaces.ECPrivateKey) this.privateKey).getD());

    ECPublicKeySpec pubSpec = new ECPublicKeySpec(Q, ecSpec);
    PublicKey publicKeyGenerated = keyFactory.generatePublic(pubSpec);
    this.publicKey = publicKeyGenerated;

编辑:删除了根据@MaartenBodewes注释解码ECPoint的代码。



 类似资料:
  • 以下网站经常被引用,而且我认为是准确的: https://gobittest.appspot.com/Address 我试图在Golang中重现这些步骤,但第一步就失败了:-( 有人能给我提供一个Golang片段,给定ECDSA私钥,返回公钥吗?我想我可能具体指的是上述站点示例中的私钥指数和公钥指数。 i、 例如,给定随机生成的(十六进制编码的)私钥(指数?)<代码>E83385AF76B2B19

  • 我试图从私钥中生成一个公共ECDSA密钥,但我还没有在互联网上找到多少关于如何实现这一点的帮助。几乎所有的事情都是为了从公钥规范生成公钥,我不知道如何得到它。到目前为止,我总结了以下内容: 但是,在运行时,我会出现以下错误: 我做错了什么?有更好/更简单的方法吗? 编辑:我已经设法编译了一些代码,但它不能正常工作: 当我运行它时,它会生成一个公钥,但它不是私钥对应的公钥。

  • 我有这样的代码来导入一个ECDH键: 这是可行的,但是它只返回私钥,而不是整个密钥对。如何从私钥中导出公钥?

  • 我正在尝试用c#签署比特币交易。我有两段代码要完成。我可以使用Bouncy castle创建一组私钥和公钥。我可以将其转换为钱包导入格式ok。 我还可以从ECDSA公钥生成比特币地址。 然而,我想签署一项交易,我所拥有的只是我的私钥。我不想把东西放进钱包里签名。那么,在只提供私钥的情况下,如何生成公钥呢? 我发现了一个javascript方法可以做到这一点: 我在充气城堡看到的唯一方法是生成随机一

  • 从这里我指出了自己如何获得公钥,并使用EC_POINT_bn2point,而不是hex2point,根据OpenSSL源代码,它在内部执行BN_hex2bn。 那么,为什么EC_POINT_bn2point返回null呢?我正在认真考虑重新编译OpenSSL,并放一些调试例程来找出它失败的原因。

  • 我正试图使用弹跳城堡来生成ECDSA密钥。从Java的角度来看,代码似乎工作得很好;但是,当我转储文件并试图验证数据时,OpenSSL不喜欢数据的格式。 经过一些研究,我认为bouncy castle正在将私钥编码为公钥。 null