Mastersthesis Hudde Code Based Cryptography Library
Mastersthesis Hudde Code Based Cryptography Library
EMSEC
Abstract
Declaration
I hereby declare that this submission is my own work and that, to the best of my
knowledge and belief, it contains no material previously published or written by another
person nor material which to a substantial extent has been accepted for the award of any
other degree or diploma of the university or other institute of higher learning, except
where due acknowledgment has been made in the text.
Erklärung
Hiermit versichere ich, dass ich die vorliegende Arbeit selbstständig verfasst und keine
anderen als die angegebenen Quellen und Hilfsmittel benutzt habe, dass alle Stellen der
Arbeit, die wörtlich oder sinngemäß aus anderen Quellen übernommen wurden, als solche
kenntlich gemacht sind und dass die Arbeit in gleicher oder ähnlicher Form noch keiner
Prüfungsbehörde vorgelegt wurde.
1 Introduction 1
1.1 Motivation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
1.2 Existing implementations . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
1.3 Contribution . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
1.4 Outline . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
2 Code-based cryptography 7
2.1 Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
2.2 Security parameters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
2.3 Classical McEliece cryptosystem . . . . . . . . . . . . . . . . . . . . . . . 9
2.3.1 Key generation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
2.3.2 Encryption . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
2.3.3 Decryption . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
2.4 Modern McEliece cryptosystem . . . . . . . . . . . . . . . . . . . . . . . . 11
2.4.1 Key generation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
2.4.2 Encryption . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
2.4.3 Decryption . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
2.5 Niederreiter cryptosystem . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
2.5.1 Key generation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
2.5.2 Encryption . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
2.5.3 Decryption . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
2.6 Security . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
2.6.1 Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
2.6.2 Attacks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
2.6.3 Ciphertext indistinguishability . . . . . . . . . . . . . . . . . . . . 19
2.7 Key length . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
3 Coding theory 21
3.1 Preliminaries . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
3.2 Linear block codes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
3.2.1 Basic definitions . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
3.2.2 Important code classes . . . . . . . . . . . . . . . . . . . . . . . . . 24
3.3 Construction of Goppa codes . . . . . . . . . . . . . . . . . . . . . . . . . 26
3.3.1 Binary Goppa codes . . . . . . . . . . . . . . . . . . . . . . . . . . 26
3.3.2 Parity Check Matrix of Goppa Codes . . . . . . . . . . . . . . . . 27
iv Contents
4 Implementation 39
4.1 Memory management on AVR . . . . . . . . . . . . . . . . . . . . . . . . 40
4.2 Design criteria . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
4.3 Fast finite field arithmetics . . . . . . . . . . . . . . . . . . . . . . . . . . 41
4.3.1 Field element representations . . . . . . . . . . . . . . . . . . . . . 41
4.3.2 Avoiding duplicate conversions (The FASTFIELD switch) . . . . . . 43
4.4 Key management . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
4.4.1 Matrix datatype . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
4.4.2 Key matrices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
4.4.3 Key generation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
4.5 Encryption . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
4.5.1 Encoding . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
4.5.2 Multiplication . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
4.5.3 Error addition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
4.6 Decryption . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50
4.6.1 Syndrome computation . . . . . . . . . . . . . . . . . . . . . . . . 50
[Link] McEliece: syndrome computation variants . . . . . . . . 51
[Link] Niederreiter: Constructing a syndrome of double length . 53
4.6.2 Patterson implementation . . . . . . . . . . . . . . . . . . . . . . . 54
4.6.3 Berlekamp-Massey implementation . . . . . . . . . . . . . . . . . . 55
4.6.4 Root extraction using Berlekamp-Trace . . . . . . . . . . . . . . . 55
4.7 Constant weight encoding . . . . . . . . . . . . . . . . . . . . . . . . . . . 56
4.8 CCA2-secure conversions . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
4.8.1 Kobara-Imai-Gamma conversion . . . . . . . . . . . . . . . . . . . 60
4.8.2 Fujisaki-Okamoto conversion . . . . . . . . . . . . . . . . . . . . . 61
5 Evaluation 67
5.1 Memory usage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67
5.1.1 Key size . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67
5.1.2 Message-related memory . . . . . . . . . . . . . . . . . . . . . . . . 68
5.1.3 Precomputations . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
Contents v
6 Conclusion 87
6.1 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87
6.2 Future Work . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88
A Acronyms 91
B Appendix 93
B.1 Listings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93
B.1.1 Listing primitive polynomials for the construction of Finite fields . 93
B.1.2 Computing a normal basis of a Finite Field using SAGE . . . . . . 93
B.2 Definitions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94
B.2.1 Hamming weight and Hamming distance . . . . . . . . . . . . . . . 94
B.2.2 Minimum distance of a codeword . . . . . . . . . . . . . . . . . . . 94
B.2.3 One-way functions . . . . . . . . . . . . . . . . . . . . . . . . . . . 94
B.2.4 Cryptographic Hash functions . . . . . . . . . . . . . . . . . . . . . 95
B.2.5 One-time pad . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95
List of Figures 97
List of Tables 99
Bibliography 103
1 Introduction
Two years after the first publication of an asymmetric cryptosystem — the Diffie-Hellman
key exchange in 1976 — Robert McEliece developed an asymmetric cryptosystem based
on error-correcting codes. Mainly due to its very long key size, McEliece’s proposal has
been neglected until the recent rise of interest in Post-Quantum cryptography.
This chapter introduces the reader to the background and objectives of this thesis.
Section 1.1 motivates the need for Post-Quantum cryptography in general and the de-
velopment of a Code-based cryptography library for constricted devices in particular.
Section 1.2 gives an overview of already existing implementations of Code-based cryp-
tosystems. Section 1.3 defines the goals of this thesis and points out the contributions of
this work to the research process. Finally an outline of the thesis is given in Section 1.4.
1.1 Motivation
Impact of quantum computers on public-key cryptography Public-key cryptography
is an integral part of today’s digital communication. For example, it enables two or
more parties to communicate confidentially without having a previously shared secret
key. All popular public-key cryptosystems rely on the assumption that there is no effi-
cient solution for the Integer Factorization problem or the Discrete Logarithm problem.
According to Canteaut and Chabaud [CC95] public-key cryptography has become “dan-
gerously dependent” on the difficulty of these two problems.
Unfortunately, both problems are known to be solvable in polynomial time on quan-
tum computers using Shor’s algorithm [Sho94]. Hence, a sufficiently large quantum
computer would be able to break popular cryptosystems such as RSA, Elliptic Curve
Cryptography (ECC) or ElGamal in polynomial time. This would "cause a tremendous
shock to the worlds economy and security" wrote Overbeck [Ove07] in 2007, explain-
ing the increased amount of research performed on the field of cryptosystems resisting
quantum computers1 . Such cryptosystems are dubbed Post-Quantum cryptography.
The first demonstration of Shor’s algorithm was done by IBM in 2001[VSB+ 01] and
used 7 qubits2 to factorize the number 15. Ten years later, chinese researchers [XZL+ 11]
were already able to factorize 143 using adiabatic quantum algorithms.
In May 2011, the quantum computing company D-Wave Systems claimed to have build
the “world’s first commercially available quantum computer” and was able to remove
some of the doubts regarding the actual usage of quantum mechanical properties with an
1
See [Nit] for a short and comprehensible introduction to quantum computers and their impact on
cryptography.
2
A qubit is a unit of quantum information, analogous to the classical bit, but allowing a superposition
of its states.
2 1 Introduction
article published in the renowned science magazine Nature [JAG+ 11, tec12]. In January
2012, D-Wave researchers [BCM+ 12] report a successful computation using 84 qubits.
At the same time, IBM announced “major advances in quantum computing device
performance” [IBM12], fueling speculations that quantum computers might be available
in 10 to 15 years. In September 2012, a research team led by Australian engineers
succeeded in isolating, measuring and controlling an electron belonging to a single silicon
atom, creating a qubit formed of just a single atom. One month later, physicists David
Wineland and Serge Haroche were rewarded with a Nobel Prize for their fundamental
research on quantum computers.
Embedded devices Given today’s memory and network capacities the key length is
not a problem for typical desktop systems, but it still is problematic for embedded
devices. However, the need for security in embedded devices is continuously rising, be
it in smartphones, electronic door locks, industrial controllers or medical equipment.
According to the public private partnership association ARTEMIS, which claims to
represent the interests of industry and the research community in the field of embedded
devices, “98% of computing devices are embedded”4 devices. This applies to consumer
electronics as well as industrial applications. Hence, efficient implementations for em-
bedded devices are indispensable to achieve acceptance for code-based cryptosystems in
practice.
1.3 Contribution
While some implementations of code-based cryptography on constricted devices already
exist, they mostly focus on one specific variant and leave room for optimizations. This
thesis aims to provide an extensible code-based crypography library for microcontrollers.
It provides implementations of both McEliece and Niederreiter including two different
methods of CCA2-secure conversions. Furthermore it includes decoding via either Pat-
terson or Berlekamp-Massey algorithm and several variants for root extraction and syn-
drome calculation. Finally, all the variants are evaluated and compared to existing
implementations and to traditional public-key cryptosystems. Therefore, the thesis and
implementation help in advancing Code-based cryptography and provide valuable hints
for future implementations regarding the decision which approaches are most promising.
1.4 Outline 5
1.4 Outline
The remainder of the thesis is structured as follows: Chapter 2 provides a high-level
introduction to Code-based cryptography. It discusses the McEliece and Niederreiter
cryptosystem and examines security aspects and practical issues. Chapter 3 provides
the reader with basic definitions and methods of Coding theory. Moreover, it explains
the construction of the important class of Goppa codes and provides algorithms for de-
coding and root extraction, some of which apply to a very broad range of code classes.
The implementation of these algorithms with regard to the embedded target platforms
is discussed in Chapter 4. Furthermore, it covers the conversion of McEliece and Nieder-
reiter into CCA2-secure cryptosystems. Chapter 5 evaluates the implementation with
regard to memory usage and execution time of the implemented variants. Finally, a con-
clusion in Chapter 6 summarizes the results and provides an outlook to future research
directions.
2 Code-based cryptography
This chapter introduces the reader to the basics of code-based cryptography and discusses
the cryptographic and practical strengths and weaknesses of the presented systems. Sec-
tion 2.1 provides a rough introduction to the fundamentals of linear codes and the basic
mechanisms of Code-based cryptography, followed by a presentation of currently rec-
ommended security parameters in Section 2.2. Then, the Classical (Section 2.3) and
Modern (Section 2.4) version of McEliece and of Niederreiter (Section 2.5) are discussed,
without yet delving into the finer details of Coding theory. In Section 2.6 security as-
pects of Code-based cryptography are discussed, including the relation of Code-based
cryptography to the General Decoding problem, important attack types and the notion
of Semantic security. Finally, attempts at reducing the key length are briefly reviewed
in Section 2.7.
2.1 Overview
Linear codes Error-detection and correction techniques have been used since the early
days of telecommunication and computing to allow the transmission of information over
a noisy channel, starting with the Hamming code invented by Richard Hamming in 1950.
The basic idea is adding redundancy to the message, which can be used by the receiver
to check the consistency and correct the errors to some extent.
Linear block codes belong to the most widely used class of error-detecting and error-
correcting codes. They use a generator matrix G to transform a message vector m into
a codeword c, and a parity check matrix H derived from G to check the consistency of a
codeword. If s = c · H = 0 the codeword is free of detectable errors. Otherwise s, which
is called syndrome, can be used to identify the error positions and error values.
A linear code of length n, dimension k, and minimal code word distanceApp. B.2.2
d is called an [n, k, d] code. For example, a binary linear [n, k, d] code has a length
of n bits, it holds k bits payload and n − k bits redudancy, and the minimum ham-
ming distanceApp. B.2.1 of its codewords is d. A code is efficient if it maximizes d for a
given n and k. In general, such a code is able to correct t = ⌊ d−1
2 ⌋ errors.
Goppa codes are an important class of linear codes. They are defined using a poly-
nomial g(z) over the Galois Field GF (pm ) with a so-called support L being a subset of
elements of GF (pm ) that has no roots in g(z). They will be discussed in more detail in
Chapter 3.
be used to encrypt a message and the secret key is required to decrypt the resulting
ciphertext. Such schemes can be specified by giving a triple of algorithms: key generation,
encryption and decryption.
All popular public-key cryptosystems are based on one-way functionsApp. B.2.3 . A one-
way function can informally be defined as a function that can be computed efficiently
for every input, but is hard to revert in the sense of complexity theory. A special case of
a one-way function is a trapdoor function, which is hard to revert in general, but easy
to revert with the help of some secret additional information.
Code-based cryptosystems make use of the fact that decoding the syndrome of a
general linear code is known to be N P-hard, while efficient algorithms exist for the
decoding of specific linear codes. Hence the definition of a trapdoor function applies.
For encryption, the message is converted into a codeword by either adding random
errors to the message or encoding the message in the error pattern. Decryption recovers
the plaintext by removing the errors or extracting the message from the errors. An
adversary knowing the specific used code would be able to decrypt the message, therefore
it is imperative to hide the algebraic structure of the code, effectively disguising it as an
unknown general code.
The original proposal by Robert McEliece suggested the use of binary Goppa codes,
but in general any other linear code could be used. While other types of code may have
advantages such as a more compact representation, most proposals using different codes
were proven less secure1 . The Niederreiter cryptosystem is an indepently developed
variation of McEliece which is proven to be equivalent in terms of security [LDW06].
In this thesis, the term Classical McEliece or Niederreiter is used to identify the
original cryptosystem as proposed by its author. The term Modern is used for a variant
with equivalent security that we consider more appropriate for actual implementations.
While this chapters introduces the reader to both variants, throughout the remainder of
the thesis we will always consider only the Modern variant.
Table 2.1: Parameters sets for typical security levels according to [BLP08]
security level for the originally suggested parameters by McEliece fell from arround 280 in
1986 to 259.9 in 2009 [FS09]. Table 2.1 shows parameter sets for typically used security
levels. The corresponding key lengths depend on the respective cryptosystem variant
and the storing method and will be discussed in Section 2.7 after the presentation of the
cryptosystems.
2.3.2 Encryption
2.3.3 Decryption
The McEliece decryption shown in Alg. 2.3.3 consists mainly of the removal of the applied
errors using the known decoding algorithm DGoppa (c) for the code C. Before the decoding
algorithm can be applied, the permutation P needs to be reversed. After the decoding
step the scrambling S needs to be reversed. Decoding is the most time consuming part
of decryption and makes decryption much slower than encryption. Details are given in
Chapter 3.
Decryption works correctly despite of the transformation of the code C because the
following equations hold:
2.4 Modern McEliece cryptosystem 11
ĉ = c · P −1 (2.1)
−1
= (m · Ĝ + e) · P (2.2)
−1
= (m · S · G · P + e) · P (2.3)
−1 −1
=m·S·G·P ·P +e·P (2.4)
−1
= m · S · G · +e · P (2.5)
Remember from Section 2.3.1 that permutation P does not affect the Hamming weight
of c, and the multiplication S · G · P with S being non-singular produces a generator
matrix for a code equivalent to C. Therefore the decoding algorithm is able to extract
the vector of permuted errors e · P −1 and thus m̂ can be recovered.
stresses that “such a conversion is needed anyway” [OS09]. Section 2.6.3 discusses this
requirement in greater detail.
The algorithms shown in this section present the Modern McEliece variant applied to
Goppa codes.
It starts with the selection of a random Goppa polynomial g(z) of degree t. The
support L is then chosen randomly as a subset of elements of GF (pm ) that are not roots
of g(z). Often n equals pm and g(z) is chosen to be irreducible, so all elements of GF (pm )
are in the support. In Classical McEliece, the support is fixed and public and can be
handled implicitly as long as n = pm . In Modern McEliece, the support is not fixed but
random, and it must be kept secret. Hence it is sometimes called Lsec , with Lpub being
the public support, which is only used implicitly through the use of Gsys .
Using a relationships discussed in Section 3.3.2, the parity check matrix H is com-
puted according to g(z) and L, and brought to systematic form using Gauss-Jordan
elimination. Note that for every column swap in Gauss-Jordan, also the corresponding
support elements need to be swapped. Finally the public key in the form of the system-
atic generator matrix G is computed from H. The private key consists of the support L
and the Goppa polynomial, which form a code for that an efficient decoding algorithm
DGoppa (c) is known.
Table 2.2 illustrates the relationship between the public and private versions of gener-
ator matrix, parity check matrix and support.
2.4.2 Encryption
Encryption in Modern McEliece (see Alg. 2.4.2) is identical to encryption in Classical
McEliece, but can be implemented more efficiently, because the multiplication of the
plaintext with the identity part of the generator matrix results in a mere copy of the
plaintext to the ciphertext.
2.5 Niederreiter cryptosystem 13
2.4.3 Decryption
Decryption in the Modern McEliece variant shown in Alg. 2.4.3 consists exclusively of
the removal of the applied errors using the known decoding algorithm DGoppa (c) for the
code C. The permutation is handled implicitly through the usage of the permuted secret
support during decoding. The ‘scrambling’ does not need to be reversed neither, because
the information bits can be readly directly from the first k bits of the codeword.
2.5.2 Encryption
For encryption, the message M needs to be represented as a CW word of length n and
hamming weight t. There exist several techniques for CW encoding, one of which will
be presented in Section 4.7. The CW encoding is followed by a simple vector-matrix
multiplication.
Encryption is shown in Alg. 2.5.3. It is identical for the Classical and Modern variant
apart from the fact that the multiplication with a systematic parity check matrix can
be realized more efficiently.
2.5.3 Decryption
For the decoding algorithm to work, first the scrambling needs to be reverted by mul-
tiplying the syndrome with S −1 . Afterwards the decoding algorithm is able to extract
the error vector from the syndrome. In the Classical Niederreiter decryption as given in
Alg. 2.5.4, the error vector after decoding is still permuted, so it needs to be multiplied
by P −1 . In the Modern variant shown in Alg. 2.5.5, the permutation is reverted implic-
itly during the decoding step. Finally CW decoding is used to turn the error vector back
into the original plaintext.
2.6 Security
This section provides an overview of the security of McEliece-type cryptosystems. First,
the hardness of the McEliece problem is discussed. Then we give a rough overview
on classical and side channel attacks. Finally the concept of indistinguishability and
CCA2-secure conversions are introduced.
16 2 Code-based cryptography
2.6.1 Overview
The McEliece problem can be defined as the task of finding the message corresponding to
a given ciphertext and public key according to the McEliece or Niederreiter cryptosystem.
According to Minder [Min07] there are mainly two assumptions concerning the security
of the McEliece problem: The hardness of decoding a general unknown code, which is
known to be N P-hard [BMvT78], and the hardness of structural attacks reconstructing
the underlying code.
• Obviously the McEliece problem can be broken by an adversary who is able to solve
the General Decoding problem. On the other hand, solving the McEliece problem
would presumably solve the General Decoding problem only “in a certain class of
codes”, since it allows only the decoding of a permutation-equivalent3 code of a
specific known code. Therefore “[w]e can not assume that the McEliece-Problem is
N P-hard” conclude Engelbert et al. in [EOS06]. Minder adds that N P-hardness
is a worst-case criterion and hence not very useful “to assess the hardness of an
attack” [Min07]. Overbeck [OS09] points out several differentiations of the decod-
ing problem, concluding that although there is no proof for the hardness of the
McEliece problem, there is at least no sign that using McEliece-type cryptosystems
with Goppa codes could ‘fall into an easy case‘.
• The hardness of reconstructing the underlying code given the generator matrix
differs greatly across different codes. For example, the original McEliece using
Goppa codes remains unbroken aside from key length adjustments, whereas the
usage of Generalized Reed-Solomon Code (GRS) codes as suggested by Niederreiter
turned out to be insecure due to structural attacks.
So far, there are “no known classical or quantum computer attacks on McEliece’s
cryptosystem which have sub-exponential running time” conclude Engelbert et al. in
[EOS06].
2.6.2 Attacks
A public-key cryptosystem can be considered broken if it is feasible to extract the secret
key or to decrypt a ciphertext without knowledge of the secret key. Note that we consider
3
Note that attempts at more general transformations exist, see for example [BBC+ 11].
2.6 Security 17
Key security Structural attacks typically aim at extracting the secret key from the
public key or from plaintext/ciphertext pairs. For example, Sidelnikov and Shestakov
[SS92] proposed a structural attack to GRS codes in 1992. Although Goppa codes are
subfield subcodes of GRS codes, McEliece and Niederreiter using Goppa codes do not
seem to be affected by this attack [EOS06]. This applies also to newer variants of the
attack, like the extension by Wieschebrink [Wie10].
The security of McEliece-type cryptosystems is related to the problem of Code Equiv-
alence: an adversary who is able to decide whether two generator matrices are code-
equivalent may have an advantage in finding the secret key matrix. This can be ac-
complished using the Support Splitting Algorithm (SSA) by Sendrier [Sen00], which
computes the permutation between two equivalent codes for Goppa codes and some
other code classes. Attacking the McEliece cryptosystem using SSA requires the adver-
sary to guess the secret generator matrix G, for example by testing all possible Goppa
polynomials of the respective degree and checking the corresponding code using SSA.
18 2 Code-based cryptography
Side channel attacks Side channel attacks attempt to extract secret information of
a cryptosystem by analyzing information that a specific implementation leaks over side
channels such as power consumption, electromagnetic emissions or timing differences.
They represent a serious threat especially to devices in hostile environments, where an
adversary has unconditional physical access to the device. Since this thesis is focused
on embedded devices, this is probably the case for most real world use cases of this
implementation.
Contrary to the previously discussed attacks, side channel attacks do not question the
security of the cryptosystem itself, but only of the implementation. Nevertheless it is
possible to identify attack vectors that are likely to occur in all implementations of a
specific cryptosystem, for example if the system includes an algorithm whose duration
depends strongly on the secret key.
The recent rise of interest in post-quantum cryptography also brought side channel
analysis of McEliece-type cryptosystem more into focus and spawned several papers re-
searching susceptibility and countermeasures. Strenzke et al. [Str10, Str11, SSMS10]
published several papers on timing attacks against the secret permutation, syndrome in-
version and the Patterson algorithm and also pointed out some countermeasures. Heyse,
Moradi and Paar [HMP10] evaluated practical power analysis attacks on 8-bit imple-
mentations of McEliece provided by [Hey09]. More recently, Schacht [Sch12] evaluated
timing and power analysis attacks and countermeasures with a focus on variants of the
syndrome decoding algorithm.
A typical example for a side channel in McEliece based on a binary code is the bit flip
attack: If an attacker toggles a random bit in the ciphertext and the bit happens to be an
error bit, the decoding algorithm has one less error to correct. Without countermeasures,
this typically results in a reduced runtime and hence allows the attacker to find the
2.6 Security 19
complete error vector by toggling all bits one after another. Note that this attack
cannot be applied straightforwardly to Niederreiter, since toggling a bit in a Niederreiter
ciphertext typically renders it undecodable.
Research on side channels in code-based cryptosystems needs to be intensified, but the
existing papers already provide valuable advice on common pitfalls and countermeasures.
Although side channel attacks are not in the focus of this thesis, we will come back to
the topic in the following chapters where necessary.
3.1 Preliminaries
In this section, we briefly reiterate important concepts that form the basis of Coding
theory. Unless otherwise noted, it is based on on several papers by Heyse (e.g. [Hey09])
and a thesis written by Hoffmann [Hof11].
Finite fields Most linear codes rely on the algebraic structure of finite fields – also
named Galois Fields – to form the code alphabet.
A finite field is a set of a finite number of elements for which an abelian addition and
abelian multiplication operation is defined and distributivity is satisfied. This requires
that the operations satisfy closure, associativity and commutativity and must have an
identity element and an inverse element.
A finite field with q = pm elements is denoted Fpm or GF(pm ) or Fq , where p is a prime
number called the characteristic of the field and m ∈ N . The number of elements is called
order. Fields of the same order are isomorphic. Fpm is called an extension field of Fp
and Fp is a subfield of Fpm . α is called a generator or primitive element of a finite field if
every element of the field F∗pm = Fpm \{0} can be represented as a power of α. Algorithms
for solving algebraic equations over finite fields exist, for example polynomial division
using the Extended Euclidean Algorithm (EEA) and several algorithms for finding the
roots of a polynomial. More details on finite fields can be found in [HP03].
Polynomials over Finite fields Here we present some definitions and algorithms con-
cerning polynomials with coefficients in F.
Polynomials over finite fields can be manipulated according to the well-known rules for
transforming algebraic expressions such as associativity, commutativity, distributivity.
Apart from the trivial addition and multiplication, also a polynomial division can be
defined, which is required for the EEA that is used by the decoding algorithms shown
in Section 3.4.
Definition 3.1.5 (GCD) The greatest common divisor gcd(f, g) of two polynomials
f, g in F is the polynomial of highest possible degree that evenly divides f and g.
The GCD can be efficiently computed recursively using the Euclidean algorithm, which
relies on the relation gcd(f, q) = gcd(f, f + rg) for any polynomial r. The Extended
Euclidean Algorithm shown in Alg. 3.1.1 additionally finds polynomials x, y in F that
satisfy Bézout’s identity
Analogous to the usage of EEA for the calculation of a multiplicative inverse in a finite
field, EEA can be used to calculate the inverse of a polynomial a(z) mod b(z) in a field
F. Then, x(z) is the inverse of a(z) mod b(z), i.e. a(z)x(z) mod b(z) ≡ const.
Definition 3.2.1 (Linear block code) A linear block code C is an injective mapping
Σk → Σn of a string of length k over some alphabet Σ to a codeword of length n. Recall
from Section 2.1 that C is called a [n, k, d] code if the minimal code word distanceApp. B.2.2
is dmin = minx,y ∈ C dist(x, y), where dist denotes a distance function, for example Ham-
ming distanceApp. B.2.1 . The distance of x to the null-vector wt(x) := dist(0, x) is called
weight of x.
Definition 3.2.2 (Codes over finite fields) Let Fnpm denote a vector space of n tu-
ples over Fpm . A (n, k)-code C over a finite field Fpm is a k-dimensional subvectorspace
of Fnpm . For p = 2, it is called a binary code, otherwise it is called p-ary.
Generator matrix and parity check matrix A convenient way to specify a code is to
give a generator matrix G whose rows form a basis of C. A codeword c representing
a message m of length n can be computed as c = m · G. Note that in general G is
not uniquely determined and an equivalent code can be obtained by performing linear
transformations and a permutation. Equivalently, the code can be defined using a parity
check matrix H with G · H T = 0.
As long as less errors than the error-correction capability t of the code occured, a
syndrome uniquely identifies all errors, thus allowing the decoding of the erroneous
codeword by the means of an syndrome decoding algorithm. The syndrome equation is
satisfied by all 2k possible error patterns e, however patterns with a low number of errors
are usually more likely. Hence, in practice a maximum-likelihood-principle is applied, so
the decoder tries to find the codeword with the minimum hamming distance to the
recieved vector ĉ. Syndrome decoding uses the linearity of the code to allow a minimum
distance decoding with a reduced lookup table for the nearest match. Section 3.4 presents
two decoding algorithms which have been implemented for this thesis.
Polynomial codes Codes that use a fixed and often irreducible generator polynomial
for the construction of the codeword are called polynomial codes. Valid codewords are
all polynomials that are divisible by the generator polynomial. Polynomial division of a
recieved message by the generator polynomial results in a non-zero remainder exactly if
the message is erroneous.
Cyclic codes A code is called cyclic if for every codeword cyclic shifts of components
result in a codeword again. Every cyclic code is a polynomial code.
Generalized Reed-Solomon GRS codes are a generalization of the very common class
of Reed-Solomon (RS) codes. While RS codes are always cyclic, GRS are not necessarily
cyclic. GRS codes are Maximum Distance Separable (MDS) codes, which means that
3.2 Linear block codes 25
they are optimal in the sense of the Singleton bound, i.e. the minimum distance has the
maximum value possible for a linear (n, k)-code, which is dmin = n − k + 1.
For some polynomial f (z) ∈ Fpm [z]<k , pairwise distinct elements L = (α0 , . . . , αn−1 ) ∈
Fnpm , non-zero elements V = (v0 , . . . , vn−1 ) ∈ Fnpm and 0 ≤ k ≤ n, GRS code can be
defined as
Alternant codes An alternant matrix has the form Mi,j = fj (αi ). Alternant codes use
a parity check matrix H of alternant form and have a minimum distance dmin ≥ t + 1
and a dimension k ≥ n − mt. For pairwise distinct αi ∈ Fpm , 0 ≤ i < n and non-zero
vi ∈ Fpm , 0 ≤ j < t, the elements of the parity check matrix are defined as Hi,j = αij vi .
Alternant codes are subfield subcodes of a GRS codes, i.e. they can be obtained by
restricting GRS-codes to the subfield Fp :
Generalized Srivastava codes Generalized Srivastava (GS) codes [Per12] are alternant
codes that use a further refined alternant form for the parity check matrix H. For
s, t ∈ N, let αi ∈ Fpm , 0 ≤ i < n and wi ∈ Fpm , 0 ≤ i < s be n + s pairwise distinct
elements and let vi ∈ Fpm , 0 ≤ j < t be non-zero. A GS code of length n over Fpm with
26 3 Coding theory
Goppa codes Goppa codes are alternant codes over Fpm that are restricted to a Goppa
polynomial g(z) with deg(g) = t and a support L with g(αi ) 6= 0∀i. Here, g is just another
representation of the previously used tuple of non-zero elements V and polynomial f (z).
Hence, a definition of Goppa codes can be derived from the definition of GRS codes as
follows:
The minimum distance of a Goppa code is dmin ≥ t + 1, in case of binary Goppa codes
with an irreducible Goppa polynomial even dmin ≥ 2t + 1. Details for constructing and
decoding Goppa codes are given in Section 3.3.
BCH codes, RM codes, RS codes There exist several important special cases of Goppa
codes (which have been first described in 1969), most prominently BCH codes (1959),
Reed-Muller codes (1954) and Reed-Solomon codes (1960). For example, primitive BCH
codes are just Goppa codes with g(z) = z 2t [Ber73].
Definition 3.3.1 Let m and t be positive integers and let the Goppa polynomial
t
gi z i ∈ F2m [z]
X
g(z) = (3.5)
i=0
be a subset of n distinct elements of F2m . For any vector ĉ = (c0 , · · · , cn−1 ) ∈ Fn2m , in
accordance with Definition 3.2.5 we define the syndrome of ĉ as
n−1
X ĉi g(z) − g(αi )
Sĉ (z) = − mod g(z). (3.7)
i=0
g(αi ) z − αi
In continuation of Eq. 3.4, we now define a binary Goppa code over F2m using the
syndrome equation. c ∈ Fn2m is a codeword of the code exactly if Sc = 0:
n−1
ci
Goppan,k,2 (L, g(z)) := { c ∈ Fn2m | Sc (z) =
X
≡ 0 mod g(z)}. (3.8)
i=0
z − αi
If g(z) is irreducible over F2m then Goppa(L, g) is called an irreducible binary Goppa
code. If g(z) has no multiple roots, then Goppa(L, g) is called a separable code and g(z)
a square-free polynomial.
g(α0 )
0
g(α1 )
0
··· g(αn−1 )
Note that it can be shown that ω(z) = σ ′ (z) is the formal derivative of the error
locator polynomial.
Since the Patterson algorithm is designed only for binary Goppa codes, ω(z) does not
occur there explicitly. Nevertheless, both algorithms implicitly or explicitly solve the
following key equation
ω(z) ≡ σ(z) · S(z) mod g(z). (3.14)
3.4 Decoding algorithms 29
X ĉα X eα
S(z) ≡ mod g(z) ≡ mod g(z) (3.15)
α∈F2m
z − αi α∈F2m
z − αi
Both methods and a third, more efficient variant were implemented and are described
in Section 4.6.1.
3.4.3 Berlekamp-Massey-Sugiyama
The Berlekamp-Massey algorithm was proposed by Berlekamp in 1968 and works on
general alternant codes. The application to LFSRs performed by Massey is of less
importance to this thesis. Compared to the Patterson algorithm, BM can be described
and implemented in a very compact form using EEA. Using this representation, it is
equivalent to the Sugiyama algorithm [SKHN75].
BM returns an error locator polynomial σ(z) and error value polynomial ω(z) satisfying
the key equation Eq. 3.14. Applied to binary codes, σ(z) does not need to be taken into
account.
Then, he constructs a relation between σ(z) (Eq. 3.12) and ω(z) (Eq. 3.13) and the
known Si by dividing ω(z) by σ(z).
∞
ω(z) X yj xj z
Si z m
X
=1+ =1+ (3.16)
σ(z) j
1 − x j z i=1
where xi are the error positions and yi the error values known from Section 3.4.1.
Thus, he obtains the key equation
(1 + S(z)) · σ ≡ ω mod z 2t+1 (3.17)
already known from Section 3.4.1.
For solving the key equation, Berlekamp proposes “a sequence of successive approxi-
mations, ω (0) , σ (0) , ω (1) , σ (1) , . . . , σ (2t) , ω (2t) , each pair of which solves an equation of the
form (1 + S(z))σ (k) ≡ ω (k) mod z k+1 ” [Ber72].
The algorithm that Berlekamp gives for solving these equations was found to be very
similar to the Extended Euclidean Algorithm (EEA) by numerous researchers. Dornstet-
ter proofs that the iterative version of the Berlekamp-Massey “can be derived from a nor-
malized version of Euclid’s algorithm” [Dor87] and hence considers them to be equivalent.
Accordingly, BM is also very similar to the Sugiyama Algorithm [SKHN75], which sets up
the same key equation and explicitly applies EEA. However, Bras-Amorós and O’Sullivan
state that BM “is widely accepted to have better perfomance than the Sugiyama algo-
rithm” [BAO09]. On the contrary, the authors of [HP03] state that Sugiyama “is quite
comparable in efficiency”.
For this thesis, we decided to implement and describe BM using EEA in order to
keep the program code size small. Then, the key equation can be solved by applying
EEA to S(z), G(z)), which returns σ and ω as coefficients of Bézouts identity given in
Eq. 3.1. The error positions xi can be determined by finding the roots of σ, as shown in
Section 3.5. For non-binary codes, also ω needs to be evaluated to determine the error
values. This can be done using a formula due to Forney [For65], which computes the
error values as
ω(x−1
i )
ei = − (3.18)
σ (x−1
′
i )
3.4 Decoding algorithms 31
BM and t-error correction The Patterson algorithm is able to correct t errors for
Goppa codes with a Goppa polynomial of degree t, because the minimum distance of
a separable binary Goppa code is at least dmin = 2t + 1. This motivates the search
for a way to achieve the same error-correction capability using the Berlekamp-Massey
algorithm, which by default does not take advantage of the property of binary Goppa
codes allowing t-error correction.
Using the well-known equivalence [MS78]
which is true for any square-free polynomial g(z), we can construct a syndrome poly-
nomial of degree 2t based on a parity check matrix of double size for Goppa(L, g(z)2 ).
Recall that the Berlekamp-Massey algorithm sets up a set of syndrome equations, of
which only S1 , . . . , St are known to the decoder. Using BM modulo g(z)2 produces 2t
known syndrome equations, which allows the algorithm to use all inherent information
provided by g(z). This allows the Berlekamp-Massey algorithm to correct t errors and is
essentially equivalent to the splitting of the error locator polynomial into odd and even
parts in the Patterson algorithm, which yields a ‘new’ key equation as well.
3.4.4 Patterson
In 1975, Patterson presented a polynomial time algorithm which is able to correct t errors
for binary Goppa codes with a designed minimum distance dmin ≥ 2t + 1. Patterson
achieves this error-correction capability by taking advantage of certain properties present
in binary Goppa codes [EOS06], whereas general decoding algorithms such as BM can
only correct 2t errors by default.
Preliminaries Alg. 3.4.2 summarizes Patterson’s algorithm for decoding the syndrome
of a vector ĉ = c + e ∈ Fn2m using a binary Goppa code with an irreducible Goppa
polynomial g(z) of degree t. c is a representation of a binary message m of length k,
which has been transformed into a n bit codeword in the encoding step by multiplying m
with the generator matrix G. The error vector e has been added to c either intentionally
like in code-based cryptography, or unintendedly, for example during the transmission
of c over a noisy channel. The Patterson algorithm ensures the correction of all errors
only if a maximum of t errors occured, i.e. if e has a weight wt(e) ≤ t.
Solving the key equation The Patterson algorithm does not directly solve the key
equation. Instead, it transforms Eq. 3.14 to a simpler equation using the property
ω(z) = σ ′ (z) and the fact that yi = 1 at all error positions.
X Y
ω(z) ≡ σ(z) · S(z) ≡ xi (1 − z) mod g(z) (3.20)
i∈E j6=i∈E
3.5 Extracting roots of the error locator polynomial 33
Now, formal derivation and application of the original key equation yields
Choosing g(z) irreducible ensures the invertibility of the syndrome S. To solve the
equation for a(z) and b(z), we now compute an inverse polynomial T (z) ≡ Sĉ (z)−1
mod g(z) and obtain
If T (z) = z, we obtain the trivial solutions a(z) = 0 and b(z)2 = zb(z)2 ·S(z) mod g(z),
yielding σ(z) = z. Otherwise we use an observation by [Hub96] for polynomials in F2m
giving a simple expression for the polynomial r(z) which solves r(z)2 ≡ t(x) mod g(z).
To 2
p satisfy Hubers equation, we set R(z) ≡ T (z) + z mod g(z) and obtain R(z) ≡
T (z) + z. Finally, a(z) and b(z) satisfying
can be computed using EEA and applied to Eq. 3.21. As deg(σ(z)) ≤ g(z) = t, the
equation implies that deg(a(z)) ≤ ⌊ 2t ⌋ and deg(b(z)) ≤ ⌊ t−1
2 ⌋ [Hey08, OS09]. Observing
the iterations of EEA (Alg. 3.1.1) one finds that the degree of a(z) is constantly decreas-
ing from a0 = g(z) while the degree of b(z) increases starting from zero. Hence, there is
an unique point where the degree of both polynomials is below their respective bounds.
Therefore, EEA can be stopped at this point, i.e. when a(z) drops below 2t .
As stated already in Section 3.4.1, the roots of σ(z) = ti=0 σi z i are elements of the
P
support L, where the position of the roots inside of L correspond to the error positions in
ĉ. Let L(i) denote the field element at position i in the support and L−1 (i) the position
of the element i in the support. Then, for all 0 ≤ i < n the error vector e = (e0 , . . . , en−1 )
is defined as
(
1 σ(L(i)) ≡ 0
ei = (3.27)
0 otherwise
timing side channel vulnerability, similar to the stop of the algorithm after t errors have
been found.
Let ai,j denote (αi )j · σj . From the above equations we obtain ai+1,j = ai,j · αj and thus
σ(αi ) = tj=0 ai,j = ai,0 + ai,1 + · · · + ai,t = σ0 + σ1 · αi + · · · + σt · (αi )t . Hence, if
P
Pt i −1 i
j=0 ai,j = 0, then α is a root of σ(z), which determines an error at position L (α ).
Note that the zero element needs special handling, since it cannot be represented as an
αi ; this is not considered in Alg. 3.5.2.
Chien search can be used to perform a bruteforce search over all support elements,
similar to the previous algorithm using Horner scheme. However, the search has to be
performed in order of the support, since results of previous step are used.
For small m and some fixed t, this process can be efficiently implemented in hard-
ware, since it reduces all multiplications to the multiplication of a precomputed constant
αj ∀ 1 ≤ j ≤ t with one variable. Moreover, all multiplications of one step can be
executed in parallel.
However, this is of little or no advantage for a software implementation. In the worst
case, Chien search requires (pm − 1) × t multiplications and additions, which is identical
or even worse than the bruteforce approach using Horner.
As before, the search can be stopped as soon as t errors have been found, at the price
of introducing a potential side channel vulnerability.
and maps elements of Fpm to Fp . This can be used to uniquely represent any element α ∈
Fpm using a basis B = (β1 , . . . , βm ) of Fpm over Fp as a tuple (Tr(βi · α), . . . , Tr(βm · α)).
Berlekamp prooves that
Y
f (z) = gcd(f (z), Tr(βi z) − s) ∀ 0 ≤ j < m (3.29)
s∈Fp
where gcd(·) denotes the monic common divisor of greatest degree. Moreover, he shows
that at least one of these factorizations is non-trivial. Repeating this procedure recur-
sively while iterating on βi ∈ B until the degree of each factor is 1 allows the extraction
of all roots of f (z) in O(mt2 ) operations [BH09]. If BTZ is used, proceed with Zinovievs
algorithms as soon as degree dz is reached, instead of factorizing until degree 1.
Alg. 3.5.3 shows the BTZ algorithm, but omits all details of Zinoviev’s algorithms.
The first call to the algorithm sets i = 1 to select β1 and f = σ(z) and the error vector e
to zero. Note that the polynomials Tr(βi z) mod f (z) ∀ 0 ≤ i < m can be precomputed.
the modular addition c = ĉ + e. For binary codes, e is a binary vector and the addition
can be performed using a XOR operation, i.e. flipping all bits in ĉ corresponding to the
error positions in e.
For the McEliece cryptosystem, the message is restored from the codeword by comput-
ing a pseudo-inverse G−1 of the generator matrix G and multiplying it with the codeword:
m̂ ← c · G−1 . If a systematic generator matrix has been used, c can be mapped to m
simply by removing the appended parity data.
In the Niederreiter cryptosystem, constant weight encoding (see Section 4.7) is used
to encode the message into the error vector instead of into the codeword. To restore the
message, the reverse operation needs to be applied.
4 Implementation
In this chapter, we present some aspects of the implementation of our Code-based cryp-
tography library. It includes implementations of both the McEliece and Niederreiter cryp-
tosystems with Berlekamp-Massey (BM) and Patterson as possible decoding algorithms,
the CCA2-secure conversion by Kobara-Imai and Fujisaki-Okamoto, root searching al-
gorithms by Chien, Berlekamp and Horner as well as several options for algorithmical
details such as the manner of syndrome decoding. Parameter sets for 60-, 80-, 128- and
256-bit security are predefined, but the library is not limited to these sets. Unfortunately,
to date the library is restricted to binary codes. In this chapter, we will however point
out where changes are necessary to deal with q-ary codes.
The implementation is written in plain C code, apart from a small precompilation
script written in Python for the sake of simplicity, and some parts in Assembly code
mostly belonging to the included implementation of the SHA3 hash function.
Our main target platform is the frequently used AVR ATxmega256A3, which is an
8-bit RISC microcontroller operating at a clock frequency of up to 32 MHz. With 16
kBytes SRAM and 256 kBytes flash memory, it provides a comparably large amount of
memory space, but apart from that it is a relatively simple device. This decision was
made to prove that Code-based cryptography is actually usable in any context, including
applications in the huge field of low-priced embedded devices with limited ressources.
The implementation was developed using the open source IDE Code::Blocks 10.05 and
compiled using the AVR 8-bit GNU Toolchain avr-gcc 4.6.2 respectively gcc 4.4.3 for
x86 computers. Communication with the device was performed via JTAG using avrdude
5.1 for programming and via UART using screen for all I/O.
This chapter is organized as follows. First the reader is introduces to some peculiari-
ties concerning memory management on the AVR platform in Section 4.1. Section 4.2
describes consequences drawn from the time-memory conflict fueled by the large key sizes
in Code-based cryptography and shortly deals with secure storage on microcontrollers.
Section 4.3 first introduces the gf_t and poly_t types and then describes how lookup tables
and the FASTFIELD switch speed up the basic blocks of our implementation. matrix_t is
the third important data structure, which is presented in Section 4.4 before discussing the
key generation and key management. Encryption is discussed in Section 4.5 and decryp-
tion including the Patterson and Berlekamp-Massey decoding algorithms in Section 4.6.
Afterwards, constant weight encoding is introduced briefly in Section 4.7. Finally, we
present the CCA2-conversions by Kobara-Imai and Fujisaki-Okamoto in Section 4.8.
40 4 Implementation
of this thesis. This prohibits us for example from using time-memory tradeoffs in some
places, including an broader use of function inlining. Furthermore, we decided to avoid
any call to alloc in order to prevent heap fragmentation, which is a common problem
on memory-constrained devices. Hence, all parameters need to be known at compile
time. Also the choice of algorithms for decoding, root searching and so on is fixed at
compile time in order to allow the compiler to ban any unneeded function from wasting
program memory1 .
Nevertheless, for Code-based cryptography to be become an accepted alternative to
conventional cryptosystems, implementations still need to have an acceptable speed.
Since finite field arithmetic is used intensively throughout the entire system, we decided
to retain the common practice of speeding up field arithmetic by using lookup tables of
field elements, although they require 16 kB for parameters as above.
Another issue that needs to be considered is the secure storage of the secret key. For
this purpose, we rely on the lock-bit feature provided by AVR microcontrollers. Once
the lock bit for a code region is set to deny all read access, it can only be unset by a
complete chip erase, removing all data from flash memory. Note that it might still be
possible to extract key data using side channel attacks or sophisticated invasive attacks,
given enough time and ressources.
The implementation requires a random source at several occasions, for instance in
the key generation algorithm, but also during encryption. Since the AVR has no true
random number source, we use the the AVR libc rand() function and seed it using the
least significant bits of an unconnected A/D converter. As an alternative (or additional)
random source, uninitialied SRAM values could be used. However, this ensures no
cryptographically secure random. Realword applications should therefore use a more
sophisticated approach, for example involving the AVR crypto modules to construct a
cryptographically secure PRNG.
Exponential representation The exponential representation uses the fact that every
field element except zero can be represented as a power of the generator element α, such
that a = αi where 0 ≤ i < pm − 1. This representation allows for example an efficient
m
multiplication of two elements a = αx , b = αy as a·b ≡ αx ·αy ≡ αx+y mod p −1 . Division
m
works analogously by substracting the exponents (αx−y mod p −1 ). Squaring can be
m
implemented as a left shift in the exponent ((αx )2 ≡ αx<<1 mod p −1 ). Exponentiations
are computed using Square & Multiply. Square roots can be computed as a right shift
if the exponent is even, otherwise by a sequence of left shifts and modulo reductions.
m
Inversion is a simple negation of the exponent ((αx )−1 ≡ α−x mod p −1 ).
For exponential representation, it is useful to store the field element in form of its
exponent. For typical parameters in the binary case, the exponent happens to fit in
the same two-byte value as the polynomial representation. The ability to store both
representations in the same datatype gf_t is advantageous in many cases due to the
frequent conversions, so we decided to use gf_t in both cases. However, in the non-
binary case, a separate type for the different representations seems more useful, requiring
refactoring mainly of the gf_* and some poly_* functions.
m
GFEXP(i) returns the element x generated by αi . The zero element is inserted as αp −1 ,
m m
which would usually refer to the first element again, since αp −1 mod p −1 ≡ α0 . Hence,
the tables contain GFLOG(0)= pm − 1 and GFEXP (pm − 1) = 0. This always needs to be
handled as a special case.
The table for polynomial representation requires at least pm ·log2 (p)·m bits of memory.
In practice, there is an overhead. In the binary case, we use two bytes per field element,
thus having an overhead of 16 − m bits per element, where m is typically ≤ 13. In the
non-binary case, the overhead also depends on the number of bits used per coefficient.
For the exponential representation table, we need to store an exponent for each field
element, which typically fits in two bytes. Hence the table uses pm · 16 bits of memory.
Since these lookup tables are too big to fit in SRAM for typical parameters, they are
precomputed and stored in ‘near’ flash memory, below the 64 KByte boundary.
rows × ⌈cols/8⌉ bytes. For convenience, ⌈cols/8⌉ is stored in an additional struct field
words_per_row .
If cols is not divisible by 8, each row has an overhead of up to 7 bit.
For binary matrices, access to matrix_t occurs mostly on bit level, but there are several
instances where efficient row-wise XORs can be used, for example during Gauss-Jordan
elemination or vector-matrix multiplication.
The best access time could be achieved using the straightforward approach using
an array of dimension rows × columns with one element per column. While this would
present an disproportionate overhead in the binary case, it may be appropriate for larger
non-binary parameters. However, for small fields up to F15 it seems more reasonable
to combine multiple matrix elements into one array element, as done in the binary case.
Then, the MATRIX_GET, MATRIX_SET macros would need to be adapted to accept and return
values of desired length.
then derived directly from H2 . The reverse operation is performed during the generation
of the syndrome polynomial from the binary syndrome vector.
• In the Niederreiter cryptosystem, the systematic parity check matrix H forms the
public key, while the computation of G is not required. However, Niederreiter
requires the matrix S to be retained, which brings the parity check matrix to
systematic form, since it is needed for decryption. Hence, the secret key is identical
to the McEliece secret key with the addition of S.
The key generation is typically not executed on the device due to the high memory
requirements. Note that for typical parameters, it is impossible to fit the key generation
data into SRAM (16 kByte) or EEPROM (4 kByte) completely. Hence, the implemen-
tation would need to write to the flash memory during execution of the code, which is
possible due to a feature called Self programming Program memory that all recent AVR
46 4 Implementation
• Select an irreducible monic polynomial. Although there are faster methods for
constructing irreducible polynomials [Sho93], we opted for the simple yet effective
method of choosing a polynomial at random and then testing its irreducibility
using Rabin’s algorithm [Rab80].
• Next, the support is selected. If n was chosen to be pm , the support consists of all
field elements of Fpm . Otherwise, only n of pm elements are chosen. In both cases,
the elements are chosen in random order to obtain a permuted support, which
inherits the role of the permutation matrix P originally used by McEliece.
Note that all data that is not discarded needs to be allocated outside the key generation
function if alloc is to be avoided, either as a global variable or in some superior function.
For this implemetation, we decided to define macros KEYGEN_INIT respectively KEYGEN_LOAD ,
which allocate respectively references the required memory chunks as arrays and are
4.5 Encryption 47
called in the main function. For easy handling, all key-related variables are combined
in a struct called cryptocontainer which is provided as an argument to all functions that
require some of the contained data. This was done mainly to provide a streamlined
interface to all functions independent of the currently selected variant, without spilling
the global namespace.
4.5 Encryption
Remember from Chapter 2 that encryption for both McEliece and Niederreiter involves
an encoding step, a straightforward vector-matrix multiplication and for McEliece the
addition of an error vector to the multiplication result.
4.5.1 Encoding
Encoding a plaintext message M of length x bits for the McEliece cryptosystem is the
process of splitting M into parts of length ≤ k bits. Although no standard procedure
has been introduced so far, the most obvious way to handle message parts with less than
k bits is to pad them with zeros. As a proof of concept, this has been implemented
using the functions matrix_readbits() and matrix_writebits(), which use the matrix_t type to
provide bit-wise access to a file or a memory buffer of arbitrary length. However, for
the evaluation we concentrate on the encryption of fixed-size blocks. The encryption
of arbitrary length data has not been optimized or evaluated for security in any way.
Instead, a focus has been placed on the CCA2-secure conversion, which also deals with
the conversion of a message to an ciphertext in a secure way. It will be discussed in
Section 4.8.
In the Niederreiter scheme, the encoding step is more complex, since the message
needs to be encoded in a vector of length n with the constant weight t. This will be
discussed in Section 4.7.
4.5.2 Multiplication
A multiplication of a plaintext vector with a matrix belonging to the public key occurs in
both McEliece and Niederreiter. In McEliece, the plaintext vector is a codeword m and
the matrix is the systematic generator matrix G, whereas the plaintext in Niederreiter is
the error vector e and the matrix is the transposed systematic parity check matrix H T .
Listing 4.3 shows the encryption in the case of McEliece and illustrates the usage of
flash memory beyond the 64 kByte boundary, as described in Section 4.1. In the binary
case, the multiplication m · G the multiplication is reduced to a row-wise XOR: if a bit
in the plaintext is set, XOR the corresponding row of G to the ciphertext. Due to the
matrix_t design, a row-wise XOR can be performed efficiently byte-wise, whereas the XOR
of a row and a column would have to be executed bit by bit. Therefore the generator
matrix is stored in transposed form. Note that only the non-identity part of G is stored,
and the multiplication of the plaintext vector with the identity part has no effect. Hence,
48 4 Implementation
the ciphertext c does not hold the entire codeword resulting of the multiplication but
only the parity part, while the other part is available as the unchanged plaintext.
1 uint32_t G = FAR(KEYMATRIX); // KEYMATRIX address known at compile-time
2 MATRIX_DATATYPE *c = ciphertext->data; // pointer to ’data’ element of matrix_t
3 for(i=0;i<GOPPA_k;i++){
4 // if bit (i.e. column) i in plaintext is set, XOR line i of matrix G to ciphertext
5 if(MATRIX_ISSET(plaintext, 0, i))
6 {
7 for(w=0;w<GENERATORMATRIX_WORDS_PER_ROW;w++) // iterate over every word of the current row
8 {
9 MATRIX_DATATYPE x = pgm_read_byte_far(G+w);
10 c[w] ^= x;
11 }
12 }
13 G+=GENERATORMATRIX_WORDS_PER_ROW; // points now to next row
14 }
In the non-binary case, the row-wise XOR needs to be replaced with the slower element-
wise standard matrix multiplication modulo p, since the matrix elements belong to Fp .
4.6 Decryption
Decryption in McEliece and Niederreiter is essentially the process of decoding the syn-
drome in order to find the error positions and if necessary the error values. In this
section, we discuss implementational aspects of the decoding steps, which are roughly
illustrated for all variants in the overview in Fig. 4.2.
Figure 4.2: Overview on variants of the decryption process in McEliece and Niederreiter
In the McEliece scheme, the syndrome needs to be computed from the ciphertext. This
can be done either by computing c · H T or by computing the relevant elements of H on
the fly, avoiding the problem of holding the matrix in memory completely.
The ciphertext in the Niederreiter scheme is already a syndrome. However, the ‘scram-
bling’ caused by the transformation of the public key to a systematic first needs to be
reverted. This is done by multiplying the syndrome with the reverse scrambling matrix
S −1 which is part of the secret key. Moreover, to allow the Berlekamp-Massey (BM)
algorithm to correct all errors in the binary case, the syndrome needs to be transformed
to double length using Eq. 3.19.
In all cases, the result of these operations is a binary version of the syndrome, which
needs to be turned into a polynomial. This is a straightforward process, since the
binary version is a simple concatenation of fixed-width bit strings holding the binary
representation of the polynomial coefficients.
4.6 Decryption 51
Syndrome I (SYN_H) The most simple variant of computing the syndrome is the straight-
forward multiplication of the ciphertext ĉ = c+e with a precomputed (or newly generated
from the Goppa polynomial and support) parity check matrix H T . We skip this variant
here, since its implementation contains no new ideas. Note however that the multipli-
cation must be performed using the double-sized parity check matrix based on g(z)2 if
BM for binary codes is used afterwards.
Syndrome II (SYN_EEA) From the syndrome definition and Eq. 3.7 we know that a syn-
drome satisfies the equation
n−1
X 1
Sĉ (z) ≡ mod g(z). (4.1)
i=0
z − αi
Hence, the syndrome can be computed by iterating over all support elements and invert-
ing z − αi using EEA, as shown in Listing 4.5.
If BM is used, sk->goppapoly holds g(z)2 instead of g(z) and the syndrome vector syn is
of double length. The same applies to the third variant.
Syndrome III (SYN_INVZA) The third variant is similar to the previous, but applies a trick
described in [Pau10] to invert the polynomial without using EEA. Denoting the Goppa
52 4 Implementation
Pt i,
polynomial as g(z) = i=0 gi z the following relation holds:
t
1 1
gj αj−s−1
X
≡ i mod g(z), ∀ 0 ≤ s < t − 1 (4.2)
z − αi g(αi ) j=s+1
Considering that g(z) is monic, the syndrome can be computed as shown in Listing 4.6
using less operations than in the SYN_EEA variant.
Side channel attacks on the syndrome computation The recent side channel analysis
by Schacht [Sch12] also evaluates the three syndrome computation variants presented
here. An attacker is able to reconstruct the secret key if he can extract the support
L or Goppa polynomial g(z) by observing side channels like execution time or power
consumption. Given L and some valid codewords, g(z) can be recovered using GCD
and Eq. 3.15 [Uma11] or using the SSA [LS01]. SSA can also be used to compute L
given g(z) and the public key by constructing a generator matrix G′ from g(z) using an
arbitrarily chosen L̂ and applying SSA to G′ and G [LS01].
Schacht shows that effective side channel attacks are possible on the syndrome decod-
ing variants implemented for the classical McEliece scheme by reconstructing the secret
permutation P . However, in the modern version implemented for this thesis, P does not
exist anymore explicitly and hence cannot be recovered. The data-dependent instruc-
tions exploited in the attack on the classical version depend only on the ciphertext in the
modern version. Since the ciphertext is public anyway, the attacker draws no advantage
from this.
However, there are also attack vectors on the modern version. Even if any data-
dependent instruction has been successfully avoided, data leaks are possible, for example
due to the fact that the memory consumption of a transfer of a word on a data-bus
depends on the value of the word. However, Schacht points out that these differences
are far more difficult to exploit and do not provide enough information to recover the
secret key completely, but only reduce the search space for an exhaustive key search.
4.6 Decryption 53
key matrices in Section 4.4, or it needs to be live-computed. We opt for the first variant
in order to avoid the repeated computational expensive computation during decryption.
into an odd and even part T (z) + z = R0 (z)2 + z · R1 (z)2 is a simple coefficient-wise
operation. Thanks to Huber it is known that for every g(z) there exists a polynomial
W (z) with W (z)2 ≡ z mod g(z) such that R(z) ≡ R0 (z) + W (z) · R1 (z) mod g(z).
W (z) can be computed by splitting the Goppa polynomial into odd and even parts
and using EEA to compute polynomials a, b such that 1 ≡ b · g0 (z) + a · g1 (z). Then,
W (z) can be computed as W (z) = b(z) · g0 (z) + za(z) · g1 (z).
1 void poly_split(poly_t p, poly_t even, poly_t odd){
2 uint16_t d = p->deg/2;
3 for(i=0;i<d;i++){
4 even->coeff[i] = gf_sqrt(p->coeff[2*i]);
5 odd->coeff[i] = gf_sqrt(p->coeff[2*i+1]);
6 }
7 even->coeff[d] = gf_sqrt(p->coeff[2*d]);
8
9 if(xmod2(p->deg,2)) // if deg(p) odd
10 odd->coeff[d] = gf_sqrt(p->coeff[p->deg]); // 2*i+1
11 }
12
13 /// Precomputation of W(z) for decode_patterson_huber
14 void decode_patterson_huber_precompute(crypt_t sk){
15 poly_split(sk->goppapoly, even, odd); // split g(z)
16 poly_eea(even, odd, a, b, 0); // 1 = b * even(z) + a * odd(z)
17 // w(z) = b(z) * even(z) + z * a(z) * odd(z) = w0(z) + z * w1(z)
18 poly_mul(even, b, w0);
19 poly_mul(odd, a, w1);
20
21 // compute W(z)
22 W->coeff[0] = w0->coeff[0];
23 for(i=1;i<degree;i++)
24 w->coeff[i] = gf_add(w0->coeff[i], w1->coeff[i-1]);
25 }
26
27 /// Square root of p(z) mod g(z) (for rings of characteristic 2)
28 void decode_patterson_huber(crypt_t sk, poly_t p, poly_t result){
29 poly_split(p, even, odd);
30 poly_mul(odd, sk->patterson_huber_w, tmp);
31 poly_mod(tmp, sk->goppapoly);
32 poly_add(tmp, even, result);
33 }
Note that W (z) depends only on the Goppa polynomial, hence it can be precomputed
at startup. Listing 4.8 shows the implementation of the three relevant functions for the
computation of R(z).
One can see that z always occurs in powers of p. Hence, the Trace polynomial has
degree pm−1 , but only m coefficients are unequal to zero. Moreover, one can see that
the Trace polynomial is cyclic: the coefficient of z 2 in Tr(β1 z) is the coefficient of z
in Tr(β2 z), and so on. Hence, the ‘next’ Trace polynomial can be computed from the
i
previous one by performingm a cyclic shift of the coefficients of z p from the higher to the
lower coefficient. Since βip = βi in F210 , the Trace polynomials repeat after m steps,
i.e. Tr(βm+1 z) = Tr(β1 z).
Therefore we decided to precompute only Tr(β1 z) and to store only the m coefficients
unequal to zero. However, there is a problem remaining: if we want to retain a low mem-
ory footprint throughout the BTA procedure, we need to be able to actually work with
the sparse representation during the BTA computations. Therefore, we implemented
two versions of BTA:
• The computation of the polynomial greatest common divisor gcd(Tr(βi · z), σ(z))
consists of a repeated modular reduction of the trace polynomial modulo σ(z).
Hence it is possible to perform such a reduction in advance using an algorithm
that is able to work with sparse polynomial representations. Observing that our
usual polynomial reduction function poly_mod works on a steadily moving window of
only t + 1 elements of the input and output polynomial, we implemented a sparse
polynomial reduction function poly_sparsemod . Using this approach, the expanded
polynomial is used at no stage, hence all polynomials have a degree of t or less. It
can be activated using the ROOT_BTA_SPARSE switch.
• Otherwise, in every recursion the algorithm has to expand the sparse representa-
tion to a polynomial of full degre pm−1 . For 128-bit security parameters, such a
polynomial has a size of 4 kB, which makes up 25% of the SRAM available on our
target platform. However, a memory area shared across all recursion levels can be
used for the expanded polynomial in all recursion levels. Implemented this way the
big polynomial has to be allocated only once, instead of once at every recursion
level.
Listing 4.9 shows relevant code parts of the Trace polynomial precomputation, usage
in BTA and the modular polynomial reduction.
bytes and stored in the configuration macro CWBYTES. However, depending on n and t it
has to be adjusted by a few bytes.
Apart from the rewrite to an iterative algorithm, the main idea of Heyse’s modification
is to avoid floating point arithmetic and division operations. This is done by modifying
the procedure to compute an optimal value for the parameter d, which determines how
many message bits are to be encoded into the current block of zeros. d depends on n
and t, which constantly decrease until the encoding algorithm terminates. Originally, d
is computed as
t−1 1 ln(2) t−1
d≈ n− 1− ≈ n−
2 21/t t 2
where the second approximation holds only for large enough t. Sendrier notes that re-
stricting d to powers of 2 “greatly simplifies the encoding process and gives a significant
advantage in speed while the loss of efficiency is very limited”. Heyse follows this ap-
proach by computing d as 2u and providing a lookup table for u that approximates the
original value of d as computed using the second approximation. To keep the table small,
it does not store the computed d for every possible combination of n and t, but uses a
combination of n and t for the lookup, where the least significant bits hold the value of
t, and the remaining bits hold the upper bits of n. Heyse showed that ignoring the lower
bits of n keeps the difference to the original value d small.
Listing 4.10 shows the computation of the lookup table for u. It is written in Python
since it is part of the precompilation step, which is written in Python entirely for the sake
of simplicity. However, it can be easily converted to C code. The table is then written
to the precompile.h file as an uint8_t array and loaded to flash memory or SRAM. For
typical values such as n = 2960, t = 56 (128-bit security) the table size is approximately
3 kB.
If no lookup table shall be used to save memory, it is possible to approximate u by
computing (n − (t − 1)/2)/t at runtime and mapping the result to the small range of
possible values using a series of if and else conditions. This is essentially a smaller
lookup table, which avoids a part of the expensive floating point arithmetic. However,
4.8 CCA2-secure conversions 59
1 def bestU(N,T):
2 tbits=int([Link]([Link](t,2))) # number of bits of the binary representation of t
3 T_MASK_LSB = ( (1<<tbits) - 1 ) # mask for selecting only the r least significant bits
4 T_MASK_MSB = ctypes.c_uint32( (~T_MASK_LSB) & 0xffff).value # mask selecting all other bits
5 maxindex=(N & T_MASK_MSB) + T + 1 # number of entries in the lookup table
6 table=[0]*(maxindex) # create the table, set all to 0
7
8 i=0
9 while i < maxindex: # loop over all table entries
10 i+=1
11 t = i & T_MASK_LSB # compute t from index i
12 n = i & T_MASK_MSB # compute n from index i
13
14 if t == 0:
15 d=n
16 elif n == 0:
17 continue # table entry remains 0
18 else:
19 d = (ln2/t) * ( n - ( (t-1) / (2) ) ) # ln2=0.693147181
20 # d=(n-((t-1)/2)) * (1 - [Link](2,-1/t))
21
22 if d > 0: # if d negative, table entry remains 0
23 u = [Link](d, 2) # compute u such that d=2^u
24 if u > 0:
25 table[i-1]=u
26 return table
the result is even less precise than the previously discussed table. Hence the number of
bytes that can be encoded in a string of given weight and length may be further reduced.
as SHA-3. The reference implementation also includes a version optimized for 8-bit AVR
microcontrollers, which has been used for our implementation.
KIC for McEliece Alg. 4.8.1 shows the Kobara-Imai-γ conversion applied to McEliece.
It requires a constant string C, a hash function H, a cryptographically secure pseudo
random string generator Gen(seed) with a random seed and output of fixed length, a
CW encoding and decoding function CW and CW −1 , and the McEliece encryption E
and decryption D. Note that the algorithm was simplified by omitting the optional value
y5 included in the original proposal, since it is not used in our implementation.
y1 ← Gen(r) ⊕ (m||C)
y2 ← r ⊕ H(y1 )
(y4 ||y3 ) ← (y2 ||y1 )
e ← CW (y4 )
M cEliece
return c ← EK pub
(y3 , e)
Decryption
M cEliece
(y3 , e) ← DK sec
(c)
y4 ← CW −1 (e)
(y2 ||y1 ) ← (y4 ||y3 )
r̂ ← y2 ⊕ H(y1 )
(m̂||Ĉ) ← y1 ⊕ Gen(r̂)
IF C = Ĉ return m ← m̂
ELSE return ⊥
KIC for Niederreiter KIC for McEliece has already been implemented and discussed
in [Pau10]. Instead of reiterating it here again, we concentrate on the adaption of KIC
4.8 CCA2-secure conversions 61
Encryption
Input: Binary message m
Output: Ciphertext c
y1 ← Gen(r) ⊕ (m||C)
y2 ← r ⊕ H(y1 )
(y4 ||y3 ) ← (y2 ||y1 )
e ← CW (y3 )
N iederreiter
return c ← y4 |EK pub
(e)
Decryption
Input: Ciphertext c = (y4 ||s)
Output: Binary message m
N iederreiter
e ← DK sec
(s)
y3 ← CW −1 (e)
(y2 ||y1 ) ← (y4 ||y3 )
r̂ ← y2 ⊕ H(y1 )
(m̂||Ĉ) ← y1 ⊕ Gen(r̂)
IF C = Ĉ return m ← m̂
ELSE return ⊥
Table 4.1: Length of parameters for Kobara-Imai-γ applied to the Niederreiter scheme
4.8 CCA2-secure conversions 63
two Hash function calls than by the use of CW encoding. Hence, Cayrel et al. argue that
their construction “preserves the fast encryption better than the Kobara-Imai approach.”
In the Niederreiter cryptosystem, the plaintext is encoded into the error vector, which
always requires CW encoding by design. Hence, the advantage of the Fujisaki-Okamoto
conversion does not apply, whereas the disadvantage of the additional encryption during
decryption still applies. Therefore, we decided to implement Fujisaki-Okamoto only for
McEliece.
Decryption
Input: Ciphertext c = (c1 ||c2 )
Output: Binary message m
M cEliece
σ̂ ← DK sec
(c1 )
return ⊥ in case of decoding failure
m̂ ← H2 (σ̂) ⊕ c2
r̂ ← H1 (σ̂||m̂)
M cEliece
IF c1 = EK pub
(r̂, σ̂) return m ← m̂
ELSE return ⊥
Alg. 4.8.3 shows the application of FOC to McEliece, taking the improvements of
Cayrel et al. into account. Similar to the Kobara-Imai conversion, FOC utilizes McEliece
to encrypt a random seed σ which is used to generate a keystream using the Hash
function H2 . This is used to encrypt the plaintext m in a one-time padApp. B.2.5 fashion
by XORing it with the keystream. To avoid CW encoding, σ is chosen randomly such
that its length is n and its weight is t. Generated this way, it can be used in place of
the former error vector e without any need for encoding. Then, σ and and the plaintext
m are cryptographically bound to each other using the Hash function H1 . The result
r takes the place of the former message m of the original McEliece scheme. Applying
McEliece we obtain EK M cEliece (ṁ = r, ė = σ) = ṁG
pub sys + ė = rGsys + σ. Since r is used
only as a check value and no information on m can be derived from r, it does not matter
that parts of it are visible in the McEliece ciphertext due to the usage of a systematic
4.8 CCA2-secure conversions 65
generator matrix.
The decryption process reconstructs σ from the ciphertext using McEliece decryption.
If decryption fails, the ciphertext may have been modified and the algorithm terminates
with an error. From σ, the keystream can be recomputed to obtain the plaintext m̂. To
check whether m̂ is the actual plaintext m without any modification, r is recomputed
and fed into McEliece encryption. If the result matches c1 , the unmodified plaintext m
has been decrypted successfully. Otherwise the ciphertext and hence r, σ or m have
been detected to be modified and the algorithm terminates with an error.
Listing 4.12 shows the decryption of a ciphertext using FOC. Note that for high secu-
rity parameters, encryption and decryption do not fit in the AVR memory at the same
time. The implementation includes options to perform only encryption or decryption;
however, using FOC the decryption-only switch cannot be used, since the decryption
uses an encryption operation.
1 // Since the ciphertext (c1) is modified during McEliece decryption, but is required
2 // for later verification, it needs to be copied. Note that for efficiency reasons,
3 // the ciphertext is stored across the plaintext and ciphertext memory
4 matrix_clone(sk->plaintext, c1_copy_pt); matrix_clone(sk->ciphertext, c1_copy_ct);
5
6 // Decrypt c1 to obtain error positions (equivalent to sigma) and r.
7 // Note that we simply ignore r and instead recompute it from H1(sigma||m) later
8 mce_decrypt_block(sk);
9
10 // Construct sigma from error positions, but allocate an array large enough to hold (sigma||m)
11 uint8_t sigmax[n_in_bytes + MESSAGEBYTES];
12 MATRIX_FROM_ARRAY(sigma, 1, GOPPA_n, sigmax); // transform first part of sigmax to matrix sigma
13 matrix_zero(sigma); // set sigma to zero
14 for(i=0; i < CODE_ERRORS; i++) // iterate over error positions and set corresponding bits
15 MATRIX_SET1(sigma, 0, sk->error_pos[i]);
16
17 // Compute a hash only over sigma, i.e. the first part of sigmax.
18 // Store hash value directly to second part of sigmax, where m will be constructed
19 cbc_hash(&(sigmax[n_in_bytes]), sigmax, n_in_bytes);
20
21 // m = h2(sigma) XOR c2, i.e. XOR c2 to the second part of sigmax
22 for(i=0;i<MESSAGEBYTES;i++) sigmax[n_in_bytes+i] ^= sk->cca2_fujimoto_c2[i];
23
24 // compute hash of sigmax and write it to r, where it is taken from for encryption
25 uint8_t *r = sk->plaintext->data;
26 cbc_hash(r, sigmax, n_in_bytes+MESSAGEBYTES); h1(sigma||m)
27
28 mce_encrypt_block(sk); // if r G + sigma == c1: m is unmodified plaintext (SUCCESS)
29 if( matrix_cmp(sk->plaintext, c1_copy_pt) != 0 || matrix_cmp(sk->ciphertext, c1_copy_ct) != 0)
30 DIE("FAIL");
31
32 for(i=0; i<MESSAGEBYTES; i++) message[i]=sigmax[n_in_bytes+i]; // copy plaintext to output
equivalent non-systematic matrices is listed. Note that Table 5.1 shows the theoretical
size, whereas the implementation stores the matrices with an overhead of up to 7 bits
per row, as described in Section 4.4.1.
For the Niederreiter cryptosystem, also the inverse matrix of S is required to revert
the permutation of the ciphertext that comes with the systematic parity check matrix.
Hence, the (n − k) · (n − k) matrix S −1 needs to be stored as a part of the private key.
Note, however, that the difference of memory consumption for H and Hsys is relatively
small. Hence, for smaller parameter sets – where the difference amounts to only a few
kilobyte – it may be reasonable to refrain from using a systematic parity check matrix.
Then, S can be generated at random and only the seed for the random generator needs
to be stored, while S −1 can be generated on-the-fly during decryption.
The private key also consists of the permuted support L with n elements in Fq and
the Goppa polynomial g(z) with t coefficients. Given the representation of field elements
as uint16_t, the storage of the permuted support requires between 2 kB (60-bit security)
and 13 kB (256-bit security) and the Goppa polynomial requires approximately 76 Byte
to 230 Byte.
Obviously, the major problem concerning memory usage is the encryption. Gsys , Hsys
and S −1 clearly do not fit into the 16 kB SRAM, hence they must be written to flash
memory, providing slow access times. Moreover, since the matrices are mostly larger
than 64 kB, they are placed in ‘far’ flash memory beyond the 64k-boundary, which makes
access even less efficient. For 256-bit security, a public key of nearly 1 MB size is required.
Hence, using this parameter set, encryption is not usable on our target platform without
external memory. Using the Niederreiter cryptosystem, even decryption is not usable
due to the large matrix S −1 . Recalling that the Fujisaki-Okamoto conversion requires
an encryption step during decryption, this conversion is also barred from execution on
the ATxmega256A3 for 256-bit security.
Finally, Table 5.1 also suggests not execute key generation on the target platform,
especially since key generation has to deal not only with the non-systematic versions of
H and G, but also with H and G at the same time if McEliece is used. Considering the
security level 128-bit, the size of G is n·k = 826 kB and the size of H is (n−k)·n = 243 kB.
Moreover, for the Niederreiter cryptosystem the matrix S −1 needs to be computed, which
requires augmenting H and S with an identity matrix that needs to be stored explicitly
during the key generation procedure for the Gauss-Jordan elimination. Considering that
for most scenarios it seems reasonable to transfer precomputed keys to the device, no
attempt was made at handling the key generation on the target device.
Table 5.2: Message-related memory consumption with example size in Bytes (B) for 128-
bit security
parameters as an example. Note that this table does not represent the actual memory
usage, since on many occasions additional temporary memory is required and smaller
structures are not considered. On the other hand, the implementation is able to save
some memory by reusing the plaintext memory for the ciphertext. However, the table
provides an overview over the dynamic memory consumption and demonstrates that
SRAM poses no major problem to the implementation as long as care is taken that all
constant parts are hold in flash memory.
5.1.3 Precomputations
Several precomputations or lookup tables are used throughout the implementation, most
notably the log and antilog tables (GF tables) used for field arithmetic. For each item
and parameterset, Table 5.3 lists the memory requirements, references the section where
the item was introduced and states to which code path it applies and whether it can
be disabled. For example, the precomputation of Huber’s polynomial W (z) for the
Patterson algorithm cannot be disabled if Patterson is actually used, but otherwise it is
not included.
For increasing parameters, some lookup tables like the GF tables quickly require too
much memory to be hold in SRAM. Hence they can alternatively be accessed directly
from flash memory without loading them to SRAM at startup. The table denotes
whether an item is always accessed from SRAM or always from flash memory, or if
both is possible (*) and determined using a compiler switch. The performance gain
by accessing items from SRAM instead of from flash memory is analyzed in the next
section. Note that all items shown in this table are accessed from ‘near’ flash memory
70 5 Evaluation
below the 64k-boundary, which can be accessed more efficiently than memory beyond
this boundary.
• 80-bit security: 66540 Byte (65005 Byte without overhead) for the systematic key
matrix, 8192 Byte for GF tables and 4096 Byte for support (Sum: 77293 Byte)
• 128-bit security: 192192 Byte (there is no overhead for this parameter set) for the
systematic key matrix, 16384 Byte for GF tables and 5920 Byte for support (Sum:
214496 Byte)
The same compiler flags (i.e. -Os to optimize for size) have been used for the compila-
tion of all examples. Some interesting and some less surprising results can be seen from
these values.
• Using parameters for the 80-bit security level, the larger amount of available mem-
ory for the program code causes the compiler to produce larger code. This is done
to optimize the code for speed, for example by inlining small functions.
2
The tool avr-size or the -Map linker option can be used for this task.
5.2 Performance 71
Table 5.4: Size of executables without key matrices, GF tables and support
• Niederreiter has a higher code complexity than McEliece, mainly due to the fact
that it requires constant weight encoding. However, if Niederreiter is used with the
Kobara-Imai-γ conversion, the additional functionality causes nearly no increase
in code size.
• The examples marked with an asterisk (*) show cases where the total size of the
executable is larger than the available flash memory. This can be circumvented by
not using encryption and decryption at the same time; however, the results would
not be comparable.
• The same goes for the root extraction variants, i.e. Horner scheme, Chien search
and Berlekamp-Trace algorithm.
5.2 Performance
In this section, we evaluate the execution time of our implementation, comparing al-
ternative computation methods and testing the effectivity of individual optimizations.
For brevity, we denote by MCE60, . . . , MCE256 the McEliece cryptosystem using pa-
rameters achieving a security level of 60-bit, . . . , 256-bit according to Table 5.1, and
respectively for the Niederreiter cryptosystem, denoted as NR60, . . . , NR256.
5.2.1 Overview
To introduce the reader to typical performance values, we start by giving the cycle count
for commonly used parameters without special optimizations. Table 5.5 presents the
average amount of clock cycles for an encryption and decryption run of 80-bit McEliece
and Niederreiter. Decoding is shown for both the Patterson algorithm (PAT) and the
Berlekamp-Massey (BM). The syndrome in McEliece is computed using a precomputed
parity check matrix H, i.e syndrome computation variant I (SYN_H). For root extraction,
the simple bruteforce search using Horner scheme is used. For the combination of NR
72 5 Evaluation
McEliece Niederreiter
Operation Cycles % Operation Cycles %
Encryption 994,056 13/14 Encryption 46,734 .8/.9
c=m·G 987,615 99.35 CW encoding 16,120 34.49
ĉ = c + e 6,441 0.65 c = eH 30,614 65.51
Decryption (PAT) 6,196,454 86.18 Decryption (PAT) 5,577,774 99.17
Syndrome I: s = cH 942,940 15.22 Syndrome: s = S −1 c 141,563 2.54
Bin. syn. to polynomial 8,392 0.14 Bin. syn. to polynomial 7,982 0.13
Patterson 780,043 12.59 Patterson 854,553 15.32
T = s√−1 456,225 58.49 T = s√−1 527,110 61.68
R= T +z 99,835 12.8 R= T +z 99,824 11.68
EEA 217,768 27.9 EEA 221,205 25.89
σ = a2 + b2 6,355 0.82 σ = a2 + b2 6,414 0.75
Find roots & correct errors 4,434,585 71.5 Find roots & correct errors 4,493,003 80.55
CW decoding 19,962 0.36
Decryption (BM) 6,868,866 87.38 Decryption (BM) 5,510,006 99.09
Syndrome s = cH2 1,702,513 24.79 Syndrome s2 = sH2 255,228 4.63
BM (EEA) 716,809 10.44 BM (EEA) 741,172 13.45
Find roots & correct errors 4,425,157 64.42 Find roots & correct errors 4,473,280 81.18
and BM, syndrome stretching using a parity check matrix computed modolu g(z)2 is
performed. For constant weight encoding, the bestU lookup table is utilized.
The cycle count difference between runs with different keys amounts to few thousand
cycles per encryption and decryption run. This was considered by averaging the cycle
counts over several runs with different keys; however, the keys need to be written to the
microcontroller manually between those runs, since key generation cannot be performed
on the device. Averaging over thousands of different plaintexts is easy, since a loop count
can be configured in selftest mode and plaintexts are generated at random, or can be
fed into the device automatically via UART communication.
If percentages (respectively cycle counts) at the same indentation level do not sum up
to 100% (respectively the value at the higher indentation level), the remainder is due to
computational overhead like UART communication, or due to minor neglected steps of
the algorithm, like the addition of the error vector to the codeword in McEliece. Two
values are given for the percentage of encryption, where the first denotes the percentage
of encryption compared to decryption using Patterson and the second the percentage
compared to decryption using Berlekamp-Massey.
• Niederreiter vs. McEliece The most obvious result from Table 5.5 is the
fact that encryption and decryption in the Niederreiter cryptosystem is faster
than in the McEliece cryptosystem. Note, however, that a McEliece plaintext
for these parameters is k = 1751 bit long, whereas the Niederreiter plaintext is
only ⌊log2 2048 bit long. Hence, McEliece needs 567.7 cycles per bit for
27 ⌋ = 203
5.2 Performance 73
encryption and 3538.8 cycles per bit for decryption (Patterson), whereas Niederre-
iter needs only 230.2 cycles per bit for encryption, but 27476.7 cycles for decryption
(Patterson). However, these values are not very useful for a fair comparison, since
we know from Section 2.6.3 that CCA2-secure conversions are required to obtain a
secure cryptosystem from McEliece and Niederreiter. We will see in the next sec-
tions that conversions affect the performance comparison considerably. Another
aspect is that the performance of constant weight encoding is mostly insignificant
to decryption, but not to encryption.
• PAT vs. BM For McEliece, the Patterson algorithm is faster than Berlekamp-
Massey. For Niederreiter, BM is faster, but the difference is marginal. Moreover,
BM requires a double-size parity check matrix H2 mod g(z)2 that has to be precom-
puted and stored in flash memory. As shown in Table 5.6, this causes significant
differences in the flash memory consumption. For NR+BM, the first k columns
of H2 are omitted as described in Section [Link], whereas MCE+BM requires the
entire matrix. NR+PAT achieves the lowest size, since it requires only the matrices
H and S −1 , but not H2 or G.
• Memory usage For 80-bit security parameters, already 92% of the available
internal flash memory on an ATxmega256 is used in one case. Therefore, a different
configuration must be used to evaluate the 128-bit security level, and the results
74 5 Evaluation
will not be directly comparable. In particular, the parity check matrix H for the
syndrome computation in McEliece must be replaced by a on-the-fly computation,
as shown in Section 4.6.1. However, this comes with a significant performance
penalty, as discussed in Section 5.2.4.
McEliece, because H2 does not fit in flash memory for 128-bit security.
Using this configuration, encryption and decryption functionality can coexist in mem-
ory for all systems but 128-bit Niederreiter. As can be seen from Table 5.1, Niederreiter
with 128-bit security level results in an systematic parity check matrix H of 187 kB and
the reverse scrambling matrix S −1 of 55 kB, occupying 94.53% of the available memory.
Hence, benchmarking must be performed separately for encryption and decryption in
this case.
• Niederreiter vs. McEliece Whereas the cycle count difference between MCE
and NR was relatively small in Table 5.5, a huge difference can be observed from
Table 5.7. Encryption and decryption of NR128 are faster than those of MCE80
and even MCE128. The main reason is the slow live computation for the syndrome
computation in the decryption procedure of McEliece, which is not required for
the Niederreiter cryptosystem. Moreover, the vector-matrix multiplication eH in
NR encryption is faster than mG in McEliece encryption, for the same reasons as
discussed in the previous example. Note, however, that the factor by which the
cycle count of the multiplication increases from 80 to 128-bit security is higher for
NR than for McEliece; the same applies for the syndrome-related computations
in decryption. Concerning the Patterson algorithm and root extraction,there is
no significant difference between NR and MCE, as expected. The performance
of constant weight encoding is now mostly insignificant for both decryption and
encryption.
• Hash function KIC requires a Hash function for both encryption and decryption.
As described in Section 4.8, Keccak-f1600[r=1088,c=512] is used. As a result, en-
cryption is dominated by the Hash function, consuming 38% to 89% of encryption
clock cycles and 4% to 13% of decryption cycles. However, the performance could
be improved by utilizing lightweight parameters for Keccak. Furthermore, the in-
put data length to the Hash function is not based on the security level in KIC
for NR: the input length depends only on the size of a public constant value and
the message length, which can both be chosen freely in some boundaries. Hence,
in the above example, the Hash cycle count for NR80 and NR128 is nearly identi-
cal (Hash input length: 40B), whereas it differs for MCE80 (232B) and MCE128
(323B). The Hash output length is fixed at 32B for all cases.
• Increasing the plaintext length For calculating the data throughput, the cycle
count must be set in relation to the processed information bits, i.e the plaintext
length. For MCE+KIC, in our implementation the plaintext length depends on
code parameters t (CWBYTES ) and k. For NR+KIC, MESSAGEBYTES can be set to any
large enough value. KIC essentially turns NR into a stream cipher, in which the
Niederreiter cryptosystem is mainly used to encrypt the seed that generates the
key stream. Hence, when increasing the plaintext length (MESSAGEBYTES), the basic
NR operations are not affected. However, the larger plaintext increases the input
length to the Hash function and it affects the key stream generator Gen(r) and
the copy and XOR operations of the conversion. The latter are very efficient (they
76 5 Evaluation
Table 5.8: Performance of MCE and NR with PAT+KIC using the same plaintext lengths
do not even occur explicitly in the above table), so that the only notable difference
in the performance is the increased cycle count of the Hash function. Note that
a similar construction can also be achieved using the McEliece cryptosystem, as
mentioned in Section 4.8.
• Data throughput Table 5.8 shows the same measurement as the previous table,
with the only difference being the plaintext size for the Niederreiter set to the
same size as the plaintext of McEliece to allow a direct comparison. Moreover,
the table shows the number of cycles per plaintext byte need for encryption and
decryption and the data throughput at 32 Mhz. As stated before, this does not
mean that McEliece is inherently slower than Niederreiter, but only that the cur-
rent implementation allows the Niederreiter cryptosystem to use the stream cipher
approach more efficiently. Moreover, the throughput of Niederreiter can be further
increased by increasing the plaintext length until the performance is dominated
by KIC-operations (Hash, XOR) instead of by the Code-based encryption and de-
cryption procedures. However, it is often not desirable to set the plaintext length
to big blocks.
for constant weight encoding. However, as we have already seen, on our implementation
for AVR microcontrollers constant weight encoding is a minor factor, which amounts
to a negligible cycle count in most cases, far below 1% of the total runtime. The only
exception is shown in Table 5.5, where CW encoding amounts to 34% of the Niederreiter
encryption runtime, if Niederreiter is used without a CCA2-secure conversion. However,
this was due to the very fast encryption in the Niederreiter cryptosystem, which does
not apply to McEliece to the same degree.
Moreover, we already saw in the previous section that the Hash function – which is
called twice in encryption and decryption – consumes a significant percentage of cycles
(although this problem could be reduced using a lightweight hash function). Furthermore,
an additional call to McEliece encryption occurs during FOC decryption. While McEliece
encryption is fast in general, encryption on the AVR platform is less performant than
on other platforms that provide a faster access to the key matrix.
Finally, the plaintext length is determined by the output length of the Hash function
H2 . Although the output length can be arbitrarily chosen for Keccak, it needs to be fixed
at compile time for the currently used implementation. Since the same Hash function is
used for H1 , whose size is determined by the parameter k of the underlying Goppa code,
k determines also the plaintext length in our implementation. This prevents us from
increasing the plaintext length until the performance is dominated by FOC-operations
(Hash, XOR) instead of by the McEliece procedures.
Therefore, it comes with no surprise that the Fujisaki-Okamoto conversion yields
a worse performance than the Kobara-Imai-γ conversion. Encryption is substantially
slower due to two Hash function calls (making up roughly 80% of encryption), whereas
the performance loss of decryption is less significant, since the Hash procedure amounts
only to 15% to 25% of decryption. The results are summarized for 60- to 128-bit security
in Table 5.9.
Table 5.11: Cycle count of Syndrome III for MCE128 using various optimizations
• Support in SRAM The same can be done to the array of support elements,
which also holds n elements á 2 Bytes (6 kB for MCE128).
• Faster field arithmetic The FASTFIELD switch has already been described in
Section 4.3.2. It reduces the number of conversions between polynomial and expo-
nential representation of field elements during arithmetic operations.
• Inline polynomial evaluation Using __inline__ poly_eval has no effect (i.e. same
cycle count and call to poly_eval still visible in compiled assembly), probably because
of the ‘optimize for code size’ compilation flag. Hence the function was manually
inlined, which can be enabled by setting INLINE_POLY_EVAL=TRUE. Unfortunately this
actually has a negative effect on performance.
Of course these optimizations can be used to improve the performance of the whole
process, not only of the syndrome computation.
For 80-bit security and syndrome computation I, we have already seen in Section 5.2.1
that decrypting using BM is slightly faster than decrypting using Patterson if applied
to the Niederreiter cryptosystem, whereas it is slower if applied to McEliece. From
Table 5.5 one can see that the actual decoding step is in fact faster using BM in both
cases, i.e. 716,809 instead of 780,043 cycles for McEliece, and 741,172 instead of 854,553
cycles for Niederreiter. However, for decoding all errors using BM, a syndrome of double
size must be computed before the actual decoding algorithm.
For McEliece, this means computing the syndrome by multiplying the ciphertext c with
the double size parity check matrix H2 computed modulo g(z)2 instead of H computed
modulo g(z). For the configuration used in this example, this takes takes 1,702,513
cycles for c · H2 , instead of 942,940 cycles for c · H. Obviously this difference cannot
be compensated by the small performance advantage of BM, hence on the whole the
Patterson algorithm is faster.
For Niederreiter, syndrome computation is a part of the encryption process and the
ciphertext c is already a syndrome. Since c is a syndrome of standard size, it needs to be
transformed to double size to allow the correction of all errors using BM, as described
in Section [Link]. However, this transformation already includes the descrambling of
c, which otherwise takes 141,563 cycles in this example measurement. Since the trans-
formation takes only 255,228 cycles, the performance loss is smaller than the gain from
using BM instead of Patterson. Hence, for Niederreiter BM is faster than Patterson.
However, all considerations so far are based on 80-bit security and – for McEliece –
the fast syndrome computation variant I. For higher security parameters, the syndrome
needs to be computed using slower on-the-fly computations. Hence, the comparison
of BM and Patterson can be expected to turn out a huge advantage for Patterson if
McEliece is used. The results shown in Table 5.12 confirm this assumption.
Moreover, even for Niederreiter the Patterson algorithm turns out to be faster for
higher security parameters. Although Berlekamp-Massey remains slightly faster than
Patterson for NR128, the performance loss during the syndrome transformation is too
big to be compensated.
Hence, using Berlekamp-Massey for binary codes can only be recommended in special
cases according to our implementation. Moreover, the memory requirement for BM are
higher due to the larger parity check matrix.
5.2 Performance 81
• The FASTFIELD switch has already been discussed and applies to all implemented
algorithms.
• The LREVERSE_LOOKUPTABLE switch computes a reverse lookup table for the permuted
secret support, which can be used in Chien search and BTA. For a given support
element x the lookup table contains the position of x in the permuted support.
Without the table, the support array needs to be searched iteratively until the
element has been found.
Table 5.13 comparises the performance of Horner scheme, Chien search and both vari-
ations of BTA (see Section 4.6.4) as well as both optimizations. The simple bruteforce
search using Horner scheme proves to be the most effective variant, and can be improved
by 20.45% using the FASTFIELD optimization due to the excessive use of polynomial evalu-
ation. The weaker performance of the Chien search comes with little surprise after the
analysis in Section 3.5.2, showing that software implementations do not profit from the
structure of the Chien search as hardware implementation do.
BTA clearly suffers from a huge overhead due to the recursion and the expensive
handling of large polynomials, both in sparse and full representation. The vast amount
of cycles of BTA using a sparse representation is used for the sparse polynomial reduction
82 5 Evaluation
Table 5.14: Comparison of cycle counts for constant weight encoding in different modes
modulo sigma(z). While this saves a considerable amount of SRAM, it almost doubles
the – already unacceptable long – runtime. Accordingly, BTA cannot be recommended
for our set of parameters. It is however possible that it proves to be an appropriate
choice for (far) larger codes. Moreover, an implementation of BTA including the Zinoviev
procedures may provide better results. However, it would need to reduce the number of
recursive calls to below 10% of the current calls in order to achieve the same performance
as the bruteforce search using Horner scheme.
All previous measurements utilizing constant weight encoding used the bestU lookup table
described in Section 4.7. It can be accessed either from flash memory or from SRAM.
Since the impact of constant weight encoding turned out to be mostly insignificant,
using precious SRAM is not recommended. The third option is the computation of
(n − (t − 1)/2)/t and a very small mapping as an approximation of u at runtime. Note
that this approximation is too inaccurate to reliably encode the same number of bytes
into the constant weight word.
The locally optimal value of u is computed at every step of encoding and decoding.
Table 5.14 compares the resulting number of clock cycles for the three discussed variants.
As expected, accessing the table from SRAM is slightly faster than from flash memory,
and the runtimecomputation is slowest. Depending on the parameters, decoding or
encoding may be faster than the respective operation.
5.2 Performance 83
Table 5.15: Optimized performance of McEliece and Niederreiter using Patterson de-
coder, Kobara-Imai-γ conversion and Horner scheme
5.2 Performance 85
with *) were scaled accordingly to allow a fair comparison. One can see that our im-
plementation outperforms all other implementations: it is faster than the previous im-
plementations of McEliece and Niederreiter, as well as comparable implementations of
RSA and ECC. The difference between our and the previous Niederreiter implementa-
tion is marginal, whereas a huge improvement could be achieved over previous McEliece
implementations. This is due to the fact that the previous implementations used either
non-systematic key matrices or Quasi-Dyadic Goppa codes. Note, however, that Quasi-
Dyadic Goppa codes have the important advantage of providing a very compact key
representation, hence drastically reducing the memory requirements.
Both our Niederreiter and our McEliece implementation are faster than comparable
RSA- and ECC implementations even with the CCA2-secure Kobara-Imai-γ conversion
applied. This is due to the fact that KIC effectively turns McEliece and Niederreiter
into a stream cipher, where Code-based public-key encryption is used only to encrypt a
seed, whereas the message encryption uses fast XOR operations.
86 5 Evaluation
6.1 Summary
In this thesis, we presented an implementation of a broad range of methods and tech-
niques from Code-based cryptography, tailored to the constricted execution environment
of embedded devices such as the 8-bit microcontroller AVR ATxmega256A3. Our library
includes implementations of both the McEliece and Niederreiter cryptosystem and ex-
tends previous implementations providing only 80-but security to the more suitable
security level of 128-bit security. Higher security levels are possible and mainly1 limited
by the amount of available memory. For example, instances providing 256-bit security
have been tested successfully and would also run on AVR microcontrollers that provide
enough memory (approximately 1 MB is required for encryption).
The substitution of the ‘classical’ McEliece and Niederreiter cryptosystems by a security-
equivalent modern variant using systematic key matrices proved to be a valuable choice
for reducing the high memory requirements and additionally help in improving the per-
formance of the system.
Our library includes two CCA2-secure conversions, which are strictly required for
virtually any practical application of McEliece and Niederreiter. We showed that the
Kobara-Imai-γ conversion achieves a high data throughput and discussed under which
conditions the Fujisaki-Okamoto conversion could provide an alternative to the Kobara-
Imai conversion.
We implemented to two different decoding algorithms. The Patterson algorithm can
be applied only to binary Goppa codes, but turned out to be very efficient. On the
other hand, the Berlekamp-Massey-Sugiyama algorithm can be applied to general alter-
nant codes and can be implemented in a very compact form. We demonstranted how
Berlekamp-Massey can be tuned to achieve the same error-correction capacity as the
Patterson algorithm for binary codes and implemented the additional steps necessary to
apply it to the Niederreiter cryptosystem.
Finding the roots of the error locator polynomial and the computation of the syndrome
in the McEliece cryptosystem with limited memory ressources turned out to be the
computationally most expensive steps of decryption. Therefore we implemented and
optimized three variants of root extraction and three methods of syndrome computation.
1
It is also limited by the currently utilized 16-bit data types. For example, gf_t cannot hold elements
of the field F2m for m > 15 without changes.
88 6 Conclusion
Depending on the parameters, a performance gain between 15% and 25% has been
achieved.
An extensive evaluation has been carried out to analyze the performance of the im-
plementation variants and optimizations. The flexible configuration of our Code-based
cryptography library offers the chance to find an individually optimal balance between
memory usage and performance. Several computations can optionally be speed up using
precomputations and lookup tables, which can be accessed either from the fast SRAM
or the slower flash memory according to the users’ needs.
Our implementation shows that Code-based cryptosystems providing security levels
fulfilling real-world requirements can be executed on microcontrollers with more than
satisfying performance: it actually outperforms comparable implementations of conven-
tional cryptosystems in terms of data throughput. This provides further evidence that
McEliece and Niederreiter can evolve to a fully adequate replacement for traditional cryp-
tosystems such as RSA. Hence, we continue to believe that intensifying the research on
Code-based cryptography is an important step to overcome the dangerous dependence of
today’s cryptosystems on the difficulty of the closely related problems of Integer Factor-
ization and Discrete Logarithm. McEliece and Niederreiter remain promising candidates
for providing security in the post-quantum world, as well as for advancing the diversifi-
cation of public-key cryptography.
B.1 Listings
B.1.1 Listing primitive polynomials for the construction of Finite fields
The open source mathematical software SAGE1 can be used to print a list of primitive
polynomials, which are required for the construction of a finite field Fpm .
1 p=2; m=1; mmax=32;
2 while m <= mmax:
3 F.<z> = FiniteField(p^m)
4 print "GF(%d^%d)" % (p,m),
5 print [Link]()
6 m+=1
For p=2,m=11,mmax=11 this function outputs GF(2^11) z^11 + z^2 + 1. Rewriting this polyno-
mial as 1 · z 11 + . . . 0 · · · + 1 · z 2 + 0 · z 1 + 1 · z 0 , we find the representation 1000000001012 =
205310 . Hence, for each Finite field used in the implementation, we provide a definition
like
1 #if GF_m == 11
2 #define PRIM_POLY 2053
3 #endif
1
[Link]
94 B Appendix
15 for m in range(2,16):
16 F.<a> = GF(2^m)
17 print "GF(%d^%d)" % (2,m),
18 basis = normalbase(m)
19 print a^basis, "=", (a^basis).int_repr()
20 print
The code is adapted from [Ris] and outputs the first elemenet of a normal basis like
GF(2^11) a^9 = 512, which is used to provide a definition for each used Finite field.
1 #if GF_m == 11
2 #define NORMAL_BASIS 512
3 #endif
B.2 Definitions
B.2.1 Hamming weight and Hamming distance
The Hamming distance between two words x and y is defined as the number of symbols
(e.g. bits for binary strings) in which x and y differ. The Hamming weight wt(x) is the
number of non-zero symbols of x.
One-way functions A function f (x) = y is one-way if for any input x the output y
can be computed efficiently, but it is computationally infeasible to compute x given only
y. More formally, the success probability P (f (A(f (x)) = f (x)) is negligible. If f is a
permutation, it is also called one-way permutation.
Partially Trapdoor functions If a trapdoor one-way function does not allow a complete
inversion, but just a partial one, it is called a partially trapdoor one-way function. More
formally, a one-way function f (x1 , x2 ) = y with secret s is a partially trapdoor function
if given y and s, it is possible to compute a x1 such that there exists an x2 that satisfies
f (x1 , x2 ) = y.
[BBC+ 11] Marco Baldi, Marco Bianchi, Franco Chiaraluce, Joachim Rosenthal, and
Davide Schipani. Enhanced public key security for the McEliece cryptosys-
tem. CoRR, abs/1108.2462, 2011.
[BCGO09] Thierry P. Berger, Pierre-Louis Cayrel, Philippe Gaborit, and Ayoub Ot-
mani. Reducing Key Length of the McEliece Cryptosystem. In Proceed-
ings of the 2nd International Conference on Cryptology in Africa: Progress
in Cryptology, AFRICACRYPT ’09, pages 77–97, Berlin, Heidelberg, 2009.
Springer-Verlag.
[BCM+ 12] Zhengbing Bian, Fabian Chudak, William G. Macready, Lane Clark, and
Frank Gaitan. Experimental determination of Ramsey numbers with quan-
tum annealing. January 2012.
[BDPA11] Guido Bertoni, Joan Daemen, Michaël Peeters, and Gilles Van Assche. The
Keccak reference, 2011.
[Be] Daniel J. Bernstein and Tanja Lange (editors). eBACS: ECRYPT Bench-
marking of Cryptographic Systems. [Link]
[Ber11] Daniel J. Bernstein. List decoding for binary goppa codes. In Proceedings
of the Third international conference on Coding and cryptology, IWCC’11,
pages 62–80, Berlin, Heidelberg, 2011. Springer-Verlag.
[BH09] Bhaskar Biswas and Vincent Herbert. Efficient Root Finding of Polynomials
over Fields of Characteristic 2. In WEWoRC 2009, LNCS. Springer-Verlag,
2009.
[BJMM12] Anja Becker, Antoine Joux, Alexander May, and Alexander Meurer. De-
coding Random Binary Linear Codes in 2n/20 : How 1 + 1 = 0 Improves
Information Set Decoding. IACR Cryptology ePrint Archive, 2012:26, 2012.
[BLP08] Daniel J. Bernstein, Tanja Lange, and Christiane Peters. Attacking and
defending the McEliece cryptosystem. Cryptology ePrint Archive, Report
2008/318, 2008.
[BLP11] Daniel J. Bernstein, Tanja Lange, and Christiane Peters. Wild mceliece. In
Proceedings of the 17th international conference on Selected areas in cryp-
tography, SAC’10, pages 143–158, Berlin, Heidelberg, 2011. Springer-Verlag.
[Bou07] Iliya G. Bouyukliev. About the code equivalence., pages 126–151. Hackensack,
NJ: World Scientific, 2007.
[BS99] Mihir Bellare and Amit Sahai. Non-malleable Encryption: Equivalence be-
tween Two Notions, and an Indistinguishability-Based Characterization. In
Michael J. Wiener, editor, CRYPTO, volume 1666 of Lecture Notes in Com-
puter Science, pages 519–536. Springer, 1999.
[BS08a] Bhaskar Biswas and Nicolas Sendrier. The hybrid mceliece encrip-
tion scheme, May 2008. [Link]
[Link]?pg=hymes.
[Can98] Anne Canteaut. A new algorithm for finding minimum-weight words in a lin-
ear code: Application to McEliece’s cryptosystem and to narrow-sense BCH
codes of length 511. IEEE Transactions on Information Theory, 44:367–378,
1998.
[Cov06] T. Cover. Enumerative source encoding. IEEE Trans. Inf. Theor., 19(1):73–
77, September 2006.
[EGHP09] Thomas Eisenbarth, Tim Güneysu, Stefan Heyse, and Christof Paar. Mi-
croEliece: McEliece for Embedded Devices. In Christophe Clavier and Kris
Gaj, editors, CHES, volume 5747 of Lecture Notes in Computer Science,
pages 49–64. Springer, 2009.
[For65] Jr. Forney, G. On decoding BCH codes. Information Theory, IEEE Trans-
actions on, 11(4):549 – 557, oct 1965.
[FS09] Matthieu Finiasz and Nicolas Sendrier. Security Bounds for the Design of
Code-Based Cryptosystems. In Proceedings of the 15th International Confer-
ence on the Theory and Application of Cryptology and Information Security:
Advances in Cryptology, ASIACRYPT ’09, pages 88–105, Berlin, Heidelberg,
2009. Springer-Verlag.
[Gop69] V.D. Goppa. A New Class of Linear Correcting Codes. Probl. Peredachi
Inf., 6(3):24–30, 1969.
[GPW+ 04] Nils Gura, Arun Patel, Arvinderpal Wander, Hans Eberle, and Sheuel-
ing Chang Shantz. Comparing Elliptic Curve Cryptography and RSA on
8-bit CPUs. In CHES, pages 119–132, 2004.
[GPZ60] Daniel Gorenstein, W. Wesley Peterson, and Neal Zierler. Two-Error Correct-
ing Bose-Chaudhuri Codes are Quasi-Perfect. Inf. Comput., 3(3):291–294,
September 1960.
[Hey08] Stefan Heyse. Efficient Implementation of the McEliece Crypto System for
Embedded Systems, October 2008.
[HMP10] Stefan Heyse, Amir Moradi, and Christof Paar. Practical power analysis
attacks on software implementations of mceliece. In Nicolas Sendrier, editor,
PQCrypto, volume 6061 of Lecture Notes in Computer Science, pages 108–
125. Springer, 2010.
[IBM12] IBM. IBM Quantum Computing Press Release, February 2012. http://
[Link]/.
[Jab01] A. Kh. Al Jabri. A Statistical Decoding Algorithm for General Linear Block
Codes. In Proceedings of the 8th IMA International Conference on Cryptog-
raphy and Coding, pages 1–8, London, UK, UK, 2001. Springer-Verlag.
[KI01] Kazukuni Kobara and Hideki Imai. Semantically Secure McEliece Public-
Key Cryptosystems-Conversions for McEliece PKC. In Proceedings of the 4th
International Workshop on Practice and Theory in Public Key Cryptography:
108 Bibliography
Public Key Cryptography, PKC ’01, pages 19–35, London, UK, UK, 2001.
Springer-Verlag.
[LDW06] Yuan Xing Li, R. H. Deng, and Xin Mei Wang. On the equivalence of
McEliece’s and Niederreiter’s public-key cryptosystems. IEEE Trans. Inf.
Theor., 40(1):271–273, September 2006.
[LGK10] Zhe Liu, Johann Großschädl, and Ilya Kizhvatov. Efficient and Side-Channel
Resistant RSA Implementation for 8-bit AVR Microcontrollers. In Proceed-
ings of the 1st Workshop on the Security of the Internet of Things (SECIOT
2010), pages 00–00. IEEE Computer Society, 2010.
[LS98] P. Loidrean and N. Sendrier. Some weak keys in McEliece public-key cryp-
tosystem. In Information Theory, 1998. Proceedings. 1998 IEEE Interna-
tional Symposium on, page 382, aug 1998.
[LS01] P. Loidreau and N. Sendrier. Weak keys in the McEliece public-key cryp-
tosystem. Information Theory, IEEE Transactions on, 47(3):1207 –1211,
mar 2001.
[Mas69] James L. Massey. Shift-register synthesis and BCH decoding. IEEE Trans-
actions on Information Theory, 15:122–127, 1969.
[MB09] Rafael Misoczki and Paulo S. Barreto. Selected areas in cryptography. chap-
ter Compact McEliece Keys from Goppa Codes, pages 376–392. Springer-
Verlag, Berlin, Heidelberg, 2009.
[Min07] Lorenz Minder. Cryptography Based on Error Correcting Codes. PhD thesis,
Ècole Polytechnique Fédérale de Lausanne, July 2007.
[MMT11] Alexander May, Alexander Meurer, and Enrico Thomae. Decoding random
linear codes in O(20.054n ). In ASIACRYPT, pages 107–124, 2011.
Bibliography 109
[MS78] F.J. MacWilliams and N.J.A. Sloane. The Theory of Error-Correcting Codes.
North-holland Publishing Company, 2nd edition, 1978.
[MVO96] Alfred J. Menezes, Scott A. Vanstone, and Paul C. Van Oorschot. Handbook
of Applied Cryptography. CRC Press, Inc., Boca Raton, FL, USA, 1st edition,
1996.
[NC11] Robert Niebuhr and Pierre-Louis Cayrel. Broadcast Attacks against Code-
Based Schemes. In Frederik Armknecht and Stefan Lucks, editors, WE-
WoRC, volume 7242 of Lecture Notes in Computer Science, pages 1–17.
Springer, 2011.
[Nie86] H. Niederreiter. Knapsack-type cryptosystems and algebraic coding the-
ory. Problems Control Inform. Theory/Problemy Upravlen. Teor. Inform.,
15(2):159–166, 1986.
[Nie12] Robert Niebuhr. Attacking and Defending Code-based Cryptosystems. PhD
thesis, Technische Universität Darmstadt, 2012.
[Nit] Abderrahmane Nitaj. Quantum and post quantum cryptography. http://
[Link]/~nitaj/[Link].
[NMBB12] Robert Niebuhr, Mohammed Meziani, Stanislav Bulygin, and Johannes
Buchmann. Selecting Parameters for Secure McEliece-based Cryptosystems.
International Journal of Information Security, 11(3):137–147, Jun 2012.
[OS09] Raphael Overbeck and Nicolas Sendrier. Code-based cryptography. Bern-
stein, Daniel J. (ed.) et al., Post-quantum cryptography. First international
workshop PQCrypto 2006, Leuven, The Netherland, May 23–26, 2006. Se-
lected papers. Berlin: Springer. 95-145 (2009)., 2009.
[OTD10] Ayoub Otmani, Jean-Pierre Tillich, and Léonard Dallot. Cryptanalysis of
Two McEliece Cryptosystems Based on Quasi-Cyclic Codes. Mathematics
in Computer Science, 3(2):129–140, 2010.
[Ove07] Raphael Overbeck. Public Key Cryptography based on Coding Theory. Doc-
toral thesis, Technische Universität Darmstadt, 2007.
[Pat75] N. Patterson. The algebraic decoding of Goppa codes. Information Theory,
IEEE Transactions on, 21(2):203 – 207, mar 1975.
[Pau10] Olga Paustjan. Post quantum cryptography on embedded devices: An
efficient implementation of the mceliece key scheme based on quasi-
dyadic goppa codes. Diploma thesis, Ruhr-Universität Bochum, July
2010. [Link]
post_quantum.pdf.
[Per12] Edoardo Persichetti. Compact mceliece keys based on quasi-dyadic srivas-
tava codes. J. Mathematical Cryptology, 6(2):149–169, 2012.
110 Bibliography
[PR97] Erez Petrank and Ron M. Roth. Is Code Equivalence Easy to Decide? IEEE
Transactions on Information Theory, 43:1602–1604, 1997.
[Rhe80] W.C. Rheinboldt. Horner’s Scheme and Related Algorithms. Modules and
monographs in undergraduate mathematics and its applications. Birkhauser
Boston, 1980.
[Ris] Thomas Risse. SAGE, ein open source CAS vor allem auch für
die diskrete mathematik. [Link]
papers/Frege2010_03/.
[Ris11] Thomas Risse. How SAGE helps to implement Goppa codes and McEliece
PKCSs. Home page of Thomas Risse, 2011. [Link]
[Link]/risse/papers/ICIT11/526_ICIT11_Risse.pdf.
[Sch12] Sara Schacht. McEliece and its Vulnerabilities to Side Channel Attacks.
Bachelor thesis, Ruhr-Universität-Bochum, November 2012.
[Sen00] Nicolas Sendrier. Finding the permutation between equivalent linear codes:
The support splitting algorithm. IEEE Transactions on Information Theory,
46(4):1193–1203, 2000.
[Sho93] Victor Shoup. Fast construction of irreducible polynomials over finite fields.
In Proceedings of the fourth annual ACM-SIAM Symposium on Discrete al-
gorithms, SODA ’93, pages 484–492, Philadelphia, PA, USA, 1993. Society
for Industrial and Applied Mathematics.
[XZL+ 11] Nanyang Xu, Jing Zhu, Dawei Lu, Xianyi Zhou, Xinhua Peng, and Jiangfeng
Du. Quantum factorization of 143 on a dipolar-coupling nmr system. 2011.