Hello!
I am porting some openssl code to nettle. It involves working with SHA1 keys. What would people recommend as a guide to doing this port? I know very little about cryptography.
The code can be found here:
https://github.com/GrokImageCompression/asdcplib/blob/master/src/KM_prng.cpp
Thanks so much, Aaron
Aaron Boxer boxerab@gmail.com writes:
Hello!
I am porting some openssl code to nettle. It involves working with SHA1 keys. What would people recommend as a guide to doing this port?
[...]
https://github.com/GrokImageCompression/asdcplib/blob/master/src/KM_prng.cpp
For SHA1 and AES, start by checking the Nettle manual and the sha1 example program:
https://www.lysator.liu.se/~nisse/nettle/nettle.html#Example https://www.lysator.liu.se/~nisse/nettle/nettle.html#Conventions https://www.lysator.liu.se/~nisse/nettle/nettle.html#AES https://www.lysator.liu.se/~nisse/nettle/nettle.html#SHA1
Then your Gen_FIPS_186_Value function also uses some basic bignum arithmetic. You'd need to rewrite this to use GNU GMP, and I guess you'd want to use the C++ interface, gmpxx.h, which I'm not very familiar with. See https://gmplib.org/manual/C_002b_002b-Interface-Integers.html#C_002b_002b-In...
Not sure how to do base256 conversion (the BN_bin2bn and BN_bn2bin in openssl) in the C++ interface, you may need to use the functions mpz_import and mpz_export on the underlying C type mpz_t.
Regards, /Niels
Hi Niels,
Thanks so much for your replay. I stayed with the c interface, and I think I correctly ported most of the code, following your guides.
The only remaining issue is converting between big endian byte arrays and gmp types, but I have asked about this on the gmp forum.
Would you be able to do a quick review of the port once I am done?
Thanks again, Aaron
On Thu, May 26, 2016 at 3:16 AM, Niels Möller nisse@lysator.liu.se wrote:
Aaron Boxer boxerab@gmail.com writes:
Hello!
I am porting some openssl code to nettle. It involves working with SHA1 keys. What would people recommend as a guide to doing this port?
[...]
https://github.com/GrokImageCompression/asdcplib/blob/master/src/KM_prng.cpp
For SHA1 and AES, start by checking the Nettle manual and the sha1 example program:
https://www.lysator.liu.se/~nisse/nettle/nettle.html#Example https://www.lysator.liu.se/~nisse/nettle/nettle.html#Conventions https://www.lysator.liu.se/~nisse/nettle/nettle.html#AES https://www.lysator.liu.se/~nisse/nettle/nettle.html#SHA1
Then your Gen_FIPS_186_Value function also uses some basic bignum arithmetic. You'd need to rewrite this to use GNU GMP, and I guess you'd want to use the C++ interface, gmpxx.h, which I'm not very familiar with. See
https://gmplib.org/manual/C_002b_002b-Interface-Integers.html#C_002b_002b-In...
Not sure how to do base256 conversion (the BN_bin2bn and BN_bn2bin in openssl) in the C++ interface, you may need to use the functions mpz_import and mpz_export on the underlying C type mpz_t.
Regards, /Niels
-- Niels Möller. PGP-encrypted email is preferred. Keyid C0B98E26. Internet email is subject to wholesale government surveillance.
Aaron Boxer boxerab@gmail.com writes:
The only remaining issue is converting between big endian byte arrays and gmp types, but I have asked about this on the gmp forum.
For an example, you can also look at the nettle_mpz_to_octets and nettle_mpz_from_octets functions in https://git.lysator.liu.se/nettle/nettle/blob/master/bignum.c. If you use the mpz_ interface (not mpn_), mpz_import and mpz_export are the functions to use.
Would you be able to do a quick review of the port once I am done?
I could probably do a basic review.
Regards, /Niels
On Thu, May 26, 2016 at 9:47 AM, Niels Möller nisse@lysator.liu.se wrote:
Aaron Boxer boxerab@gmail.com writes:
The only remaining issue is converting between big endian byte arrays and gmp types, but I have asked about this on the gmp forum.
For an example, you can also look at the nettle_mpz_to_octets and nettle_mpz_from_octets functions in https://git.lysator.liu.se/nettle/nettle/blob/master/bignum.c. If you use the mpz_ interface (not mpn_), mpz_import and mpz_export are the functions to use.
Thanks, I will try this. I am also having trouble with the BN_num_bytes method. Do you know of an equivalent method in gmp ?
Would you be able to do a quick review of the port once I am done?
I could probably do a basic review.
Even a 5 minute review would be very much appreciated.
Regards, Aaron
Aaron Boxer boxerab@gmail.com writes:
Thanks, I will try this. I am also having trouble with the BN_num_bytes method. Do you know of an equivalent method in gmp ?
You'd use something like (mpz_sizeinbase(x, 2) + 7) / 8.
But in your code, don't you know the byte size a priori?
Regards, /Niels
Niels, Here is a link to my changes, if you have time to take a look.
https://github.com/GrokImageCompression/asdcplib/commit/39cbb6188bce7112d826...
Thanks again, Aaron
On Thu, May 26, 2016 at 9:47 AM, Niels Möller nisse@lysator.liu.se wrote:
Aaron Boxer boxerab@gmail.com writes:
The only remaining issue is converting between big endian byte arrays and gmp types, but I have asked about this on the gmp forum.
For an example, you can also look at the nettle_mpz_to_octets and nettle_mpz_from_octets functions in https://git.lysator.liu.se/nettle/nettle/blob/master/bignum.c. If you use the mpz_ interface (not mpn_), mpz_import and mpz_export are the functions to use.
Would you be able to do a quick review of the port once I am done?
I could probably do a basic review.
Regards, /Niels
-- Niels Möller. PGP-encrypted email is preferred. Keyid C0B98E26. Internet email is subject to wholesale government surveillance.
Aaron Boxer boxerab@gmail.com writes:
Here is a link to my changes, if you have time to take a look.
https://github.com/GrokImageCompression/asdcplib/commit/39cbb6188bce7112d826...
I've had a quick look. I'm assuming you intend to delete the commented out parts, so I'm not saying anything more about them?
src/AS_DCP_AES.cpp:
* If you use only 128-bit aes, then it's better to use the aes128_ctx and related functions. aes_ctx should be used only if for some reason you really need an interface with variable key size at runtime.
* The m_KeyBuf member variable seems useless.
* You may want to use nettle's HMAC implementation, instead of implementing it yourself.
src/KM_prng.cpp:
+ sha1_update(&SHA, sizeof(m_Context), (byte_t*)&m_Context );
This won't work, m_Context is an aes_ctx, and you'll get different results on big-endian and little-endian. Worse, it has space for more subkeys than are used for aes128, so you will hash uninitialized data. You probably want to hash the original, unexpanded, 128-bit key?
+ sha1_digest(&SHA,SHA1_DIGEST_SIZE, sha_buf);
I tend to use the style
sha1_digest (sizeof(sha_buf), sha_buf);
+ aes_set_encrypt_key(&m_Context, RNG_KEY_SIZE_BITS, sha_buf);
Size argument to aes_set_encrypt_key is in octets, not bits. (And if you use aes128_set_encrypt_key instead, as I suggest, there's no size argument).
+ aes_encrypt(&m_Context,AES128_KEY_SIZE, buf + gen_count, m_ctr_buf);
AES128_KEYSIZE here looks a bit strange. sizeof(m_ctr_buf)? (Even if the value, 16, is intentionally the same).
Delete the code computing c_2powb, and use mpz_fdiv_r_2exp instead of mpz_mod.
You don't need bn_tmp, the mpz interface allows in-place operations.
Dob't access _mp_size field, if you really want the (platform dependent) limb size, use the mpz_size function. But generally, mpz_sizeinbase is more useful.
I don't think your use of mpz_export is correct in the case that the base-256 representation has leading zeros. I think you need to handle the zero-padding yourself (or maybe the initial memset is enough? But for big-endian, you still have to know the number of leading zeros).
Regards, /Niels
Niels,
Thank you so much for taking the time to look at my code. I really do appreciate it.
I have made the modifications you suggested on AS_DCP_AES.cpp file, and pushed to github.
For KM_prng.cpp , are you suggesting that I use 128 bit AES instead of 256 bit ? I think the original code used 256 bit.
Still working on the mpz changes that you suggested.
Thanks again, Aaron
On Mon, May 30, 2016 at 9:57 AM, Niels Möller nisse@lysator.liu.se wrote:
Aaron Boxer boxerab@gmail.com writes:
Here is a link to my changes, if you have time to take a look.
https://github.com/GrokImageCompression/asdcplib/commit/39cbb6188bce7112d826...
I've had a quick look. I'm assuming you intend to delete the commented out parts, so I'm not saying anything more about them?
src/AS_DCP_AES.cpp:
If you use only 128-bit aes, then it's better to use the aes128_ctx and related functions. aes_ctx should be used only if for some reason you really need an interface with variable key size at runtime.
The m_KeyBuf member variable seems useless.
You may want to use nettle's HMAC implementation, instead of implementing it yourself.
src/KM_prng.cpp:
- sha1_update(&SHA, sizeof(m_Context), (byte_t*)&m_Context );
This won't work, m_Context is an aes_ctx, and you'll get different results on big-endian and little-endian. Worse, it has space for more subkeys than are used for aes128, so you will hash uninitialized data. You probably want to hash the original, unexpanded, 128-bit key?
- sha1_digest(&SHA,SHA1_DIGEST_SIZE, sha_buf);
I tend to use the style
sha1_digest (sizeof(sha_buf), sha_buf);
- aes_set_encrypt_key(&m_Context, RNG_KEY_SIZE_BITS, sha_buf);
Size argument to aes_set_encrypt_key is in octets, not bits. (And if you use aes128_set_encrypt_key instead, as I suggest, there's no size argument).
aes_encrypt(&m_Context,AES128_KEY_SIZE, buf + gen_count,
m_ctr_buf);
AES128_KEYSIZE here looks a bit strange. sizeof(m_ctr_buf)? (Even if the value, 16, is intentionally the same).
Delete the code computing c_2powb, and use mpz_fdiv_r_2exp instead of mpz_mod.
You don't need bn_tmp, the mpz interface allows in-place operations.
Dob't access _mp_size field, if you really want the (platform dependent) limb size, use the mpz_size function. But generally, mpz_sizeinbase is more useful.
I don't think your use of mpz_export is correct in the case that the base-256 representation has leading zeros. I think you need to handle the zero-padding yourself (or maybe the initial memset is enough? But for big-endian, you still have to know the number of leading zeros).
Regards, /Niels
-- Niels Möller. PGP-encrypted email is preferred. Keyid C0B98E26. Internet email is subject to wholesale government surveillance.
Aaron Boxer boxerab@gmail.com writes:
For KM_prng.cpp , are you suggesting that I use 128 bit AES instead of 256 bit ? I think the original code used 256 bit.
I might have misread the code. If the original code used 256-bit aes, always, you should use nettle's aes256_ctx when porting it over.
Regards, /Niels
On Mon, May 30, 2016 at 3:16 PM, Niels Möller nisse@lysator.liu.se wrote:
Aaron Boxer boxerab@gmail.com writes:
For KM_prng.cpp , are you suggesting that I use 128 bit AES instead of
256
bit ? I think the original code used 256 bit.
I might have misread the code. If the original code used 256-bit aes, always, you should use nettle's aes256_ctx when porting it over.
Niels, you were right, the code does use 128 bit encryption.
Thanks so much, Aaron
nettle-bugs@lists.lysator.liu.se