En/Decrypt Mismatch: Command-Line Tool vs. Crypt::OpenSSL::RSA

Discussion in 'Perl Misc' started by Jerry Krinock, Aug 14, 2008.

  1. I posted this to openssl-users-at-openssl.org a couple days ago but no
    one seems to know the answer.

    I cannot get RSA-encrypted messages which I generate using
    Crypt::OpenSSL::RSA to decrypt using the openssl command-line tool.
    It may be something easy/stupid since I am a new openssl user.

    Attempting to cut the problem in half, I then did another experiment
    to see if they would generate the same signature. They don't. So I
    conclude that the problem is in the ENcrypting. I gave both
    encryptors (Crypt::OpenSSL::RSA and openssl command) the...

    Same message
    Same private key
    Same padding (PKCS1)
    Same digest (SHA1)
    Both running on same Macintosh, presumably using the same
    OpenSSL version 0.9.7l library in Mac OS X 10.5.4.

    Here are my commands/code and results, starting with the command-line:

    ###############################################################
    # Create a private key
    Jerrys-Mac-Mini: jk$ openssl genrsa -out Test248.private.pem
    Generating RSA private key, 512 bit long modulus
    ..........++++++++++++
    ..............++++++++++++
    e is 65537 (0x10001)

    # Create signature of message "Bonehead" using the key in file
    # Test248.private.pem, SHA1 digest and PKCS padding [1]:

    Jerrys-Mac-Mini: jk$ echo -n "Bonehead" \
    | openssl dgst -sha1 -binary\
    | openssl rsautl -pkcs -sign -inkey Test248.private.pem -hexdump
    0000 - 8a c6 56 19 97 f5 e7 16-20 30 f2 2f 0e af 7c 28
    0010 - df 9d cd 5a 0e b0 11 c1-cc bb f2 3b 03 87 f0 96
    0020 - 0d ce b4 55 dc 69 81 bc-30 40 75 9d 74 b8 b7 bd
    0030 - 3b 15 a0 5d c2 db ab 9a-8d d3 f2 4b 77 e1 e9 a1
    ##############################################################

    Now I try to create the same signature using a perl script:

    ##############################################################
    #!/usr/local/bin/perl -w

    use strict ;
    use warnings ;

    use Crypt::OpenSSL::Random ;
    use Crypt::OpenSSL::RSA ;

    # Read in the key file just created
    my $private_key_string = "" ;
    my $key_path = "/Users/jk/Documents/SheepSystems/Keys/
    Test248.private.pem" ;
    open (KEY_FILE, $key_path) ;
    while (my $line = <KEY_FILE>) {
    $private_key_string .= $line ;
    }
    close(KEY_FILE);

    print "Read key from file:\n$private_key_string\n" ;

    my $rsa_priv = Crypt::OpenSSL::RSA-
    >new_private_key($private_key_string);


    # Use same message, padding and digest as in the command-line test
    my $msg = "Bonehead" ;
    $rsa_priv->use_pkcs1_padding();
    $rsa_priv->use_sha1_hash() ;

    my $signature = $rsa_priv->sign($msg);
    my $showHexSig = showHex($signature) ;
    print "signature of 'Bonehead':\n$showHexSig\n" ;

    # sub showHex is shown at the bottom of this message
    ##############################################################

    Running the above script, I get this:

    ##############################################################
    Read key from file:
    -----BEGIN RSA PRIVATE KEY-----
    MIIBOgIBAAJBALE2d5DpKbYxfIqv+6jYnW6DDvDyJFCdQt+s432GQsy8+ymL9DOR
    mPcRQfk1jas1pqtsy+GGUlYd4R1kxbBZb4UCAwEAAQJANqtw83ma7qQRoc9sucgp
    uUAhSd/JqDz7tnllrQHQdcyLMRSCBxvZ/i72YVixRRTHb1GVZ79iJWBmzh8ATLvj
    uQIhAOuYWu6Vkve+zQ4Cd5EGWpytY/Or/6ZXvQf3L9ELIB07AiEAwI+miVT8t22w
    Ge1IX+Q3L7lK2uBm97Pkwix9Wf7K2j8CIFUrQtQ1ZmgBpgeGhMr8zQ0O8a9JYqYz
    2bZjefnMV9O5AiEAqSrKLKYcKm1To0NhLNUKYoPPLkCsVPqWgruhGDoOLfMCIE1E
    kpJF13Dtq3KQOsaCoXbL4vo350vkBUrSovu45/6p
    -----END RSA PRIVATE KEY-----

    signature of 'Bonehead':
    64 bytes:
    78 b3 43 22 4b 4b 86 7f 47 25 00 f1 62 a2 66 70
    e6 7e 82 f2 7a b6 cf ff ab dd f1 8a ff 0d cf a1
    b5 3d 60 dc ac 9f 6f 0c 83 b9 51 c9 ac fa 7d 15
    0b cc 97 cf 99 e5 6b ee 41 f0 d1 35 a1 a0 c1 09
    ##############################################################

    As you can see the two signatures are both 64 bytes long but do not
    match.

    What might I be missing?

    Thanks very much,

    Jerry Krinock

    [1] The reason I used PKCS padding (-pkcs) is because if I change it
    to -oaep in the command-line test, I get an error message:
    RSA operation error
    error:04066076:rsa routines:RSA_EAY_PRIVATE_ENCRYPT:unknown padding
    type:rsa_eay.c:360:
    which does not make sense because my version is:
    Jerrys-Mac-Mini:Keys jk$ openssl
    OpenSSL> version
    OpenSSL 0.9.7l 28 Sep 2006
    and "RSA_padding_add_PKCS1_OAEP() and RSA_padding_check_PKCS1_OAEP()
    were added in OpenSSL 0.9.2b" according to documentation:
    http://openssl.org/docs/crypto/RSA_padding_add_PKCS1_type_1.html#

    [2]
    sub showHex {
    my $data = shift ;
    use bytes ;
    my $len = length($data) ;
    my $i ;
    my $show = "" ;
    for ($i=0; $i<$len; $i++) {
    my $value = ord(substr($data, $i, 1)) ;
    $show .= " " ;
    $show .= sprintf("%02x", $value) ;
    if ((($i+1) % 16) == 0) {
    $show .= "\n" ;
    }
    }

    return "$len bytes:\n$show" ;
    }
    Jerry Krinock, Aug 14, 2008
    #1
    1. Advertising

  2. Well, I got this working, although I there are several things that
    don't seem to work they way they should. Short summary: Must use
    perl function private_encrypt() instead of sign(), even though, to
    generate the same signature, the command-line tool must use -sign.
    Must use the SHA1 digest generated by command-line tool, since
    $rsa_priv->use_sha1_hash() has no effect on private_encrypt().

    I don't understand this well enough to say that these are bugs. More
    comments are in the code in case anyone is interested.

    Here are my revised commands/code and working results, starting with
    the command-line:

    ###############################################################
    # Create a private key
    jk$ openssl genrsa -out Test248.private.pem
    Generating RSA private key, 512 bit long modulus
    ..........++++++++++++
    ..............++++++++++++
    e is 65537 (0x10001)

    # Create SHA1 digest of message "Bonehead".
    # The, write digest to file for later use by perl script.
    # Finally, sign the digest using the key in file Test248.private.pem
    # and PKCS padding. Why PKCS? See note [1].
    echo -n "Bonehead" > clearMsg.txt
    openssl dgst -sha1 -binary -out msgDigest clearMsg.txt
    cat msgDigest | openssl rsautl -pkcs -sign -inkey Test248.private.pem -
    hexdump

    0000 - 8a c6 56 19 97 f5 e7 16-20 30 f2 2f 0e af 7c 28
    0010 - df 9d cd 5a 0e b0 11 c1-cc bb f2 3b 03 87 f0 96
    0020 - 0d ce b4 55 dc 69 81 bc-30 40 75 9d 74 b8 b7 bd
    0030 - 3b 15 a0 5d c2 db ab 9a-8d d3 f2 4b 77 e1 e9 a1
    ##############################################################

    Now create the same signature using a Crypt::OpenSSL in Perl:

    ##############################################################
    #!/usr/local/bin/perl -w

    use strict ;
    use warnings ;

    use Crypt::OpenSSL::Random ;
    use Crypt::OpenSSL::RSA ;

    # Read in key from file
    my $private_key_string = "" ;
    my $key_path = "/Users/jk/Documents/SheepSystems/Keys/
    Test248.private.pem" ;
    open (KEY_FILE, $key_path) ;
    while (my $line = <KEY_FILE>) {
    $private_key_string .= $line ;
    }
    close(KEY_FILE);
    print "Read key from file:\n$private_key_string\n" ;

    my $rsa_priv = Crypt::OpenSSL::RSA-
    >new_private_key($private_key_string);


    $rsa_priv->use_pkcs1_padding() ;
    =com
    Padding is a big mystery.
    The above affects encrypting with the private key
    but does not affect signature generation. As a matter of
    fact, it is necessary when using the private_encrypt()
    method. Without the above, private_encrypt() will fail
    with error. I believe the problem is that OpenSSL does not
    support oaep padding for signing, which is what you're
    doing when you encrypt with the private key, despite doc to
    the contrary. See note [2].
    =cut


    # $rsa_priv->use_sha1_hash() ;
    # The above has no effect on the output of the
    # private_encrypt() method. So, I don't use it.

    my $output ;
    my $outputHex ;


    my $msgDigest ;
    my $msgDigest_path = "/Users/jk/Documents/SheepSystems/Keys/
    msgDigest" ;
    open (MSG_DIGEST_FH, $msgDigest_path) ;
    # SHA1 Digest is 20 bytes...
    read MSG_DIGEST_FH, $msgDigest, 20 ;
    close(MSG_DIGEST_FH) ;
    $output = $rsa_priv->private_encrypt($msgDigest);
    # If you use sign() instead of private_encrypt()
    # above you get a different output. This does not make sense
    # to me because I thought that signing was the same as
    # encrypting with the private key.
    $outputHex = showHex($output) ;
    print "privately encrypted msgDigest:\n$outputHex\n" ;

    # sub showHex is shown at the bottom of this message
    ##############################################################

    Running the above script, I get this:

    ##############################################################
    Read key from file:
    -----BEGIN RSA PRIVATE KEY-----
    MIIBOgIBAAJBALE2d5DpKbYxfIqv+6jYnW6DDvDyJFCdQt+s432GQsy8+ymL9DOR
    mPcRQfk1jas1pqtsy+GGUlYd4R1kxbBZb4UCAwEAAQJANqtw83ma7qQRoc9sucgp
    uUAhSd/JqDz7tnllrQHQdcyLMRSCBxvZ/i72YVixRRTHb1GVZ79iJWBmzh8ATLvj
    uQIhAOuYWu6Vkve+zQ4Cd5EGWpytY/Or/6ZXvQf3L9ELIB07AiEAwI+miVT8t22w
    Ge1IX+Q3L7lK2uBm97Pkwix9Wf7K2j8CIFUrQtQ1ZmgBpgeGhMr8zQ0O8a9JYqYz
    2bZjefnMV9O5AiEAqSrKLKYcKm1To0NhLNUKYoPPLkCsVPqWgruhGDoOLfMCIE1E
    kpJF13Dtq3KQOsaCoXbL4vo350vkBUrSovu45/6p
    -----END RSA PRIVATE KEY-----

    privately encrypted msgDigest:
    64 bytes:
    8a c6 56 19 97 f5 e7 16 20 30 f2 2f 0e af 7c 28
    df 9d cd 5a 0e b0 11 c1 cc bb f2 3b 03 87 f0 96
    0d ce b4 55 dc 69 81 bc 30 40 75 9d 74 b8 b7 bd
    3b 15 a0 5d c2 db ab 9a 8d d3 f2 4b 77 e1 e9 a1

    ##############################################################

    which matches the output from the command-line openssl.

    Thanks for reading. If anyone can explain some of the anomalies
    noted, let us know.

    Jerry


    [1] The reason I used PKCS padding (-pkcs) is because if I change it
    to -oaep in the command-line test, I get an error message:
    RSA operation error
    error:04066076:rsa routines:RSA_EAY_PRIVATE_ENCRYPT:unknown padding
    type:rsa_eay.c:360:
    which does not make sense because my version is:

    Jerrys-Mac-Mini:Keys jk$ openssl
    OpenSSL> version
    OpenSSL 0.9.7l 28 Sep 2006

    and "RSA_padding_add_PKCS1_OAEP() and RSA_padding_check_PKCS1_OAEP()
    were added in OpenSSL 0.9.2b" according to documentation:
    http://openssl.org/docs/crypto/RSA_padding_add_PKCS1_type_1.html#

    [2]
    sub showHex {
    my $data = shift ;
    use bytes ;
    my $len = length($data) ;
    my $i ;
    my $show = "" ;
    for ($i=0; $i<$len; $i++) {
    my $value = ord(substr($data, $i, 1)) ;
    $show .= " " ;
    $show .= sprintf("%02x", $value) ;
    if ((($i+1) % 16) == 0) {
    $show .= "\n" ;
    }
    }

    return "$len bytes:\n$show" ;
    }
    Jerry Krinock, Aug 20, 2008
    #2
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. AdrianK
    Replies:
    0
    Views:
    1,533
    AdrianK
    Jul 9, 2003
  2. John Bergstrom
    Replies:
    0
    Views:
    1,218
    John Bergstrom
    Aug 3, 2003
  3. Cosmia Luna
    Replies:
    4
    Views:
    324
    Cosmia Luna
    Mar 11, 2012
  4. John Bergstrom
    Replies:
    0
    Views:
    96
    John Bergstrom
    Aug 3, 2003
  5. Taylor Venable
    Replies:
    0
    Views:
    195
    Taylor Venable
    Oct 4, 2007
Loading...

Share This Page