java.security.SignatureException: неверная кодировка для подписи.подпись подтверждена Azure - PullRequest
1 голос
/ 30 июня 2019

При проверке подписи с помощью Signature.verify я получаю исключение "Недопустимая кодировка для подписи". При проверке той же подписи с помощью службы Azure подпись проверяется.

У меня есть хеш-данные (SHA-256), открытый ключ и подпись, которую я пытаюсь проверить. Подпись была получена с использованием метода com.microsoft.azure.keyvault.KeyVaultClient.sign с алгоритмом подписи «ES256».

Это работает (с использованием алгоритма ES256):

    com.microsoft.azure.keyvault.KeyVaultClient keyVaultClient;
    String keyPairIdentifier;

    boolean verify(byte[] hashData, byte[] signature, JsonWebKeySignatureAlgorithm signingAlgorithm) {
        com.microsoft.azure.keyvault.models.KeyVerifyResult result = keyVaultClient.verify(keyPairIdentifier, signingAlgorithm, hashData, signature);
        return result.value().booleanValue();
    }

Сбой (сертификат содержит тот же открытый ключ, который хранится в Azure keyvault):

    Signature ecdsaSign = Signature.getInstance("SHA256withECDSA");
    ecdsaSign.initVerify(certificate.getPublicKey());
    ecdsaSign.update(hashData);
    ecdsaSign.verify(signature)

Ожидаемый результат - true (подпись проверена)

Фактический результат:

java.security.SignatureException: Could not verify signature
    at sun.security.ec.ECDSASignature.engineVerify(ECDSASignature.java:325)
    at java.security.Signature$Delegate.engineVerify(Signature.java:1222)
    at java.security.Signature.verify(Signature.java:655)
    at TestKV.KeyVault.VerifyDPSignature.verifySignatureUsingCertificate(VerifyDPSignature.java:143)
    at TestKV.KeyVault.VerifyDPSignature.main(VerifyDPSignature.java:104)
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)

Ответы [ 2 ]

0 голосов
/ 01 июля 2019

dave_thompson_085 - спасибо!В коде, который вы прикрепили, было несколько ошибок, теги частей подписи должны быть 0x02, а не 0x30, и вы не увеличили o после копирования первой части.Это код после изменений:

    byte[] r = new BigInteger(1,Arrays.copyOfRange(signature,0,32)).toByteArray();
    byte[] s = new BigInteger(1,Arrays.copyOfRange(signature,32,64)).toByteArray();
    byte[] der = new byte[6+r.length+s.length];
    der[0] = 0x30; // Tag of signature object
    der[1] = (byte)(der.length-2); // Length of signature object
    int o = 2;
    der[o++] = 0x02; // Tag of ASN1 Integer
    der[o++] = (byte)r.length; // Length of first signature part
    System.arraycopy (r,0, der,o, r.length);
    o += r.length;
    der[o++] = 0x02; // Tag of ASN1 Integer
    der[o++] = (byte)s.length; // Length of second signature part
    System.arraycopy (s,0, der,o, s.length);

После изменения формата я не получил исключение «Ошибка тега последовательности».Но проверка все равно не удалась.

Спасибо!

0 голосов
/ 30 июня 2019

Azure выполняет JWS , который просто объединяет I2OSP фиксированного размера из r и s , но Java JCE, как и большинство, но не все стандарты, использует кодировку ASN.1 DER , например. rfc3279 (предостережение: теперь есть EID для ECDSA с другими хэшами).

Чтобы преобразовать JWS / plain в DER, см. Мой (крест) https://security.stackexchange.com/questions/174095/convert-ecdsa-signature-from-plain-to-der-format подход C, но Java упрощает, потому что BigInteger делает для вас половину работы:

// byte[64] plain contains the JWS-style r,s (de-base64-ed if necessary)
byte[] r = new BigInteger(1,Arrays.copyOfRange(plain,0,32)).toByteArray();
byte[] s = new BigInteger(1,Arrays.copyOfRange(plain,32,64)).toByteArray();
byte[] der = new byte[6+r.length+s.length]; der[0] = 0x30; der[1] = der.length-2; int o = 2;
der[o++] = 0x30; der[o++] = (byte)r.length; System.arraycopy (r,0, der,o, r.length); t+=r.length;
der[o++] = 0x30; der[o++] = (byte)s.length; System.arraycopy (s,0, der,o, s.length); //t+=s.length;
...