Newby needs help from an OpenSSL expert

Dear friends,

Thank you for reading this post.

Please download files here: http://www.idanfe.com/dl/files.zip

This is my problem:

I have to sign a file like my teste1.txt

One sample signed file is example.txt

I am also including a private key I generated called private.pem, and its public key: public.pem

Please notice at the end of the example.txt file the string:

EAD4D714CF40A31A2AE3A26A5295082089EC554B51A4B307F044AC84BEC9A34223A11A3B64BE4DB4DE7DDBFF06D3394499A6A55C74D0AB24343589FCDE9CB0AC989AE451B2C15AFF7689368A16499C67DC9076A69DACCA38A73B4EDCA3ACA15AD06800EE74CCEB36864C408C0CAB46593774F1979A8345B4327A55C19D1C4D4EEBD

Please notice that the "EAD" is present in all files and is not part of the signature, I have to place the signature as "EAD" + signature.

These are the instructions I have from the standart written by the brazilian taxing department:

---- begins Google translation ----

TECHNICAL DATA FOR THE GENERATION OF DIGITAL SIGNATURE

The digital signature should be generated by the following:

1 - apply the MD5 one-way function only once in the entire file, except for the EAD record. The result is a code of 128 bits or 16 ASCII characters, corresponding to a 32-digit hexadecimal numbers. Should be used in the calculations the hexadecimal number, considering it as a single block;

2 - create a private key of 1024 bits, equivalent to a 256-digit hexadecimal number, known only to the company developing the PAF-ECF;

3 - encrypt the hexadecimal code generated as provided in item 1, using the key referred to in item 2, the RSA public key algorithm;

---- ends google translation -----

(ITEM 1)

I think I have been able to generate item 1 by submitting to shell the following command:

md5 teste1.txt

And as a result I have:

867af78828b9dfdc8cfc52211571399e

I have a GUI tool given to me running under windows to do the job, and it results in:

867AF78828B9DFDC8CFC52211571399E

So, I guess I am correct on item number 1.

(ITEM 2)

I ran this command on shell:

openssl rsa -in private.pem -modulus -out modulo.txt

It resulted me the string:

A01386F3AB113FABC633EE9E95B0E4B5BB1057D3AEFCE7CF859D03FA9B356B902550A6BDFBBA55480CBA99D0C487CE4B74214757BBBD596D5B8F41E84E158C110150F42F107FBECFB774F6A8FDF853DE70516BC088F551B020AB9B921A270D8038AB77227545FBC28331906FBAEEDD2CC1848455524D874762ABD90128BD60E3

So I think, I have done step 2 so far...

(ITEM 3)

I simply am stuck here, don't know what to do now.

I have a tool running under windows that when I submit my private key and teste1.txt to it, and gives me:

953F2F56387ACBF724A7D6BF565A4FAA274214CBC70190330FD9FED7F65474306A3356E6129444A0971DA561282BC1786FFC0C968EBB4411053A3265EC6C1A683CDD0D4BD21862A4DB29D4F2B7F628BAC0354F9B04174952287E51CA48993DB3C1292310AEF0419FD55162B41145A3F77ACFD0FC889E778E0A1A21A661C3786E

Can someone be so kind to help me with this?

How can I obtain the same string using openssl?

I understand I have to use the md5 result from teste1.txt and the modulus result, but have no idea on what command to send to shell.

Thank you for reading this,

I think the output for 1 needs to be the binary digits of the checksum, because they are after 16 ASCII characters representing the 32 digit HEX number, so:

openssl md5 -binary teste1.txt

I would of thought that this is what you need, but the output dosn't match your GUI tool:

$ openssl md5 -binary teste1.txt | openssl rsautl -sign -inkey private.pem -hexdump
0000 - 68 2e e5 27 6d 96 2e f3-9f 9b 4d e7 7e a4 5c 48   h..'m.....M.~.\H
0010 - 5e 62 b1 62 18 11 d8 34-10 f8 c7 58 24 72 61 16   ^b.b...4...X$ra.
0020 - 9c 21 2c 06 70 67 7d 24-85 0e b3 64 ed 81 5b 9e   .!,.pg}$...d..[.
0030 - 27 fc 84 f6 3a e7 3b 10-bc ae 39 b9 94 5e 19 86   '...:.;...9..^..
0040 - 6c d9 70 f5 50 6e 73 d4-90 9b 7b bd 64 93 67 14   l.p.Pns...{.d.g.
0050 - 2b 21 7e c7 7d 8b 05 49-4c c9 33 dd d1 29 0a dd   +!~.}..IL.3..)..
0060 - ac a8 11 be 8c bd 65 aa-35 dc b0 58 dc c5 dd 09   ......e.5..X....
0070 - 38 16 46 fe 23 79 8b 1b-fc c5 a4 71 2d d6 31 4c   8.F.#y.....q-.1L

Some final od / awk tricks to get the hex string:

$ openssl md5 -binary teste1.txt | openssl rsautl -sign -inkey private.pem | od -h -w2 | awk '{o=o substr($2,3) substr($2,1,2)} END { print toupper(o)}'
682EE5276D962EF39F9B4DE77EA45C485E62B1621811D83410F8C758247261169C212C0670677D24850EB364ED815B9E27FC84F63AE73B10BCAE39B9945E19866CD970F5506E73D4909B7BBD649367142B217EC77D8B05494CC933DDD1290ADDACA811BE8CBD65AA35DCB058DCC5DD09381646FE23798B1BFCC5A4712DD6314C

---------- Post updated 10-08-12 at 12:44 AM ---------- Previous update was 09-08-12 at 12:12 PM ----------

OK I have a solution - seems the data is padded in a funny way first byte is the datalength and then padded with zeros to 128 chars:

xxd -r -ps gui.out | openssl rsautl -verify -raw -inkey public.pem -pubin | xxd -ps -u
10867AF78828B9DFDC8CFC52211571399E00000000000000000000000000
000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000
0000000000000000

I'm not that good with openssl so I don't know if there is an option to pad like this.

Anyway this script builds the correct data block using xxd (from vim) and awk,
then signs this directly with the openssl -raw option. Again using xxd to produce final output of 1 long string of HEX digits:

$ openssl md5 -hex teste1.txt | awk '{i=length($2)/2; printf "%02x%s", i, $2;
i=128-i; for(;--i;) printf "00" }' | xxd -r -ps | openssl rsautl -sign -raw -inkey private.pem | xxd -ps -u -c 256
953F2F56387ACBF724A7D6BF565A4FAA274214CBC70190330FD9FED7F654
74306A3356E6129444A0971DA561282BC1786FFC0C968EBB4411053A3265
EC6C1A683CDD0D4BD21862A4DB29D4F2B7F628BAC0354F9B04174952287E
51CA48993DB3C1292310AEF0419FD55162B41145A3F77ACFD0FC889E778E
0A1A21A661C3786

Note: I've folded the output above so it displays better. If you don't have vim I might be able to build a solution using pure awk.

Helo Chubler_XL,

You saved my life, many, many thanks...

Your most welcome. Since md5 sums are always 16 chars we can just put 16 (20 octal) on the front and 111 zeros on the back.

Here is a simplier pipeline solution that dosn't need xxd:

( printf "\020" ;
  openssl md5 -binary teste1.txt
  for ((i=17;i<128;i++)) { printf "\0"; }
) | openssl rsautl -sign -raw -hexdump -inkey private.pem |
awk '{gsub(/-/," ");for(i=3;i<18;i++) printf "%s", toupper($i)}'

Dear Chubler, I sent you a private message. Please check.