Commit 4ebc67a7 authored by Niels Möller's avatar Niels Möller

RSA documentation update.

parent d78467e1
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
......
......@@ -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?
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment