如果公钥的算法为EC,如何在Java中验证签名?

时间:2019-10-13 08:19:00

标签: java signature public-key elliptic-curve ecdsa

给出一个人的X509证书对象。 (对象的类型为sun.security.x509.X509CertImpl)。此人用他的私钥在字符串上签名。给定此人在签名上述String对象时所做出的签名。

我的任务是验证此签名,但遇到困难。

当我尝试使用以下代码验证签名时:

    ...
    X509Certificate x509Certificate = getCertificate(certificate);

    Signature signature = Signature.getInstance("SHA256withECDSA");

    signature.initVerify(x509Certificate.getPublicKey());

    signature.update(unsignedData);
    boolean bool = signature.verify(signatureToVerify);
    System.out.println("The signature is " + (bool ? "" : "NOT") + " valid");

我得到java.security.SignatureException: Could not verify signature

您有一个主意,我如何使它起作用?

已编辑: 最后,我设法使其正常运行,但尚不了解原因: 在将签名传递给verify方法之前,我需要对其进行以下修改:

    byte[] rBytes = Arrays.copyOfRange(signatureHash, 0, 32);
    byte[] sBytes = Arrays.copyOfRange(signatureHash, 32, 64);

    BigInteger r = new BigInteger(1, rBytes);
    BigInteger s = new BigInteger(1, sBytes);

    ASN1Integer asn1R = new ASN1Integer(r);
    ASN1Integer asn1S = new ASN1Integer(s);

    DERSequence seq = new DERSequence(new ASN1Integer[]{asn1R, asn1S});
    byte[] signatureToVerify2 = seq.getEncoded();
    // verifying the signatureToVerify2 instead of the original brings success
    boolean bool = signature.verify(signatureToVerify2);

1 个答案:

答案 0 :(得分:0)

这是一个(半)工作的应用程序,用于在故事涉及ECDSA时验证签名的进一步参考:

import org.bouncycastle.asn1.ASN1Integer;
import org.bouncycastle.asn1.DERSequence;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.Signature;
import java.security.SignatureException;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.Arrays;

public class SignatureTest {

    public static void main(String[] args) throws CertificateException, InvalidKeyException, SignatureException, NoSuchAlgorithmException, IOException {
        byte[] certificateAsByteArray = ...;
        byte[] dataToVerifyAsByteArray = ...;
        byte[] signatureHashAsByteArray = ...;

        CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
        InputStream in = new ByteArrayInputStream(certificateBytes);
        X509Certificate x509Certificate = (X509Certificate) certFactory.generateCertificate(in);

        Signature signature = Signature.getInstance("SHA256withECDSA");

        signature.initVerify(x509Certificate.getPublicKey());

        signature.update(dataToVerifyAsHexaString);

        byte[] rBytes = Arrays.copyOfRange(signatureHash, 0, 32);
        byte[] sBytes = Arrays.copyOfRange(signatureHash, 32, 64);

        ASN1Integer asn1R = new ASN1Integer(rBytes);
        ASN1Integer asn1S = new ASN1Integer(sBytes);

        DERSequence seq = new DERSequence(new ASN1Integer[] {asn1R, asn1S});

        boolean isSignatureOK = signature.verify(seq.getEncoded());

        System.out.println("The signature is " + (isSignatureOK ? "" : "NOT ") + "VALID");
    }
}