If I generate a public RSA key into a PEM file and then base64-decode the contents (this is in Emacs):
(string-to-unibyte (base64-decode-string "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAreGA/Qky9W3izQV0kzba 7wKl/wzwxkbbQxvcUqUT1krgAbO/n1tYFjXdJZoWwbMO/qv7NRoMDY4yPWGpsQfY +PSIknAhTZVbgwXrm/wb37+hKRKax2UZ9A/Rx4vJZRYlkpvZ9LbBziseFNN7SMWW qkjBO/NeT8/I9mURDa+4RoYfT6ZwjTvt808PH7uIghk+MHAx9EMBAfafF1Jn9TqW y+Hgdqik9sZteMvCumvGK4grSwzdfPO5I05tt/0I7QVPxlXbHIk/bBsE7mpgOxur P0DAkFKtYDM7oZPBwB6X778ba2EEFKPpVIyzw/jlDPd9PB6gE6dixmax3Hlg69RI EwIDAQAB"))
I seem unable to load that as a public key (SCHARS macro == length, SDATA macro == data):
struct rsa_public_key key; rsa_public_key_init(&key); rsa_keypair_from_der (&key, NULL, 0, SCHARS (public_key), SDATA (public_key))
It keeps failing. From the docs and example it seems like that should work. Can you see what I'm doing wrong? I've spent a few hours on it and can't trace the problem. If not I will start digging into the key loading functions, but was hoping it's something obvious (and if you have a working example that would be great).
As soon as I have this working I will publish my work for review; the RSA signatures are the last piece missing.
Ted
From: Ted Zlatanov tzz@lifelogs.com Date: Sat, 05 Oct 2013 10:39:56 -0400
If I generate a public RSA key into a PEM file and then base64-decode the contents (this is in Emacs):
(string-to-unibyte (base64-decode-string "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAreGA/Qky9W3izQV0kzba 7wKl/wzwxkbbQxvcUqUT1krgAbO/n1tYFjXdJZoWwbMO/qv7NRoMDY4yPWGpsQfY +PSIknAhTZVbgwXrm/wb37+hKRKax2UZ9A/Rx4vJZRYlkpvZ9LbBziseFNN7SMWW qkjBO/NeT8/I9mURDa+4RoYfT6ZwjTvt808PH7uIghk+MHAx9EMBAfafF1Jn9TqW y+Hgdqik9sZteMvCumvGK4grSwzdfPO5I05tt/0I7QVPxlXbHIk/bBsE7mpgOxur P0DAkFKtYDM7oZPBwB6X778ba2EEFKPpVIyzw/jlDPd9PB6gE6dixmax3Hlg69RI EwIDAQAB"))
I seem unable to load that as a public key (SCHARS macro == length, SDATA macro == data):
You don't need string-to-unibyte, the result of base64-decode-string is already a unibyte string. Just use it.
On Sat, 05 Oct 2013 17:55:21 +0300 Eli Zaretskii eliz@gnu.org wrote:
EZ> You don't need string-to-unibyte, the result of base64-decode-string EZ> is already a unibyte string. Just use it.
Thanks. I was playing around with the tests to see if I had missed something :)
Ted
Ted Zlatanov tzz@lifelogs.com writes:
If I generate a public RSA key into a PEM file and then base64-decode the contents (this is in Emacs):
(string-to-unibyte (base64-decode-string "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAreGA/Qky9W3izQV0kzba
[...]
EwIDAQAB"))
rsa_keypair_from_der (&key, NULL, 0, SCHARS (public_key), SDATA (public_key))
It keeps failing. From the docs and example it seems like that should work. Can you see what I'm doing wrong?
The data corresponds to (according to dumpasn1):
0 290: SEQUENCE { 4 13: SEQUENCE { 6 9: OBJECT IDENTIFIER rsaEncryption (1 2 840 113549 1 1 1) 17 0: NULL : } 19 271: BIT STRING : 30 82 01 0A 02 82 01 01 00 AD E1 80 FD 09 32 F5 : 6D E2 CD 05 74 93 36 DA EF 02 A5 FF 0C F0 C6 46 : DB 43 1B DC 52 A5 13 D6 4A E0 01 B3 BF 9F 5B 58 : 16 35 DD 25 9A 16 C1 B3 0E FE AB FB 35 1A 0C 0D : 8E 32 3D 61 A9 B1 07 D8 F8 F4 88 92 70 21 4D 95 : 5B 83 05 EB 9B FC 1B DF BF A1 29 12 9A C7 65 19 : F4 0F D1 C7 8B C9 65 16 25 92 9B D9 F4 B6 C1 CE : 2B 1E 14 D3 7B 48 C5 96 AA 48 C1 3B F3 5E 4F CF : [ Another 142 bytes skipped ] : }
Which looks ok to me. But Nettle's rsa_keypair_from_der wants the contents of that BIT STRING only, not the complete object. Hava a look at tools/pkcs1-conv.c, which I think is the only example code using these functions.
BTW, you might want to have a look at the unfinished openpgp code in Nettle (pgp.h, pgp-encode.c and rsa2openpgp.c). But it's not very useful in the current state.
Regards, /Niels
On Sat, 05 Oct 2013 18:05:37 +0200 nisse@lysator.liu.se (Niels Möller) wrote:
NM> Ted Zlatanov tzz@lifelogs.com writes:
It keeps failing. From the docs and example it seems like that should work. Can you see what I'm doing wrong?
NM> The data corresponds to (according to dumpasn1):
NM> 0 290: SEQUENCE { NM> 4 13: SEQUENCE { NM> 6 9: OBJECT IDENTIFIER rsaEncryption (1 2 840 113549 1 1 1) NM> 17 0: NULL NM> : } NM> 19 271: BIT STRING NM> : 30 82 01 0A 02 82 01 01 00 AD E1 80 FD 09 32 F5 NM> : 6D E2 CD 05 74 93 36 DA EF 02 A5 FF 0C F0 C6 46 NM> : DB 43 1B DC 52 A5 13 D6 4A E0 01 B3 BF 9F 5B 58 NM> : 16 35 DD 25 9A 16 C1 B3 0E FE AB FB 35 1A 0C 0D NM> : 8E 32 3D 61 A9 B1 07 D8 F8 F4 88 92 70 21 4D 95 NM> : 5B 83 05 EB 9B FC 1B DF BF A1 29 12 9A C7 65 19 NM> : F4 0F D1 C7 8B C9 65 16 25 92 9B D9 F4 B6 C1 CE NM> : 2B 1E 14 D3 7B 48 C5 96 AA 48 C1 3B F3 5E 4F CF NM> : [ Another 142 bytes skipped ] NM> : }
NM> Which looks ok to me. But Nettle's rsa_keypair_from_der wants the NM> contents of that BIT STRING only, not the complete object. Hava a look NM> at tools/pkcs1-conv.c, which I think is the only example code using NM> these functions.
Aha, thank you for the tip. For the tests I don't need the generic ASN1 parser, just to extract the data, so I hard-coded the bitstring offsets in nettle.el:
#+begin_src lisp ;; key generated with: ;; openssl genrsa -out privkey.pem 2048 ;; openssl rsa -in privkey.pem -pubout > pubkey.pem (let* ((key (substring " -----BEGIN PUBLIC KEY----- MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAreGA/Qky9W3izQV0kzba 7wKl/wzwxkbbQxvcUqUT1krgAbO/n1tYFjXdJZoWwbMO/qv7NRoMDY4yPWGpsQfY +PSIknAhTZVbgwXrm/wb37+hKRKax2UZ9A/Rx4vJZRYlkpvZ9LbBziseFNN7SMWW qkjBO/NeT8/I9mURDa+4RoYfT6ZwjTvt808PH7uIghk+MHAx9EMBAfafF1Jn9TqW y+Hgdqik9sZteMvCumvGK4grSwzdfPO5I05tt/0I7QVPxlXbHIk/bBsE7mpgOxur P0DAkFKtYDM7oZPBwB6X778ba2EEFKPpVIyzw/jlDPd9PB6gE6dixmax3Hlg69RI EwIDAQAB -----END PUBLIC KEY----- " 28 426)) ;; 24 skipped bytes are the header (key-bitstring (substring (base64-decode-string key) 24))) ;; invalid signature, valid key (should-not (nettle-rsa-verify "Test the Nettle RSA signature" "Test the Nettle RSA signature" key-bitstring "sha1")) ;; valid signature, valid key ; doesn't work; generated with "openssl rsautl -sign -in /tmp/test -inkey /tmp/privkey.pem" but contains other baggage (should (nettle-rsa-verify "Test the Nettle RSA signature" (decode-hex-string "abf710d920de0a210167e62995d5cb06fb0ff6a3f81e2f1965dd3f4716883ab61b7dec40d1ebde89b0657473a434d0333177f183f71a9f4b84a49781b1e4bc440e042f2eb4441000ba07168cdb190c5aebba8c433420f6fc28b6997cbfee061170210bfa65294199e6d6c8c5e1a16421942371f6115d77263b859a75645b6b70d56f14ad378c8499318ff05eda9d24a61d854a3d7f6b67b037abb8d25e4b11ca3e42bdb823cfac34c70057ecd55cbb8449346c0824b46f6c668d14f1744bad7d05470953981df32fde24d2a1f27e58bf9e7d99b20b39b25844c53945dcbbd8b406e78bc0b8aee48c0ec8a26e70301eeeb12ba733e0baf7b82c8e25ac3ee89291") key-bitstring "sha1"))) #+end_src
Take a look at the second test above; this is the signed text but it contains baggage (including the original data). This last test fails currently (all the others in nettle.el pass). Can you give me a similar hint of how to extract just the signature, for testing purposes only? The OpenSSL docs were not helpful in figuring out the structure of the signed content. In the comments I note how I generated the signature and I can post the privkey.pem file if that would help.
I have cross-posted version 1 of the patch here and to the emacs-devel mailing list for comments. I hope the Emacs C syntax is not a big impediment to your review. Later I will add the PBKDF2 rewrite you suggested, so please ignore that bit.
Most of the work has actually been in writing the tests, not the C-level integration!
(I have to note that arcfour (RC4) generates a FPE sometimes in my testing so I removed it from `test-nettle-002-ciphers'. I will file a bug separately on that if I can replicate it.)
NM> BTW, you might want to have a look at the unfinished openpgp code in NM> Nettle (pgp.h, pgp-encode.c and rsa2openpgp.c). But it's not very useful NM> in the current state.
After I finish the first-level TODO items to complete the Emacs-Nettle integration, I will certainly take a look at these files. Thanks for the pointer.
Ted
Ted Zlatanov tzz@lifelogs.com writes:
;; valid signature, valid key ; doesn't work; generated with "openssl rsautl -sign -in /tmp/test -inkey /tmp/privkey.pem" but contains other baggage (should (nettle-rsa-verify "Test the Nettle RSA signature" (decode-hex-string "abf710d920de0a210167e62995d5cb06fb0ff6a3f81e2f1965dd3f4716883ab61b7dec40d1ebde89b0657473a434d0333177f183f71a9f4b84a49781b1e4bc440e042f2eb4441000ba07168cdb190c5aebba8c433420f6fc28b6997cbfee061170210bfa65294199e6d6c8c5e1a16421942371f6115d77263b859a75645b6b70d56f14ad378c8499318ff05eda9d24a61d854a3d7f6b67b037abb8d25e4b11ca3e42bdb823cfac34c70057ecd55cbb8449346c0824b46f6c668d14f1744bad7d05470953981df32fde24d2a1f27e58bf9e7d99b20b39b25844c53945dcbbd8b406e78bc0b8aee48c0ec8a26e70301eeeb12ba733e0baf7b82c8e25ac3ee89291") key-bitstring "sha1")))
#+end_src
Take a look at the second test above; this is the signed text but it contains baggage (including the original data).
Are you sure it includes the data? If the hex string is interpreted as a raw bignum, it's 2048 bits, which sounds plausible. I guess "Test the Nettle RSA signature" is the mesage being signed? Maybe double check that you didn't get a trailing newline or something when generating the openssl signture.
I'm not very familiar with the openssl tools. What's the correct command line to let openssl verify the signature using the given public key?
Regards, /Niels
nettle-bugs@lists.lysator.liu.se