Search code examples
javarsadigital-signaturexml-signaturersa-sha256

Get the sha1-hashed value from XML signature value


I need someone to help me understand XML digital signature method rsa-sha1. I suppose the signature value = RSA-encrypt(sha1(signedInfo), privatekey).

Note Base64.encode(sha1(signedInfo)) contains 28 characters. So I think Base64.encode(RSA-decrypt(signaturevalue), publickey) should return 28 characters as well. However, I actually got a 48-character string.

Base64 base64 = new Base64();
byte[] encrypted = base64.decode(signatureValue);
try {
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.DECRYPT_MODE, getX509Cert().getPublicKey());
        byte[] cipherText = cipher.doFinal(encrypted);

        System.out.println(base64.encodeToString(cipherText));
        //print out MCEwCQYFKw4DAhoFAAQU0G+7jFPydS/sWGO1QPjB0v3XTz4=
        //which contains 48 characters. 
 }
 catch (Exception ex){
    ex.printStackTrace();
 }

Signature method as indicated in XML file

<ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>

Solution

  • RSA signing is not actually the same as encrypting with the private key, but JCE promotes this mistake by allowing 'backwards' operations in Cipher for RSA (only) which actually do PKCS1-v1_5 signature and recovery instead of encryption and decryption as they were designed to.

    For the original standardized RSA signature scheme in PKCS1 through v1.5, now retronymed RSASSA-PKCS1-v1_5, the value that is padded (with 'type' 01 multiple FFs and one 00) and modexp'ed with the private key is not just the hash but an ASN.1 structure containing the hash. See the encoding operation EMSA-PKCS1-v1_5 in section 9.2 of rfc8017 or rfc3447 or 9.2.1 in rfc2437, especially step 2 and (for the newer two versions) 'Notes' item 1.

    Dupe Using SHA1 and RSA with java.security.Signature vs. MessageDigest and Cipher
    and Separate digest & signing using java security provider