Bobby,
This thread brings several issues together and it is easy to get
confused, so let me try to clarify.
Le 20/10/2023 à 16:43, Bobby McGee a écrit :
> The "changes" in FIPS 203 were made to make things clearer, i.e. each
> of the two samplings is generation of NTT(A), done the same way, with
> the transpose put in the appropriate place. I think it's an
> improvement to have line 6 of both key gen and encryption read
>
> 6: Aˆ [i, j] ← SampleNTT(XOF(ρ, i, j))
>
> and someone at NIST though so too. If you know how the algorithm
> works and why the transpose is there, it's not like you're going to
> accidentally forget it.
I agree with you that dropping the transpose in line 6 makes things
clearer in the sense that the sampling is now obviously done the same
way in KeyGen and Encrypt.
However, the real issue is that the row/column indices are swapped in
the input of XOF compared to Kyber, making the two schemes incompatible
with each other.
More precisely, each coefficient of A is generated (both in KeyGen and
Encrypt):
- from the output of XOF(rho, row, column) in the FIPS-203 draft
- from the output of XOF(rho, column, row) in the Kyber specification.
To be honest, I was focused on the transposition, thought everything was
fine, and I missed this index swap at first. Several responses in this
thread seem to show that I am not the only one.
Summarizing, as said by Paul Duncan earlier, "FIPS 203 draft and Kyber
round 3 specification are both internally consistent with themselves,
but not with each other".
As an additional issue, this change was not mentioned in section "1.3
Differences From the CRYSTALS-KYBER Submission"; this means someone
trying to patch an existing Kyber implementation could easily miss that,
and get an implementation that would NOT be interoperable with compliant
implementations.
So:
- if this change is intentional, it should be mentioned in section 1.3
- if not, the indices should be swapped (both in KeyGen and Encrypt) to
maintain compatibility with the Kyber spec.
Discussion with Quynh Dang reached the conclusion that this change was
most likely a typo, and that the initial intent was to keep the same
underlying PKE for Kyber and ML-KEM. I was then encouraged to submit an
official comment (included below for reference) to
fips-203...@nist.gov in order to formally raise the issue.
Best regards,
Robin Larrieu
> Dear NIST,
>
> The PQC-forum group had a discussion about the generation of the
> public matrix A in ML-KEM that does not match what was done in the
> Kyber submission.
> See the thread "[pqc-forum] Question about Ahat_transposed in ML-KEM /
> Kyber".
> Recall that in ML-KEM, the matrix A is generated in NTT representation
> by deterministically expanding a pseudo-random string from a seed and
> the row/column indices. Specifically, the coefficient in row i and
> column j of the matrix A, denoted Ahat[i,j] is generated:
> - from the output of XOF(rho, i, j) in the FIPS-203 draft
> - from the output of XOF(rho, j, i) in the Kyber submission
>
> Notice that the row/column indices in the input of XOF are swapped in
> FIPS-203 compared to the Kyber submission. According to Dang, Quynh H.
> (Fed) <
quynh...@nist.gov>, this mismatch is unintentional, and the
> underlying PKE should have been the same in ML-KEM and Kyber.
> - Assuming this is the case, there are a few changes to do in the
> description of algorithms 12 -- K-PKE.KeyGen() and 13 --
> K-PKE.Encrypt() as proposed below.
> - If this change was in fact intentional, the difference should be
> mentioned in section "1.3 Differences From the CRYSTALS-KYBER
> Submission" (and the rest of this email can be ignored).
>
>
> # Changes required in algorithm 12 -- K-PKE.KeyGen():
>
> Indices i,j must be swapped in the input of XOF, that is rewrite line
> 6 as
> Ahat[i,j] <- SampleNTT(XOF(ρ, j, i))
> instead of
> Ahat[i,j] <- SampleNTT(XOF(ρ, i, j))
>
>
> # Changes required in algorithm 13 -- K-PKE.Encrypt()
>
> For correctness of the scheme, generation of matrix Ahat must be done
> in a compatible way with what is done in KeyGen. Due to the
> multiplication by Ahat_transpose in line 19, there are several
> possible presentations that make sense, each with their own advantages
> and disadvantages. Here are the main possibilities that I can think of
>
> 1) Simply swap the indices as in KeyGen, that is
> - rewrite line 6 as Ahat[i,j] <- SampleNTT(XOF(ρ, j, i))
>
> 2) Sample directly the transpose of Ahat, using either of the two
> options:
> 2.a) as in the Kyber specification
> - rewrite line 6 as Ahat_transpose[i,j] <- SampleNTT(XOF(ρ, i, j))
>
> 2.b) using an auxiliary notation Bhat for Ahat_transpose:
> - rewrite the comment in line 4 as "re-generate matrix A in [snip], by
> its transpose Bhat=Ahat_transpose"
> - rewrite line 6 as: Bhat[i,j] <- SampleNTT(XOF(ρ, i, j))
> - rewrite line 19 as: u <- NTT^(-1)( * r) + e1
>
> 3) Use left-multiplication in line 19
> - rewrite line 6 as Ahat[i,j] <- SampleNTT(XOF(ρ, j, i))
> - rewrite line 19 as: u <- NTT^(-1)(r_hat * Ahat) + e1
> - rewrite line 21 as: v <- NTT^(-1)(r_hat * t_hat) + e2 + mu
>
>
> # Advantages and disadvantages of each option (personal opinion)
>
> Option 1) makes it clear that generation of matrix Ahat is done in the
> same way in KeyGen and Encrypt.
> On the other hand, this means implementers must be careful of the
> transpose in line 19 (u <- NTT^(-1)(Ahat_transpose * r) + e1). Recall
> that page 10 gives the formula for a multiplication of the form yhat =
> Ahat_transpose * uhat, so this is well defined.
>
> Option 2) corresponds to a straightforward implementation trick of
> generating A directly in its transposed form, as used in the Kyber
> reference implementation. In particular, option 2.a) matches exactly
> the Kyber specification, but it may be confusing due to the multiple
> appearances of Ahat_transpose. Option 2.b) avoids most risk of
> confusion by removing all matrix transposition in the pseudo-code, at
> the cost of introducing a new notation.
>
> Option 3) visually echoes what happens in KeyGen and Decrypt which
> could give a better intuition on how the scheme works as a whole and
> why it is correct. It also makes it clear that generation of matrix
> Ahat is done in the same way in KeyGen and Encrypt, while also
> removing all matrix transposition to avoid confusion. It would however
> require a more extensive editing work in the rest of the document to
> make all equations consistent.
>
> I do not have a strong opinion on which option is the best, but if I
> had to choose one I would recommend option 1.
>
>
> Best regards,
> Robin Larrieu
> CryptoNext Security