diff --git a/ChangeLog b/ChangeLog index 852af17a1673757787bb23028f6a85e771ea719e..e38d5c7870bc76a1992c4dcda66028a416062eb8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2016-01-10 Niels Möller <nisse@lysator.liu.se> + + * nettle.texinfo (RSA): Document the rsa_pkcs1_verify and + rsa_pkcs1_sign functions, and the new rsa_*_tr functions. + 2015-12-18 Niels Möller <nisse@lysator.liu.se> * testsuite/testutils.h: Fix include order, system headers before diff --git a/nettle.texinfo b/nettle.texinfo index 1b362e29c1954fadbf68dc723edbef0a1972cb25..3af75ed63b8f2001ad6cc8a015e3571c90662be3 100644 --- a/nettle.texinfo +++ b/nettle.texinfo @@ -3537,7 +3537,7 @@ F(x) = x^e mod n I.e. raise x to the @code{e}'th power, while discarding all multiples of @code{n}. The pair of numbers @code{n} and @code{e} is the public key. @code{e} can be quite small, even @code{e = 3} has been used, although -slightly larger numbers are recommended. @code{n} should be about 1000 +slightly larger numbers are recommended. @code{n} should be about 2000 bits or larger. If @code{n} is large enough, and properly chosen, the inverse of F, @@ -3546,8 +3546,8 @@ But, where's the trapdoor? Let's first look at how @acronym{RSA} key-pairs are generated. First @code{n} is chosen as the product of two large prime numbers @code{p} -and @code{q} of roughly the same size (so if @code{n} is 1000 bits, -@code{p} and @code{q} are about 500 bits each). One also computes the +and @code{q} of roughly the same size (so if @code{n} is 2000 bits, +@code{p} and @code{q} are about 1000 bits each). One also computes the number @code{phi = (p-1)(q-1)}, in mathematical speak, @code{phi} is the order of the multiplicative group of integers modulo n. @@ -3591,6 +3591,16 @@ from the message in the same way as above. Then @code{s^e mod n} is computed, the operation returns true if and only if the result equals @code{x}. +The @acronym{RSA} algorithm can also be used for encryption. RSA encryption uses +the public key @code{(n,e)} to compute the ciphertext @code{m^e mod n}. +The @cite{PKCS#1} padding scheme will use at least 8 random and non-zero +octets, using @var{m} of the form @code{[00 02 padding 00 plaintext]}. +It is required that @code{m < n}, and therefor the plaintext must be +smaller than the octet size of the modulo @code{n}, with some margin. + +To decrypt the message, one needs the private key to compute @code{m = +c^e mod n} followed by checking and removing the padding. + @subsubsection Nettle's @acronym{RSA} support Nettle represents @acronym{RSA} keys using two structures that contain @@ -3641,17 +3651,60 @@ zero if the key can't be used, for instance if the modulo is smaller than the minimum size needed for @acronym{RSA} operations specified by PKCS#1. @end deftypefun +For each operation using the private key, there are two variants, e.g., +@code{rsa_sha256_sign} and @code{rsa_sha256_sign_tr}. The former +function is older, and it should be avoided, because it provides no +defenses against side-channel attacks. The latter function use +randomized @acronym{RSA} blinding, which defends against timing attacks +using chosen-ciphertext, and it also checks the correctness of the +private key computation using the public key, which defends against +software or hardware errors which could leak the private key. + Before signing or verifying a message, you first hash it with the appropriate hash function. You pass the hash function's context struct to the @acronym{RSA} signature function, and it will extract the message digest and do the rest of the work. There are also alternative functions -that take the hash digest as argument. +that take the hash digest as argument. There is currently no support for using SHA224 or SHA384 with @acronym{RSA} signatures, since there's no gain in either computation time nor message size compared to using SHA256 and SHA512, respectively. -Creation and verification of signatures is done with the following functions: +Creating an @acronym{RSA} signature is done with one of the following +functions: + +@deftypefun int rsa_md5_sign_tr(const struct rsa_public_key *@var{pub}, const struct rsa_private_key *@var{key}, void *@var{random_ctx}, nettle_random_func *@var{random}, struct md5_ctx *@var{hash}, mpz_t @var{signature}) +@deftypefunx int rsa_sha1_sign_tr(const struct rsa_public_key *@var{pub}, const struct rsa_private_key *@var{key}, void *@var{random_ctx}, nettle_random_func *@var{random}, struct sha1_ctx *@var{hash}, mpz_t @var{signature}) +@deftypefunx int rsa_sha256_sign_tr(const struct rsa_public_key *@var{pub}, const struct rsa_private_key *@var{key}, void *@var{random_ctx}, nettle_random_func *@var{random}, struct sha256_ctx *@var{hash}, mpz_t @var{signature}) +@deftypefunx int rsa_sha512_sign_tr(const struct rsa_public_key *@var{pub}, const struct rsa_private_key *@var{key}, void *@var{random_ctx}, nettle_random_func *@var{random}, struct sha512_ctx *@var{hash}, mpz_t @var{signature}) +The signature is stored in @var{signature} (which must have been +@code{mpz_init}'ed earlier). The hash context is reset so that it can be +used for new messages. The @var{random_ctx} and @var{random} pointers +are used to generate the @acronym{RSA} blinding. Returns one on success, +or zero on failure. Signing fails if an error in the computation was +detected, or if the key is too small for the given hash size, e.g., it's +not possible to create a signature using SHA512 and a 512-bit +@acronym{RSA} key. +@end deftypefun + +@deftypefun int rsa_md5_sign_digest_tr(const struct rsa_public_key *@var{pub}, const struct rsa_private_key *@var{key}, void *@var{random_ctx}, nettle_random_func *@var{random}, const uint8_t *@var{digest}, mpz_t @var{signature}) +@deftypefunx int rsa_sha1_sign_digest_tr(const struct rsa_public_key *@var{pub}, const struct rsa_private_key *@var{key}, void *@var{random_ctx}, nettle_random_func *@var{random}, const uint8_t *@var{digest}, mpz_t @var{signature}) +@deftypefunx int rsa_sha256_sign_digest_tr(const struct rsa_public_key *@var{pub}, const struct rsa_private_key *@var{key}, void *@var{random_ctx}, nettle_random_func *@var{random}, const uint8_t *@var{digest}, mpz_t @var{signature}) +@deftypefunx int rsa_sha512_sign_digest_tr(const struct rsa_public_key *@var{pub}, const struct rsa_private_key *@var{key}, void *@var{random_ctx}, nettle_random_func *@var{random}, const uint8_t *@var{digest}, mpz_t @var{signature}) +Creates a signature from the given hash digest. @var{digest} should +point to a digest of size @code{MD5_DIGEST_SIZE}, +@code{SHA1_DIGEST_SIZE}, @code{SHA256_DIGEST_SIZE}, or +@code{SHA512_DIGEST_SIZE}respectively. The signature is stored in +@var{signature} (which must have been @code{mpz_init}:ed earlier). +Returns one on success, or zero on failure. +@end deftypefun + +@deftypefun int rsa_pkcs1_sign_tr(const struct rsa_public_key *@var{pub}, const struct rsa_private_key *@var{key}, void *@var{random_ctx}, nettle_random_func *@var{random}, size_t @var{length}, const uint8_t *@var{digest_info}, mpz_t @var{signature}) +Similar to the above @code{_sign_digest_tr} functions, but the input is not the +plain hash digest, but a PKCS#1 ``DigestInfo'', an ASN.1 DER-encoding +of the digest together with an object identifier for the used hash +algorithm. +@end deftypefun @deftypefun int rsa_md5_sign (const struct rsa_private_key *@var{key}, struct md5_ctx *@var{hash}, mpz_t @var{signature}) @deftypefunx int rsa_sha1_sign (const struct rsa_private_key *@var{key}, struct sha1_ctx *@var{hash}, mpz_t @var{signature}) @@ -3669,13 +3722,23 @@ it's not possible to create a signature using SHA512 and a 512-bit @deftypefunx int rsa_sha1_sign_digest (const struct rsa_private_key *@var{key}, const uint8_t *@var{digest}, mpz_t @var{signature}); @deftypefunx int rsa_sha256_sign_digest (const struct rsa_private_key *@var{key}, const uint8_t *@var{digest}, mpz_t @var{signature}); @deftypefunx int rsa_sha512_sign_digest (const struct rsa_private_key *@var{key}, const uint8_t *@var{digest}, mpz_t @var{signature}); -Creates a signature from the given hash digest. @var{digest} should -point to a digest of size @code{MD5_DIGEST_SIZE}, -@code{SHA1_DIGEST_SIZE}, or @code{SHA256_DIGEST_SIZE}, respectively. The -signature is stored in @var{signature} (which must have been +Creates a signature from the given hash digest; otherwise analoguous to +the above signing functions. @var{digest} should point to a digest of +size @code{MD5_DIGEST_SIZE}, @code{SHA1_DIGEST_SIZE}, +@code{SHA256_DIGEST_SIZE}, or @code{SHA512_DIGEST_SIZE}, respectively. +The signature is stored in @var{signature} (which must have been @code{mpz_init}:ed earlier). Returns one on success, or zero on failure. @end deftypefun +@deftypefun int rsa_pkcs1_sign(const struct rsa_private_key *@var{key}, size_t @var{length}, const uint8_t *@var{digest_info}, mpz_t @var{s}) +Similar to the above _sign_digest functions, but the input is not the +plain hash digest, but a PKCS#1 ``DigestInfo'', an ASN.1 DER-encoding +of the digest together with an object identifier for the used hash +algorithm. +@end deftypefun + +Verifying an RSA signature is done with one of the following functions: + @deftypefun int rsa_md5_verify (const struct rsa_public_key *@var{key}, struct md5_ctx *@var{hash}, const mpz_t @var{signature}) @deftypefunx int rsa_sha1_verify (const struct rsa_public_key *@var{key}, struct sha1_ctx *@var{hash}, const mpz_t @var{signature}) @deftypefunx int rsa_sha256_verify (const struct rsa_public_key *@var{key}, struct sha256_ctx *@var{hash}, const mpz_t @var{signature}) @@ -3688,17 +3751,18 @@ the hash context is reset so that it can be used for new messages. @deftypefunx int rsa_sha1_verify_digest (const struct rsa_public_key *@var{key}, const uint8_t *@var{digest}, const mpz_t @var{signature}) @deftypefunx int rsa_sha256_verify_digest (const struct rsa_public_key *@var{key}, const uint8_t *@var{digest}, const mpz_t @var{signature}) @deftypefunx int rsa_sha512_verify_digest (const struct rsa_public_key *@var{key}, const uint8_t *@var{digest}, const mpz_t @var{signature}) -Returns 1 if the signature is valid, or 0 if it isn't. @var{digest} should -point to a digest of size @code{MD5_DIGEST_SIZE}, -@code{SHA1_DIGEST_SIZE}, or @code{SHA256_DIGEST_SIZE}, respectively. +Returns 1 if the signature is valid, or 0 if it isn't. @var{digest} +should point to a digest of size @code{MD5_DIGEST_SIZE}, +@code{SHA1_DIGEST_SIZE}, @code{SHA256_DIGEST_SIZE}, or +@code{SHA512_DIGEST_SIZE} respectively. @end deftypefun -The RSA algorithm can also be used for encryption. RSA encryption uses -the public key @code{(n,e)} to compute the ciphertext @code{m^e mod n}. -The PKCS#1 padding scheme will use at least 8 random and non-zero -octets, using @var{m} of the form @code{[00 02 padding 00 plaintext]}. -It is required that @code{m < n}, and therefor the plaintext must be -smaller than the octet size of the modulo @code{n}, with some margin. +@deftypefun int rsa_pkcs1_verify(const struct rsa_public_key *@var{key}, size_t @var{length}, const uint8_t *@var{digest_info}, const mpz_t @var{signature}) +Similar to the above _verify_digest functions, but the input is not the +plain hash digest, but a PKCS#1 ``DigestInfo'', and ASN.1 DER-encoding +of the digest together with an object identifier for the used hash +algorithm. +@end deftypefun The following function is used to encrypt a clear text message using RSA. @deftypefun int rsa_encrypt (const struct rsa_public_key *@var{key}, void *@var{random_ctx}, nettle_random_func *@var{random}, size_t @var{length}, const uint8_t *@var{cleartext}, mpz_t @var{ciphertext}) @@ -3724,8 +3788,13 @@ that isn't supported by the above functions Nettle also includes a function that computes @code{x^d mod n} and nothing more, using the @acronym{CRT} optimization. +@deftypefun int rsa_compute_root_tr(const struct rsa_public_key *@var{pub}, const struct rsa_private_key *@var{key}, void *@var{random_ctx}, nettle_random_func *@var{random}, mpz_t @var{x}, const mpz_t @var{m}) +Computes @code{x = m^d}. Returns one on success, or zero if a failure in +the computation was detected. +@end deftypefun + @deftypefun void rsa_compute_root (struct rsa_private_key *@var{key}, mpz_t @var{x}, const mpz_t @var{m}) -Computes @code{x = m^d}, efficiently. +Computes @code{x = m^d}. @end deftypefun At last, how do you create new keys?