使用NIST P-256类型密钥和SHA-256算法验证签名

时间:2018-02-14 13:44:58

标签: java x509certificate signature sha256 ecdsa

我在使用SHA-256算法和NIST P-256类型密钥验证Java中的签名时遇到了问题。

我有一个X509证书(由证书颁发机构提供),其中包含一个公钥,我应该证明我收到的消息的真实性。

我收到的签名用Base32编码(103个字符),我将其解码为二进制。我获得了一个64字节的字节数组。

关于公钥的信息:

Sun EC public key, 256 bits
  public x coord: 76693623628200764797317561328856095594448010045454057728566183687964056347177
  public y coord: 111784915166853162657631137717721670318464358783507947441022826650722573271612
  parameters: secp256r1 [NIST P-256, X9.62 prime256v1] (1.2.840.10045.3.1.7)

(编辑)我用来验证邮件真实性的方法:

public static void verify(String message, String signatureReceived, String pathToCertificate) {

    try {

        final X509Certificate certificat = getCertificate(pathToCertificate);
        final PublicKey publicKey = certificat.getPublicKey();

        final byte[] signatureReceivedInBinary = BaseEncoding.base32().decode(signatureReceived);

        byte[] rBytes = Arrays.copyOfRange(signatureReceivedInBinary, 0, 32);
        byte[] sBytes = Arrays.copyOfRange(signatureReceivedInBinary, 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[] encoded = seq.getEncoded();

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

        signature.initVerify(publicKey);
        signature.update(message.getBytes("UTF-8"));

        if (signature.verify(encoded)) {
            System.out.println("Signature OK");
        } else {
            System.out.println("Signature KO");
        }

    } catch (Exception e) {
        e.printStackTrace();
    }

}

主要课程:

public static void main(String[] args)
        throws NoSuchAlgorithmException, CertificateException, IOException,
        KeyStoreException {

    final String message = "MessageToValidate";
    final String certificatPath = "<PATH_TO_CERTIFICATE>\\public_certificat.crt";
    final String signature = "UBFF4NY7MIXQVUZYMRDRGXBTVWIVMCNP76TN7SA24QUJ4AAHG4WTLA2QZ5TSC54F2OQRMWOAKSHLXJLNHXH4GJPBHBWXBO3PMSDOVZI";

    try {
        Test.verify(message, signature, certificatPath);
    } catch (final Exception e) {
        System.out.println(e.getMessage());
    }

}

当我执行我的应用程序时,我收到此错误:

Exception in thread "main" java.security.SignatureException: Could not verify signature
    at sun.security.ec.ECDSASignature.engineVerify(ECDSASignature.java:325)
    at java.security.Signature$Delegate.engineVerify(Signature.java:1219)
    at java.security.Signature.verify(Signature.java:652)
    at fr.altes.music.utils.Test.verify(Test.java:56)
    at fr.altes.music.Application.main(Application.java:54)
Caused by: java.security.SignatureException: Invalid encoding for signature
    at sun.security.ec.ECDSASignature.decodeSignature(ECDSASignature.java:400)
    at sun.security.ec.ECDSASignature.engineVerify(ECDSASignature.java:322)
    ... 4 more
Caused by: java.io.IOException: Sequence tag error
    at sun.security.util.DerInputStream.getSequence(DerInputStream.java:330)
    at sun.security.ec.ECDSASignature.decodeSignature(ECDSASignature.java:376)
    ... 5 more

0 个答案:

没有答案