簡體   English   中英

Java 8 上的 java.security.InvalidAlgorithmParameterException 但適用於 Java 11

[英]java.security.InvalidAlgorithmParameterException on Java 8 but works on Java 11

因此,讓我們假設您要使用帶有 BrainpoolP256r1 橢圓曲線的 ECDSA 算法的公鑰來驗證簽名。

要運行以下代碼,請執行以下步驟:

  1. 使用以下命令生成一個大腦池的密鑰對:
openssl ecparam -name brainpoolP256r1 -genkey -noout -out ec-brainpoolP256r1-priv-key.pem
openssl ec -in ec-brainpoolP256r1-priv-key.pem -pubout > ec-brainpoolP256r1-pub-key.pem
openssl pkcs8 -topk8 -nocrypt -in ec-brainpoolP256r1-priv-key.pem -out ec-brainpoolP256r1-priv-key-pkcs8.pem (to read it with tomitribe PEM utility, we need the PKCS8 format)
  1. 使用生成的密鑰后運行以下代碼:
package com.test.ecdsa;

import org.tomitribe.auth.signatures.PEM;

import java.io.ByteArrayInputStream;
import java.nio.charset.StandardCharsets;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;

public class Main {
    public static void main(String[] args) throws Exception {
        String privateKeyPem = "[use here the content from ec-brainpoolP256r1-priv-key-pkcs8.pem]";

        Signature signer = Signature.getInstance("SHA256withECDSA");
        PrivateKey privateKey = PEM.readPrivateKey(new ByteArrayInputStream(privateKeyPem.getBytes(StandardCharsets.UTF_8)));

        signer.initSign(privateKey);
        signer.update("testMessage".getBytes(StandardCharsets.UTF_8));
        byte[] signature = signer.sign();

        String publicKeyPem = "[use here the content from ec-brainpoolP256r1-pub-key.pem]";

        PublicKey publicKey = PEM.readPublicKey(new ByteArrayInputStream(publicKeyPem.getBytes(StandardCharsets.UTF_8)));
        Signature signatureVerifier = Signature.getInstance("SHA256withECDSA");
        signatureVerifier.initVerify(publicKey);
        signatureVerifier.update("testMessage".getBytes(StandardCharsets.UTF_8));

        boolean result = signatureVerifier.verify(signature);

        System.out.println(result);
    }
}

在 java 8 上運行此代碼將導致:

Exception in thread "main" java.security.SignatureException: Could not sign data
    at sun.security.ec.ECDSASignature.signDigestNative(ECDSASignature.java:367)
    at sun.security.ec.ECDSASignature.engineSign(ECDSASignature.java:386)
    at java.security.Signature$Delegate.engineSign(Signature.java:1382)
    at java.security.Signature.sign(Signature.java:698)
    at com.ing.obp.jws.lib.Main.main(Main.java:29)
Caused by: java.security.InvalidAlgorithmParameterException
    at sun.security.ec.ECDSASignature.signDigest(Native Method)
    at sun.security.ec.ECDSASignature.signDigestNative(ECDSASignature.java:364)
    ... 4 more

使用 java 11 控制台將打印“true”。

這是為什么?

好吧,在 java 11 中添加了 Brainpool 和其他 ECC 支持(自 java 7 起不可用,我發現這個鏈接很有趣: https ://bugs.openjdk.java.net/browse/JDK-7007966)

如果您仍想使用 java 8 來讀取密鑰、簽名、驗證簽名,那么您將需要 BouncyCastleProvider。

Maven依賴:

<dependency>
    <groupId>org.bouncycastle</groupId>
    <artifactId>bcpkix-jdk15on</artifactId>
    <version>1.70</version>
</dependency>

要使用它,您可以將提供程序注冊到 java 的安全層,然后使用 BouncyCastleProvider.PROVIDER_NAME 在 Signature.getInstance 中引用它。

像這樣:

...
import org.bouncycastle.jce.provider.BouncyCastleProvider;
...
public class Main {
    static {
        Security.addProvider(new BouncyCastleProvider());
    }
...
        Signature signer = Signature.getInstance("SHA256withECDSA", BouncyCastleProvider.PROVIDER_NAME);
...
        Signature signatureVerifier = Signature.getInstance("SHA256withECDSA", BouncyCastleProvider.PROVIDER_NAME);
...
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM