When you issue openssl dgst -sign key <file it follows the PKCS#1 standard to generate a digital signature.

  1. hash file with some hash digest function
  2. encode the hashed value in DER format, specifying the hash function used, and the hash function used.
  3. sign the actual binary DER data with RSA PKCS#1, which pads it if needed.

I want to do these actions step by step with the openssl command line.

I can use openssl dgst <file to generate a hash.

I can use openssl rsautl -sign -inkey key -in file to generate RSA signature for file, and pad it correctly.

But I don't know how to take the hash, and encode it with the appropriate DER format. Is that possible?

1 Answer 1


The ASN.1 structure we are talking about here is:

DigestInfo ::= SEQUENCE {
    digestAlgorithm  AlgorithmIdentifier,
    digest           OCTET STRING

AlgorithmIdentifier ::= SEQUENCE {
    algorithm        OBJECT IDENTIFIER,
    parameters       ANY DEFINED BY algorithm OPTIONAL

When encoded in DER, the actual hash value (the raw bytes) will be located at the very end of the encoded structure. So the DER encoding of the structure, for a given hash function, is equivalent to concatenating a fixed string of bytes with the hash value. The string of bytes for various hash functions are given in extenso in PKCS#1 (section 9.2, page 38 of version 2.1 of the standard).

So, on a Unix-like system, to get from hash value contained in file hash-value.bin to the DER-encoded structure specifying SHA-256, you would do this:

(printf '\x30\x31\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x01\x05\x00\x04\x20' ; cat hash-value.bin) > encoded-hash.der

The Devil hides in the details, and ASN.1 is so much full of details that it should rightfully be burnt at the stake. In this case, notice how the parameters field is marked OPTIONAL. In a much older version of another standard, a typographic error resulted in the omission of that keyword; hence, some implementers found it that they had to include some parameters, even so the OID was enough to designate the hash function. Hence, they added an ASN.1 NULL value as parameters (it shows as the 0x05 0x00 bytes in the encoded headers). However, some later implementers found it fit to "correct" the issue and omit the unneeded parameters altogether, as is permitted by the OPTIONAL keyword. The bottom-line is the following: for a given hash function, there are two versions of the "fixed header string" to be concatenated with the hash value. For instance, for SHA-256, PKCS#1 says that the header is:

30 31 30 0d 06 09 60 86 48 01 65 03 04 02 01 05 00 04 20

but one may also encounter this alternate header:

30 2f 30 0b 06 09 60 86 48 01 65 03 04 02 01 04 20

which some implementation use. According to PKCS#1, you shall use the first one when producing signature, but you also shall accept both when verifying signatures.

  • So, no way for openssl to generate the header for me, or at least do openssl derseq file1 file2. Bummer, but thanks. Jan 16, 2012 at 16:43

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .