256 lines
8.6 KiB
Plaintext
256 lines
8.6 KiB
Plaintext
Some notes on using libntruencrypt.
|
|
|
|
Providing a source of randomness
|
|
================================
|
|
|
|
libntruencrypt needs a cryptographically secure source of random bits!
|
|
|
|
The library contains an internal deterministic random bit generator (DRBG)
|
|
that can be used to whiten an external random bit source that is of low
|
|
entropy. However, if a source of cryptographically random bits is available
|
|
(such as /dev/urandom on Linux) it can be used directly without whitening.
|
|
|
|
The mechanism is selected by calling one of two instantiation functions:
|
|
|
|
DRBG_HANDLE handle;
|
|
ntru_crypto_drbg_instantiate(..., &handle); /* HMAC based DRBG */
|
|
--or--
|
|
ntru_crypto_drbg_external_instantiate(..., &handle); /* External Source */
|
|
|
|
The later interface is substantially simpler, and is preferable on most
|
|
platforms. The following two sections describe how to use the interfaces.
|
|
|
|
Regardless of the instantiation method, a DRBG handle is destroyed by calling
|
|
ntru_crypto_drbg_uninstantiate(&handle);
|
|
|
|
|
|
Note: If you use NTRU for quantum resistance and use an external DRBG, make sure
|
|
it is instantiated with sufficient entropy! For security of k bits you should
|
|
instantiate your DRBG with 2*k bits of entropy from the external source. The
|
|
internal DRBG does this for you.
|
|
|
|
|
|
HMAC-DRBG
|
|
=========
|
|
|
|
One of the inputs to ntru_crypto_drbg_instantiate is an ENTROPY_FN. If you use
|
|
the internal HMAC-DRBG it is imperative that you write your entropy function
|
|
correctly. ENTROPY_FN is typedef'd as
|
|
|
|
typedef uint8_t (*ENTROPY_FN)(ENTROPY_CMD cmd, uint8_t *out);
|
|
|
|
and an ENTROPY_CMD is one of
|
|
INIT,
|
|
GET_NUM_BYTES_PER_BYTE_OF_ENTROPY
|
|
GET_BYTE_OF_ENTROPY.
|
|
|
|
On input INIT your entropy function must perform any initialization of your
|
|
external source that is necessary and return 1 on success or 0 on failure.
|
|
|
|
On GET_NUM_BYTES_PER_BYTE_OF_ENTROPY your entropy function must output (by
|
|
setting `out') a value between 1 and 8 representing the entropy of your
|
|
random source. A value of k indicates that the one cryptographically random
|
|
byte can be extracted from k bytes of output from your source. For instance
|
|
an output of 1 indicates that the source is perfectly random, and an output
|
|
of 8 indicates that you can only extract one bit of randomness from each byte
|
|
of your source's output. Your entropy function should return 1 indicating
|
|
success.
|
|
|
|
On GET_BYTE_OF_ENTROPY your function must put one byte of output from your
|
|
random source in `out' and return 1 on success, 0 on failure.
|
|
|
|
Example: Suppose your platform provides a getrandombyte function
|
|
int getrandombyte(void *out);
|
|
that outputs 1 perfectly random byte at out and returns 0 on success. The
|
|
following is a reasonable ENTROPY_FN:
|
|
|
|
uint8_t
|
|
get_entropy(
|
|
ENTROPY_CMD cmd,
|
|
uint8_t *out)
|
|
{
|
|
if (cmd == INIT)
|
|
return 1;
|
|
|
|
if (out == NULL)
|
|
return 0;
|
|
|
|
if (cmd == GET_NUM_BYTES_PER_BYTE_OF_ENTROPY)
|
|
{
|
|
*out = 1;
|
|
return 1;
|
|
}
|
|
|
|
if (cmd == GET_BYTE_OF_ENTROPY)
|
|
{
|
|
if(0 == getrandombyte(out))
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
To use your get_entropy function:
|
|
|
|
uint32_t rc;
|
|
DRBG_HANDLE handle;
|
|
uint32_t sec_strength = 256;
|
|
|
|
rc = ntru_crypto_drbg_instantiate(sec_strength, NULL, 0,
|
|
&get_entropy, &handle);
|
|
if(rc != DRBG_RESULT(DRBG_OK))
|
|
{ ... }
|
|
|
|
The internal HMAC-DRBG is seeded with 3/2 * sec_strength * k bits of input
|
|
from get_entropy where k is the value returned by
|
|
get_entropy(GET_NUM_BYTES_PER...).
|
|
The maximum value of sec_strength is 256.
|
|
The second and third arguments are for specifying an optional
|
|
'personalization string' of up to 32 bytes of non-secret data that are to be
|
|
used in conjunction with the entropy source to seed the DRBG (see NIST SP
|
|
900-80A for details).
|
|
|
|
|
|
External random sources
|
|
=======================
|
|
|
|
If you trust an external random source, for example because you are using
|
|
libntruencrypt inside of a larger crypto suite that provides a random source,
|
|
then you can use that source directly.
|
|
|
|
One of the inputs to ntru_crypto_drbg_external_instantiate is a pointer to
|
|
a RANDOM_BYTES_FN, typedef'd as
|
|
|
|
typedef uint32_t (*RANDOM_BYTES_FN)(uint8_t *out, uint32_t num_bytes);
|
|
|
|
To use an external random source you simply wrap it in an RANDOM_BYTES_FN.
|
|
|
|
Example: Suppose your platform provides a getrandom function
|
|
int getrandom(void *buf, size_t buflen);
|
|
that accepts a buflen between 1 and 256 and returns either the number of
|
|
bytes output or -1 on failure.
|
|
|
|
#include "ntru_crypto_drbg.h"
|
|
...
|
|
uint32_t randombytes(uint8_t *out, uint32_t num_bytes)
|
|
{
|
|
size_t i;
|
|
while(num_bytes > 0)
|
|
{
|
|
if(num_bytes > 256) {
|
|
i = 256;
|
|
} else {
|
|
i = num_bytes;
|
|
}
|
|
|
|
i = getrandom(out, i);
|
|
if(i == -1)
|
|
DRBG_RET(DRBG_ENTROPY_FAIL);
|
|
|
|
num_bytes -= i;
|
|
out += i;
|
|
}
|
|
DRBG_RET(DRBG_OK);
|
|
}
|
|
|
|
Note the use of DRBG_RET. This is required.
|
|
|
|
To use your randombytes function:
|
|
|
|
uint32_t rc;
|
|
DRBG_HANDLE handle;
|
|
rc = ntru_crypto_drbg_external_instantiate(&randombytesfn, &handle);
|
|
if(rc != DRBG_RESULT(DRBG_OK))
|
|
{ ... }
|
|
|
|
|
|
Parameter sets
|
|
==============
|
|
|
|
libntruencrypt provides all of the NTRUEncrypt parameter sets defined in the
|
|
IEEE 1363.1 standard -- a superset of those defined in X9.98. In the table
|
|
below the line labeled Product contains the parameter sets that are unique to
|
|
1363.1. These parameter sets are also faster and more compact than the other
|
|
sets in their respective columns, and these sets are preferable unless X9.98
|
|
compatibility is required. The column headers denote estimated bit security.
|
|
|
|
112 128 192 256
|
|
Product NTRU_EES401EP2 NTRU_EES439EP1 NTRU_EES593EP1 NTRU_EES743EP1
|
|
|
|
Size NTRU_EES401EP1 NTRU_EES449EP1 NTRU_EES677EP1 NTRU_EES1087EP2
|
|
Balanced NTRU_EES541EP1 NTRU_EES613EP1 NTRU_EES887EP1 NTRU_EES1171EP1
|
|
Speed NTRU_EES659EP1 NTRU_EES761EP1 NTRU_EES1087EP1 NTRU_EES1499EP1
|
|
|
|
|
|
Cryptographic functions
|
|
=======================
|
|
|
|
All of the cryptographic functions support two calling mechanisms. One to
|
|
obtain the lengths of any buffers that need to be allocated before performing
|
|
the operation, and a second to actually perform the operation
|
|
|
|
The DRBG inputs to keygen and encrypt are ignored when getting the buffer
|
|
lengths, and the DRBG need not be initialized at that time.
|
|
|
|
|
|
|
|
Keygen
|
|
NULL public_key requests public_key_len, NULL private_key requests
|
|
private_key_len. drbg argument is ignored.
|
|
|
|
Example:
|
|
/* Get public/private key buffer sizes */
|
|
rc = ntru_crypto_ntru_encrypt_keygen(drbg, NTRU_EES401EP2,
|
|
&public_key_len, NULL,
|
|
&private_key_len, NULL);
|
|
if(rc != NTRU_RESULT(NTRU_OK)) {...}
|
|
|
|
/* Allocate memory for keys */
|
|
...
|
|
/* Perform the key generation */
|
|
rc = ntru_crypto_ntru_encrypt_keygen(drbg, NTRU_EES401EP2,
|
|
&public_key_len, public_key,
|
|
&private_key_len, private_key);
|
|
if(rc != NTRU_RESULT(NTRU_OK)) {...}
|
|
|
|
Encrypt
|
|
NULL ciphertext requests length, drbg, plaintext_len and plaintext arguments
|
|
are ignored.
|
|
|
|
Example:
|
|
/* Get the ciphertext buffer size */
|
|
rc = ntru_crypto_ntru_encrypt(drbg, public_key_len, public_key,
|
|
0, NULL,
|
|
&ciphertext_len, NULL);
|
|
if(rc != NTRU_RESULT(NTRU_OK)) {...}
|
|
|
|
/* Allocate memory for ciphertext */
|
|
...
|
|
/* Perform the encryption */
|
|
rc = ntru_crypto_ntru_encrypt(drbg, public_key_len, public_key,
|
|
message_len, message,
|
|
&ciphertext_len, ciphertext);
|
|
if(rc != NTRU_RESULT(NTRU_OK)) {...}
|
|
|
|
|
|
Decrypt
|
|
NULL plaintext requests length, ciphertext_len and ciphertext arguments
|
|
are ignored.
|
|
|
|
Example:
|
|
/* Get maximum plaintext length */
|
|
rc = ntru_crypto_ntru_decrypt(private_key_len, private_key,
|
|
0, NULL,
|
|
&max_msg_len, NULL);
|
|
|
|
/* Allocate memory for plaintext */
|
|
...
|
|
/* Perform the encryption.
|
|
* Note that plaintext_len will contain the actual output length
|
|
* on success
|
|
*/
|
|
rc = ntru_crypto_ntru_decrypt(private_key_len, private_key,
|
|
ciphertext_len, ciphertext,
|
|
&plaintext_len, plaintext);
|
|
if(rc != NTRU_RESULT(NTRU_OK)) {...}
|
|
|