2014/03/18: Creating Signatures

We will show the different options to creating digital signatures.

Keywords: cryptography, signatures


Introduction

Signatures are used to verify that a given person has signed a given sequence of bytes. We will be using openssl to generate signatures and see what the outcome looks like.

First, let us create a new key for this sample, using:

$ openssl genrsa -out mykey.key 2048

The constituents of the key such as modulus, exponent, etc., we can show using the following command:

$ openssl rsa -text <keyfile.key

Creating the Hash

To sign a message, we need to create a hash value of the message that needs to be signed. This can be accomplished using the following command:

$ openssl dgst -sha256 <myfile
(stdin)= 06160430cd3d59a68fb4f4a5602ae8c8e2560e9645df2a618034d80ba6debad5

This displays the hash value in a human readable form which is fine for experiments but not the approach typically taken. Instead, we want to generate the hash value in binary form which can be generated with the -binary option:

$ openssl dgst -binary -sha256 <myfile >myfile.sha256
$ xxd myfile.sha256
0000000: 0616 0430 cd3d 59a6 8fb4 f4a5 602a e8c8  ...0.=Y.....`*..
0000010: e256 0e96 45df 2a61 8034 d80b a6de bad5  .V..E.*a.4......

As the hexdump shows it is the same hash, just in binary form.

Signing the Hash Value

Once we have the binary hash value, we need to sign it. openssl provides two ways of doing this which we will have a look at:

$ openssl rsautl -sign -inkey mykey.key <myfile.sha256 >myfile.sha256.sig
$ openssl sha -sha256 -sign mykey.key <myfile >myfile.sig

Verifying a Signature

Both of the above signatures can be verified using the following command:

$ openssl rsautl -raw -verify -inkey mykey.key <signature | xxd

When we apply this command to the two signature files above, we will get different output (instead of using xxd, one can also add the -hexdump command line option to openssl):

$ openssl rsautl -raw -verify -inkey mykey.key <myfile.sha256.sig | xxd
0000000: 0001 ffff ffff ffff ffff ffff ffff ffff  ................
0000010: ffff ffff ffff ffff ffff ffff ffff ffff  ................
0000020: ffff ffff ffff ffff ffff ffff ffff ffff  ................
0000030: ffff ffff ffff ffff ffff ffff ffff ffff  ................
0000040: ffff ffff ffff ffff ffff ffff ffff ffff  ................
0000050: ffff ffff ffff ffff ffff ffff ffff ffff  ................
0000060: ffff ffff ffff ffff ffff ffff ffff ffff  ................
0000070: ffff ffff ffff ffff ffff ffff ffff ffff  ................
0000080: ffff ffff ffff ffff ffff ffff ffff ffff  ................
0000090: ffff ffff ffff ffff ffff ffff ffff ffff  ................
00000a0: ffff ffff ffff ffff ffff ffff ffff ffff  ................
00000b0: ffff ffff ffff ffff ffff ffff ffff ffff  ................
00000c0: ffff ffff ffff ffff ffff ffff ffff ffff  ................
00000d0: ffff ffff ffff ffff ffff ffff ffff ff00  ................
00000e0: 0616 0430 cd3d 59a6 8fb4 f4a5 602a e8c8  ...0.=Y.....`*..
00000f0: e256 0e96 45df 2a61 8034 d80b a6de bad5  .V..E.*a.4......
$ openssl rsautl -raw -verify -inkey mykey.key <myfile.sig | xxd
0000000: 0001 ffff ffff ffff ffff ffff ffff ffff  ................
0000010: ffff ffff ffff ffff ffff ffff ffff ffff  ................
0000020: ffff ffff ffff ffff ffff ffff ffff ffff  ................
0000030: ffff ffff ffff ffff ffff ffff ffff ffff  ................
0000040: ffff ffff ffff ffff ffff ffff ffff ffff  ................
0000050: ffff ffff ffff ffff ffff ffff ffff ffff  ................
0000060: ffff ffff ffff ffff ffff ffff ffff ffff  ................
0000070: ffff ffff ffff ffff ffff ffff ffff ffff  ................
0000080: ffff ffff ffff ffff ffff ffff ffff ffff  ................
0000090: ffff ffff ffff ffff ffff ffff ffff ffff  ................
00000a0: ffff ffff ffff ffff ffff ffff ffff ffff  ................
00000b0: ffff ffff ffff ffff ffff ffff ffff ffff  ................
00000c0: ffff ffff ffff ffff ffff ffff 0030 3130  .............010
00000d0: 0d06 0960 8648 0165 0304 0201 0500 0420  ...`.H.e....... 
00000e0: 0616 0430 cd3d 59a6 8fb4 f4a5 602a e8c8  ...0.=Y.....`*..
00000f0: e256 0e96 45df 2a61 8034 d80b a6de bad5  .V..E.*a.4......

By supplying the -raw command line option, we also seeing the bytes with which the signature was padded before it has been encrypted.

The difference in the two output files comes from the fact that the first one does not encode the hash algorithm which was used to generate the hash value. One explanation is that the openssl rsautl function does not know it (also there is no command line option to supply this) whereas the second one supplies this information. More precisely, the second one encodes the algorithm and the hash value into an ASN.1 string. We can have a look at this using the following command:

openssl rsautl -verify -inkey mykey.key -asn1parse <myfile.sig
    0:d=0  hl=2 l=  49 cons: SEQUENCE          
    2:d=1  hl=2 l=  13 cons:  SEQUENCE          
    4:d=2  hl=2 l=   9 prim:   OBJECT            :sha256
   15:d=2  hl=2 l=   0 prim:   NULL              
   17:d=1  hl=2 l=  32 prim:  OCTET STRING      
      0000 - 06 16 04 30 cd 3d 59 a6-8f b4 f4 a5 60 2a e8 c8   ...0.=Y.....`*..
      0010 - e2 56 0e 96 45 df 2a 61-80 34 d8 0b a6 de ba d5   .V..E.*a.4......

Generally speaking, the second version should be preferred because otherwise clients do not know what precisely has been signed with the user's private key.

A synonym for the second option is the following command:

openssl dgst -sha256 -sign mykey.key <myfile >myfile.sig

Thomas Gschwind