openssl command line to verify the signature
I found two solutions to your problem.
You can use rsautl that way: (with private key: my.key and public key my-pub.pem)
$ openssl rsautl -sign -inkey my.key -out in.txt.rsa -in in.txt
Enter pass phrase for my.key:
$ openssl rsautl -verify -inkey my-pub.pem -in in.txt.rsa -pubin
Bonjour
With this method, all the document is included within the signature file and is outputted by the final command.
But in my case, my certificate says: Signature Algorithm: sha1WithRSAEncryption.
So I would recommend you to use the standard way of signing document in 4 steps: (This method is used for all asymmetric electronic signatures in order not to overcharge the signature file and/or CPU usage)
- Create digest of document to sign (sender)
- Sign digest with private key (sender)
- Create digest of document to verify (recipient)
- Verify signature with public key (recipient)
OpenSSL does this in two steps:
$ openssl dgst -sha256 -sign my.key -out in.txt.sha256 in.txt
Enter pass phrase for my.key:
$ openssl dgst -sha256 -verify my-pub.pem -signature in.txt.sha256 in.txt
Verified OK
With this method, you sent the recipient two documents: the original file plain text, the signature file signed digest. Attention: the signature file does not include the whole document! Only the digest.
Generating, Signing and Verifying Digital Signature
Don’t use rsautl
for this.
According to PKCS1.5, when signing the format of the data that goes into the RSA operation looks something like this:
<padding><metadata><hash of input>
(The metadata specifies which hash function has been used.)
This format is what openssl dgst -verify
is looking for when you try to verify the signature. However this is not what you create in your steps.
First of all the default output of openssl dgst
is the hex encoding of the resulting hash, not the raw bytes.
Secondly, rsautl
is fairly “low level”, and when signing doesn’t add the metadata that openssl dgst -verify
is expecting, although it does add the padding.
These two things together mean that the data you are using looks like this:
<padding><hex digits of hash of input>
Obviously this doesn’t match what openssl dgst -verify
is expecting, so the verification fails.
It would be possible to create a correctly formatted input for rsautl
, but it would be awkward and involve dealing with ASN.1 details. You could also use rsautl -verify
instead of dgst -verify
, but that would also require a few more details and would mean you are using a non-standard signature format.
The simplest solution is to use openssl dgst
for both the creation and verification of the signature. Replace your steps 3 and 4 (except for creating the example.txt
file) with the single command:
$ openssl dgst -sha256 -sign private.pem -out example.sha256 example.txt
This hashes the data, correctly formats the hash and performs the RSA operation it. The resulting file should correctly verify with the openssl dgst -verify
command.
Digital signature for a file using openssl
Yes, the dgst and rsautl component of OpenSSL can be used to compute a signature given an RSA key pair.
Signing:
openssl dgst -sha256 data.txt > hash
openssl rsautl -sign -inkey privatekey.pem -keyform PEM -in hash >signature
Verifying just the signature:
openssl rsautl -verify -inkey publickey.pem -pubin -keyform PEM -in signature
Update: Capturing Reto's comments from below because this is an important nuance. Presumably if you are going to the trouble to verify, you want to know the signature was produced on the plaintext to which it is attached:
This might sound obvious for some but: Be aware, rsautl verify
just decrypts the file signature
. The output of this call is guaranteed to be produced by the owner of the private key, but beside that nothing else is being checked. So to actually verify the consistency of data.txt
you have to regenerate the digest and then compare it against the output of openssl rsautl -verify
.
Verifying that the owner of the private key does vouch for data.txt
:
openssl dgst -sha256 -verify publickey.pem -signature signature data.txt
For this operation, openssl requires the public key, the signature, and the message.
verifying a file signature with openssl dgst
openssl dgst -verify foo.pem
expects that foo.pem
contains the "raw" public key in PEM format. The raw format is an encoding of a SubjectPublicKeyInfo
structure, which can be found within a certificate; but openssl dgst
cannot process a complete certificate in one go.
You must first extract the public key from the certificate:
openssl x509 -pubkey -noout -in cert.pem > pubkey.pem
then use the key to verify the signature:
openssl dgst -verify pubkey.pem -signature sigfile datafile
Verifying signature created using OpenSSL with BearSSL
The signature file contents shown as
$ hexdump signature
0000000 4530 2002 ac54 51af 8ac0 cee8 dc74 4120
...
is displayed as 16-bit values.
The signature in the C program is defined as an array of 8-bit values
uint8_t signature[] = {
0x45, 0x30, 0x20, 0x02, 0xac, 0x54, 0x51, 0xaf, 0x8a, 0xc0, 0xce, 0xe8, 0xdc, 0x74, 0x41, 0x20,
...
};
Depending on the byte order this may or may not be correct. Does 4530
correspond to 45
, 30
or 30
, 45
?
With little-endian byte-order, the hex dump
4530 2002 ...
would correspond to (*)
uint8_t signature[] = {
0x30, 0x45, 0x02, 0x20, ...
};
I suggest to display the hex dump as 8-bit values, e.g. by using
od -t x1 signature
and, if necessary, fix the array initialization in the C code.
According to dave_thompson_085's comment, the correct byte order is 0x30, 0x45, so the proposed fix (*) is the solution.
And an ECDSA signature on a 256-bit group definitely starts with first tag=SEQUENCE+constructed (always 0x30) then body length usually 68 to 70 (0x44 to 0x46)
Verify Signature ECDSA signature with Openssl
The openssl dgst command "-hex" parameter means that the output is NOT binary but a hex dump of the binary output.
Quote:
-hex
digest is to be output as a hex dump. This is the default case for a
"normal" digest as opposed to a digital signature. See NOTES below for
digital signatures using -hex.
And the note section:
Hex signatures cannot be verified using openssl. Instead, use "xxd -r"
or similar program to transform the hex signature into a binary
signature prior to verification.
So if you use the -hex option for a hex dump, you need to convert it back to binary yourself somehow before passing it into openssl to verify.
Related Topics
How to Deal with the Conflict Between Activesupport::JSON and the JSON Gem
Differencebetween Integer and Fixnum
How to Decompress Gzip String in Ruby
Installing Ruby on MAC Os X 10.8.2
Ruby: How to Add "# Encoding: Utf-8" Automatically
Ruby on Rails - Drop Down Box on Change Event
How to Find the Namespace/Module Name Programmatically in Ruby on Rails
Colon (:) Appears as Forward Slash (/) When Creating File Name
How to Require Active Record Working Outside of Rails
Rails Route to Username Instead of Id
How to Use Hash Keys as Methods on a Class
Calling Another Method in Super Class in Ruby
Difference Between Truncation, Transaction and Deletion Database Strategies
How to Cancel Scheduled Job with Delayed_Job in Rails
How to Install Ruby 1.9.3 in MAC Os X Mountain Lion Without Xcode
Bundle Failing - Can't Find the Postgresql Client Library (Libpq)