java - 在 bouncy caSTLe 中生成 ECDSA 私钥返回公钥

标签 java openssl bouncycastle ecdsa

我正在尝试使用充气城堡生成 ECDSA key 。从 Java 的角度来看,代码似乎运行良好;但是,当我转储文件并尝试验证数据时,OpenSSL 不喜欢数据格式。

经过一些研究,我认为充气城堡正在将私钥编码为公钥。

这是我的 Java 代码:

public class Test {
    public static void main(String[] args) {
        Security.addProvider(new BouncyCastleProvider());
        System.out.println("Starting...");
        String name = "prime256v1";
        try {
            KeyPairGenerator kpg = KeyPairGenerator.getInstance("ECDSA", BouncyCastleProvider.PROVIDER_NAME);
            kpg.initialize(new ECGenParameterSpec(name));
            KeyPair keyPair = kpg.generateKeyPair();    
            FileOutputStream writer = new FileOutputStream("private.key");
            writer.write(keyPair.getPrivate().getEncoded());
            writer.close();
        } catch(Exception e) {
            e.printStackTrace();
        }
    }
}

文件 private.key 以有效的 DER 格式生成;但是,当我运行以下命令以查看 key 的 ASN.1 结构时:

$ openssl asn1parse -inform DER -in /my/path/private.key
    0:d=0  hl=3 l= 147 cons: SEQUENCE          
    3:d=1  hl=2 l=   1 prim: INTEGER           :00
    6:d=1  hl=2 l=  19 cons: SEQUENCE          
    8:d=2  hl=2 l=   7 prim: OBJECT            :id-ecPublicKey
   17:d=2  hl=2 l=   8 prim: OBJECT            :prime256v1
   27:d=1  hl=2 l= 121 prim: OCTET STRING      [HEX DUMP]: <hex data>

为了比较,如果我运行以下命令使用 OpenSSL 生成 ECDSA key ,我会得到以下 ASN.1 结构:

 $ openssl ecparam -name prime256v1 -genkey -noout -outform DER -out private.key
 $ openssl asn1parse -inform DER -in private.key
     0:d=0  hl=2 l= 119 cons: SEQUENCE          
     2:d=1  hl=2 l=   1 prim: INTEGER           :01
     5:d=1  hl=2 l=  32 prim: OCTET STRING      [HEX DUMP]: <hex data>
    39:d=1  hl=2 l=  10 cons: cont [ 0 ]        
    41:d=2  hl=2 l=   8 prim: OBJECT            :prime256v1
    51:d=1  hl=2 l=  68 cons: cont [ 1 ]        
    53:d=2  hl=2 l=  66 prim: BIT STRING        

所以,我想我的问题是

  • 有什么我遗漏的吗?
  • 或者这是一个已知错误?
  • 有没有办法绕过它?

最佳答案

Java 以编码格式输出 key 。你应该尝试:

private String getPrivateKeyAsHex(PrivateKey privateKey) {

    ECPrivateKey ecPrivateKey = (ECPrivateKey) privateKey;
    byte[] privateKeyBytes = new byte[PRIVATE_KEY_LENGTH];
    writeToStream(privateKeyBytes, 0, ecPrivateKey.getS(), PRIVATE_KEY_LENGTH);

    String hex = Hex.toHexString(privateKeyBytes);

    logger.debug("Private key bytes: " + Arrays.toString(privateKeyBytes));
    logger.debug("Private key hex: " + hex);

    return hex;
}

private String getPublicKeyAsHex(PublicKey publicKey) {

    ECPublicKey ecPublicKey = (ECPublicKey) publicKey;
    ECPoint ecPoint = ecPublicKey.getW();

    byte[] publicKeyBytes = new byte[PUBLIC_KEY_LENGTH];
    writeToStream(publicKeyBytes, 0, ecPoint.getAffineX(), PRIVATE_KEY_LENGTH);
    writeToStream(publicKeyBytes, PRIVATE_KEY_LENGTH, ecPoint.getAffineY(), PRIVATE_KEY_LENGTH);

    String hex = Hex.toHexString(publicKeyBytes);

    logger.debug("Public key bytes: " + Arrays.toString(publicKeyBytes));
    logger.debug("Public key hex: " + hex);

    return hex;
}

private void writeToStream(byte[] stream, int start, BigInteger value, int size) {
    byte[] data = value.toByteArray();
    int length = Math.min(size, data.length);
    int writeStart = start + size - length;
    int readStart = data.length - length;
    System.arraycopy(data, readStart, stream, writeStart, length);
}

关于java - 在 bouncy caSTLe 中生成 ECDSA 私钥返回公钥,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40552688/

相关文章:

java - SWT - 在我的 TableViewer 中使用 EditingSupport

java - Hibernate中级联删除: What order to delete from tables?

java - 仅将数组中的第一行添加到数据库 Java

ios - 使用位码构建 openSSL

java - 如何提取文本集合的子字符串?

javascript - 无法在 Node.js 中使用 IP 作为自签名证书

c++ - 如何在没有套接字管理的情况下使用 OpenSSL 库?

java - 充气城堡安全提供程序不会在 Java 11/12 下加载

c# - 使用 BouncyCaSTLe : AESEngine, AESFastEngine 或 AESLightEngine 进行 AES 加密?

java - 使用充气城堡从证书中提取 keyUsage 扩展