Как проверить подпись в Java, если алгоритм открытого ключа EC? - PullRequest
1 голос
/ 13 октября 2019

С учетом объекта сертификата 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

У вас есть идея, как мне заставить это работать?

Отредактировано: В конце концов мне удалось заставить его работать, но пока не понимаю причину: перед передачей подписи методу проверки мне нужно было внести в нее следующие изменения:

    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 голосов
/ 14 октября 2019

Вот (полу) рабочее приложение для дальнейшего использования, которое проверяет подпись, когда 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");
    }
}
...