<?xml version="1.0" encoding="utf-8"?>
<!-- name="GENERATOR" content="github.com/mmarkdown/mmark Mmark Markdown Processor - mmark.miek.nl" -->
<rfc version="3" ipr="trust200902" docName="draft-fluhrer-cfrg-ntru-01" submissionType="IETF" category="info" xml:lang="en" xmlns:xi="http://www.w3.org/2001/XInclude" indexInclude="true" consensus="true">

<front>
<title abbrev="NTRU">NTRU Key Encapsulation</title><seriesInfo value="draft-fluhrer-cfrg-ntru-01" stream="IETF" status="informational" name="Internet-Draft"></seriesInfo>
<author initials="S." surname="Fluhrer" fullname="Scott Fluhrer"><organization>Cisco Systems</organization><address><postal><street></street>
</postal><email>sfluhrer@cisco.com</email>
</address></author><author initials="S." surname="Prorock" fullname="Michael Prorock"><organization>mesur.io</organization><address><postal><street></street>
</postal><email>mprorock@mesur.io</email>
</address></author><author initials="M." surname="Celi" fullname="Sofia Celi"><organization>Brave</organization><address><postal><street></street>
</postal><email>cherenkov@riseup.net</email>
</address></author><author initials="J." surname="Gray" fullname="John Gray"><organization>Entrust</organization><address><postal><street></street>
</postal><email>john.gray@entrust.com</email>
</address></author><date/>
<area>Internet</area>
<workgroup>CFRG</workgroup>
<keyword>NTRU</keyword>
<keyword>post quantum</keyword>
<keyword>kem</keyword>

<abstract>
<t>This draft documents NTRU as a post-quantum Key Encapsulation Mechanism (KEM)
scheme. The NTRU method from KEM is believed to be IPR free and
cryptographically sound for both classical and post-quantum threat environments.</t>
<t>NIST has run a competition to select post-quantum primitives and preliminary
selected Kyber for standarization as a KEM.  Kyber unfortunately has plausible
patent claims against it and there are currently undisclosed agreements with the
patent holders and NIST. It is unknown whether those agreements would be
universally acceptable; if not, there will be organizations for which Kyber is
unusable until the patents expire.  This lack of clarity around licensing or
other restrictions on Kyber has provided the motivation to author this draft.</t>
<t>This document does not define any new cryptography, only describes an existing
cryptographic system.</t>
</abstract>

</front>

<middle>

<section anchor="conventions-and-definitions"><name>Conventions and Definitions</name>
<t>{::boilerplate bcp14-tagged}</t>
</section>

<section anchor="notational-conventions"><name>Notational Conventions</name>
<t>The key words &quot;<bcp14>MUST</bcp14>&quot;, &quot;<bcp14>MUST NOT</bcp14>&quot;, &quot;<bcp14>REQUIRED</bcp14>&quot;, &quot;<bcp14>SHALL</bcp14>&quot;, &quot;<bcp14>SHALL NOT</bcp14>&quot;, &quot;<bcp14>SHOULD</bcp14>&quot;,
&quot;<bcp14>SHOULD NOT</bcp14>&quot;, &quot;<bcp14>RECOMMENDED</bcp14>&quot;, &quot;<bcp14>MAY</bcp14>&quot;, and &quot;<bcp14>OPTIONAL</bcp14>&quot; in this
document are to be interpreted as described in <xref target="RFC2119"></xref>.</t>
</section>

<section anchor="terminology"><name>Terminology</name>
<t>The following functions, terminology and notation are used throughout the
document.</t>

<ul spacing="compact">
<li>For any object <tt>x</tt>, we write <tt>len(x)</tt> to denote its length in bytes.</li>
<li>For two byte arrays <tt>x</tt> and <tt>y</tt>, write <tt>x || y</tt> to denote their
concatenation.</li>
<li>I2OSP(x, xLen): Converts a non-negative integer <tt>x</tt> into a byte array of
specified length <tt>xLen</tt> as described in {{!RFC8017}}. Note that this function
returns a byte array in big-endian byte order.</li>
<li><tt>n</tt> and <tt>q</tt> are coprime positive integers. The first defines the size of the
polynomials (treated as a zero indexed arrays), and the latter refers to the
modulus.</li>
</ul>
</section>

<section anchor="introduction"><name>Introduction</name>
<t>This document describes the key encapsulation mechanism (KEM) scheme based on
Hoffstein, Pipher, and Silverman's NTRU encryption scheme, commonly referred to
as NTRU. NTRU is constructed from a deterministic public key scheme (correct
DPKE) into a KEM (which has tight proof of IND-CCA2 security in a classical and
quantum model).  The method described here is based on a combination of prior
approaches, which eventually merged into the NTRUEncrypt and NTRU-HRSS-KEM
submissions (as submitted to Round 2 of the NIST PQC project). The algorithm
described here is based on the Round 3 submission and permits the use of three
well defined and reviewed parameter sets.</t>
</section>

<section anchor="parameter-sets"><name>Parameter sets</name>
<t>We define three parameter sets:</t>

<section anchor="ntru-hps-2048509"><name>NTRU-HPS 2048509</name>

<ul spacing="compact">
<li>Type: HPS</li>
<li>N: 509</li>
<li>Q: 2048</li>
<li>Hash: SHA3-256.</li>
<li>ID: 0x0001</li>
</ul>
</section>

<section anchor="ntru-hps-2048677"><name>NTRU-HPS 2048677</name>

<ul spacing="compact">
<li>Type: HPS</li>
<li>N: 677</li>
<li>Q: 2048</li>
<li>Hash: SHA3-256.</li>
<li>ID: 0x0002</li>
</ul>
</section>

<section anchor="ntru-hps-4096821"><name>NTRU-HPS 4096821</name>

<ul spacing="compact">
<li>Type: HPS</li>
<li>N: 821</li>
<li>Q: 4096</li>
<li>Hash: SHA3-256.</li>
<li>ID: 0x0003</li>
</ul>
</section>
</section>

<section anchor="cryptographic-dependencies"><name>Cryptographic Dependencies</name>

<section anchor="polynomials"><name>Polynomials</name>
<t>NTRU is based on polynomials; these can be viewed as a vector of N small values
(either between 0 and Q-1, or sometimes either 0, 1 or -1), where the values of
both N and Q are specified by the parameter set.  In all parameter sets, Q is
less than 65536, hence each small value fits within a 16 bit value.</t>
<t>Each polynomial is an array of values a(n-1), a(n-2), ..., a(0), with the
implicit polynomial being
a(n-1)x^(n-1) + a(n-2)x^(n-2) + ... + a(2)x^2 + a(1)x + a(0)
(where x is an independent variable that doesn't take a specific value).
In this case, we don't think of a polynomial as a function of x that we can
evaluate; instead, it is a quantity in and of itself.</t>
<t>When we multiply two polynomials, we first do it as we do in standard algebra;
we multiply each pair of terms (including x exponential), and then sum the
products which have the same resulting x term.  For example,
(2x^2 + 3x + 5)(4x + 8) =
(2*4)x^3 + (2*8 + 3*4)x^2 + (3*8 + 4*5)x + 5*8 = 8x^3 + 28x^2 + 44x + 40.</t>
<t>For NTRU, however, we do two additional reductions to this multiplication.
First, for each sum of the product, we compute that sum modulo a constant factor
(either 3 or the value Q; NTRU uses both at times).  In the above example, if we
were reducing things modulo 3, we would actually get the resulting polynomial (8
mod 3)x^3 + (28 mod 3)x^2 + (44 mod 3)x + (40 mod 3) = 2x^3 + x^2 + 2x + 1.</t>
<t>In addition, we compute the multiplication modulo x^n - 1 (where the value of n
is specified in the parameter set); that is, we subtract multiples of x^n-1
until the result is a polynomial of degree n-1 or less. An equivalent way of
expressing this is to add the resulting coefficent to the term x^(i+n) to the
coefficent to the term x^i (modulo the constant factor), and then discard all
terms x^n and above.</t>
<t>In the above example, assuming n=2, the final result would be (2+2 mod 3)x +
(1+1 mod 3) = x + 2.</t>
<t>A polynomal can be conveniently represented by an array of n values (with the
x^i factor being implicit in the positions in the array); 16 bits per value are
sufficient to represent all the coefficients that are encountered within NTRU.</t>
<t>For most polynomials A = a(n-1)x^(n-1) + a(n-2)x^(n-2) + ... + a(0), there is a
second polynomial B = b(n-1)x^(n-1) + b(n-2)x^(n-2) + ... + b(0), such that when
we multiply A and B together (and do the above reductions), we end up with the
polynomial 1 = 0x^(n-1) + 0x^(n-2) + ... + 0x + 1. We state this relationship as
B = inv(A).</t>
<t>Inverses can be computed efficiently, and also have the property that similar
polynomials have inverses that are quite different.</t>

<section anchor="trinary-polynomials"><name>Trinary Polynomials</name>
<t>Some of the polynomials that NTRU uses are 'trinary polynomials'.
These are standard polynomials that have all their coefficients being either 0, 1 or Q-1.
The standard operations (including polynomial multiplication and inversion) can be done the same.
However, an implementation may decide to optimize some operations based on a specific polynomial being trinary.</t>
</section>
</section>

<section anchor="polynomial-addition"><name>Polynomial Addition</name>
<t>When NTRU adds two polynomials, it does it by adding each element of the vector
independently modulo Q.</t>
</section>

<section anchor="polynomial-subtraction"><name>Polynomial Subtraction</name>
<t>When NTRU subtracts two polynomials, it does it by subtracting each element of
the vector independently modulo Q; that is, if the subtraction of two elements
results in a negative value, it adds Q to the difference.</t>
</section>

<section anchor="polynomial-multiplication"><name>Polynomial Multiplication</name>
<t>When NTRU multiplies two polynomials, it does it by multiplying each pair of
elements from each polynomial, and adding that result to the element indexed by
the sum of the indicies (wrapping around if the sum is N or more).</t>
<t>Note that this can be optimized; in many cases, one of the polynomials will be
of special form (for example, consists of only 0, 1 and -1), more efficient
algorithms may be available.</t>
</section>

<section anchor="polynomial-inversion"><name>Polynomial Inversion</name>
<t>When NTRU 'inverts a polynomial' X, it finds a polynomial Y such that
polynomial_multiply(X, Y) gives the polynomial 0x^(n-1) + 0x^(n-2) + ... + 0x^2 + 0x^1 + 1 = (1, 0, 0, 0, ..., 0).</t>
</section>

<section anchor="computing-a-polynomial-modulo-x-n-1-x-1"><name>Computing a Polynomial Modulo (x<sup>n-1)/(x-1)</sup></name>
<t>At one point, we need to take a polynomial modulo x<sup>(n-1)+x</sup>(n-2)+...+1 =
(x^n-1)/(x-1). We refer to this operation as modPhiN, and can be performed by
taking the top coefficient, and subtracting it from all the other coefficients.</t>
</section>
</section>

<section anchor="selecting-random-polynomials"><name>Selecting Random Polynomials</name>
<t>When running NTRU, we need at times random polynomials with specific forms;
doing this is referred to a sampling.</t>
<t>We need to do this both when generating keys as well as when encrypting a
message. It MUST rely on a cryptographically secure random number generator to
select these values.</t>

<section anchor="sample-a-random-trinary-polynomial"><name>Sample a random trinary polynomial</name>
<t>This function (called sample_iid in the reference code) selects a random trinary
polynomial, that is, one where all the coefficients are either 0, 1 or q-1, with
 the last coefficient 0.</t>
<t>This operation is performed by calling the rng n-1 times to generate n-1 bytes,
and then taking each byte modulo 3, mapping 2 to q-1 (and setting the last
coefficient to be 0) While this operation is not precisely uniform, it is close
enough for the purposes of NTRU.</t>
</section>

<section anchor="sample-a-random-balanced-trinary-polynomial"><name>Sample a random balanced trinary polynomial</name>
<t>This function (called sample_fixed_type by the reference code) selects a random
trinary sample with a specific weight; it consists of q/16-1 cofficients which
are 1, q/16-1 coefficients which are q-1, and the remainder (which includes
coefficient n) as 0.</t>
<t>This can be done by generating n-1 random values; tagging q/16-1 of the values
as 1; q/16-1 of the values as q-1 and the rest tagged as 0.  Then, you can sort
(in constant time) the random values; the resulting tags are in the required
random order.  You then scan through the list, and assign the coefficients to
the values of the tags.</t>
</section>
</section>

<section anchor="validating-polynomials"><name>Validating polynomials</name>
<t>We also need to validate polynomials generated during decapsulation; that is,
whether they were possible outputs of the sample_iid or sample_fixed_type
procedures.</t>

<section anchor="validr"><name>ValidR</name>
<t>This verifies that R is a possible output of the sample_iid procedure; that is,
that the coefficients of the polynomial R consists only of 0, 1 and q-1, and
that the last coefficient is 0.</t>
</section>

<section anchor="validm"><name>ValidM</name>
<t>This verifies that M is a possible output of the sample_fixed_type procedure;
that is, that the coefficients of the polynomial R consists only of 0, 1 and
q-1, that the last coefficient is 0, and that there are precisely q/16-1 1
values and q/16-2 q-1 values.</t>
</section>
</section>

<section anchor="converting-between-polynomials-and-byte-strings"><name>Converting Between Polynomials and Byte Strings</name>
<t>NTRU needs to convert polynomials into byte strings and vice versa, both to
export public keys and ciphertexts, as well as being able to hash those
polynomials. We refer to this process as serialization and deserialization.</t>

<section anchor="serialize-a-polynomial-base-q"><name>Serialize a polynomial base q</name>
<t>This function (called pack_Rq0 by the reference code) converts a polynomial into
a byte string.</t>
<t>This function takes the first n-1 coefficients (each a value between 0 and q-1),
expresses each as a log_2(q) bit bitstring as a little endian integer.  All n-1
coefficients are of length log_2(q).  Then, it concatinates those n-1 bit strings
into a long bit string; the result is that bit string being parsed into bytes
(with any trailing bits in the last byte being set to 0).</t>
<t>The inverse function (called) unpack_Rq0) converts that byte string back into a
polynomial.</t>
<t>It takes the byte string, parses it into n-1 consecutive log_2(q) bit strings,
takes each such bit string as a little endian integer and sets the corresponding
coefficient of the polynomial to that integer.  Since all bit strings are of equal
length, this can be done efficiently.  Then, it adds all those n-1 coefficients
together, and sets the n-th coefficient to the negation of that sum
modulo q.</t>
<t>A close reading of the above algorithms will note that the pack_Rq0 doesn't
actually depend on the last coefficient.  This is because this code assumes that
the polynomial is a multiple of the polynomial x-1; the unpack_Rq0 code uses
that assumption to reconstruct that last coefficient.</t>
<t>This assumption is true within NTRU because pack_Rq0 will be called only for
polynomials that are a multiple of the polynomial G; we always sample G values
that have an equal number of 1 and -1 coefficients (with the rest 0), and any
such polynomial will always be a multiple of x-1.</t>
</section>

<section anchor="serialize-a-trinary-polynomial"><name>Serialize a trinary polynomial</name>
<t>This function (called pack_S3 by the reference code) converts a trinary
polynomial into a byte string.  It works by taking the coefficients in
groups of 5, and packing each such group into a byte.</t>
<t>This function takes the n-1 coefficients in sets of 5; it converts the five
coefficients c0, c1, c2, c3, c4 into the values 0, 1 or 2. Then it sums up the
coefficients as c0 + 3*c1 + 9*c2 + 27*c3 + 81*c4, and then stores that value as
the next byte in the byte string.</t>
<t>If the last set of 5 is incomplete (which will happen if n-1 is not a multiple
of 5), then the higher missing coefficients are assumed to be zero.</t>
<t>Now, if the polynomial happens to not be trinary, then it doesn't matter what
byte we store; we need to store some value, and this code still needs to be
constant time. The reason we don't care is this happens only on decryption
failure (someone handed us an invalid ciphertext); in that case, the value of
the hash will end up being ignored. Of course, no matter what the coefficient
is, this still needs to be done in constant time.</t>
<t>This output of this function will be used only for hashing, hence there is no
need for an inverse function.</t>
</section>
</section>

<section anchor="ntru"><name>NTRU</name>

<section anchor="overview"><name>Overview</name>
<t>This section provides a simplified overview how NTRU works. Minor details are
omitted for clarity reasons, and the Security Considerations section should be
consulted prior to implementation.</t>
<t>To generate a public/private keypair, Alice selects two 'short' polynomials F
and G (where short means that the coefficients are all 0, 1 or q-1). She then
multiplies each coefficient of G by 3, and then computes H = Inv(F) x G; that is
the public key. She stores F in the private key, and computes Inv(F) (with this
inverse taken over the modulo 3 polynomial), and stores that in the private key
as well. She also computes Inv(H), and stores that in the private key.</t>
<t>To generate a KEM key share with the public key H, Bob selects two short
polynomials R and M, and computes C = R x H + M; that is the ciphertext. Bob also
hashes R and M to generate his copy of the shared secret.</t>
<t>When Alice receives C = R x Inv(F) x G + M, she first multiplies that by F; this
results in C x F = R x G + M x F. Since all the polynomials R, G, M, F are
short, the resulting coefficients are not large (that is, always less than Q/2
in absolute value), and so the fact that we computed everything modulo Q can be
ignored. Note that some of the coefficients may be 'negative' (that is, in the
range Q/2 to Q-1); those need to be treated as negative values for this next
step. Then, she take all the coefficients modulo 3 (taking into account the
negative coefficients); because all the coefficients of G are multiples are 3
(and so is R x G), those drop out, and Alice is left with M x F (with each
coefficient taken modulo 3). She then multiples that polynomial by Inv(F) (this
time over the modulo 3 polynomial), recovering M. She then uses M, the original
ciphertext and the stored value Inv(H) to recover R. She then hashes R and M
together to generate her copy of the shared secret.</t>
<t>Assuming Bob received Alice's public key H correctly, and Alice recieved Bob's
ciphertext C correctly, they will derive the same shared secret.</t>
</section>

<section anchor="private-and-public-key-generation"><name>Private and Public Key Generation</name>
<t>To generate a public/private keypair, we can follow this procedure:</t>

<ul spacing="compact">
<li>Generate a random polynomial f using using the <tt>sample_iid</tt> procedure.</li>
<li>Generate a random polynomial g using the the <tt>sample_fixed_type</tt> procedure</li>
<li>Multiply each coefficient of g by 3.</li>
<li>Compute FG_inv = Inverse( f * g  mod q)  mod q.</li>
<li>Compute H = FG_inv * g * g (modulo q)</li>
<li>Compute H_inv = FG_inv * f * f (modulo q)</li>
<li>Compute F_inv = Inverse( f ) (this computation is done modulo 3)</li>
<li>Generate a random 32 byte value s randomly</li>
</ul>
<t>The resulting public key is the value H (serialized by the pack_Rq0 procedure);
the resulting private key are the values F, H_inv, F_inv and S.  Any other
intermediate values should be securely disposed.</t>
<t>n.b. the initial generation of random polynomials can be combined into a single
procedure</t>
</section>

<section anchor="key-encapsulation"><name>Key Encapsulation</name>
<t>This takes a public key H, and generates both a ciphertext C as well as a secret
string K. The ciphertext C should be sent to the holder of the private key; the
string K should be used as the secret.</t>
<t>We can follow this procedure:</t>

<ul spacing="compact">
<li>Unpack the public key (using the unpack_Rq0 procedure) to obtain the
polynomial H</li>
<li>Sample a random R using the sample_iid procedure</li>
<li>Sample a random M using the sample_fixed_type procedure</li>
<li>Compute C = R*H + M (perfoming both the polynomial multiplication and
polynomial addition modulo q)</li>
<li>Serialize both R and M (using the pack_S3 procedure on both) and use SHA3-256
to hash the concatination; the resulting 32 bytes is the secret string K</li>
<li>Return K and C serialized using the pack_Rq0 procedure</li>
</ul>
</section>

<section anchor="key-decapsulation"><name>Key Decapsulation</name>
<t>This takes a private key (F, H_inv, F_inv, S) and a ciphertext C, and produces a
secret string K. If the ciphertext is the same as what was proceduced by the key
encapsulation procedure, then this will generate the same secret string K.</t>
<t>We can follow this procedure:</t>

<ul>
<li><t>Unpack the ciphertext (using the unpack_Rq0 procedure) to obtain the polynomial C</t>
</li>
<li><t>Compute A = C*F (modulo q)</t>
</li>
<li><t>For each coeffient x in A, if it is &lt; q/2, replace it with x mod 3; if it is
&gt;= q/2, replace it with 2 - (q-1-x) mod 3</t>
</li>
</ul>
<t>[THIS STEP IS NEEDED BECAUSE WE REPRESENT COEFFICIENTS IN THE RANGE 0..Q-1 -
WOULD A BALANCED REPRESENTATION BE CLEARER?]</t>

<ul>
<li><t>Compute M = A*F_inv (modulo 3) - note the change of moduli</t>
</li>
<li><t>For each 2 coefficient within M, replace it with q-1</t>
</li>
<li><t>Compute R = (C - M) * H_inv (modulo q)</t>
</li>
<li><t>Compute R = modPhiN(R) (modulo q)</t>
</li>
<li><t>Set Success = ValidM(M) AND ValidR(R)</t>
</li>
<li><t>Serialize both R and M (using the pack_S3 procedure on both) and use SHA3-256
to hash the concatination; the resulting 32 bytes is K1</t>
</li>
<li><t>Use SHA3-256 to hash the concatination of S (from the private key) and C, the
resulting 32 bytes is K2</t>
</li>
<li><t>If Success, return K=K1; otherwise, return K=K2</t>
</li>
</ul>
</section>
</section>

<section anchor="parameter-sets-1"><name>Parameter Sets</name>
<table>
<thead>
<tr>
<th>Parameter Set</th>
<th>Polynomial Size N</th>
<th>Modulus Q</th>
</tr>
</thead>

<tbody>
<tr>
<td>ntruhps2048509</td>
<td>509</td>
<td>2048</td>
</tr>

<tr>
<td>ntruhps2048677</td>
<td>677</td>
<td>2048</td>
</tr>

<tr>
<td>ntruhps4096821</td>
<td>821</td>
<td>4096</td>
</tr>
</tbody>
</table><t>Other parameter sets do exist, such as ntruhrss701, hovewver they are not
supported by this RFC at this time as they introduce complexity without
significant value to security, size or performance.</t>
</section>

<section anchor="usage"><name>Usage</name>
<t>NTRU solves the problem where two systems (we'll call them Alice and Bob) wish
to establish a common secret string that they can use to derive keys to protect
future communication. They share a communication path that is authenticated
(that is, the problem of detecting changes to messages between Alice and Bob is
solved by something else), but that communication path may be monitored. What
NTRU tries to achieve is to ensure that someone monitoring the communication
path cannot rederive the common secret string (and hence cannot derive the
communication keys).</t>
<t>To do this, Alice and Bob follow this three step process</t>

<ul>
<li><t>Step 1: Alice follows the 'Private and Public Key Generation' procedure; this
creates a private key (which Alice keeps to herself) and a public key, which
she sends to Bob.  Alternatively, she may decide to reuse a previously
generated keypair.</t>
</li>
<li><t>Step 2: Bob receives Alice's public key, and follows the 'Key Encapsulation'
procedure; this creates a secret string (which Bob keeps to himself) and a
ciphertext, which he sends to Alice</t>
</li>
<li><t>Step 3: Alice recieves Bob's ciphertext, and follows the 'Key Decapuslation'
procedure; this creates a secret string (which Alice keeps to herself).  Alice
can then either destroy her private key, or keep it around for next time.</t>
</li>
</ul>
<t>The secret strings that Alice and Bob generate are the same, and can be used for
creating symmetric keys or other key shared material used to protect future
communications.</t>

<section anchor="comparison-with-dh"><name>Comparison with DH</name>
<t>NTRU at first glace appears as though it may be performing the same job as
Diffie-Hellman. In fact, NTRU can be viewed as a drop-in replacement for DH
(with larger key shares) in some protocols. However, the equivalence is not
exact; with NTRU, Bob cannot compute the ciphertext until he possesses the
public key.</t>
<t>In contrast, in Diffie-Hellman, both sides can generate their key share g^x mod
p independently. Some use cases take advantage of this property of
Diffie-Hellman (for example, everyone publishes their key shares in a central
directory; to generate keys with someone else, we can download their public key
from the directory, and obtain the same key as they get when they download our
key from the directory). A protocol that does this is known as a NonInteractive
Key Exchange (NIKE). NTRU does NOT provide NIKE capabilities, and if non
interactive use cases are required to be supported, a different approach should
be selected.</t>
</section>
</section>

<section anchor="security-considerations"><name>Security Considerations</name>
<t>Current best practices should be followed, especially in regards to known
plaintext attacks, such as Meet-In-The-Middle (MITM), and known ciphertext
attacks.</t>
<t>Lattice reductions via Lenstra-Lenstra-Lovasz may be possible against NTRU with
weak parameter set selection.</t>

<section anchor="parameter-set-security"><name>Parameter set security</name>
<t>In all paramter sets, indistinguishability under adaptive chosen ciphertext
attack (IND-CCA2) is a desired property.</t>
<t>Equivalent bit strengths of the described parameter sets are outlined in the
table below:</t>
<table>
<thead>
<tr>
<th>Parameter Set</th>
<th>Security Model</th>
<th>Bit Strength</th>
</tr>
</thead>

<tbody>
<tr>
<td>ntruhps2048509</td>
<td>IND-CCA2</td>
<td>128</td>
</tr>

<tr>
<td>ntruhps2048677</td>
<td>IND-CCA2</td>
<td>192</td>
</tr>

<tr>
<td>ntruhps4096821</td>
<td>IND-CCA2</td>
<td>256</td>
</tr>
</tbody>
</table></section>

<section anchor="public-key-reuse"><name>Public key reuse</name>
<t>NTRU public/private keys can be safely reused for certain use cases.
Reusing an NTRU key may be tempting, because the NTRU key generation process is
considerably more costly than the key encapsulation or decapsulation operations.
On the other hand, if you do reuse NTRU keys, you lose the Perfect Forward
Secrecy property. That is, as long as you don't zeroize the NTRU private key,
then an attacker that can break into the system can extract that private key,
and then recover any symmetric keys that were negotiated with that private key.</t>
<t>If keys are reused, key revocation mechansims should be considered.</t>
</section>
</section>

<section anchor="iana-considerations"><name>IANA Considerations</name>
<t>This document has no IANA actions.</t>
</section>

<section anchor="open-questions"><name>Open Questions</name>

<ul>
<li><t>HRSS - currently, we omit that parameter set - it does perform slightly faster
than the HPS parameter set at the same security level (at the cost of a larger
public key/ciphertext).  My expectation is that the larger keyshare size for
HRSS is a more significant cost than the larger computational cost for HPS.
It would also complicate the logic somewhat (as we would need to specify both
the HPS and the HRSS ways of doing things).  Is the decision to leave it out
the correct one?</t>
</li>
<li><t>We don't specify a flattened format for a private key.  In my view, there is
no need; systems will generally use ephemerial public/private key pairs, that
is, create them on the fly, use them for one or a handful of exchanges and
then throw them away.  In this use case, there is no need to transfer a
private key to another device.  Now, it is possible for NTRU to be used with
static keys - should we try to address that case?</t>
</li>
<li><t>There is a tiny chance of failure during key generation (if F happens to be
selected as all 0); this happens with probability &lt; 2^-800 (that is, it'll
never happen in practice, unless the random number generator broke).  When
this happens, the computation of the inverse of F will fail; what happens
in that case would depend on the inverter implementation.
Should we ignore it or address it?</t>
</li>
<li><t>It appears that the parameter set HPS4096821 was added lately to the NTRU
definition, and did not undergo the same vetting that the other parameter
sets did.  As such, it is unclear whether that parameter set gives the
claimed level of security.  Should we remove it from this RFC, or just add
some warning text within the security considerations?</t>
</li>
</ul>

<section anchor="test-vectors"><name>Test vectors</name>
<t>TBD</t>
</section>
</section>

</middle>

<back>
<references><name>Normative References</name>
<xi:include href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.2119.xml"/>
</references>

<section anchor="acknowledgments"><name>Acknowledgments</name>
<t>Acknowledge TBD.</t>
</section>

</back>

</rfc>
