Only this pageAll pages
Powered by GitBook
1 of 80

CryptoBook

Loading...

Loading...

Loading...

Loading...

Loading...

Fundamentals

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Number Theory

Loading...

Loading...

Loading...

Loading...

Loading...

Abstract algebra

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Elliptic Curves

Loading...

Lattices

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Asymmetric Cryptography

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Symmetric Cryptography

Loading...

Loading...

Loading...

Loading...

Loading...

Hashes

Loading...

Loading...

Isogeny Based Cryptography

Loading...

Loading...

Loading...

Appendices

Loading...

Loading...

Ring-LWE

Sample Page

A rough guideline to a page

Introduction

Give a description of the topic, and what you hope the reader will get from this. For example, this page will cover addition of the natural numbers. Talk about how this relates to something in cryptography, either through a protocol, or an attack. This can be a single sentence, or verbose.

Laws of Addition

For all integers, the addition operation is

  • Associative: a+(b+c)=(a+b)+ca + (b + c) = (a + b) + ca+(b+c)=(a+b)+c

  • Commutative: a+b=b+aa + b = b + aa+b=b+a

  • Distributive: a(b+c)=ab+aca(b + c) = ab + aca(b+c)=ab+ac

  • Contains an identity element: a+0=0+a=aa + 0 = 0 + a = aa+0=0+a=a

  • Has an inverse for every element: a+(โˆ’a)=(โˆ’a)+a=0a + (-a) = (-a) + a = 0a+(โˆ’a)=(โˆ’a)+a=0

  • Closed: โˆ€a,bโˆˆZ,a+bโˆˆZ\forall a, b \in \mathbb{Z}, a + b \in \mathbb{Z}โˆ€a,bโˆˆZ,a+bโˆˆZ

Interesting Identity

(1+2+3+โ€ฆ+n)2=13+23+33+โ€ฆ+n3(1 + 2 + 3 + \ldots + n)^2 = 1^3 + 2^3 + 3^3 + \ldots + n^3(1+2+3+โ€ฆ+n)2=13+23+33+โ€ฆ+n3

Sage Example

sage: 1 + (2 + 3) == (1 + 2) + 3
True
sage: 1 + 2 == 2 + 1
True
sage: 5*(7 + 11) == 5*7 + 5*11
True
sage: sum(i for i in range(1000))^2 == sum(i^3 for i in range(1000))
True

Further Resources

  • Links to

  • Other interesting

  • Resources

Contributors

Optional space to say that you've worked on the book

Thank you!

๐Ÿฅณ CryptoBook is the result of the hard work of the CryptoHack community. Thanks to all of our writers, whether it's been line edits or whole section creation. This only exists because of the generosity and passion of a group of cryptographers.

Our Writers

  • ...

  • You?

Join CryptoBook

If you would like to join the team, come over to our Discord Channel and talk with us about your ideas

Euclidean Algorithm

Introduction

Although we have functions that can compute our gcdโก\gcdgcdeasily it's important enough that we need to give and study an algorithm for it: the euclidean algorithm.

It's extended version will help us calculate modular inverses which we will define a bit later.

Euclidean Algorithm

Important Remark

If a=bโ‹…q+ra = b \cdot q + ra=bโ‹…q+rand d=gcdโก(a,b)d = \gcd(a, b)d=gcd(a,b) then dโˆฃrd | rdโˆฃr. Therefore gcdโก(a,b)=gcdโก(b,r)\gcd(a, b) = \gcd(b, r)gcd(a,b)=gcd(b,r)

Algorithm

We write the following:

a=q0โ‹…b+r0b=q1โ‹…r0+r1r0=q2โ‹…r1+r2โ‹ฎrnโˆ’2=rnโˆ’1โ‹…qnโˆ’1+rnrn=0 a = q_0 \cdot b + r_0 \\ b = q_1 \cdot r_0 + r_1 \\ r_0 = q_2 \cdot r_1 + r_2 \\ \vdots \\ r_{n-2} = r_ {n-1} \cdot q_{n - 1} + r_n \\ r_n = 0a=q0โ€‹โ‹…b+r0โ€‹b=q1โ€‹โ‹…r0โ€‹+r1โ€‹r0โ€‹=q2โ€‹โ‹…r1โ€‹+r2โ€‹โ‹ฎrnโˆ’2โ€‹=rnโˆ’1โ€‹โ‹…qnโˆ’1โ€‹+rnโ€‹rnโ€‹=0

Or iteratively rkโˆ’2=qkโ‹…rkโˆ’1+rkr_{k-2} = q_k \cdot r_{k-1} + r_krkโˆ’2โ€‹=qkโ€‹โ‹…rkโˆ’1โ€‹+rkโ€‹ until we find a 000. Then we stop

Now here's the trick:

gcdโก(a,b)=gcd(b,r0)=gcd(r0,r1)=โ‹ฏ=gcdโก(rnโˆ’2,rnโˆ’1)=rnโˆ’1=d\gcd(a, b) = gcd(b, r_0) = gcd(r_0, r_1) = \dots = \gcd(r_{n-2}, r_{n-1}) = r_{n-1} = dgcd(a,b)=gcd(b,r0โ€‹)=gcd(r0โ€‹,r1โ€‹)=โ‹ฏ=gcd(rnโˆ’2โ€‹,rnโˆ’1โ€‹)=rnโˆ’1โ€‹=d

If d=gcdโก(a,b)d = \gcd(a, b)d=gcd(a,b) then ddd divides r0,r1,...rnโˆ’1r_0, r_1, ... r_{n-1}r0โ€‹,r1โ€‹,...rnโˆ’1โ€‹

Pause and ponder. Make you you understand why that works.

Example:

Calculate gcdโก(24,15)\gcd(24, 15)gcd(24,15)

24=1โ‹…15+915=1โ‹…9+69=1โ‹…6+36=2โ‹…3+0โ‡’3=gcdโก(24,15)24 = 1 \cdot 15 + 9 \\ 15 = 1 \cdot 9 + 6 \\ 9 = 1 \cdot 6 + 3 \\ 6 = 2 \cdot 3 + 0 \Rightarrow 3 = \gcd(24, 15) 24=1โ‹…15+915=1โ‹…9+69=1โ‹…6+36=2โ‹…3+0โ‡’3=gcd(24,15)

Code

def my_gcd(a, b):
    # If a < b swap them
    if a < b: 
        a, b = b, a
    # If we encounter 0 return a
    if b == 0: 
        return a
    else:
        r = a % b
        return my_gcd(b, r)

print(my_gcd(24, 15))
# 3

Exercises:

  1. Pick 2 numbers and calculate their gcdโก\gcdgcdby hand.

  2. Implement the algorithm in Python / Sage and play with it. Do not copy paste the code

Extended Euclidean Algorithm

This section needs to be expanded a bit.

Bezout's identity

Let d=gcdโก(a,b)d = \gcd(a, b)d=gcd(a,b). Then there exists u,vu, vu,v such that au+bv=dau + bv = dau+bv=d

The extended euclidean algorithm aims to find d=gcdโก(a,b),ย andย u,vd = \gcd(a, b), \text{ and }u, vd=gcd(a,b),ย andย u,vgiven a,ba, ba,b

# In sage we have the `xgcd` function
a = 24
b = 15
g, u, v = xgcd(a, b)
print(g, u, v)
# 3 2 -3 

print(u * a + v * b)
# 3 -> because 24 * 2 - 15 * 3 = 48 - 45 = 3

Book Plan

A summary we plan to cover

Philosophy

The aim of CryptoBook is to have a consolidated space for all of the mathematics required to properly learn and enjoy cryptography. The focus of any topic should be to introduce a reader to a subject in a way that is fun, engaging and with an attempt to frame it as an applied resource.

The second focus should be to cleanly implement the various topics using SageMath, so that there is a clear resource for a new reader to gain insight on how SageMath might be used to create the objects needed.

Write about what you love and this book will be a success.

Descriptions of attacks against cryptosystems are strongly encouraged, however full SageMath implementations should not be included, as this has the potential for destroying CryptoHack challenges, or making all attacks known by so many people that CTFs become a total nightmare!!

Proposed topics

This list is not complete so please add to it as you see fit.

Mathematical Background

Fundamentals

  • Congruences

  • GCD, LCM

    • Bรฉzout's Theorem

    • Gauss' Lemma and its ten thousand corollaries

  • Euclid's algorithm

  • Modular Arithmetic

  • Morphisms et al.

  • Frobenius endomorphism

Number Theory

Mainly thinking things like

  • Prime decomposition and distribution

  • Primality testing

  • Euler's theorem

  • Factoring

  • Legendre / Jacobi symbol

Abstract Algebra

Mainly thinking things like:

  • Groups, Rings, Fields, etc.

  • Abelian groups and their relationship to key-exchange

  • Lagrange's theorem and small subgroup attacks

Basilar Cryptanalysis forms

  • Introduction to Cryptanalysis

  • A linear Approach to Cryptanalysis

  • Matsui's Best biases algorithm

  • A Differential Approach to Cryptanalysis

Elliptic Curves

  • Weierstrass

  • Montgomery

  • Edwards

  • Counting points (Schoof's algorithm)

  • Complex multiplication

    • Good reference, thanks Joachim

Generating Elliptic Curves

  • Generating Anomalous curves

  • Generating curves of prime order

  • Generating supersingular curves Wikipedia

  • Generating non-supersinular curves of low embedding degree

  • Generating curves of arbitary order (hard)

    • Thesis on the topic

    • Sage implementation ChiCube's script

Hyperelliptic curves

  • Generalization of elliptic curves

  • Recovering a group structure using the Jacobian

  • Example: genus one curves, jacobian is isomorphic to the set of points

  • Mumford representation of divisors

  • Computing the order of the Jacobian

    • For characteristic 2^n: Example 56

    • Hyper Metroid example

Security background

  • Basic Concepts

    • Confidentiality, Integrity etc

    • Encryption, Key generation

  • Attacker goals + Attack games

  • Defining Security - Perfect security, semantic security

  • Proofs of security + Security Reductions

Asymmetric Cryptography

RSA

  • Textbook protocol

  • Padding

    • Bleichenbacher's Attack

    • OAEP

  • Coppersmith

    • Hรฅstad's Attack

    • Franklin-Reiter Attack

  • Wiener's Attack

  • RSA's Integer fattorization Attacks

    • Fermat Factoring Attack

    • Quadratic Sieve Attack

    • Number Fielde Sieve Attack

  • RSA Digital Signature Scheme

  • Timing Attacks on RSA

  • RSA with Chinese Remainder Theorem (CRT)

    • Fault Attack on RSA-CRT

    • Bellcore Attack (Low Voltage Attack)

Paillier Cryptosystem

  • Textbook protocol

ElGamal Encryption System

  • Textbook protocol

  • ElGamal Digital Signature Scheme

Diffie-Hellman

  • Textbook protocol

  • Strong primes, and why

Elliptic Curve Cryptography

  • ECDSA

  • EdDSA

Symmetric Cryptography

One Time Pad

  • XOR and its properties

  • XOR as One Time Pad

  • Generalized One Time Pad

Block Ciphers

  • AES

Stream Ciphers

  • Affine

  • RC4

Hashes

  • Introduction

  • Trapdoor Functions

  • MD family

  • SHA family

  • BLAKE Hash family

  • // TODO: Insert Attacks

Isogeny Based Cryptography

  • Isogenies

  • Isogeny graphs

  • Torsion poins

  • SIDH

  • SIKE

  • BIKE

Cryptographic Protocols

Zero-knowledge proofs

  • Schnorr proof of knowledge for dlog

  • Core definitions

  • Proof of equality of dlog

  • Proof of knowledge of a group homomorphism preimage

Formal Verification of Security Protocols

  • Definition of Formal Verification

  • Uses of Formal Verification

  • Handshake protocols, flawed protocols

  • The external threat: Man-In-The-Middle attacks

  • Attacking the (flawed) Needham-Shroeder public key exchange protocol

Usefull Resources ( Books, articles ..) // based on my material

  • Cryptanalytic Attacks on RSA (Yan, Springer, 2008)

  • Algorithmic Cryptanalysis (Antoine Joux, CRC Press, 2009)

  • Algebraic Cryptanalysis (Brad, Springer, 2009)

  • RC4 stream Cipher and its variants (H. Rosen, CRC Press, 2013)

  • Formal Models and Techniques for Analyzing Security Protocols (Cortier, IOS Press, 2011)

  • Algebraic Shift Register Sequences (Goresky && Klapper, Cambridge Press, 2012)

  • The Modelling and Analysis of Security Protocols (Schneider, Pearson, 2000)

  • Secure Transaction Protocol Analysis (Zhang && Chen, Springer, 2008)

Euler's Theorem in Detail

Todo

CryptoBook

About this project

CryptoBook is a community project, developed by members of to create a resource for people to learn cryptography. The focus of this project is to create a friendly resource for the mathematical fundamentals of cryptography, along with corresponding implementation.

Think of this as an alternative SageMath documentation source, where the focus is its application in solving cryptographic problems.

If you're interested in contributing, come chat to us in our

Style Guide

Work in progress

Working together

  • If something doesn't make sense, make a comment using GitBook, or ask in the Discord.

  • If you are confident that something is wrong, just fix it. There's no need to ask.

  • If you think something doesn't have enough detail, expand on it, or leave a comment suggesting that.

  • If a page is getting too long, break it down into new pages. If you're unsure, then leave a comment or talk in the discord

  • If you want to write about something new and learn as you type, this is fine! But please leave a warning at the top that this is new to you and needs another pair of eyes.

  • If there's big subject you're working on, claim the page and save it, show us that that's what you're doing so we don't overlap too much

General Tips

  • Introduce new objects slowly, if many things need to be assumed, then try to plan for them to appear within the somewhere.

  • It is better to cover less, and explain something well, than it is to quickly cover a lot. We're not racing

  • When explaining anything, imagine you are introducing it for a first time. Summaries exist elsewhere online, the goal of CryptoBook is education

  • Contribute as much or as little as you want, but try to only work on topics that

    • You are interested in

    • You have some experience of thinking about

  • External resources should be included at the end of the page. Ideally the book should be self-contained (within reason) but other resources are great as they offer other ways to learn

If anything on any page is unclear, then please leave a comment, or talk in the discord. We are all at different levels, and I want this to be useful for everyone. Let's work on this as a big team and create something beautiful.

  • Try and use the hints / tips blocks to break up dense text, for example:

To use , you can wrap your text in $$maths here$$. If this is at the beginning of a paragraph, it makes it block, otherwise it is inline

Page Structure

  • A page should have a clear educational goal: this should be explained in the introduction. References to prerequisites should be kept within the book and if the book doesnt have this yet, it should be placed into .

  • The topic should be presented initially with theory, showing the mathematics and structures we will need. A discussion should be pointed towards how this appears within Cryptography

Motivating a new reader is the biggest challenge of creating a resource. People will be coming here to understand cryptography and SageMath, so keep pointing back to the goal!

  • Within a discussion of a topic, a small snippet of code to give an example is encouraged

  • If you write code better than you write maths, then just include what you can and the page will form around that

  • An example page is given in

Formatting

Mathematics notation

There's no "right or wrong" but it's good to be consistent, I think?

  • All maths must be presented using using either both block and inline

  • We seem to be using mathbb for our fields / rings. So let's stick with that? Maybe someone has a good resource for notation we can work from?

Code Blocks

  • Make sure all code blocks have the right language selected for syntax highlighting

  • Preference is to SageMath, then to Python, then others.

  • Code should be cope-pastable. So if you include print statement, include the result of the output as a comment

Algorithms

  • Algorithms should be presented as??

Mathematical Notation

Introduction

Throughout CryptoBook, discussions are made more concise by using various mathematical symbols. For some of you, all of these will feel familiar, while for others, it will feel new and confusing. This chapter is devoted to helping new readers gain insight into the notation used.

If you're reading a page and something is new to you, come here and add the symbol, someone else who understands it can explain its meaning

Mathematical Objects

Special Sets

  • : denotes the set of complex numbers

  • : denotes the set of real numbers

  • : denotes the set of integers

  • : denotes the set of rational numbers

  • : denotes the set of natural numbers (non-negative integers)

  • : denotes the set of integers mod

  • We refer to unit groups by or . Example:

  • We refer to finite fields with elements by

  • We refer to a general field by

  • We refer to the algebraic closure of this field by

Relation operators

  • means is an element of (belongs to)

Logical Notation

  • means for all

  • means there exists. means uniquely exists

Operators

  • means the probability of an event to happen. Sometimes denoted as or as

Modular Arithmetic

Authors: A~Z, perhaps someone else but not yet (or they've decided to remain hidden like a ninja)

Introduction

Thinking not over the integers as a whole but modulo some integerinstead can prove quite useful in a number of situation. This chapter attempts to introduce to you the basic concepts of working in such a context.

Congruences

For the following chapter, we will assumeis a natural integer, andandare two integers. We say thatandare congruent modulowhen, or equivalently when there is an integersuch that. We denote this byor . I will use the first notation throughout this chapter.

Remark: When, we have, whereis the remainder in the euclidean division ofby

This relation has a number of useful properties:

  • The proofs are left as an exercise to the reader :p (Hint: go back to the definition)

Seeing as addition and multiplication are well defined, the integers moduloform a ring, which we note. In sage, you can construct such ring with either of the following

Powering modulois relatively fast, thanks to the algorithm, so we needn't worry about it taking too much time when working with high powers

As a side note, remember that if an equality holds over the integers, then it holds modulo any natural integer. This can be used to prove that a relation is never true by finding a suitable modulus, or to derive conditions on the potential solutions of the equation.

Example: by choosing an appropriate modulus, show that not even god is able to find integersandsuch that

Modular Inverse

Since we can multiply, a question arises: can we divide? The answer is yes, under certain conditions. Dividing by an integeris the same as multiplying by its inverse; that is we want to find another integersuch that. Since, it is clear from that such an inverse exists if and only if. Therefore, the units moduloare the integers coprime to, lying in a set we call the unit group modulo:

Finding the modular inverse of a number is an easy task, thanks to the (that outputs solutions inandto the equationfrom above).

Division and Greatest common divisor

Author: Zademn

Introduction

Two of the skills a cryptographer must master are:

  1. Knowing his way and being comfortable to work with numbers.

  2. Understanding and manipulating abstract objects.

This chapter of fundamentals proposes to prepare you for understanding the basics of number theory and abstract algebra .We will start with the most basic concepts such as division and build up knowledge until you, future cryptographer, are able to follow and understand the proofs and intricacies of the cryptosystems that make our everyday life secure.

We will provide examples and snippets of code and be sure to play with them. If math is not your strongest suit, we highly suggest to pause and ponder for each concept and take it slow.

For the math-savy people we cover advanced topics in specific chapters on the subjects of number theory and group theory.

So what are we waiting for? Let's jump right in!

Division

Let be the set denoting the integers.

Definition - Divisibility

For we say that divides if there is some such that

Notation:

Example

For we have because we can find such that .

Properties

  • and implies

    • Example: Let and

    • and . We can find such that

  • and implies

  • if and then

Definition - Division with remainder

Let with ,

There exists unique such that and

is called the quotient and the remainder

Examples:

  • To find python offers us the divmod() function that takes as arguments

  • If we want to find only the quotient we can use the // operator

  • If we want to find the remainder we can use the modulo % operator

Exercises:

  1. Now it's your turn! Play with the proprieties of the division in Python and see if they hold.

Greatest common divisor

Definition

Let be 2 integers. The greatest common divisor is the largest integer such that and

Notation:

Examples:

Remark:

  • for all other common divisors of we have

Things to think about

What can we say about numbers with ? How are their divisors?

Ideals

Example: Ideals of the integers

Definition - Ideal of

is an ideal we have

Example: - multiples of

Remarks:

  1. we have

  2. is an ideal

Example: Consider . This ideal contains

Greatest common divisor

Let be 2 integers. If

Theorems of Wilson, Euler, and Fermat

Wilson's Theorem

A positive integer is a prime if and only if:

Euler's Theorem

Let and s.t. , then:

Fermat's Little Theorem

Let be a prime and , then:

or equivalently:

Reference

C\mathbb{C}C
R\mathbb{R}R
Z\mathbb{Z}Z
Q\mathbb{Q}Q
N\mathbb{N}N
Z/nZ\mathbb{Z}/n\mathbb ZZ/nZ
nnn
"""
We can call each of these sets with Sage using the 
following commands. Comments are the result of the
input.
"""
CC
# Complex Field with 53 bits of precision
RR
# Real Field with 53 bits of precision
ZZ
# Integer Ring
QQ
# Rational Field
NN
# Non negative integer semiring
Zmod(11) # or `Integers(11)` or `IntegerModRing(11)` 
# Ring of integers modulo 11
Rร—R^\timesRร—
Rโˆ—R^*Rโˆ—
(Z/nZ)ร—(\mathbb Z/n \mathbb Z)^\times(Z/nZ)ร—
qqq
Fq\mathbb{F}_qFqโ€‹
kkk
kห‰\bar{k}kห‰
"""
Example of defining a field and then its 
algebraic closure
"""
GF(3)
# Finite Field of size 3 , where GF stands for Galois Field 
GF(3).algebraic_closure()
# Algebraic closure of Finite Field of size 3
"""
If you want to find which field an element belongs to you can use the 
`.parent()` function
"""

x = 7
print(x.parent())
# Integer Ring

y = 3.5
print(y.parent())
# Real Field with 53 bits of precision
"""
If you want to "lift" an element from a quotient ring R/I to the ring R
use the `.lift()` function
"""
R = ZZ
RI = Zmod(11)
x =  RI(5)

print(x.parent())
# Ring of integers modulo 11

y = x.lift()
print(y.parent())
# Integer Ring

print(y in R)
# True
โˆˆ\inโˆˆ
โˆ€\forallโˆ€
โˆƒ\existsโˆƒ
โˆƒ!\exists!โˆƒ!
Pr(A)Pr(A)Pr(A)
AAA
Pr[A]Pr[A]Pr[A]
P(A)P(A)P(A)
Z={โ€ฆ,โˆ’1,0,1,2,3โ€ฆโ€‰}\mathbb{Z} = \{\dots , -1, 0, 1, 2, 3 \dots \}Z={โ€ฆ,โˆ’1,0,1,2,3โ€ฆ}
a,b,โˆˆZa, b, \in \mathbb{Z} a,b,โˆˆZ
aaa
bbb
kโˆˆZk \in \mathbb{Z}kโˆˆZ
aโ‹…k=ba \cdot k = baโ‹…k=b
aโˆฃba | baโˆฃb
a=2,b=6a = 2, b = 6a=2,b=6
2โˆฃ62 | 62โˆฃ6
k=3k = 3k=3
6=2โ‹…36 = 2 \cdot 36=2โ‹…3
aโˆฃa,ย 1โˆฃaย andย aโˆฃ0a | a, \ 1 | a \text{ and } a | 0aโˆฃa,ย 1โˆฃaย andย aโˆฃ0
aโˆฃba | baโˆฃb
aโˆฃc a | c aโˆฃc
aโˆฃ(bu+cv)ย โˆ€u,v,โˆˆZa | (bu + cv) \ \forall u, v, \in \mathbb{Z}aโˆฃ(bu+cv)ย โˆ€u,v,โˆˆZ
b=6,u=5b = 6, u = 5b=6,u=5
c=9,v=2c = 9, v = 2 c=9,v=2
3โˆฃ63 | 63โˆฃ6
3โˆฃ9โ‡’3โˆฃ(6โ‹…5+9โ‹…2)โ€…โ€ŠโŸบโ€…โ€Š3โˆฃ483 | 9 \Rightarrow 3 | (6 \cdot 5 + 9 \cdot 2) \iff 3 | 483โˆฃ9โ‡’3โˆฃ(6โ‹…5+9โ‹…2)โŸบ3โˆฃ48
k=16k = 16k=16
48=3โ‹…1648 = 3 \cdot 1648=3โ‹…16
aโˆฃba | baโˆฃb
bโˆฃc b | c bโˆฃc
aโˆฃc a | caโˆฃc
aโˆฃba|baโˆฃb
bโˆฃab|abโˆฃa
a=ยฑba = \pm ba=ยฑb
a,bโˆˆZa, b \in \mathbb{Z}a,bโˆˆZ
bโ‰ฅ1bโ‰ฅ1bโ‰ฅ1
q,rโˆˆZq, r \in \mathbb{Z}q,rโˆˆZ
a=bq+r\boxed{a = bq + r}a=bq+rโ€‹
0โ‰คr<b0 \leq r < b0โ‰คr<b
qq q
rrr
q,rq, rq,r
a,ba, ba,b
q, r = divmod(6, 2)
print(q, r)
# 3 0 

q, r = divmod(13, 5)
print(q, r)
# 2 3 
# Note that 13 = 2 * 5 + 3
qqq
rrr
q = 13 // 5
print(q)
# 2

r = 13 % 5
print(r)
# 3
a,bโˆˆZa, b \in \mathbb{Z}a,bโˆˆZ
dโˆˆZd \in \mathbb{Z}dโˆˆZ
dโˆฃad | adโˆฃa
dโˆฃbd | bdโˆฃb
gcdโก(a,b)=d\gcd(a, b) = dgcd(a,b)=d
# In python we can import math to get the GCD algo
import math
print(math.gcd(18, 12)) # -> 6
# Sage has it already!
print(gcd(18, 12)) # -> 6
ccc
a,ba, ba,b
cโˆฃdc | dcโˆฃd
a,b a, ba,b
gcdโก(a,b)=1\gcd(a, b) = 1gcd(a,b)=1
Z\mathbb{Z}Z
IโІZ I \subseteq \mathbb{Z}IโІZ
โ€…โ€ŠโŸบโ€…โ€Šโˆ€ย a,bโˆˆIย and,zย โˆˆZ\iff \forall \ a, b \in I \text{ and} , z\ \in \mathbb{Z}โŸบโˆ€ย a,bโˆˆIย and,zย โˆˆZ
a+bโˆˆIย andย azโˆˆIa + b \in I \text{ and } az \in Ia+bโˆˆIย andย azโˆˆI
aZ={azย :ย zโˆˆZ}โ†’2Z,3Z,4Z,โ€ฆa\mathbb{Z} = \{az \ : \ z \in \mathbb{Z} \} \to 2\mathbb{Z}, 3\mathbb{Z}, 4\mathbb{Z}, \dotsaZ={azย :ย zโˆˆZ}โ†’2Z,3Z,4Z,โ€ฆ
aaa
โˆ€a,bโˆˆZ\forall a, b \in \mathbb{Z}โˆ€a,bโˆˆZ
bโˆˆaZโ€…โ€ŠโŸบโ€…โ€Šaโˆฃbb \in a\mathbb{Z} \iff a | bbโˆˆaZโŸบaโˆฃb
I1+I2={a1+a2ย :ย a1โˆˆI1,a2โˆˆI2}I_1 + I_2 = \{a_1 + a_2 \ : \ a_1 \in I_1 , a_2 \in I_2\}I1โ€‹+I2โ€‹={a1โ€‹+a2โ€‹ย :ย a1โ€‹โˆˆI1โ€‹,a2โ€‹โˆˆI2โ€‹}
18Z+12Z18\mathbb{Z} + 12\mathbb{Z}18Z+12Z
6=18โ‹…1+12โ‹…(โˆ’1)โ‡’18Z+12Z=6Z6 = 18 \cdot 1 + 12 \cdot (-1) \Rightarrow 18\mathbb{Z} + 12\mathbb{Z} = 6\mathbb{Z}6=18โ‹…1+12โ‹…(โˆ’1)โ‡’18Z+12Z=6Z
a,bโˆˆZa, b \in \mathbb{Z}a,bโˆˆZ
d=gcdโก(a,b)โ‡’aZ+bZ=dZd = \gcd(a, b) \Rightarrow a\mathbb{Z} + b\mathbb{Z} = d\mathbb{Z}d=gcd(a,b)โ‡’aZ+bZ=dZ
CryptoHack
SageMath
Discord Channel
LaTeX\LaTeXLATEโ€‹X
LaTeX\LaTeXLATEโ€‹X
# Example
a = 3
b = 6
print(a+b)
# 9
// todo
Book Plan
Book Plan
Sample Page
nnn
nnn
aaa
bbb
aaa
bbb
nnn
nโˆฃ(bโˆ’a)n\mid (b-a)nโˆฃ(bโˆ’a)
kkk
a=b+kna=b+kna=b+kn
aโ‰กbย [n]a\equiv b~ [n]aโ‰กbย [n]
aโ‰กbmodโ€‰โ€‰na \equiv b\mod naโ‰กbmodn
bโ‰ 0b\neq0b๎€ =0
aโ‰กrย [b]a\equiv r~[b]aโ‰กrย [b]
rrr
aaa
โˆ€cโˆˆZ,aโ‰กbย [n]โ€…โ€ŠโŸนโ€…โ€Šacโ‰กbcย [n]\forall c\in \mathbb Z, a\equiv b~[n] \implies ac \equiv bc ~ [n]โˆ€cโˆˆZ,aโ‰กbย [n]โŸนacโ‰กbcย [n]
โˆ€cโˆˆZ,aโ‰กbย [n]โ€…โ€ŠโŸนโ€…โ€Ša+cโ‰กb+cย [n]\forall c \in \mathbb Z, a\equiv b~[n] \implies a+c\equiv b+c ~[n]โˆ€cโˆˆZ,aโ‰กbย [n]โŸนa+cโ‰กb+cย [n]
โˆ€cโˆˆZ,aโ‰กbย [n]ย andย bโ‰กcย [n]โ€…โ€ŠโŸนโ€…โ€Šaโ‰กcย [n]\forall c \in \mathbb Z, a \equiv b ~[n] \text{ and } b\equiv c~[n]\implies a\equiv c ~[n]โˆ€cโˆˆZ,aโ‰กbย [n]ย andย bโ‰กcย [n]โŸนaโ‰กcย [n]
โˆ€mโˆˆN,aโ‰กbย [n]โ€…โ€ŠโŸนโ€…โ€Šamโ‰กbmย [n]\forall m \in \mathbb N, a\equiv b~[n] \implies a^m\equiv b^m ~[n]โˆ€mโˆˆN,aโ‰กbย [n]โŸนamโ‰กbmย [n]
nnn
Z/nZ\mathbb Z/n\mathbb ZZ/nZ
Zn = Zmod(5)
Zn = Integers(5)
Zn = IntegerModRing(5)
# Ring of integers modulo 5
Zn(7)
# 2
Zn(8) == Zn(13)
# True
nnn
pow(2, 564654533, 7) # Output result as member of Z/7Z
# 4
power_mod(987654321, 987654321, 7) # Output result as simple integer
# 6
Zmod(7)(84564685)^(2^100) # ^ stands for powering in sage. To get XOR, use ^^.
# 5
nnn
aaa
bbb
a2=2+4ba^2 = 2 + 4ba2=2+4b
ccc
ddd
cdโ‰ก1ย [n]cd\equiv 1~[n]cdโ‰ก1ย [n]
cdโ‰ก1ย [n]โ€…โ€ŠโŸบโ€…โ€ŠโˆƒkโˆˆZ,cd=1+kncd\equiv 1~[n]\iff\exists k\in\mathbb Z, cd = 1 + kncdโ‰ก1ย [n]โŸบโˆƒkโˆˆZ,cd=1+kn
gcdโก(c,n)=1\gcd(c, n) = 1gcd(c,n)=1
nnn
nnn
nnn
(Z/nZ)ร—\left(\mathbb Z/n\mathbb Z\right)^\times(Z/nZ)ร—
Zn = Zmod(10)
Zn(7).is_unit()
# True
Zn(8).is_unit()
# False
3 == 1/Zn(7) == Zn(7)^(-1) == pow(7,-1,10) # member of Z/10Z
# True
inverse_mod(7, 10) # simple integer
# 3
Zn(3)/7
# 9
Zn(3)/8
# ZeroDivisionError: inverse of Mod(8, 10) does not exist
Zn.unit_group()
# Multiplicative Abelian group isomorphic to C4 (C4 being the cyclic group of order 4)
ddd
kkk
cdโˆ’kn=1cd-kn=1cdโˆ’kn=1
xgcd(7, 10) # find (gcd(a, b), u, v) in au + bv = gcd(a, b)
# (1, 3, -2) <-- (gcd(7, 10), d, -k)
double-and-square
Bรฉzout's Identity
extended euclidean algorithm
n>1n > 1n>1
(nโˆ’1)!โ‰กโˆ’1modโ€‰โ€‰n(n-1)! \equiv -1 \mod n (nโˆ’1)!โ‰กโˆ’1modn
nโˆˆZ+n \in \mathbb{Z}^{+}nโˆˆZ+
aโˆˆZa \in \mathbb{Z}aโˆˆZ
gcd(a,n)=1gcd(a, n) = 1gcd(a,n)=1
aฯ•(n)โ‰ก1modโ€‰โ€‰na^{\phi(n)} \equiv 1 \mod naฯ•(n)โ‰ก1modn
ppp
aโˆˆZa \in \mathbb{Z}aโˆˆZ
apโ‰กamodโ€‰โ€‰pa^p \equiv a \mod papโ‰กamodp
apโˆ’1โ‰ก1modโ€‰โ€‰pa^{p-1} \equiv 1 \mod papโˆ’1โ‰ก1modp
Wilson's Theorem - Brilliant
Euler's Theorem - Brilliant
Fermat's Little Theorem - Brilliant

Pollard rho

Continued Fractions

Continued Fractions

Continued fractions are a way of representing a number as a sum of an integer and a fraction.

Mathematically, a continued fraction is a representation

a0+b0a1+b1a2+b2โ‹ฑa_{0} + \frac{b_{0}}{ a_{1} + \frac{b_{1}}{ a_{2} + \frac{b_{2}}{ \ddots }}}a0โ€‹+a1โ€‹+a2โ€‹+โ‹ฑb2โ€‹โ€‹b1โ€‹โ€‹b0โ€‹โ€‹

ai,bia_{i}, b_{i}aiโ€‹,biโ€‹are complex numbers. The continued fraction with bi=1ย โˆ€ib_{i} = 1\ \forall ibiโ€‹=1ย โˆ€i is called a simple continued fraction and continued fractions with finite number of aia_{i}aiโ€‹ are called finite continued fractions.

Consider example rational numbers,

1711=1+611116=1+5665=1+1551=5+0\frac{17}{11} = 1 + \frac{6}{11} \\[10pt] \frac{11}{6} = 1 + \frac{5}{6} \\[10pt] \frac{6}{5} = 1 + \frac{1}{5} \\[10pt] \frac{5}{1} = 5 + 01117โ€‹=1+116โ€‹611โ€‹=1+65โ€‹56โ€‹=1+51โ€‹15โ€‹=5+0

the continued fractions could be written as

51=565=1+15116=1+56=1+165=1+11+151711=1+611=1+1116=1+11+11+15\frac{5}{1} =5 \\[10pt] \frac{6}{5} = 1 + \frac{1}{5} \\[10pt] \frac{11}{6} = 1 + \frac{5}{6} = 1 + \frac{1}{\frac{6}{5}} = 1 + \frac{1}{1 + \frac{1}{5}} \\[10pt] \frac{17}{11} = 1 + \frac{6}{11} = 1 + \frac{1}{\frac{11}{6}} = 1 + \frac{1}{1 + \frac{1}{1 + \frac{1}{5}}}15โ€‹=556โ€‹=1+51โ€‹611โ€‹=1+65โ€‹=1+56โ€‹1โ€‹=1+1+51โ€‹1โ€‹1117โ€‹=1+116โ€‹=1+611โ€‹1โ€‹=1+1+1+51โ€‹1โ€‹1โ€‹

Notation

a0+1a1+1a2+1โ‹ฑa_{0} + \frac{1}{ a_{1} + \frac{1}{ a_{2} + \frac{1}{ \ddots }}}a0โ€‹+a1โ€‹+a2โ€‹+โ‹ฑ1โ€‹1โ€‹1โ€‹

A simple continued fraction is represented as a list of coefficients(aia_{i}aiโ€‹) i.e

x=[a0;ย a1,ย a2,ย a3,ย a4,ย a5,ย a6,ย โ€ฆ]x = [a_{0};\ a_{1},\ a_{2},\ a_{3},\ a_{4},\ a_{5},\ a_{6},\ \ldots]x=[a0โ€‹;ย a1โ€‹,ย a2โ€‹,ย a3โ€‹,ย a4โ€‹,ย a5โ€‹,ย a6โ€‹,ย โ€ฆ]

for the above example

1711=[1;ย 1,ย 1,ย 5]ย ย ,116=[1;ย 1,ย 5]ย ย ,65=[1;5]ย ย ,51=[5;] \frac{17}{11} = [1;\ 1,\ 1,\ 5]\ \ ,\frac{11}{6} = [1;\ 1,\ 5]\ \ ,\frac{6}{5} = [1; 5]\ \ ,\frac{5}{1} = [5;]1117โ€‹=[1;ย 1,ย 1,ย 5]ย ย ,611โ€‹=[1;ย 1,ย 5]ย ย ,56โ€‹=[1;5]ย ย ,15โ€‹=[5;]

Computation of simple continued fractions

Given a number xxx, the coefficients(aia_{i}aiโ€‹) in its continued fraction representation can be calculated recursively using

x0=xai=โŒŠxiโŒ‹xi+1=1xiโˆ’aix_{0} = x \\[4pt] a_{i} = \lfloor x_{i} \rfloor \\[4pt] x_{i+1} = \frac{1}{x_{i} - a_{i}}x0โ€‹=xaiโ€‹=โŒŠxiโ€‹โŒ‹xi+1โ€‹=xiโ€‹โˆ’aiโ€‹1โ€‹

The above notation might not be obvious. Observing the structure of continued fraction with few coefficients will make them more evident:

x0=a0+1a1+1a2,ย ย ย x1=a1+1a2,ย ย ย x2=a2xi=ai+1xi+1xi+1=1xiโˆ’aix_{0} = a_{0} + \frac{1}{a_{1} + \frac{1}{a_{2}}},\ \ \ x_{1} = a_{1} + \frac{1}{a_{2}}, \ \ \ x_{2} = a_{2} \\[10pt] x_{i} = a_{i} + \frac{1}{x_{i+1}} \\[10pt] x_{i+1} = \frac{1}{x_{i} - a_{i}}x0โ€‹=a0โ€‹+a1โ€‹+a2โ€‹1โ€‹1โ€‹,ย ย ย x1โ€‹=a1โ€‹+a2โ€‹1โ€‹,ย ย ย x2โ€‹=a2โ€‹xiโ€‹=aiโ€‹+xi+1โ€‹1โ€‹xi+1โ€‹=xiโ€‹โˆ’aiโ€‹1โ€‹

SageMath provides functions continued_fraction and continued_fraction_list to work with continued fractions. Below is presented a simple implementation of continued_fractions.

def continued_fraction_list(xi):
    ai = floor(xi)
    if xi == ai: # last coefficient
        return [ai]
    return [ai] + continued_fraction_list(1/(x - ai))

Convergents of continued fraction

The kthk^{th}kthconvergent of a continued fractionx=[a0;a1,ย a2,ย a3,ย a4,โ€ฆ]x = [a_{0}; a_{1},\ a_{2},\ a_{3},\ a_{4},\ldots] x=[a0โ€‹;a1โ€‹,ย a2โ€‹,ย a3โ€‹,ย a4โ€‹,โ€ฆ]is the numerical value or approximation calculated using the firstkโˆ’1k - 1kโˆ’1coefficients of the continued fraction. The firstkkkconvergents are

a01,ย ย ย a0+1a1,ย ย ย a0+1a1+1a2,ย โ€ฆ,ย a0+1a1+โ‹ฑakโˆ’2+1akโˆ’1\frac{a_{0}}{1},\ \ \ a_{0} + \frac{1}{a_{1}}, \ \ \ a_{0} + \frac{1}{a_{1} + \frac{1}{a_{2}}}, \ \ldots,\ a_{0} + \frac{1}{a_{1} + \frac{\ddots} {a_{k-2} + \frac{1}{a_{k-1}}}}1a0โ€‹โ€‹,ย ย ย a0โ€‹+a1โ€‹1โ€‹,ย ย ย a0โ€‹+a1โ€‹+a2โ€‹1โ€‹1โ€‹,ย โ€ฆ,ย a0โ€‹+a1โ€‹+akโˆ’2โ€‹+akโˆ’1โ€‹1โ€‹โ‹ฑโ€‹1โ€‹

One of the immediate applications of the convergents is that they give rational approximations given the continued fraction of a number. This allows finding rational approximations to irrational numbers.

Convergents of continued fractions can be calculated in sage

sage: cf = continued_fraction(17/11)
sage: convergents = cf.convergents()
sage: cf
[1; 1, 1, 5]
sage: convergents
[1, 2, 3/2, 17/11]

Continued fractions have many other applications. One such applicable in cryptology is based on Legendre's theorem in diophantine approximations.

Theorem: ifโˆฃxโˆ’abโˆฃ<1b2\mid x - \frac{a}{b} \mid < \frac{1}{b^{2}}โˆฃxโˆ’baโ€‹โˆฃ<b21โ€‹, thenab\frac{a}{b}baโ€‹is a convergent ofxxx.

Wiener's attack on the RSA cryptosystem works by proving that under certain conditions, an equation of the formโˆฃxโˆ’abโˆฃ\mid x - \frac{a}{b} \midโˆฃxโˆ’baโ€‹โˆฃcould be derived wherexxxis entirely made up of public information andab\frac{a}{b}baโ€‹is made up of private information. Under assumed conditions, the inequalityโˆฃxโˆ’abโˆฃ<1b2\mid x - \frac{a}{b} \mid < \frac{1}{b^{2}}โˆฃxโˆ’baโ€‹โˆฃ<b21โ€‹is statisfied, and the valueab\frac{a}{b}baโ€‹(private information) is calculated from convergents ofxxx(public information), consequently breaking the RSA cryptosystem.

Quadratic Residues

Fermat's Little Theorem in Detail

Would you like to be an author?

Introduction

Since we can add, subtract, multiply, divide even... what would be missing? Powering! I'm not talking about some power fantasy here, but rather introduce some really really important theorems. Fermat little's theorem proves useful in a great deal of situation, and is along with Euler's theorem a piece of arithmetic you need to know. Arguably the most canonical example of using these is the RSA cryptosystem, whose decryption step is built around Euler's theorem.

Fermat's Little Theorem

Since we want to talk about powers, let's look at powers. And because I like 7, I made a table of all the powers of all the integers modulo 7.

Power

0

1

2

3

4

5

6

1

0

1

2

3

4

5

6

2

0

1

4

2

2

4

1

3

0

1

1

6

1

6

6

4

0

1

2

4

4

2

1

5

0

1

4

5

2

3

6

6

0

1

1

1

1

1

1

On the last row, there is a clear pattern emerging, what's going on??? Hm, let's try again modulo 5 this time.

Power

0

1

2

3

4

1

0

1

2

3

4

2

0

1

4

4

1

3

0

1

3

2

4

4

0

1

1

1

1

Huh, again?! Clearly, there is something going on... Sage confirms this!

p, itworks = 1, True
for _ in range(100):
    p = next_prime(p)
    Fp = GF(p) # Finite Field of size p
    itworks &= all(Fp(x)^(p-1) == 1 for x in range(1,p))

print(itworks)
# True

Claim (Fermat's Little Theorem): Letpppa prime.โˆ€aโˆˆZ,apโ‰กaย [p]\forall a\in\mathbb Z, a^p\equiv a~[p]โˆ€aโˆˆZ,apโ‰กaย [p]

Whenaโ‰ 0a\neq 0a๎€ =0, this is equivalent to what we observed:apโˆ’1โ‰ก1ย [n]a^{p-1}\equiv 1~[n]apโˆ’1โ‰ก1ย [n]. There are several proofs of Fermat's Little Theorem, but perhaps the fastest is to see it as a consequence of the Euler's Theorem which generalizes it. Still, let's look a bit at some applications of this before moving on.

A first funny thing is the following:โˆ€aโˆˆZ,aโ‹…apโˆ’2โ‰กapโˆ’1โ‰ก1ย [p]\forall a\in\mathbb Z, a\cdot a^{p-2}\equiv a^{p-1}\equiv 1~[p]โˆ€aโˆˆZ,aโ‹…apโˆ’2โ‰กapโˆ’1โ‰ก1ย [p]. Whenp>2p>2p>2, this means we have found a non-trivial integer that when multiplied toaaayields 1. That is, we have found the inverse ofaaa, wow. Since the inverse is unique moduloppp, we can always invert non-zero integers by doing this. From a human point of view, this is really easier than using the extended euclidean algorithm.

Sieves

Discrete Log Problem

Discrete log problem

Given any groupGGGand elementsa,ba,ba,bsuch that an=ba^n=ban=b, the problem of solving fornnnis known as the disctete log problem (DLP). In sage, this can be done for general groups by calling discrete_log

sage: G = DihedralGroup(99)
sage: g = G.random_element()
sage: discrete_log(g^9,g) # note that if the order of g is less than 9 we would get 9 mod g.order()
9

Discrete log over (Z/nZ)โˆ—\left(\mathbb Z/n\mathbb Z\right)^*(Z/nZ)โˆ—

Typically, one considers the discrete log problem in (Z/nZ)โˆ—\left(\mathbb Z/n\mathbb Z\right)^*(Z/nZ)โˆ—, i.e. the multiplicative group of integersmodย n\text{mod }nmodย n. Explicitly, the problem asks forxxxgiven ax=b(modn)a^x=b\pmod nax=b(modn). This can be done by calling b.log(a) in sage:

sage: R = Integers(99)
sage: a = R(4)
sage: b = a^9
sage: b.log(a)
9

This section is devoted to helping the reader understand which functions are called when for this specific instance of DLP.

Whennnnis composite and not a prime power, discrete_log() will be used, which uses generic algorithms to solve DLP (e.g. Pohlig-Hellman and baby-step giant-step).

When n=pn=pn=pis a prime, Pari znlog will be used, which uses a linear sieve index calculus method, suitable for p<1050โˆผ2166p < 10^{50} \sim 2 ^{166}p<1050โˆผ2166.

When n=pkn = p^kn=pk, SageMath will fall back on the generic implementation discrete_log()which can be slow. However, Pari znlog can handle this as well, again using the linear sieve index calculus method. To call this within SageMath we can use either of the following (the first option being a tiny bit faster than the second)

x = int(pari(f"znlog({int(b)},Mod({int(a)},{int(n)}))"))
x = gp.znlog(b, gp.Mod(a, n))

Example

Given a small prime, we can compare the Pari method with the Sage defaults

p = getPrime(36)
n = p^2
K = Zmod(n)
a = K.multiplicative_generator()
b = a^123456789

time int(pari(f"znlog({int(b)},Mod({int(a)},{int(n)}))")) 
# CPU times: user 879 ยตs, sys: 22 ยตs, total: 901 ยตs
# Wall time: 904 ยตs
# 123456789

time b.log(a)
# CPU times: user 458 ms, sys: 17 ms, total: 475 ms
# Wall time: 478 ms
# 123456789

time discrete_log(b,a)
# CPU times: user 512 ms, sys: 24.5 ms, total: 537 ms
# Wall time: 541 ms
# 123456789

We can also solve this problem with even larger primes in a very short time

p = getPrime(100)
n = p^2
K = Zmod(n)
a = K.multiplicative_generator()
b = a^123456789

time int(pari(f"znlog({int(b)},Mod({int(a)},{int(n)}))")) 
# CPU times: user 8.08 s, sys: 82.2 ms, total: 8.16 s
# Wall time: 8.22 s
# 123456789

Discrete log over E(k)E(k)E(k)

// elliptic curve discrete log functions

Integer Factorization

Overview

Given a composite integer nnn, can it be decomposed as a product of smaller integers (hopefully as a unique product of prime factors)?

As easy as it may sound, integer factorization in polynomial time on a classical computer stands one of the unsolved problems in computation for centuries!

Lets start dumb, all we need to do is check all the numbers 1<p<n1 < p < n1<p<n such that pโˆฃnp|npโˆฃnor programmatically n%p==0

def factors(n):
    divisors = []
    for p in range(1,n):
        if n%p==0:
            divisors.append(p)
    return divisors

Seems like its an O(n)O(n)O(n)algorithm! whats all the deal about? By polynomial time, we mean polynomial time in bbbwhen nnnis a b-bit number, so what we looking at is actually a O(2b)O(2^b)O(2b)which is actually exponential (which everyone hates)

Now taking a better look at it, one would realize that a factor of nnncan't be bigger than n\sqrt{n}nโ€‹ Other observation would be, if we already checked a number (say 2) to not be a divisor, we dont need to check any multiple of that number since it would not be a factor.

Polynomials With Shared Roots

Algorithmic Number Theory

  • Polynomial GCD

    • Euclidean GCD

    • Half-GCD for speed when e=0x10001

    • demo application for that one RSA related message attack?

  • Resultant

    • eliminate multivariate polynomials at the expense of increasing polynomial degree

    • demo application for that one RSA Coppersmith short padding related message attack?

  • Groebner Basis

    • what if you did GCD and Resultants at the same time, like whoa

    • and what if it took forever to run!

Another take on groups

// Visual

// Symmetries

// Permutations

Polynomials

// symmetric polynomials

// discriminants

// resultants

Rings

A setRRRwith two binary operations +,โ‹…:Rร—Rโ†’R+,\cdot:R\times R\to R+,โ‹…:Rร—Rโ†’Ris a ring if the following holds:

  • R,+R,+R,+is a commutative group with identity 000

  • R,โ‹…R,\cdotR,โ‹…is a monoid (group without the inverse axiom) with identity111.

  • Distributivity: a(b+c)=ab+ac,(a+b)c=ac+bca(b+c)=ab+ac,(a+b)c=ac+bca(b+c)=ab+ac,(a+b)c=ac+bc

// ideals, diff types of domains

Gram-Schmidt Orthogonalization

Overview

Gram-Schmidt orthogonalization is an algorithm that takes in a basis {bi}i=1n\left\{b_i\right\}_{i=1}^n{biโ€‹}i=1nโ€‹ as an input and returns a basis {biโˆ—}i=1n\left\{b_i^*\right\}_{i=1}^n{biโˆ—โ€‹}i=1nโ€‹where all vectors are orthogonal, i.e. at right angles. This new basis is defined as

biโˆ—=biโˆ’โˆ‘j=1iโˆ’1ฮผi,jbjโˆ—ฮผi,j=โŸจbi,bjโˆ—โŸฉโŸจbjโˆ—,bjโˆ—โŸฉb_i^*=b_i-\sum_{j=1}^{i-1}\mu_{i,j}b_j^*\quad\mu_{i,j}=\frac{\langle b_i,b_j^*\rangle}{\langle b_j^*,b_j^*\rangle}biโˆ—โ€‹=biโ€‹โˆ’j=1โˆ‘iโˆ’1โ€‹ฮผi,jโ€‹bjโˆ—โ€‹ฮผi,jโ€‹=โŸจbjโˆ—โ€‹,bjโˆ—โ€‹โŸฉโŸจbiโ€‹,bjโˆ—โ€‹โŸฉโ€‹

where ฮผi,j\mu_{i,j}ฮผi,jโ€‹is the Gram-Schmidt coefficients.

One can immediately check that this new basis is orthogonal, meaning

โŸจbiโˆ—,bjโˆ—โŸฉ={0iโ‰ jโˆฅbiโˆ—โˆฅ2i=j\langle b_i^*,b_j^*\rangle=\begin{cases}0&i\neq j\\\left\lVert b_i^*\right\rVert^2&i=j\end{cases}โŸจbiโˆ—โ€‹,bjโˆ—โ€‹โŸฉ={0โˆฅbiโˆ—โ€‹โˆฅ2โ€‹i๎€ =ji=jโ€‹

Let B\mathcal BBbe the matrix where the iiith row is given by bib_ibiโ€‹andBโˆ—\mathcal B^*Bโˆ—be the matrix where the iiith row is given by biโˆ—b_i^*biโˆ—โ€‹, then the Gram-Schmidt orthogonalization gives us B=ฮผBโˆ—\mathcal B=\mu\mathcal B^*B=ฮผBโˆ—where ฮผi,i=1,ฮผj,i=0\mu_{i,i}=1,\mu_{j,i}=0ฮผi,iโ€‹=1,ฮผj,iโ€‹=0and ฮผi,j\mu_{i,j}ฮผi,jโ€‹is the Gram-Schmidt coefficient. As an example, consider the basis of a subspace of R4\mathbb R^4R4:

b1=(โˆ’1โˆ’231)b2=(โˆ’6โˆ’451)b3=(551โˆ’3)\begin{matrix} b_1 &= & (&-1&-2&3&1&)\\ b_2 &= & (&-6&-4&5&1&)\\ b_3 &= & (&5&5&1&-3&) \end{matrix}b1โ€‹b2โ€‹b3โ€‹โ€‹===โ€‹(((โ€‹โˆ’1โˆ’65โ€‹โˆ’2โˆ’45โ€‹351โ€‹11โˆ’3โ€‹)))โ€‹

Instead of doing the Gram-Schmidt orthogonalization by hand, we can get sage to do it for us:

B = Matrix([
[-1, -2, 3, 1],
[-6, -4, 5, 1],
[5, 5, 1, -3]])

B.gram_schmidt()

This outputs two matrices, Bโˆ—\mathcal B^*Bโˆ—and ฮผ\muฮผ:

(
[-1 -2  3  1]  [ 1  0  0]
[-4  0 -1 -1]  [ 2  1  0]
[ 0  3  3 -3], [-1 -1  1]
)

One can quickly verify that B=ฮผBโˆ—\mathcal B=\mu\mathcal B^*B=ฮผBโˆ— and that the rows of Bโˆ—\mathcal B^*Bโˆ—are orthogonal to each other.

A useful result is that

detโก(BBT)=detโก(Bโˆ—Bโˆ—T)=โˆiโˆฅbiโˆ—โˆฅ\det\left(\mathcal B\mathcal B^T\right)=\det\left(\mathcal B^*\mathcal B^{*T}\right)=\prod_i\left\lVert b_i^*\right\rVertdet(BBT)=det(Bโˆ—Bโˆ—T)=iโˆโ€‹โˆฅbiโˆ—โ€‹โˆฅ

Intuitively, this tells us that the more orthogonal a set of basis for a lattice is, the shorter it is as the volume must be constant.

Exercises

1) Show that the basis biโˆ—b_i^*biโˆ—โ€‹is orthogonal.

2) Verify that the output of sage is indeed correct.

3) Show that ฮผฮผT=1\mu\mu^T=1ฮผฮผT=1and Bโˆ—Bโˆ—T\mathcal B^*\mathcal B^{*T}Bโˆ—Bโˆ—T is a diagonal matrix whose entries are โˆฅbiโˆ—โˆฅ\left\lVert b_i^*\right\rVertโˆฅbiโˆ—โ€‹โˆฅ. Conclude that detโก(BBT)=detโก(Bโˆ—Bโˆ—T)=โˆiโˆฅbiโˆ—โˆฅ\det\left(\mathcal B\mathcal B^T\right)=\det\left(\mathcal B^*\mathcal B^{*T}\right)=\prod_i\left\lVert b_i^*\right\rVertdet(BBT)=det(Bโˆ—Bโˆ—T)=โˆiโ€‹โˆฅbiโˆ—โ€‹โˆฅ.

4*) Given the Iwasawa decomposition B=LDO\mathcal B=LDOB=LDOwhere LLLis a lower diagonal matrix with 111on its diagonal, DDDis a diagonal matrix and OOOan orthogonal matrix, meaning OOT=1OO^T=1OOT=1, show that Bโˆ—=DO\mathcal B^*=DOBโˆ—=DOand ฮผ=L\mu=Lฮผ=L. Furthermore, prove that such a decomposition is unique.

Fields

A setFFFwith two binary operations +,โ‹…:Fร—Fโ†’F+,\cdot:F\times F\to F+,โ‹…:Fร—Fโ†’Fis a field if the following holds:

  • R,+R,+R,+is a commutative group with identity 000

  • Rโˆ’{0},โ‹…R-\{0\},\cdotRโˆ’{0},โ‹…is a commutative group with identity111.

  • Distributivity: a(b+c)=ab+ac,(a+b)c=ac+bca(b+c)=ab+ac,(a+b)c=ac+bca(b+c)=ab+ac,(a+b)c=ac+bc

// field extensions, algebraic elements

LLL reduction

Introduction

In this section, we hope to bring some intuitive understanding to the LLL algorithm and how it works. The LLL algorithm is a lattice reduction algorithm, meaning it takes in a basis for some lattice and hopefully returns another basis for the same lattice with shorter basis vectors. Before introducing LLL reduction, we'll introduce 2 key algorithms that LLL is built from, Gram-Schmidt orthogonalization and Gaussian Reduction. We give a brief overview on why these are used to build LLL.

As the volume of a lattice is fixed, and is given by the determinant of the basis vectors, whenever our basis vectors gets shorter, they must, in some intuitive sense, become more orthogonal to each other in order for the determinant to remain the same. Hence, Gram-Schmidt orthogonalization is used as an approximation to the shortest basis vector. However, the vectors that we get are in general not in the lattice, hence we only use this as a rough idea of what the shortest vectors would be like.

Lagrange's algorithm can be thought as the GCD algorithm for 2 numbers generalized to lattices. This iteratively reduces the length of each vector by subtracting some amount of one from another until we can't do it anymore. Such an algorithm actually gives the shortest possible vectors in 2 dimensions! Unfortunately, this algorithm may not terminate for higher dimensions, even in 3 dimensions. Hence, it needs to be modified a bit to allow the algorithm to halt.

LLL reduction

Overview

There are a few issues that one may encounter when attempting to generalize Lagrange's algorithm to higher dimensions. Most importantly, one needs to figure what is the proper way to swap the vectors around and when to terminate, ideally in in polynomial time. A rough sketch of how the algorithm should look like is

def LLL(B):
    d = B.nrows()
    i = 1
    while i<d:
        size_reduce(B)
        if swap_condition(B):
            i += 1
        else:
            B[i],B[i-1] = B[i-1],B[i]
            i = max(i-1,1)
    return B

There are two things we need to figure out, in what order should we reduce the basis elements by and how should we know when to swap. Ideally, we also want the basis to be ordered in a way such that the smallest basis vectors comes first. Intuitively, it would also be better to reduce a vector by the larger vectors first before reducing by the smaller vectors, a very vague analogy to filling up a jar with big stones first before putting in the sand. This leads us to the following size reduction algorithm:

def size_reduce(B):
    d = B.nrows()
    i = 1
    while i<d:
        Bs,M = B.gram_schmidt()
        for j in reversed(range(i)):
            B[i] -= round(M[i,j])*B[j]
            Bs,M = B.gram_schmidt()
    return B

We can further improve this by optimizing the Gram Schmidt computation as this algorithm does not modify Bโˆ—\mathcal B^*Bโˆ—at all. Furthermoreฮผ\muฮผchanges in a very predictable fasion and when vectors are swapped, one can write explicit formulas for howBโˆ—\mathcal B^*Bโˆ—changes as well.

Next, we need to figure a swapping condition. Naively, we want

โˆฅbiโˆฅโ‰คโˆฅbi+1โˆฅ\left\lVert b_i\right\rVert\leq\left\lVert b_{i+1}\right\rVertโˆฅbiโ€‹โˆฅโ‰คโˆฅbi+1โ€‹โˆฅ

for all iii. However, such a condition does not guarantee termination in polynomial time. As short basis vectors should be almost orthogonal, we may also want to incorperate this notion. Concretely, we want โˆฃฮผi,jโˆฃ\left|\mu_{i,j}\right|โˆฃฮผi,jโ€‹โˆฃto be somewhat small for all pairs of i,ji,ji,j, i.e. we may want something like

โˆฃฮผi,jโˆฃโ‰คc|\mu_{i,j}|\leq cโˆฃฮผi,jโ€‹โˆฃโ‰คc

However, since ฮผi,j=โŸจbi,bjโˆ—โŸฉโŸจbjโˆ—,bjโˆ—โŸฉ\mu_{i,j}=\frac{\langle b_i,b_j^*\rangle}{\langle b_j^*,b_j^*\rangle}ฮผi,jโ€‹=โŸจbjโˆ—โ€‹,bjโˆ—โ€‹โŸฉโŸจbiโ€‹,bjโˆ—โ€‹โŸฉโ€‹, this condition is easily satisfied for a sufficiently long bjโˆ—b_j^*bjโˆ—โ€‹, which is not what we want. The key idea is to merge these two in some way and was first noticed by Lovรกsz - named the Lovรกsz condition:

ฮดโˆฅbiโˆ—โˆฅ2โ‰คโˆฅbi+1โˆ—+ฮผi+1,ibiโˆ—โˆฅ2ฮดโˆˆ(14,1)\delta\left\lVert b_i^*\right\rVert^2\leq\left\lVert b_{i+1}^*+\mu_{i+1,i}b_i^*\right\rVert^2\quad\delta\in\left(\frac14,1\right)ฮดโˆฅbiโˆ—โ€‹โˆฅ2โ‰คโ€‹bi+1โˆ—โ€‹+ฮผi+1,iโ€‹biโˆ—โ€‹โ€‹2ฮดโˆˆ(41โ€‹,1)

It turns out that using this condition, the algorithm above terminates in polynomial time! More specifically, it has a time complexity of O(d5nlogโก3B)O\left(d^5n\log^3B\right)O(d5nlog3B)where we havedddbasis vectors as a subset of Rn\mathbb R^nRnand BBBis a bound for the largest norm of bib_ibiโ€‹. 14<ฮด\frac14<\delta41โ€‹<ฮด ensures that the lattice vectors are ordered roughly by size and ฮด<1\delta<1ฮด<1ensures the algorithm terminates.

Polynomial time proof

This follows the proof provided by the authors of the LLL paper. We first prove that the algorithm terminates by showing it swaps the vectors finitely many times. Letdddbe the number of basis vectors as a subset of Rn\mathbb R^nRn. Let did_idiโ€‹be the volume of the lattice generated by {bj}j=1i\left\{b_j\right\}_{j=1}^i{bjโ€‹}j=1iโ€‹at each step of the algorithm. We have di=โˆj=1iโˆฅbjโˆ—โˆฅd_i=\prod_{j=1}^i\left\lVert b_j^*\right\rVertdiโ€‹=โˆj=1iโ€‹โ€‹bjโˆ—โ€‹โ€‹. Now consider the quantity

D=โˆi=1ddiD=\prod_{i=1}^dd_iD=i=1โˆdโ€‹diโ€‹

This quantity only changes whenever some biโˆ—b_i^*biโˆ—โ€‹changes, i.e when swaps happen. Let's consider what happens when we swap bib_ibiโ€‹and bi+1b_{i+1}bi+1โ€‹. Recall the Gram-Schmidt algorithm:

biโˆ—=biโˆ’โˆ‘j=1iโˆ’1ฮผi,jbjโˆ—ฮผi,j=โŸจbi,bjโˆ—โŸฉโŸจbjโˆ—,bjโˆ—โŸฉb_i^*=b_i-\sum_{j=1}^{i-1}\mu_{i,j}b_j^*\quad\mu_{i,j}=\frac{\langle b_i,b_j^*\rangle}{\langle b_j^*,b_j^*\rangle}biโˆ—โ€‹=biโ€‹โˆ’j=1โˆ‘iโˆ’1โ€‹ฮผi,jโ€‹bjโˆ—โ€‹ฮผi,jโ€‹=โŸจbjโˆ—โ€‹,bjโˆ—โ€‹โŸฉโŸจbiโ€‹,bjโˆ—โ€‹โŸฉโ€‹

From this, see that when we swap bib_ibiโ€‹and bi+1b_{i+1}bi+1โ€‹, biโˆ—b_i^*biโˆ—โ€‹is replaced by bi+1โˆ—+ฮผi+1,ibiโˆ—b_{i+1}^*+\mu_{i+1,i}b_i^*bi+1โˆ—โ€‹+ฮผi+1,iโ€‹biโˆ—โ€‹. Now using the Lovรกsz condition, we see that we haveโˆฅbi+1โˆ—+ฮผi+1,ibiโˆ—โˆฅ2<ฮดโˆฅbiโˆ—โˆฅ2\left\lVert b_{i+1}^*+\mu_{i+1,i}b_i^*\right\rVert^2<\delta\left\lVert b_i^*\right\rVert^2โ€‹bi+1โˆ—โ€‹+ฮผi+1,iโ€‹biโˆ—โ€‹โ€‹2<ฮดโˆฅbiโˆ—โ€‹โˆฅ2, hence the value of did_idiโ€‹must decrease by at least ฮด\deltaฮด, i.e. the new did_idiโ€‹is less than diฮด\frac{d_i}\deltaฮดdiโ€‹โ€‹. All other dj,jโ‰ id_j,j\neq idjโ€‹,j๎€ =imust remain the same as the volume remains fixed when we swap basis vectors around. Hence at each swap, DDDdecreases by ฮด\deltaฮด. This is why we need ฮด<1\delta<1ฮด<1.Now we are left with showing did_idiโ€‹is bounded from below then we are done.

Let ฮป1(L)\lambda_1(L)ฮป1โ€‹(L)be the length of the shortest (nonzero) vector in the lattice. We can treat did_idiโ€‹as the volume of the lattice LiL_iLiโ€‹generated by{bj}j=1i\left\{b_j\right\}_{j=1}^i{bjโ€‹}j=1iโ€‹. Let xix_ixiโ€‹be the shortest vector in the lattice in LiL_iLiโ€‹. By using Minkowski's lattice point theorem, we have

ฮป1(L)โ‰คxiโ‰ค2ฯ€ฮ“(i2+1)1iโŸCidi1idiโ‰ฅฮป1(L)iCii=di,minโก\begin{align*} \lambda_1(L)\leq x_i&\leq\underbrace{\frac2{\sqrt\pi}\Gamma\left(\frac i2+1\right)^{\frac1i}}_{C_i}d_i^\frac1i\\ d_i&\geq\frac{\lambda_1(L)^i}{C_i^i}=d_{i,\min} \end{align*}ฮป1โ€‹(L)โ‰คxiโ€‹diโ€‹โ€‹โ‰คCiโ€‹ฯ€โ€‹2โ€‹ฮ“(2iโ€‹+1)i1โ€‹โ€‹โ€‹dii1โ€‹โ€‹โ‰ฅCiiโ€‹ฮป1โ€‹(L)iโ€‹=di,minโ€‹โ€‹

(Note that the value of CiC_iCiโ€‹isn't particularly important, one can use a easier value like i\sqrt iiโ€‹)

Hence we see that did_idiโ€‹, and hence DDDhas a (loose) lower bound Dminโก=โˆi=1ddi,minโกD_{\min}=\prod_{i=1}^dd_{i,\min}Dminโ€‹=โˆi=1dโ€‹di,minโ€‹, meaning that there are at most logโกDlogโกDminโกฮด\frac{\log D}{\log D_{\min}\delta}logDminโ€‹ฮดlogDโ€‹swaps. Since at each iteration,kkkeither increases by111when there is no swaps or decreases by at most111when there is swaps and kkkranges from222toddd, the number of time the loop runs must be at most 2logโกDlogโกDminโกฮด+d2\frac{\log D}{\log D_{\min}\delta}+d2logDminโ€‹ฮดlogDโ€‹+d, hence the algorithm terminates.

This proof also gives us a handle on the time complexity of the operation. LetBBBis the length of the longest input basis vector. Since we have diโ‰คBid_i\leq B^idiโ€‹โ‰คBi, Dโ‰คBm2+m2D\leq B^{\frac{m^2+m}2}Dโ‰คB2m2+mโ€‹and the algorithm loops O(d2logโกB)O\left(d^2\log B\right)O(d2logB)times. The Gram-Schmidt orthogonalization is the most expensive part in the entire process, taking up O(d2n)O\left(d^2n\right)O(d2n)arithmetic operations. By using classical algorithm for arithmetic operations, each takes O(nlogโกB)O\left(n\log B\right)O(nlogB)time. From this, we deduce that the time complexity of the LLL algorithm is O(d5mlogโก2B)O\left(d^5m\log^2B\right)O(d5mlog2B), a somewhat reasonable polynomial time algorithm.

Let bib_ibiโ€‹be the output of the LLL algorithm, it turns out that we have the bound

โˆฅb1โˆฅโ‰ค(44ฮดโˆ’1)dโˆ’14vol(L)1d\left\lVert b_1\right\rVert\leq\left(\frac4{4\delta-1}\right)^{\frac{d-1}4}\text{vol}(L)^\frac1dโˆฅb1โ€‹โˆฅโ‰ค(4ฮดโˆ’14โ€‹)4dโˆ’1โ€‹vol(L)d1โ€‹

which requires ฮด>14\delta>\frac14ฮด>41โ€‹. Such bounds for the shortest vector will be elaborated in more detail in the section on reduced basis.

Exercises

1) Implement the LLL in sage and experimentally verify that DDDdoes indeed decrease byฮด\deltaฮดeach time.

2) Show that the time complexity analysis is correct, and indeed each loop takes at most O(d2n)O\left(d^2n\right)O(d2n)operations.

Untitled

Extensions of Coppersmith algorithm

The Coppersmith algorithm can be made even more general. There are two main extensions, first to an unknown modulus, then to multivariate polynomials.

Unknown modulus

This extension of Coppersmith allows one to find small roots modulo an unknown some unknown factor of a number. More specifically, suppose that we have some unknown factorbbbofNNNsuch that b<Nฮฒb<N^\betab<Nฮฒand some monic polynomialfffof degreedddsuch that f(x0)=0(modb)f(x_0)=0\pmod bf(x0โ€‹)=0(modb)for some x0<Nฮฒ2dx_0<N^{\frac{\beta^2}d}x0โ€‹<Ndฮฒ2โ€‹. Then we can findx0x_0x0โ€‹in time polynomial in logโกN,d\log N,dlogN,d.

One key reason why this is possible is because we dont need to explicitly know the modulus to determine if a small root exists, i.e. โˆฅf(Bx)โˆฅ2โ‰คbd+1โ‰คNฮฒd+1\left\lVert f(Bx)\right\rVert_2\leq\frac b{\sqrt{d+1}}\leq\frac{N^{\beta}}{\sqrt{d+1}}โˆฅf(Bx)โˆฅ2โ€‹โ‰คd+1โ€‹bโ€‹โ‰คd+1โ€‹Nฮฒโ€‹is sufficient for a root less thanBBBto exist. The algorithm here is extremely similar to the Coppersmith algorithm, except we add more polynomials into the lattice. The polynomials that we will use are

gi,j(x)=Nhโˆ’jf(x)jxi0โ‰คi<d,0โ‰คj<hgi,h(x)=f(x)hxi0โ‰คi<t\begin{align*} g_{i,j}(x)&=N^{h-j}f(x)^jx^i&0\leq i<d,0\leq j<h\\ g_{i,h}(x)&=f(x)^hx^i&0\leq i<t \end{align*}gi,jโ€‹(x)gi,hโ€‹(x)โ€‹=Nhโˆ’jf(x)jxi=f(x)hxiโ€‹0โ‰คi<d,0โ‰คj<h0โ‰คi<tโ€‹

The latticeLLLgenerated by these polynomials would have

dimโก(L)=dh+t=nvol(L)=Ndh(h+1)2B(nโˆ’1)n2\dim(L)=dh+t=n\quad\text{vol}(L)=N^{\frac{dh(h+1)}{2}}B^{\frac{(n-1)n}2}dim(L)=dh+t=nvol(L)=N2dh(h+1)โ€‹B2(nโˆ’1)nโ€‹

As we require the shortest vector to have length at most Nฮฒhn\frac{N^{\beta h}}{\sqrt{n}}nโ€‹Nฮฒhโ€‹, repeating the computations from the previous section, we obtain

B<4ฮดโˆ’14(1n)1nโˆ’1N2ฮฒhnโˆ’1โˆ’dh(h+1)n(nโˆ’1)B<\sqrt{\frac{4\delta-1}4}\left(\frac1n\right)^{\frac1{n-1}}N^{\frac{2\beta h}{n-1}-\frac{dh(h+1)}{n(n-1)}}B<44ฮดโˆ’1โ€‹โ€‹(n1โ€‹)nโˆ’11โ€‹Nnโˆ’12ฮฒhโ€‹โˆ’n(nโˆ’1)dh(h+1)โ€‹

It turns out that the maxima of 2ฮฒhnโˆ’1โˆ’dh(h+1)n(nโˆ’1)\frac{2\beta h}{n-1}-\frac{dh(h+1)}{n(n-1)}nโˆ’12ฮฒhโ€‹โˆ’n(nโˆ’1)dh(h+1)โ€‹is ฮฒ2d\frac{\beta^2}ddฮฒ2โ€‹as n,hโ†’โˆžn,h\to\inftyn,hโ†’โˆž. One way to achieve this is by settingn=dฮฒhn=\frac d\beta hn=ฮฒdโ€‹hand we obtain

B<4ฮดโˆ’14(1n)1nโˆ’1N(hโˆ’1)ฮฒ2dhโˆ’ฮฒB<\sqrt{\frac{4\delta-1}4}\left(\frac1n\right)^{\frac1{n-1}}N^{\frac{(h-1)\beta^2}{dh-\beta}}B<44ฮดโˆ’1โ€‹โ€‹(n1โ€‹)nโˆ’11โ€‹Ndhโˆ’ฮฒ(hโˆ’1)ฮฒ2โ€‹

and this indeed achieves the O(Nฮฒ2d)O\left(N^{\frac{\beta^2}d}\right)O(Ndฮฒ2โ€‹)bound. Similar to the Coppersmith algorithm, one chooses a sufficiently big h,nh,nh,nsuch that the remainding bits can be brute forced in constant time while the algorithm still remains in polynomial time.

Exercises

1) We show that the maximum of2ฮฒhnโˆ’1โˆ’dh(h+1)n(nโˆ’1)\frac{2\beta h}{n-1}-\frac{dh(h+1)}{n(n-1)}nโˆ’12ฮฒhโ€‹โˆ’n(nโˆ’1)dh(h+1)โ€‹is indeed ฮฒ2d\frac{\beta^2}ddฮฒ2โ€‹. We can assume that dโ‰ฅ2,hโ‰ฅ1,0<ฮฒโ‰ค1,nโ‰ฅ2d\geq2,h\geq1,0<\beta\leq1,n\geq2dโ‰ฅ2,hโ‰ฅ1,0<ฮฒโ‰ค1,nโ‰ฅ2. Since hnโˆ’1(2ฮฒโˆ’dh+1n)\frac h{n-1}\left(2\beta-d\frac{h+1}{n}\right)nโˆ’1hโ€‹(2ฮฒโˆ’dnh+1โ€‹)and hnโˆ’1<h+1n\frac h{n-1}<\frac{h+1}nnโˆ’1hโ€‹<nh+1โ€‹, the maximum occurs when h,nโ†’โˆžh,n\to\inftyh,nโ†’โˆžand hnโˆ’1,h+1nโ†’x\frac h{n-1},\frac{h+1}n\to xnโˆ’1hโ€‹,nh+1โ€‹โ†’x, hence we have reduced this to maximizing 2ฮฒxโˆ’dx22\beta x-dx^22ฮฒxโˆ’dx2which achieves its maximum of ฮฒ2d\frac{\beta^2}ddฮฒ2โ€‹ at x=ฮฒdx=\frac\beta dx=dฮฒโ€‹.

HKZ reduced

Definition

Let ฯ€i\pi_iฯ€iโ€‹as the projection to the orthogonal complement of {bj}j=1iโˆ’1\left\{b_j\right\}_{j=1}^{i-1}{bjโ€‹}j=1iโˆ’1โ€‹.Then the basis is HKZ-reduced if it is size-reduced and โˆฃโˆฃbiโˆ—โˆฃโˆฃ=ฮป1(ฯ€i(L))||b_i^*||=\lambda_1\left(\pi_i(L)\right)โˆฃโˆฃbiโˆ—โ€‹โˆฃโˆฃ=ฮป1โ€‹(ฯ€iโ€‹(L)). This definition gives us a relatively simple way to compute a HKZ-reduced basis by iteratively finding the shortest vector in orthogonal projections.

Bounds

4i+3โ‰ค(โˆฃโˆฃbiโˆฃโˆฃฮปi(L))2โ‰คi+34\frac4{i+3}\leq\left(\frac{||b_i||}{\lambda_i(L)}\right)^2\leq\frac{i+3}4i+34โ€‹โ‰ค(ฮปiโ€‹(L)โˆฃโˆฃbiโ€‹โˆฃโˆฃโ€‹)2โ‰ค4i+3โ€‹

Lattice reduction

Overview

Having introduced the LLL reduction, we now provide a more general notions of a reduced basis for a lattice as well as provide bounds for the basis vectors. The key idea behind introducing these definitions is that once we know some basis vector is []-reduced, we can bound the sizes of the basis, which is important when algorithms require short vectors in a lattice. For fast algorithms, LLL-reduction is typically the most important notion as it can be computed quickly. Two main definitions appear often when discussing lattice reductions, which we will provide here.

Definitions

A basis{bi}i=1d\left\{b_i\right\}_{i=1}^d{biโ€‹}i=1dโ€‹is size-reduced if โˆฃฮผi,jโˆฃโ‰ค12\left|\mu_{i,j}\right|\leq\frac12โˆฃฮผi,jโ€‹โˆฃโ‰ค21โ€‹. Intuitively this captures the idea that a reduced basis being "almost orthogonal".

Let LLLbe a lattice, 1โ‰คiโ‰คdimโกL=d1\leq i\leq\dim L=d1โ‰คiโ‰คdimL=d, we define the ithi^\text{th}ithsuccessive minimaฮปi(L)\lambda_i(L)ฮปiโ€‹(L) as

ฮปi(L)=minโก(maxโก1โ‰คjโ‰คi(โˆฅvjโˆฅ):vjโˆˆLย areย linearlyย independent)\lambda_i(L)=\min\left(\max_{1\leq j\leq i}\left(\left\lVert v_j\right\rVert\right):v_j\in L\text{ are linearly independent}\right)ฮปiโ€‹(L)=min(1โ‰คjโ‰คimaxโ€‹(โˆฅvjโ€‹โˆฅ):vjโ€‹โˆˆLย areย linearlyย independent)

Intuitively, ฮปi(L)\lambda_i(L)ฮปiโ€‹(L)is the length of the "ithi^\text{th}ith shortest lattice vector". This intuition is illustrated by the definition of ฮป1\lambda_1ฮป1โ€‹:

ฮป1(L)=minโก(โˆฅvโˆฅ:vโˆˆL)\lambda_1(L)=\min\left(\left\lVert v\right\rVert:v\in L\right)ฮป1โ€‹(L)=min(โˆฅvโˆฅ:vโˆˆL)

However this is not precise as if vvvis the shortest lattice vector, then โˆ’v-vโˆ’vis also the shortest lattice vector.

Unfortunately, a basisbib_ibiโ€‹for LLLwhere ฮปi(L)=โˆฅbiโˆฅ\lambda_i(L)=\left\lVert b_i\right\rVertฮปiโ€‹(L)=โˆฅbiโ€‹โˆฅfor dimensions 555 and above. This tells us that we can't actually define "the most reduced basis" in contrast to the 2D case (see Lagrange's algorithm) and we would need some other definition to convey this intuition.

An alternate definition ofฮปi(L)\lambda_i(L)ฮปiโ€‹(L)that will be helpful is the radius of the smallest ball centered at the origin such that the ball contains at leastiiilinearly independent vectors inLLL.

Exercises

1) Show that both definitions of ฮปi\lambda_iฮปiโ€‹ are equivalent

2) Consider the lattice L=(2000002000002000002011111)L=\begin{pmatrix}2&0&0&0&0\\0&2&0&0&0\\0&0&2&0&0\\0&0&0&2&0\\1&1&1&1&1\end{pmatrix}L=โ€‹20001โ€‹02001โ€‹00201โ€‹00021โ€‹00001โ€‹โ€‹. Show that the successive minima are all222but no basisbib_ibiโ€‹can satisfy โˆฅbiโˆฅ=ฮปi\left\lVert b_i\right\rVert=\lambda_iโˆฅbiโ€‹โˆฅ=ฮปiโ€‹.

LLL reduced

Definition

Let ฮดโˆˆ(14,1)\delta\in\left(\frac14,1\right)ฮดโˆˆ(41โ€‹,1). A basis{bi}i=1d\left\{b_i\right\}_{i=1}^d{biโ€‹}i=1dโ€‹is ฮด\deltaฮด- LLL-reduced if it is size reduced and satisfy the Lovรกsz condition, i.e.

ฮดโˆฅbiโˆ—โˆฅ2โ‰คโˆฅbi+1โˆ—+ฮผi+1,ibiโˆ—โˆฅ2\delta\left\lVert b_i^*\right\rVert^2\leq\left\lVert b_{i+1}^*+\mu_{i+1,i}b_i^*\right\rVert^2ฮดโˆฅbiโˆ—โ€‹โˆฅ2โ‰คโ€‹bi+1โˆ—โ€‹+ฮผi+1,iโ€‹biโˆ—โ€‹โ€‹2

This notion of reduction is most useful to use for fast algorithms as such a basis can be found in polynomial time (see LLL reduction).

Bounds

โˆฅb1โˆฅโ‰ค(44ฮดโˆ’1)dโˆ’14vol(L)1dโˆฅbiโˆฅโ‰ค(44ฮดโˆ’1)dโˆ’12ฮปi(L)โˆi=1dโˆฅbiโˆฅโ‰ค(44ฮดโˆ’1)d(dโˆ’1)4vol(L)\begin{align*} \left\lVert b_1\right\rVert&\leq\left(\frac4{4\delta-1}\right)^{\frac{d-1}4}\text{vol}(L)^\frac1d\\ \left\lVert b_i\right\rVert&\leq\left(\frac4{4\delta-1}\right)^{\frac{d-1}2}\lambda_i(L)\\ \prod_{i=1}^d\left\lVert b_i\right\rVert&\leq\left(\frac4{4\delta-1}\right)^{\frac{d(d-1)}4}\text{vol}(L) \end{align*}โˆฅb1โ€‹โˆฅโˆฅbiโ€‹โˆฅi=1โˆdโ€‹โˆฅbiโ€‹โˆฅโ€‹โ‰ค(4ฮดโˆ’14โ€‹)4dโˆ’1โ€‹vol(L)d1โ€‹โ‰ค(4ฮดโˆ’14โ€‹)2dโˆ’1โ€‹ฮปiโ€‹(L)โ‰ค(4ฮดโˆ’14โ€‹)4d(dโˆ’1)โ€‹vol(L)โ€‹

Coppersmith algorithm

This algorithm solves for small roots of polynomials modulo any integer, meaning given some polynomial f(x)โˆˆZ[x]f(x)\in\mathbb Z[x]f(x)โˆˆZ[x]of degree dddand any integer NNN, then if f(x0)=0(modN),โˆฃx0โˆฃ<N1df(x_0)=0\pmod{N},|x_0|<N^{\frac1d}f(x0โ€‹)=0(modN),โˆฃx0โ€‹โˆฃ<Nd1โ€‹, this algorithm can findx0x_0x0โ€‹with time polynomial in logโกN\log NlogNand ddd. The key idea behind this algorithm is to construct a polynomialg(x)g(x)g(x)such that g(x0)=0g(x_0)=0g(x0โ€‹)=0in R\mathbb RR. As roots of polynomials over the reals can be found easily, this gives an easy way to find x0x_0x0โ€‹. We shall introduce the Coppersmith algorithm in a few iterations, with each iteration approaching the N1dN^{\frac1d}Nd1โ€‹bound.

Polynomials in lattices

We first consider a criteria for a root of a polynomial moduloNNNto exists over the reals as well. Supposef(x)=โˆ‘i=0dfixif(x)=\sum_{i=0}^df_ix^if(x)=โˆ‘i=0dโ€‹fiโ€‹xiis a polynomial of degreeddd. Define the โ„“2\ell_2โ„“2โ€‹normโˆฅf(x)โˆฅ2\left\lVert f(x)\right\rVert_2โˆฅf(x)โˆฅ2โ€‹ of a polynomial to be โˆ‘i=0dfi2\sqrt{\sum_{i=0}^df_i^2}โˆ‘i=0dโ€‹fi2โ€‹โ€‹. Given โˆฃx0โˆฃ<B,f(x0)=0(modN)|x_0|<B,f(x_0)=0\pmod Nโˆฃx0โ€‹โˆฃ<B,f(x0โ€‹)=0(modN), if

โˆฅf(Bx)โˆฅ2=โˆ‘i=0d(fiBi)2โ‰คNd+1\left\lVert f(Bx)\right\rVert_2=\sqrt{\sum_{i=0}^d\left(f_iB^i\right)^2}\leq\frac N{\sqrt{d+1}}โˆฅf(Bx)โˆฅ2โ€‹=i=0โˆ‘dโ€‹(fiโ€‹Bi)2โ€‹โ‰คd+1โ€‹Nโ€‹

then f(x0)=0f(x_0)=0f(x0โ€‹)=0 in R\mathbb RR. The proof is a relatively straightforward chain of inequalities:

Nd+1โ‰ฅโˆ‘i=0d(fiBi)2โ‰ฅโˆ‘i=0d(fix0i)2โ‰ฅ1d+1โˆ‘i=0dโˆฃfix0iโˆฃโ‰ฅ1d+1โˆฃโˆ‘i=0dfix0iโˆฃ\begin{align*} \frac N{\sqrt{d+1}}&\geq\sqrt{\sum_{i=0}^d\left(f_iB^i\right)^2}\\&\geq\sqrt{\sum_{i=0}^d\left(f_ix_0^i\right)^2}\\ &\geq\frac1{\sqrt{d+1}}\sum_{i=0}^d\left|f_ix_0^i\right|\\ &\geq\frac1{\sqrt{d+1}}\left|\sum_{i=0}^df_ix_0^i\right|\\ \end{align*}d+1โ€‹Nโ€‹โ€‹โ‰ฅi=0โˆ‘dโ€‹(fiโ€‹Bi)2โ€‹โ‰ฅi=0โˆ‘dโ€‹(fiโ€‹x0iโ€‹)2โ€‹โ‰ฅd+1โ€‹1โ€‹i=0โˆ‘dโ€‹โ€‹fiโ€‹x0iโ€‹โ€‹โ‰ฅd+1โ€‹1โ€‹โ€‹i=0โˆ‘dโ€‹fiโ€‹x0iโ€‹โ€‹โ€‹

and since f(x0)=0(modN)f(x_0)=0\pmod Nf(x0โ€‹)=0(modN)implies f(x0)=kNf(x_0)=kNf(x0โ€‹)=kNfor some kโˆˆZk\in\mathbb ZkโˆˆZ, we know that kkkmust be000to satisfy the inequality above.

With this, if we can find some polynomials fif_ifiโ€‹such that fi(x0)=0(modN)f_i(x_0)=0\pmod Nfiโ€‹(x0โ€‹)=0(modN), then if we can find some cic_iciโ€‹such that โˆฅโˆ‘icifi(x)โˆฅ2โ‰คNd+1\left\lVert\sum_ic_if_i(x)\right\rVert_2\leq\frac N{\sqrt{d+1}}โˆฅโˆ‘iโ€‹ciโ€‹fiโ€‹(x)โˆฅ2โ€‹โ‰คd+1โ€‹Nโ€‹, then we can find x0x_0x0โ€‹easily. This gives a brief idea as to why lattices would be useful in such a problem.

To use lattices, notice that we can encode the polynomial f(x)=โˆ‘i=0dfixif(x)=\sum_{i=0}^df_ix^if(x)=โˆ‘i=0dโ€‹fiโ€‹xias the vector with components fif_ifiโ€‹. In this way, adding polynomials and multiplying polynomials by numbers still makes sense. Lets suppose that f(x0)=0(modN),x0<Bf(x_0)=0\pmod N,x_0<Bf(x0โ€‹)=0(modN),x0โ€‹<Band fd=1f_d=1fdโ€‹=1(otherwise multiplyfffby fdโˆ’1(modN)f_d^{-1}\pmod Nfdโˆ’1โ€‹(modN). Consider the polynomials gi(x)=Nxig_i(x)=Nx^igiโ€‹(x)=Nxiand consider the latticeLLLgenerated by f(Bx)f(Bx)f(Bx)and gi(Bx)g_i(Bx)giโ€‹(Bx), 0โ‰คiโ‰คdโˆ’10\leq i\leq d-10โ‰คiโ‰คdโˆ’1. As a matrix, the basis vectors are

B=(N00โ€ฆ000NB0โ€ฆ0000NB2โ€ฆ00โ‹ฎโ‹ฎโ‹ฎโ‹ฑโ‹ฎโ‹ฎ000โ€ฆNBdโˆ’10f0f1Bf2B2โ€ฆfdโˆ’1Bdโˆ’1Bd)\mathcal B=\begin{pmatrix} N&0&0&\dots&0&0\\ 0&NB&0&\dots&0&0\\ 0&0&NB^2&\dots&0&0\\ \vdots&\vdots&\vdots&\ddots&\vdots&\vdots\\ 0&0&0&\dots&NB^{d-1}&0\\ f_0&f_1B&f_2B^2&\dots&f_{d-1}B^{d-1}&B^d\\ \end{pmatrix} B=โ€‹N00โ‹ฎ0f0โ€‹โ€‹0NB0โ‹ฎ0f1โ€‹Bโ€‹00NB2โ‹ฎ0f2โ€‹B2โ€‹โ€ฆโ€ฆโ€ฆโ‹ฑโ€ฆโ€ฆโ€‹000โ‹ฎNBdโˆ’1fdโˆ’1โ€‹Bdโˆ’1โ€‹000โ‹ฎ0Bdโ€‹โ€‹

As every element in this lattice is some polynomial g(Bx)g(Bx)g(Bx), if f(x0)=0(modN)f(x_0)=0\pmod Nf(x0โ€‹)=0(modN), theng(x0)=0(modN)g(x_0)=0\pmod Ng(x0โ€‹)=0(modN). Furthermore, if โˆฃx0โˆฃ<B|x_0|<Bโˆฃx0โ€‹โˆฃ<Band a short vectorv(Bx)v(Bx)v(Bx)has length less than Nd+1\frac N{\sqrt{d+1}}d+1โ€‹Nโ€‹, then we have v(x0)=0v(x_0)=0v(x0โ€‹)=0in R\mathbb RR.

The volume of this lattice is NdBd(d+1)2N^dB^{\frac{d(d+1)}2}NdB2d(d+1)โ€‹and the lattice has dimension d+1d+1d+1. By using the LLL algorithm, we can find a vector v(Bx)v(Bx)v(Bx) with length at most

โˆฅv(Bx)โˆฅ2=(44ฮดโˆ’1)d4โŸcฮด,dvol(L)1d+1=cฮด,dNdd+1Bd2\left\lVert v(Bx)\right\rVert_2=\underbrace{\left(\frac4{4\delta-1}\right)^{\frac d4}}_{c_{\delta,d}}\text{vol}(L)^\frac1{d+1}=c_{\delta,d}N^{\frac d{d+1}}B^{\frac d2}โˆฅv(Bx)โˆฅ2โ€‹=cฮด,dโ€‹(4ฮดโˆ’14โ€‹)4dโ€‹โ€‹โ€‹vol(L)d+11โ€‹=cฮด,dโ€‹Nd+1dโ€‹B2dโ€‹

As long as cฮด,dNdd+1Bd2<Nd+1c_{\delta,d}N^{\frac d{d+1}}B^{\frac d2}<\frac N{\sqrt{d+1}}cฮด,dโ€‹Nd+1dโ€‹B2dโ€‹<d+1โ€‹Nโ€‹, then by the above criteria we know that this vector has x0x_0x0โ€‹has a root over R\mathbb RR. This tells us that

B<N2d(d+1)(cฮด,dd+1)โˆ’2dB<N^{\frac2{d(d+1)}}\left(c_{\delta,d}\sqrt{d+1}\right)^{-\frac 2d}B<Nd(d+1)2โ€‹(cฮด,dโ€‹d+1โ€‹)โˆ’d2โ€‹

While this isn't the N1dN^{\frac1d}Nd1โ€‹bound that we want, this gives us an idea of what we can do to achieve this bound, i.e. add more vectors such that the length of the shortest vector decreases.

Achieving the N1dN^{\frac1d}Nd1โ€‹bound

One important observation to make is that any coefficients in front ofNxN^xNxdoes not matter as we can simply brute force the top bits of our small root in O(1)O(1)O(1)time. Hence we only need to getB=kN1dB=kN^{\frac1d}B=kNd1โ€‹for some fixed constantkkk.

In order to achieve this, notice that if f(x0)=0(modN)f(x_0)=0\pmod Nf(x0โ€‹)=0(modN), then f(x0)h=0(modNh)f(x_0)^h=0\pmod{N^h}f(x0โ€‹)h=0(modNh). This loosens the inequality required for a polynomial to have x0x_0x0โ€‹as a small root as our modulus is now larger. With this in mind, consider the polynomials

gi,j(x)=Nhโˆ’jf(x)jxi0โ‰คi<d,0โ‰คj<hg_{i,j}(x)=N^{h-j}f(x)^jx^i\quad0\leq i<d,0\leq j<hgi,jโ€‹(x)=Nhโˆ’jf(x)jxi0โ‰คi<d,0โ‰คj<h

where we will determinehhhlater. Here gi,j(x0)=0(modNh)g_{i,j}(x_0)=0\pmod{N^h}gi,jโ€‹(x0โ€‹)=0(modNh), hence we shall consider the lattice LLL generated by gi,j(Bx)g_{i,j}(Bx)gi,jโ€‹(Bx). As an example, if we have

f(x)=x3+2x2+3x+4h=3f(x)=x^3+2x^2+3x+4\quad h=3f(x)=x3+2x2+3x+4h=3

the basis vectors of our lattice would look like

(N3000000000BN3000000000B2N30000004N23BN22B2N2B3N20000004BN23B2N22B3N2B4N20000004B2N23B3N22B4N2B5N200016N24BN25B2N20B3N10B4N4B5NB6N00016BN24B2N25B3N20B4N10B5N4B6NB7N00016B2N24B3N25B4N20B5N10B6N4B7NB8N)\footnotesize{\left(\begin{array}{rrrrrrrrr} N^{3} & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ 0 & B N^{3} & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ 0 & 0 & B^{2} N^{3} & 0 & 0 & 0 & 0 & 0 & 0 \\ 4 \, N^{2} & 3 \, B N^{2} & 2 \, B^{2} N^{2} & B^{3} N^{2} & 0 & 0 & 0 & 0 & 0 \\ 0 & 4 \, B N^{2} & 3 \, B^{2} N^{2} & 2 \, B^{3} N^{2} & B^{4} N^{2} & 0 & 0 & 0 & 0 \\ 0 & 0 & 4 \, B^{2} N^{2} & 3 \, B^{3} N^{2} & 2 \, B^{4} N^{2} & B^{5} N^{2} & 0 & 0 & 0 \\ 16 \, N & 24 \, B N & 25 \, B^{2} N & 20 \, B^{3} N & 10 \, B^{4} N & 4 \, B^{5} N & B^{6} N & 0 & 0 \\ 0 & 16 \, B N & 24 \, B^{2} N & 25 \, B^{3} N & 20 \, B^{4} N & 10 \, B^{5} N & 4 \, B^{6} N & B^{7} N & 0 \\ 0 & 0 & 16 \, B^{2} N & 24 \, B^{3} N & 25 \, B^{4} N & 20 \, B^{5} N & 10 \, B^{6} N & 4 \, B^{7} N & B^{8} N \end{array}\right)}โ€‹N3004N20016N00โ€‹0BN303BN24BN2024BN16BN0โ€‹00B2N32B2N23B2N24B2N225B2N24B2N16B2Nโ€‹000B3N22B3N23B3N220B3N25B3N24B3Nโ€‹0000B4N22B4N210B4N20B4N25B4Nโ€‹00000B5N24B5N10B5N20B5Nโ€‹000000B6N4B6N10B6Nโ€‹0000000B7N4B7Nโ€‹00000000B8Nโ€‹โ€‹

We have the following immediate computations of LLL:

dimโก(L)=dhvol(L)=Ndh(h+1)2B(dhโˆ’1)dh2\dim(L)=dh\quad\text{vol}(L)=N^{\frac{dh(h+1)}2}B^{\frac{(dh-1)dh}2}dim(L)=dhvol(L)=N2dh(h+1)โ€‹B2(dhโˆ’1)dhโ€‹

hence when using the LLL algorithm, the shortest LLL basis vectorv(Bx)v(Bx)v(Bx)has length

โˆฅv(Bx)โˆฅ2=(44ฮดโˆ’1)dimโก(L)โˆ’14vol(L)1dimโก(L)=(44ฮดโˆ’1)dhโˆ’14Nh+12Bdhโˆ’12\begin{align*} \left\lVert v(Bx)\right\rVert_2&=\left(\frac4{4\delta-1}\right)^{\frac{\dim(L)-1}4}\text{vol}(L)^{\frac1{\dim(L)}}\\ &=\left(\frac4{4\delta-1}\right)^{\frac{dh-1}4}N^{\frac{h+1}2}B^{\frac{dh-1}2}\\ \end{align*}โˆฅv(Bx)โˆฅ2โ€‹โ€‹=(4ฮดโˆ’14โ€‹)4dim(L)โˆ’1โ€‹vol(L)dim(L)1โ€‹=(4ฮดโˆ’14โ€‹)4dhโˆ’1โ€‹N2h+1โ€‹B2dhโˆ’1โ€‹โ€‹

and we need โˆฅv(Bx)โˆฅ2<Nhdh\left\lVert v(Bx)\right\rVert_2<\frac{N^h}{\sqrt{dh}}โˆฅv(Bx)โˆฅ2โ€‹<dhโ€‹Nhโ€‹for v(x0)=0v(x_0)=0v(x0โ€‹)=0. Hence we have

B<4ฮดโˆ’14(1dh)1dhโˆ’1Nhโˆ’1dhโˆ’1B<\sqrt{\frac{4\delta-1}4}\left(\frac1{dh}\right)^{\frac1{dh-1}}N^{\frac{h-1}{dh-1}}B<44ฮดโˆ’1โ€‹โ€‹(dh1โ€‹)dhโˆ’11โ€‹Ndhโˆ’1hโˆ’1โ€‹

Since limโกhโ†’โˆžhโˆ’1dhโˆ’1=1d\lim_{h\to\infty}\frac{h-1}{dh-1}=\frac1dlimhโ†’โˆžโ€‹dhโˆ’1hโˆ’1โ€‹=d1โ€‹, this will achieve the N1dN^{\frac1d}Nd1โ€‹bound that we want. However as for big hhh, the LLL algorithm would take a very long time, we typically choose a suitably largehhhsuch that the algorithm is still polynomial in logโกN,d\log N,dlogN,dand brute force the remaining bits.

Exercises

1) We often see h=โŒˆmaxโก(d+dฮตโˆ’1d2ฯต,7d)โŒ‰h=\left\lceil\max\left(\frac{d+d\varepsilon-1}{d^2\epsilon},\frac7d\right)\right\rceilh=โŒˆmax(d2ฯตd+dฮตโˆ’1โ€‹,d7โ€‹)โŒ‰in literature. We shall now show where this mysterious7d\frac7dd7โ€‹comes from. The other term will appear in the next exercise. Typically, one sets ฮด=34\delta=\frac34ฮด=43โ€‹to simplify calculations involving the LLL algorithm as 44ฮดโˆ’1=2\frac4{4\delta-1}=24ฮดโˆ’14โ€‹=2. Suppose we want B>12Nhโˆ’1dhโˆ’1B>\frac12N^{\frac{h-1}{dh-1}}B>21โ€‹Ndhโˆ’1hโˆ’1โ€‹, show that this gives us dhโ‰ฅ7dh\geq7dhโ‰ฅ7.

2) We show that we can indeed find small roots less thanN1dN^{\frac1d}Nd1โ€‹in polynomial time. In the worse case, the longest basis vector cannot exceed O(Bdhโˆ’1Nh)O\left(B^{dh-1}N^h\right)O(Bdhโˆ’1Nh). Hence the LLL algorithm will run in at mostO(d6h6(d+h)2logโก2N)O(d^6h^6(d+h)^2\log^2N)O(d6h6(d+h)2log2N)time.

Let

ฮต=1dโˆ’hโˆ’1dhโˆ’1h=d+dฮตโˆ’1d2ฯตโ‰ˆ1dฮต\varepsilon=\frac1d-\frac{h-1}{dh-1}\quad h=\frac{d+d\varepsilon-1}{d^2\epsilon}\approx\frac1{d\varepsilon}ฮต=d1โ€‹โˆ’dhโˆ’1hโˆ’1โ€‹h=d2ฯตd+dฮตโˆ’1โ€‹โ‰ˆdฮต1โ€‹

and choose ฮต=1logโกN\varepsilon=\frac1{\log N}ฮต=logN1โ€‹, then NฮตN^\varepsilonNฮตis a constant hence the number of bits needed to be brute forced is a constant. This gives us the approximate run time of O((d+1dlogโกN)2logโก8N)O((d+\frac1d\log N)^2\log^8N)O((d+d1โ€‹logN)2log8N).

3) We shall show that this is the best bound we can hope for using lattice methods. Suppose there exists some algorithm that finds roots less than O(N1d+ฯต)O\left(N^{\frac1d+\epsilon}\right)O(Nd1โ€‹+ฯต)in polynomial time. Then consider the case whenN=p2N=p^2N=p2and f(x)=x2+pxf(x)=x^2+pxf(x)=x2+px. Show that this forces the lattice to have a size too big for the algorithm to run in polynomial time, assuming the algorithm finds all small roots.

Minkowski reduced

Definition

The basis{bi}i=1d\left\{b_i\right\}_{i=1}^d{biโ€‹}i=1dโ€‹ is Minkowski-reduced if bib_ibiโ€‹has minimum length among all vectors in LLL linearly independent from{bj}j=1iโˆ’1\left\{b_j\right\}_{j=1}^{i-1}{bjโ€‹}j=1iโˆ’1โ€‹. Equivalently, bib_ibiโ€‹has minimum length among all vectors vvvsuch that {b1,โ€ฆ,biโˆ’1,v}\left\{b_1,\dots,b_{i-1},v\right\}{b1โ€‹,โ€ฆ,biโˆ’1โ€‹,v}can be extended to form a basis ofLLL. Such a notion is strongest among all lattice reduction notions and is generally extremely hard to compute. Another equivalent definition is

โˆฅbiโˆฅโ‰คโˆฅโˆ‘j=idcjbjโˆฅgcdโก(cj)=1\left\lVert b_i\right\rVert\leq\left\lVert\sum_{j=i}^dc_jb_j\right\rVert\quad\gcd\left(c_j\right)=1โˆฅbiโ€‹โˆฅโ‰คโ€‹j=iโˆ‘dโ€‹cjโ€‹bjโ€‹โ€‹gcd(cjโ€‹)=1

Bounds

ฮปi(L)2โ‰คโˆฅbiโˆฅ2โ‰คmaxโก(1,(54)iโˆ’4)ฮปi(L)2\lambda_i(L)^2\leq\left\lVert b_i\right\rVert^2\leq\max\left(1,\left(\frac54\right)^{i-4}\right)\lambda_i(L)^2ฮปiโ€‹(L)2โ‰คโˆฅbiโ€‹โˆฅ2โ‰คmax(1,(45โ€‹)iโˆ’4)ฮปiโ€‹(L)2

The proof presented here is based off [Waerden 1956]. We proceed by induction. Letbib_ibiโ€‹be a Minkowski-reduced basis for some latticeLLL. The lower bound is immediate and for i=1i=1i=1, the upper bound is immediate as well.

Let v1,v2โ€ฆviv_1,v_2\dots v_iv1โ€‹,v2โ€‹โ€ฆviโ€‹be linearly independent vectors such thatโˆฅvjโˆฅ=ฮปj(L)\left\lVert v_j\right\rVert=\lambda_j(L)โˆฅvjโ€‹โˆฅ=ฮปjโ€‹(L). Let Liโˆ’1L_{i-1}Liโˆ’1โ€‹be the sublattice generated by b1,b2,โ€ฆbiโˆ’1b_1,b_2,\dots b_{i-1}b1โ€‹,b2โ€‹,โ€ฆbiโˆ’1โ€‹. Evidently somekkkmust exist such thatvkv_kvkโ€‹is not in Liโˆ’1L_{i-1}Liโˆ’1โ€‹. Consider the new lattice Lโ€ฒ=Lโˆฉspan(b1,b2,โ€ฆbiโˆ’1,vk)L'=L\cap\text{span}\left(b_1,b_2,\dots b_{i-1},v_k\right)Lโ€ฒ=Lโˆฉspan(b1โ€‹,b2โ€‹,โ€ฆbiโˆ’1โ€‹,vkโ€‹). Letvkโ€ฒv'_kvkโ€ฒโ€‹be the shortest vector inLโ€ฒโˆ’Liโˆ’1L'-L_{i-1}Lโ€ฒโˆ’Liโˆ’1โ€‹such thatb1,b2,โ€ฆ,biโˆ’1,vkโ€ฒb_1,b_2,\dots,b_{i-1},v'_kb1โ€‹,b2โ€‹,โ€ฆ,biโˆ’1โ€‹,vkโ€ฒโ€‹is a basis for Lโ€ฒL'Lโ€ฒand we have

vk=a1b1+a2b2+โ‹ฏ+aiโˆ’1biโˆ’1+nvkโ€ฒai,nโˆˆZโˆฅbiโˆฅโ‰คโˆฅvkโ€ฒโˆฅv_k=a_1b_1+a_2b_2+\dots+a_{i-1}b_{i-1}+nv'_k\quad a_i,n\in\mathbb Z\\ \left\lVert b_i\right\rVert\leq\left\lVert v'_k\right\rVertvkโ€‹=a1โ€‹b1โ€‹+a2โ€‹b2โ€‹+โ‹ฏ+aiโˆ’1โ€‹biโˆ’1โ€‹+nvkโ€ฒโ€‹aiโ€‹,nโˆˆZโˆฅbiโ€‹โˆฅโ‰คโˆฅvkโ€ฒโ€‹โˆฅ

Ifn=1n=1n=1, then we are done sincevkv_kvkโ€‹can be extended to a basis of LLL, so โˆฅbiโˆฅโ‰คโˆฅvkโˆฅ=ฮปk(L)โ‰คฮปi(L)\left\lVert b_i\right\rVert\leq\left\lVert v_k\right\rVert=\lambda_k(L)\leq\lambda_i(L)โˆฅbiโ€‹โˆฅโ‰คโˆฅvkโ€‹โˆฅ=ฮปkโ€‹(L)โ‰คฮปiโ€‹(L). Otherwise, we have n2โ‰ฅ4n^2\geq4n2โ‰ฅ4. Let vkโ€ฒ=p+qv_k'=p+qvkโ€ฒโ€‹=p+qwherepppis the projection ofvkโ€ฒv'_kvkโ€ฒโ€‹inLiโˆ’1L_{i-1}Liโˆ’1โ€‹. Since by definition we haveโˆฅpโˆฅ2โ‰คโˆฅpยฑbiโˆฅ2\left\lVert p\right\rVert^2\leq\left\lVert p\pm b_i\right\rVert^2โˆฅpโˆฅ2โ‰คโˆฅpยฑbiโ€‹โˆฅ2, we must have

โˆฅpโˆฅ2โ‰ค14โˆ‘j=1iโˆ’1โˆฅbjโˆฅ2\left\lVert p\right\rVert^2\leq\frac14\sum_{j=1}^{i-1}\left\lVert b_j\right\rVert^2โˆฅpโˆฅ2โ‰ค41โ€‹j=1โˆ‘iโˆ’1โ€‹โˆฅbjโ€‹โˆฅ2

Furthermore, since

ฮปk2=โˆฅvkโˆฅ2=โˆฅa1b1+a2b2+โ€ฆaiโˆ’1biโˆ’1+pโˆฅ2+n2โˆฅqโˆฅ2\lambda_k^2=\left\lVert v_k\right\rVert^2=\left\lVert a_1b_1+a_2b_2+\dots a_{i-1}b_{i-1}+p\right\rVert^2+n^2\left\lVert q\right\rVert^2ฮปk2โ€‹=โˆฅvkโ€‹โˆฅ2=โˆฅa1โ€‹b1โ€‹+a2โ€‹b2โ€‹+โ€ฆaiโˆ’1โ€‹biโˆ’1โ€‹+pโˆฅ2+n2โˆฅqโˆฅ2

we have โˆฅqโˆฅ2โ‰ค14ฮปk2\left\lVert q\right\rVert^2\leq\frac14\lambda_k^2โˆฅqโˆฅ2โ‰ค41โ€‹ฮปk2โ€‹, hence we have

โˆฅbiโˆฅโ‰ค14โˆ‘j=1iโˆ’1โˆฅbjโˆฅ2+14ฮปk2โ‰ค14โˆ‘j=1iโˆ’1maxโก(1,(54)iโˆ’4)ฮปj(L)2+14ฮปk(L)2โ‰ค14(1+โˆ‘j=1iโˆ’1maxโก(1,(54)iโˆ’4))ฮปi(L)2{=maxโก(1,(54)iโˆ’4)ฮปi(L)2iโ‰ฅ4<ฮปi(L)2i=2,3\begin{align*} \left\lVert b_i\right\rVert&\leq\frac14\sum_{j=1}^{i-1}\left\lVert b_j\right\rVert^2+\frac14\lambda_k^2\\ &\leq\frac14\sum_{j=1}^{i-1}\max\left(1,\left(\frac54\right)^{i-4}\right)\lambda_j(L)^2+\frac14\lambda_k(L)^2\\ &\leq\frac14\left(1+\sum_{j=1}^{i-1}\max\left(1,\left(\frac54\right)^{i-4}\right)\right)\lambda_i(L)^2\\ &\begin{cases}=\max\left(1,\left(\frac54\right)^{i-4}\right)\lambda_i(L)^2&i\geq4\\<\lambda_i(L)^2&i=2,3\end{cases}\\ \end{align*}โˆฅbiโ€‹โˆฅโ€‹โ‰ค41โ€‹j=1โˆ‘iโˆ’1โ€‹โˆฅbjโ€‹โˆฅ2+41โ€‹ฮปk2โ€‹โ‰ค41โ€‹j=1โˆ‘iโˆ’1โ€‹max(1,(45โ€‹)iโˆ’4)ฮปjโ€‹(L)2+41โ€‹ฮปkโ€‹(L)2โ‰ค41โ€‹(1+j=1โˆ‘iโˆ’1โ€‹max(1,(45โ€‹)iโˆ’4))ฮปiโ€‹(L)2{=max(1,(45โ€‹)iโˆ’4)ฮปiโ€‹(L)2<ฮปiโ€‹(L)2โ€‹iโ‰ฅ4i=2,3โ€‹โ€‹

but since ฮปi(L)2โ‰คโˆฅbiโˆฅ2\lambda_i(L)^2\leq \left\lVert b_i\right\rVert^2ฮปiโ€‹(L)2โ‰คโˆฅbiโ€‹โˆฅ2by definition, the case of i=2,3i=2,3i=2,3cannot occur here (hence n=1n=1n=1in these cases).

Exercises

1) Show that both definitions of Minkowski-reduced lattice are equivalent

2) Consider the lattice L=(2000002000002000002011111)L=\begin{pmatrix}2&0&0&0&0\\0&2&0&0&0\\0&0&2&0&0\\0&0&0&2&0\\1&1&1&1&1\end{pmatrix}L=โ€‹20001โ€‹02001โ€‹00201โ€‹00021โ€‹00001โ€‹โ€‹. We have showed in a previous exercise that the successive minima are all222but no basisbib_ibiโ€‹can satisfy โˆฅbiโˆฅ=ฮปi\left\lVert b_i\right\rVert=\lambda_iโˆฅbiโ€‹โˆฅ=ฮปiโ€‹, show that for any Minkowski reduced basis bib_ibiโ€‹, the basis must satisfy โˆฅbiโˆฅ2=maxโก(1,(54)iโˆ’4)ฮปi(L)2\left\lVert b_i\right\rVert^2=\max\left(1,\left(\frac54\right)^{i-4}\right)\lambda_i(L)^2โˆฅbiโ€‹โˆฅ2=max(1,(45โ€‹)iโˆ’4)ฮปiโ€‹(L)2

Applications

We shall now provide a few instances where lattices are used in various algorithms. Most of these uses the LLL algorithm as it is quite fast.

NTRU

Learning with errors (LWE)

Resources and notations

References/Resources

  1. Nguyen, P. Q., & Vallรฉe, B. (Eds.). (2010). The LLL Algorithm. Information Security and Cryptography. doi:10.1007/978-3-642-02295-1

    Massive survey, lots of detail if you're extremely interested)

  2. May, A. (2003). New RSA Vulnerabilities Using Lattice Reduction Methods. Universitรคt Paderborn.

    Excellent exposition to LLL and coppersmith as well as showing some RSA attacks via LLL

  3. Lenstra, A. K., Lenstra, H. W., & Lovรกsz, L. (1982). Factoring polynomials with rational coefficients. Mathematische Annalen, 261(4), 515โ€“534. doi:10.1007/bf01457454

    The original LLL paper, quite a nice read overall + proof that LLL works

  4. Coppersmith, D. (1996). Finding a Small Root of a Univariate Modular Equation. Lecture Notes in Computer Science, 155โ€“165. doi:10.1007/3-540-68339-9_14

  5. Coppersmith, D. (1996). Finding a Small Root of a Bivariate Integer Equation; Factoring with High Bits Known. Lecture Notes in Computer Science, 178โ€“189. doi:10.1007/3-540-68339-9_16

    Both of these paper introduces the coppersmith algorithm as well as provide some examples

  6. Waerden, B. L. (1956). Die Reduktionstheorie Der Positiven Quadratischen Formen. Acta Mathematica, 96(0), 265โ€“309. doi:10.1007/bf02392364

Notation

  • LLL lattice

    • dimโก(L)\dim(L)dim(L)dimension of lattice

    • vol(L)\text{vol}(L)vol(L)volume of lattice

  • bib_ibiโ€‹ a chosen basis for LLL

    • B\mathcal BB matrix whose iiith row vectors is bib_ibiโ€‹

  • biโˆ—b_i^*biโˆ—โ€‹ Gram-Schmidt orthogonalization of bib_ibiโ€‹(without normalization)

    • Bโˆ—\mathcal B^*Bโˆ—matrix whose iiith row vectors is biโˆ—b_i^*biโˆ—โ€‹

  • ฮผi,j=โŸจbi,bjโˆ—โŸฉโŸจbjโˆ—,bjโˆ—โŸฉ\mu_{i,j}=\frac{\langle b_i,b_j^*\rangle}{\langle b_j^*,b_j^*\rangle}ฮผi,jโ€‹=โŸจbjโˆ—โ€‹,bjโˆ—โ€‹โŸฉโŸจbiโ€‹,bjโˆ—โ€‹โŸฉโ€‹ Gram-Schmidt coefficients

  • ฮปi(L)\lambda_i(L)ฮปiโ€‹(L) the iiith successive minima of LLL

Cryptographic lattice problems

Low Private Component Attacks

Proof of correctness

We now consider cd=med=mc^d = m^{ed} = mcd=med=mnecessary for the successful description of an RSA ciphertext. The core of this result is due to Euler's theorem which states

aฯ•(n)โ‰ก1modโ€‰โ€‰na^{\phi(n)} \equiv 1 \mod naฯ•(n)โ‰ก1modn

for all coprime integers (a,n)(a,n)(a,n) and ฯ•(n)\phi(n)ฯ•(n) is Euler's totient function.

As a reminder, we say two integers are coprime if they share no non-trivial factors. This is the same statement that gcdโก(a,n)=1\gcd(a,n)=1gcd(a,n)=1.

From the definition of the protocol, we have that

edโ‰ก1modโ€‰โ€‰ฯ•(n),โ€…โ€Šโ€…โ€Šโ‡’โ€…โ€Šโ€…โ€Šed=1+kฯ•(n)ed \equiv 1 \mod \phi(n), \;\; \Rightarrow \;\; ed = 1 + k\phi(n)edโ‰ก1modฯ•(n),โ‡’ed=1+kฯ•(n)

for some kโˆˆZk \in \mathbb{Z}kโˆˆZ. Combining this with Euler's theorem, we see that we recover mmmfrom the ciphertext

cdโ‰ก(me)dmodโ€‰โ€‰nโ‰กmedmodโ€‰โ€‰nโ‰กmkฯ•+1modโ€‰โ€‰nโ‰กmkฯ•mmodโ€‰โ€‰nโ‰ก(mฯ•)kmmodโ€‰โ€‰nโ‰ก1kmmodโ€‰โ€‰nโ‰กmmodโ€‰โ€‰n\begin{align} c^d &\equiv (m^e)^d &&\mod n \\ &\equiv m^{ed} &&\mod n \\ &\equiv m^{k\phi + 1} &&\mod n \\ &\equiv m^{k\phi} m &&\mod n \\ &\equiv (m^\phi)^km &&\mod n \\ &\equiv 1^km &&\mod n \\ &\equiv m &&\mod n \\ \end{align}cdโ€‹โ‰ก(me)dโ‰กmedโ‰กmkฯ•+1โ‰กmkฯ•mโ‰ก(mฯ•)kmโ‰ก1kmโ‰กmโ€‹โ€‹modnmodnmodnmodnmodnmodnmodnโ€‹โ€‹

When the requirement gcdโก(m,n)=1\gcd(m, n) = 1gcd(m,n)=1does not hold, we can instead look at the equivalences modulo pppand qqqrespectively. Clearly, when gcdโก(m,n)=n,\gcd(m, n) = n,gcd(m,n)=n,we have that cโ‰กmโ‰ก0modโ€‰โ€‰nc \equiv m \equiv 0 \mod ncโ‰กmโ‰ก0modnand our correctness still holds. Now, consider the case m=kโ‹…p,m = k\cdot p,m=kโ‹…p,where we have that cโ‰กmโ‰ก0modโ€‰โ€‰pc \equiv m \equiv 0 \mod pcโ‰กmโ‰ก0modpand cdโ‰ก(me)d(modq).c^d \equiv (m^e)^d \pmod q.cdโ‰ก(me)d(modq).Since we have already excluded the case that gcdโก(m,q)=q,\gcd(m, q) = q,gcd(m,q)=q,we can conclude that gcdโก(m,q)=1,\gcd(m, q) = 1,gcd(m,q)=1,as qqqis prime. This means that mโ„“ฯ•(q)โ‰ก1modโ€‰โ€‰qm^{\ell\phi(q)} \equiv 1 \mod qmโ„“ฯ•(q)โ‰ก1modqand by the multiplicative properties of the ฯ•\phiฯ•function, we determine that mโ„“nฯ•(n)=mโ„“ฯ•(q)โ‰ก1modโ€‰โ€‰q.m^{\ell_n\phi(n)} = m^{\ell\phi(q)} \equiv 1 \mod q.mโ„“nโ€‹ฯ•(n)=mโ„“ฯ•(q)โ‰ก1modq.We conclude by invoking the Chinese Remainder theorem with

mโ‰ก0modโ€‰โ€‰pmโ‰ก1โ„“mmodโ€‰โ€‰q\begin{align*} m &\equiv 0 &&\mod p \\ m &\equiv 1^\ell m &&\mod q\\ \end{align*}mmโ€‹โ‰ก0โ‰ก1โ„“mโ€‹โ€‹modpmodqโ€‹

that meโ‹…dโ‰กmmodโ€‰โ€‰n.m^{e\cdot d} \equiv m \mod n.meโ‹…dโ‰กmmodn.The case for m=kโ‹…qm = k\cdot qm=kโ‹…qfollows in a parallel manner.

RSA

Will be introduced in this page the fundamentals of RSA, mathematical requirement and also some application with python and openSSL.

This page is pretty long, probably could be split up

Edit: I haved deleted the last part, application with RSA, and i made a special part for this. Maybe we can do the same with the second part: Arithmetic for RSA.

I- Introduction:

RSA is a public-key cryptosystem that is widely used in the world today to provide a secure transmission system to millions of communications, is one of the oldest such systems in existence. The acronym RSA comes from the surnames of Ron Rivest, Adi Shamir, and Leonard Adleman, who publicly described the algorithm in 1977. An equivalent system was developed secretly, in 1973 at GCHQ (the British signals intelligence agency), by the English mathematician Clifford Cocks. That system was declassified in 1997.

All public-key systems are based on the concept of trapdoor functions, functions that are simple to compute in one direction but computationally hard to reverse without knowledge of some special information called the trapdoor. In RSA, the trapdoor function is based on the hardness of factoring integers. The function involves the use of a public keyNN Nto encrypt data, which is (supposed to be) encrypted in such a way that the function cannot be reversed without knowledge of the prime factorisation ofNN N, something that should be kept private. Except in certain cases, there exists no efficient algorithm for factoring huge integers.

Further reading: Shor's algorithm

Formalize the introduction and include a discussion of the security based on the hardness of factoring integers.

II- Arithmetic for RSA

Before starting to introducing you RSA, a few arithmetic notions need to be introduce to understand perfectly other steps.

III- Key generation

  • We pick two primes ppp and qqq

  • Using ppp and qqq, we calculate modulus n=pร—qn = p\times qn=pร—q and its Euler's totient ฯ•(n)=(pโˆ’1)ร—(qโˆ’1)\phi(n) = (p-1) \times (q-1)ฯ•(n)=(pโˆ’1)ร—(qโˆ’1)

  • Now, choose the public exponent e\mathbb{e}esuch as gcd(e,ฯ•(n))=1\mathbb{gcd(e, \phi(n)) = 1}gcd(e,ฯ•(n))=1

  • By using the Extended Euclidean algorithm, we compute the invert d\mathbb{d}d of emodโ€‰โ€‰n\mathbb{e \mod n}emodn :dโ‰กeโˆ’1modโ€‰โ€‰ฯ•(n)d \equiv e^{-1} \mod \phi(n)dโ‰กeโˆ’1modฯ•(n) which is our private exponent.

  • Public key: n,en, en,e

  • Private key: n,dn, dn,d

  • Now, chose a message m\mathbb{m}mthat you convert into integers

  • We can encrypt this plaintext mmm and receive a ciphertext cโ‰กmemodโ€‰โ€‰nc \equiv m^e \mod ncโ‰กmemodn

  • We can decrypt a ciphertext ccc with mโ‰กcdmodโ€‰โ€‰nm \equiv c^d \mod nmโ‰กcdmodn

IV- Signature

A digital signature is a proof of the authenticity of a message, i.e. a proof that the message has not been tampered with. RSA allows us to sign messages by "encrypting" them using the private key, the result being a signature that anyone can verify by "decrypting" it with the public key and comparing it to the associated message. Any attempt to tamper with the message will result in it no longer matching the signature, and vice-versa. Futhermore, a signature can only be generated using the private key, making it a secure and efficient method of confirming the authenticity of messages.

Say Alice wants to send a message to Bob, but does not want Mallory, who has established herself as a middleman, to make changes to the message or swap it out entirely. Fortunately, Bob knows Alice's public key, and since eee and ddd are inverses such that edโ‰ก1modโ€‰โ€‰ฯ•(n)ed \equiv 1\mod \phi(n)edโ‰ก1modฯ•(n), Alice can sign her message mmm by "encrypting" it with the private key such that sโ‰กmdmodโ€‰โ€‰ns \equiv m^d \mod nsโ‰กmdmodn, where sss is the signature verifying that the message came from Alice. Alice can now send mmm and sss to Bob, who is now able to check the authenticity of the message by checking if mโ‰กsemodโ€‰โ€‰nm \equiv s^e \mod nmโ‰กsemodn. If Mallory tries to change mmm, this congruence no longer holds, and since she does not have the private key, she is also unable to provide a maching sssfor her tampered message.

V- Format

Diffie-Hellman

Overview

We need to make some changes: separate the explanation from the code, add a subpart about the MITM and maybe to develop more the instructions

Let's say Alice and Bob want to exchange a secret over an insecure channel. In other words, anyone can read the messages they send, but the goal is to ensure that only Alice and Bob can calculate the secret key.

Diffie-Hellman key exchange provides a solution to this seemingly impossible task. Since code may be easier to understand than a detailed explanation, I'll provide it first:

import Crypto.Util.number as cun
import Crypto.Random.random as crr


class DiffieHellman:
    def __init__(self, p: int):
        self.p = p
        self.g = 5
        self.private_key = crr.randrange(2, p-1)

    def public_key(self) -> int:
        return pow(self.g, self.private_key, self.p)

    def shared_key(self, other_public_key: int) -> int:
        return pow(other_public_key, self.private_key, self.p)


p = cun.getPrime(512)
alice = DiffieHellman(p)
bob = DiffieHellman(p)

shared_key = bob.shared_key(alice.public_key())
assert shared_key == alice.shared_key(bob.public_key())

Here's a brief explanation of the code:

  • We choose a prime ppp and a generator gโˆˆFpg \in \mathbb{F}_pgโˆˆFpโ€‹

  • Alice picks a private key aโˆˆZpโˆ’1a \in \mathbb{Z}_{p-1}aโˆˆZpโˆ’1โ€‹

  • Bob picks a private key bโˆˆZpโˆ’1b \in \mathbb{Z}_{p-1}bโˆˆZpโˆ’1โ€‹

  • Alice's public key is gamodโ€‰โ€‰pg^a \mod pgamodp

  • Bob's public key is gbmodโ€‰โ€‰pg^b \mod pgbmodp

  • Their shared key is gabโ‰ก(ga)bโ‰ก(gb)a(modp)g^{ab} \equiv (g^a)^b \equiv (g^b)^a \pmod pgabโ‰ก(ga)bโ‰ก(gb)a(modp)

So anybody observing the messages sent between Alice and Bob would see p,g,ga,gbp, g, g^a, g^bp,g,ga,gb, but they wouldn't be able to calculate the shared key gabg^{ab}gab.

This is because given ggg and gag^aga, it should be infeasible to calculate aaa. If this sounds familiar, that's because it's the Discrete Log Problem.

The original paper can be found here. It uses the group of integers modulo a prime to perform the key exchange. In practice however, any group with a hard discrete log problem can be used.

RSA application

Tutorial for application with RSA. We are going to use openSSL, openSSH and pycryptodome for key generation, key extraction and some implementation with python

Pycryptodome:

Pycryptodome is a python library about cryptography, see the documentation below: https://www.pycryptodome.org/en/latest/ There is an example of RSA key generation with pycryptodome:

from Crypto.Util.number import getPrime, bytes_to_long


def generate_keys():
    e = 0x10001    #public exponent e, we generally use this one by default
    while True:
        p = getPrime(512)
        q = getPrime(512)
        phi = (p - 1) * (q - 1)    #Euler's totient 
        d = pow(e, -1, phi)    #Private exponent d
        if d != -1:
            break

    n = p * q
    public_key = (n, e)
    private_key = (n, d)
    return public_key, private_key


def encrypt(plaintext: int, public_key) -> int:
    n, e = public_key
    return pow(plaintext, e, n)    #plaintext ** e mod n


def decrypt(ciphertext: int, private_key) -> int:
    n, d = private_key
    return pow(ciphertext, d, n)   #ciphertext ** d mod n


message = bytes_to_long(b"super_secret_message")
public_key, private_key = generate_keys()
ciphertext = encrypt(message, public_key)
plaintext = decrypt(ciphertext, private_key)

OpenSSL:

OpenSSL is a robust, commercial-grade, and full-featured toolkit for the Transport Layer Security (TLS) and Secure Sockets Layer (SSL) protocols. It is also a general-purpose cryptography library

OpenSSH:

Recovering the Modulus

When you want to recover N given some (plaintext, ciphertext) pairings

Scenario

Consider the case that that you know a set of (plaintext, ciphertext) pairings - this may be that you are provided them, or that you have access to some functionality that returns ciphertexts for provided plaintexts. If you do not know the modulus, but know the exponent used (note: this may be prone to a brute-force regardless), then given these pairings you can recover the modulus used.

What we know

Let the following be known:

  • plaintext && ciphertext pairings:

(Mi,Ci)ย forย iโˆˆ[1,โˆž](M_i,C_i) \text{ for } i \in [1,\infty] (Miโ€‹,Ciโ€‹)ย forย iโˆˆ[1,โˆž]
  • public exponent e (e.g. e = 65537 = 0x10001)

Process

The idea behind this attack is effectively finding common factors between pairings. Recall that, under general RSA encryption, we have:

C=Meย (modย N)C = M^{e} \text{ } (mod\text{ }N)C=Meย (modย N)

and recall what modular arithmetic tells us about the relation between these terms, namely that:

aโ‰กbย (modย N)a=b+kNย forย someย kโˆˆZa \equiv b\text{ }(mod\text{ } N)\\ a = b + kN \text{ for some } k \in \mathbb{Z} aโ‰กbย (modย N)a=b+kNย forย someย kโˆˆZ

This, rearranged, tells us that

aโˆ’bโ‰ก0ย (modย N)aโˆ’b=kNa - b \equiv 0\text{ } (mod \text{ } N)\\ a - b = kNaโˆ’bโ‰ก0ย (modย N)aโˆ’b=kN

What this means for our known pairings is that, given we know m,cm, cm,c and eee, we can form the relationship:

Ciโˆ’Mieโ‰ก0ย (modย N)Ciโˆ’Mie=kiNC_i - M_i^e \equiv 0\text{ } (mod \text{ } N)\\ C_i - M_i^e = k_iNCiโ€‹โˆ’Mieโ€‹โ‰ก0ย (modย N)Ciโ€‹โˆ’Mieโ€‹=kiโ€‹N

Thus we can calculate for the value kNkNkN, though don't know either value individually - we want to somehow derive NNN.

Observe that any two pairings will equate to such a value, both with NNN as a factor. We can take the gcd of these two values, and it is probable that the resulting value will be our NNN value, such that:

N=gcd(C1โˆ’M1e,C2โˆ’M2e)N = gcd(C_1 - M_1^e, C_2 - M_2^e)N=gcd(C1โ€‹โˆ’M1eโ€‹,C2โ€‹โˆ’M2eโ€‹)

However, this is only true for the case that

gcd(k1,k2)=1gcd(k_1, k_2) = 1gcd(k1โ€‹,k2โ€‹)=1

i.e., both k1k_1k1โ€‹and k2k_2k2โ€‹are coprime. In the case that they are not, i.e. gcd(k1,k2)โ‰ 1gcd(k_1, k_2) \ne 1gcd(k1โ€‹,k2โ€‹)๎€ =1, we have that

aN=gcd(C1โˆ’M1e,C2โˆ’M2e)ย s.t.ย 1โ‰ aโˆˆZaN = gcd(C_1 - M_1^e, C_2 - M_2^e) \text{ s.t. } 1 \ne a \in \mathbb{Z}aN=gcd(C1โ€‹โˆ’M1eโ€‹,C2โ€‹โˆ’M2eโ€‹)ย s.t.ย 1๎€ =aโˆˆZ

In such a case, we don't have sufficient information to completely recover the modulus, and require more plaintext-ciphertext pairs to be successful. In general, the more pairings you have, the more confident you can be the value you calculate is NNN. More specifically:

Pr(aโ‰ 1)โ†’0ย asย kโ†’โˆžPr(a \ne1) \rightarrow 0 \text{ as } k\rightarrow \inftyPr(a๎€ =1)โ†’0ย asย kโ†’โˆž

Thus:

N=limโกkโ†’โˆžgcd(C1โˆ’M1e,C2โˆ’M2e,...,Ckโˆ’Mke)N = \lim_{k \rightarrow \infty} gcd(C_1 - M_1^e, C_2 - M_2^e, ..., C_k - M_k^e)N=kโ†’โˆžlimโ€‹gcd(C1โ€‹โˆ’M1eโ€‹,C2โ€‹โˆ’M2eโ€‹,...,Ckโ€‹โˆ’Mkeโ€‹)

Practical Notes

  • In reality, you're likely to only need two or three (plaintext, ciphertext) pairings (in the context of ctf challenges and exercises), and as such computations can be manual if needed, but shouldn't be too complex

  • As it's likely you'll be dealing with large numbers, overflows and precision errors may arise in code - using libraries like gmpy provide support for integers of (theoretically) infinite size, and some nice accompanying features too (like in-built gcd and efficient modular exponentiation)

  • These two statements are mathematically equivalent, but one is easier to implement in code:

gcd(a,b,c,d,...)=gcd(a,gcd(b,gcd(c,gcd(d,...))))gcd(a, b, c, d, ...) = gcd(a, gcd(b, gcd(c, gcd(d, ...))))gcd(a,b,c,d,...)=gcd(a,gcd(b,gcd(c,gcd(d,...))))

Code Example

import gmpy2

"""
@param pairings
    list: [(pt1, ct1), (pt2, ct2), ..., (ptk, ctk)]
@param e
    int : encryption exponent
@return
    int : recovered N
"""
def recover_n(pairings, e):
    pt1, ct1 = pairings[0]
    N = ct1 - pow(pt1, e)
    
    # loop through and find common divisors
    for pt,ct in pairings:
        val = gmpy2.mpz(ct - pow(pt, e))
        N = gmpy2.gcd(val, N)
    
    return N
    

Common Modulus Attack

What to do when the same message is encrypted twice with the same modulus but a different public key?

Imagine we have Alice and Bob. Alice sends the SAME message to Bob more than once using the same public key. The internet being the internet, a problem may happen; a bit is flipped, and the public key changed while the modulus stayed the same.

What we know

Let be the following:

  • m the message in plaintext

  • e1 the public key of the first ciphertext

  • c1 the first ciphertext

  • e2 the public key of the second ciphertext

  • c2 the second ciphertext

  • n the modulus that is common to both ciphertexts

All of these but m are essentially given to us.

Conditions of the attack

Because we are going to need to calculate inverses for this attack, we must first make sure that these inverses exist in the first place:

gcd(e1,e2)=1gcd(c2,n)=1gcd(e_1, e_2) = 1 \newline gcd(c_2, n) = 1 gcd(e1โ€‹,e2โ€‹)=1gcd(c2โ€‹,n)=1

The math behind the attack

We know that RSA goes as follows:

c=meย modย nc = m^e\ mod\ nc=meย modย n

From the conditions above we also know that e1e1 e1 and e2e2e2 are co-prime. Thus using Bezout's Theorem we can get:

xe1+ye2=gcd(e1,e2)=1xe_1 +ye_2 = gcd(e_1, e_2) = 1xe1โ€‹+ye2โ€‹=gcd(e1โ€‹,e2โ€‹)=1

Using this, we can derive the original message mm m :

NB: all the calculations are done mod nn n

C1xโˆ—C2y=(me1)xโˆ—(me2)y=me1x+e2y=m1=mC_1^x * C_2^y = (m^{e_1})^x*(m^{e_2})^y \newline = m^{e_1x+e_2y} \newline = m^1 = m C1xโ€‹โˆ—C2yโ€‹=(me1โ€‹)xโˆ—(me2โ€‹)y=me1โ€‹x+e2โ€‹y=m1=m

In general, Bezout's Theorem gives a pair of positive and negative numbers. We just need to adapt this equation a little to make it work for us. In this case, let's assume yyy is the negative number:

Letย y=โˆ’aC2y=C2โˆ’a=(C2โˆ’1)a=(C2โˆ’1)โˆ’yLet\ y = -a \newline C_2^y = C_2^{-a} \newline = (C_2^{-1})^a \newline = (C_2^{-1})^{-y}Letย y=โˆ’aC2yโ€‹=C2โˆ’aโ€‹=(C2โˆ’1โ€‹)a=(C2โˆ’1โ€‹)โˆ’y

Now to truly recover the plaintext, we are actually doing:

C1xร—(C2โˆ’1)โˆ’yย modย nC_1^x \times (C_2^{-1})^{-y}\ mod\ n C1xโ€‹ร—(C2โˆ’1โ€‹)โˆ’yย modย n

MITM

Explanation of the MITM (Man In The Middle) with the Diffie-Hellmann key exchange

The One Time Pad

Author: chuck_bartowski

Introduction

The One Time Pad (OTP) is a well known example of encryption schemes that provide "perfect secrecy". Informally, this means that observing a ciphertext does no give any information to the eavesdropper. A proof of this fact will be provided later. Crucially we will assume that the sender and the receiver have both access to a common source of random bits.

XOR as a One-Time Pad

XOR(addition modulo 2) can be used as an encryption scheme as follows: The message space is MโІ{0,1}n\mathcal M \subseteq \{0, 1\}^nMโІ{0,1}n(i.e.: length n bit strings), the key space is K={0,1}\mathcal K = \{0, 1\}K={0,1} and the ciphertext space is also {0,1}\{0,1\}{0,1}

  • Encryption: Enc(m,k)=mโŠ•k\text{Enc}(m,k) = m \oplus kEnc(m,k)=mโŠ•k

  • Decryption:Dec(c,k)=cโŠ•k\text{Dec}(c,k) = c \oplus kDec(c,k)=cโŠ•k

The correctness of the schemes is easily verifiable. If the encryption produces c=mโŠ•kc = m \oplus kc=mโŠ•k, then the decryption produces mโ€ฒ=cโŠ•k=mโŠ•kโŠ•k=mm' = c \oplus k = m \oplus k \oplus k = mmโ€ฒ=cโŠ•k=mโŠ•kโŠ•k=m.

In the Python snippet below with use to os module to generate random bits.

import os

def xor(a,b):
    res = bytes([x^y for (x,y) in zip(a,b)])
    return res
    
message = b"YELLOW SUBMARINE"
key = os.urandom(len(message))
ciphertext = xor(message, key)
recovered = xor(ciphertext, key)
print(f"Message: {message}\nKey: {key}\nCiphertext: {ciphertext}\nrecovered: {recovered}")
# A possible ouput might be as below
# Message: b'YELLOW SUBMARINE'
# Key: b'\x8e<3\xc9\x8d\xbaD\x16Zb\x1b\xbb\xb3\x0c@<'
# Ciphertext: b'\xd7y\x7f\x85\xc2\xeddE\x0f V\xfa\xe1E\x0ey'
# recovered: b'YELLOW SUBMARINE'

As seen above the receiver with access to the same key can recover the message.

Generalized One-Time Pad

Although XOR is commonly used for the OTP, OTP can be made out of more general objects. If fact We can define an OTP if the message and the keys are objects from a set with a group like structure. (see GroupTheorySection #TODO)

Elliptic Curve Cryptography

Introduction to Isogeny Cryptography

Making this section as a motivation to make sure this is part of the book. Something to work towards.

Page Plan

  • Describe that there is a drive towards post-quantum algorithms

  • The incredible fact that paths within isogeny graphs commute (with the help of torsion points)

  • Supersingular โ„“\ellโ„“ isogeny graphs are (โ„“+1)(\ell + 1)(โ„“+1)regular Ramanujan graphs

  • Using paths through these graphs has spawned a whole bunch of protocols

    • SIKE / BIKE / ...

    • Hashes

    • ...

  • First we will look at the fundementals that allow these protocols to be expected as good candidates for post-quantum

  • Then we look at these protocols in more detail. Hopefully with SageMath implementations for each

References I plan to use

  • Introduction by Craig Costello

    • https://eprint.iacr.org/2019/1321.pdf

  • Mathematics of Isogeny Based Cryptography by Luca De Feo

    • https://arxiv.org/pdf/1711.04062.pdf-

  • The Arithmetic of Elliptic Curves by Joseph H. Silverman

    • https://www.springer.com/gp/book/9780387094939

The Birthday paradox / attack

Authors: Zademn, ireland Reviewed by:

Prerequisites

  • Probability theory (for the main idea)

  • Hashes (an application)

Motivation

  • Breaking a hash function (insert story)

The birthday paradox

*insert story / introduction about why it's called a paradox + use*

Birthday version

Question 1

What is the probability that 1 person has the same birthday as you?

Solution

  • Let AAA be the event that someone has the same birthday as you and Aห‰\bar{A}Aห‰ be the complementary event

    • The events are mutually exclusive => Pr(A)=1โˆ’Pr(Aห‰)Pr(A) = 1 - Pr(\bar{A})Pr(A)=1โˆ’Pr(Aห‰)

  • Let EiE_iEiโ€‹ be the events that person iii does not have your birthday

Then

  • Pr(A)=1โˆ’Pr(Aห‰)=1โˆ’โˆi=1nPr(Ei)=1โˆ’(364365)nPr(A) = 1 - Pr(\bar{A}) = 1 - \prod_{i=1}^n Pr(E_i) = 1 - \left( \dfrac {364} {365}\right)^nPr(A)=1โˆ’Pr(Aห‰)=1โˆ’โˆi=1nโ€‹Pr(Eiโ€‹)=1โˆ’(365364โ€‹)n

Reminder: Pr(A,B)=Pr(A)โ‹…Pr(B)Pr(A, B) = Pr(A) \cdot Pr(B)Pr(A,B)=Pr(A)โ‹…Pr(B)if A,BA, BA,Bare independent events

Question 2

What is the probability that 2 out of nnn people in a room share the same birthday?

  • Suppose the birthdays are distributed independently and uniformly

Solution

  • Let AAA be the event that 2 people have the same birthday, let Aห‰\bar{A}Aห‰ be the complementary event (no 2 people have the same birthday)

  • Event 1 = Person 1 is born => Pr(E1)=365365Pr(E_1) = \dfrac {365} {365}Pr(E1โ€‹)=365365โ€‹

  • Event 2 = Person 2 is born on a different day than Person 1 => Pr(E2)=364365Pr(E_2) = \dfrac {364} {365}Pr(E2โ€‹)=365364โ€‹

    โ‹ฎ\vdotsโ‹ฎ

  • Event n = Person n is born on a different day than Person 1,...,nโˆ’1โ‡’1,...,n-1 \Rightarrow1,...,nโˆ’1โ‡’ โ‡’Pr(En)=365โˆ’(nโˆ’1)365\Rightarrow Pr(E_n) = \dfrac {365-(n-1)} {365}โ‡’Pr(Enโ€‹)=365365โˆ’(nโˆ’1)โ€‹

Pr(Aห‰)=Pr(E1)โ‹…Pr(E2)โ‹…โ‹ฏโ‹…Pr(En)=365365โ‹…364365โ‹…โ‹ฏโ‹…365โˆ’(nโˆ’1)365=(1365)nโ‹…365!(365โˆ’n)!=โˆi=1nโˆ’1(1โˆ’i365)Pr(\bar{A}) = Pr(E1) \cdot Pr(E_2) \cdot \dots \cdot Pr(E_n) = \dfrac {365} {365} \cdot \dfrac {364} {365} \cdot \dots \cdot \dfrac {365-(n-1)} {365} = \left( \dfrac {1} {365} \right) ^{n} \cdot \dfrac {365!} {(365-n)!} = \prod_{i=1}^{n-1} \left(1 - \dfrac i {365}\right)Pr(Aห‰)=Pr(E1)โ‹…Pr(E2โ€‹)โ‹…โ‹ฏโ‹…Pr(Enโ€‹)=365365โ€‹โ‹…365364โ€‹โ‹…โ‹ฏโ‹…365365โˆ’(nโˆ’1)โ€‹=(3651โ€‹)nโ‹…(365โˆ’n)!365!โ€‹=โˆi=1nโˆ’1โ€‹(1โˆ’365iโ€‹)

General case

Question 1

  • Instead of 365365365 days we have dโ‡’1โˆ’(dโˆ’1d)nd \Rightarrow \boxed{1 - \left( \dfrac {d-1} {d}\right)^n}dโ‡’1โˆ’(ddโˆ’1โ€‹)nโ€‹

Question 2

  • Instead of 365365365 days we have dโ‡’1โˆ’โˆi=1nโˆ’1(1โˆ’id)d \Rightarrow \boxed{1 - \prod_{i=1}^{n-1} \left(1 - \dfrac i {d}\right)}dโ‡’1โˆ’i=1โˆnโˆ’1โ€‹(1โˆ’diโ€‹)โ€‹

Code examples

def my_birthday(n, d):
    return 1 - pow((d-1)/d , n)

def same_birthday(n, d):
    p = 1
    for i in range(1, n): #1 -> n-1
        p*=(1-i/d)
    return 1 - p

print(same_birthday(23, 365), same_birthday(32, 365), same_birthday(100, 365))
# (0.5072972343239854, 0.7533475278503207, 0.9999996927510721)

An useful approximation

From the Taylor approximation we know ex=1+x+x22!+โ‹ฏ=>exโ‰ˆ1+xe^x = 1 + x + \dfrac {x^2} {2!} + \dots => e_x\approx 1 + xex=1+x+2!x2โ€‹+โ‹ฏ=>exโ€‹โ‰ˆ1+x for xโ‰ช1x \ll 1xโ‰ช1 Apply for each event: โ‡’x=โˆ’adโ‡’eโˆ’a/dโ‰ˆ1โˆ’adโ‡’Pr(A)=1โˆ’โˆi=1nโˆ’1eโˆ’i/d=1โˆ’eโˆ’n(nโˆ’1)/2dโ‰ˆ1โˆ’eโˆ’n2/2d\Rightarrow x = -\dfrac a d \Rightarrow e^{ -a /d} \approx 1- \dfrac a d \Rightarrow Pr(A) = 1 - \prod_{i=1}^{n-1}e^{-i/d} = 1-e^{-n(n-1) /{2d}} \approx 1-\boxed{e^{-{n^2} / {2d}}}โ‡’x=โˆ’daโ€‹โ‡’eโˆ’a/dโ‰ˆ1โˆ’daโ€‹โ‡’Pr(A)=1โˆ’โˆi=1nโˆ’1โ€‹eโˆ’i/d=1โˆ’eโˆ’n(nโˆ’1)/2dโ‰ˆ1โˆ’eโˆ’n2/2dโ€‹

If we want to solve for nnn knowing Pr(A)Pr(A)Pr(A) we take the lnโก\lnln => nโ‰ˆ2dlnโก(11โˆ’Pr(A))\boxed{n \approx \sqrt{2d \ln \left(\dfrac 1 {1-Pr(A)}\right)}}nโ‰ˆ2dln(1โˆ’Pr(A)1โ€‹)โ€‹โ€‹

def approx_same_birthday(n, d):
    return 1 - pow(e, -pow(n, 2) / (2*d)).n()
    
print(approx_same_birthday(23, 365)) 
print(approx_same_birthday(32, 365))
print(approx_same_birthday(100, 365))

# 0.515509538061517
# 0.754077719532824
# 0.999998876014983

Finding a collision

  • Let H:MโŸถTH:\mathcal{M} \longrightarrow \mathcal{T}H:MโŸถT be a hash function with โˆฃMโˆฃ>>โˆฃTโˆฃ|\mathcal{M}| >> |T|โˆฃMโˆฃ>>โˆฃTโˆฃ

  • Let's denote N=โˆฃTโˆฃN = |\mathcal{T}|N=โˆฃTโˆฃ

Algorithm

1. Choose sโ‰ˆNs \approx \sqrt{N}sโ‰ˆNโ€‹ random distinct messages in M\mathcal{M}M

2. Compute ti=H(mi)t_i = H(m_i)tiโ€‹=H(miโ€‹) for 1โ‰คiโ‰คN1\leq i \leq \sqrt{N}1โ‰คiโ‰คNโ€‹

3. Look for (ti=tj)โ†’(t_i = t_j) \to(tiโ€‹=tjโ€‹)โ†’ If not found go to step 1

Example:

Consider the following hash function:

import hashlib
import random
from Crypto.Util.number import long_to_bytes, bytes_to_long

def small_hash(m, hash_bits):
    '''
    Arguments
        m: bytes -- input
        hash_bits: int -- number of bits of the hash
    Returns:
        {bytes} - hash of the message of dimension `hash_bits`
        '''
    assert hash_bits > 0, "no negative number of bits"
    
    mask = (1 << hash_bits) - 1 # Mask of bits
    t = hashlib.sha256(m).digest() # the hash in bytes
    t = bytes_to_long(t)
    t = t & mask # get the last 12 bits
    return long_to_bytes(t)

We make the following function to find the hashes:


def small_hash_colision(M_bits, T_bits):
    '''
    Arguments
        M_bits: int -- dimension of the message space
        T_bits: int -- dimension of the hash space
    Returns:
        {(bytes, bytes, bytes)} -- message1, message2, hash
        or
        {(b'', b'', b'')} -- if no collision found
    '''
    N = 1<<T_bits 
    print('Hash size: ', N)
    # This is `s`
    num_samples = 1 * isqrt(N)
    num_samples += num_samples//5 + 1 # num_samples = 1.2 * isqrt(N) + 1
    print(f'Making a list of {num_samples} hashes')
    print(f'Probability of finding a collision is {same_birthday(num_samples, N)}')
    
    m_list = []
    t_list = []
    
    # Make a list of hashes
    for i in range(num_samples):
        m = random.getrandbits(M_bits) # Get random message
        #m = random.randint(0, M_bits-1) 
        m = long_to_bytes(m)
        
        t = small_hash(m, T_bits) # Hash it
        if m not in m_list:
            m_list.append(m)
            t_list.append(t)
            
    # Check for collisionn
    for i in range(len(t_list)):
        for j in range(i+1, len(t_list)):
            if t_list[i] == t_list[j]:
                print('Collision found!')
                return m_list[i], m_list[j], t_list[i]
    else:
        print('Collision not found :(')
        return b"", b"", b""

We use it as follows:

M_bits = 30
T_bits = 20

m1, m2, t = small_hash_colision(M_bits, T_bits)
print(m1, m2, t)
print(small_hash(m1, T_bits) == small_hash(m2, T_bits))

# Hash size:  1048576
# Making a list of 1229 hashes
# Probability of finding a collision is 0.513213460854798
# Collision found!
# b'!\xafB\xc5' b'4F\xb6w' b'\x01y\xf7'
# True

Eliminating Storage Requirements with Pollard's Rho

While the above algorithm works to find a hash collision in time O(N)O(\sqrt N )O(Nโ€‹), it also requires storing O(N)O(\sqrt N )O(Nโ€‹)hash values. As such, it represents a classic time-space tradeoff over the naive approach, which involves randomly selecting pairs of inputs until they hash to the same value. While the naive approach does not require any additional storage, it does have runtime O(N)O(N )O(N).

However, there is a better approach combining the best of both worlds: constant storage requirements and O(N)O(\sqrt N)O(Nโ€‹)runtime. This approach is based on Pollard's Rho algorithm, which is better-known for its application to solving discrete logarithms. The core insight behind the algorithm is that by the Birthday Paradox, we expect to encounter a hash collision after trying O(N)O(\sqrt N)O(Nโ€‹)random inputs. However, it is possible to detect whether a collision has occurred without needing to store all of the inputs and hashes if the inputs are chosen in a clever way.

This is done by choosing the next input based on the hash of the previous input, according to the following sequence:

x0=g(seed)x1=g(H(x0))x2=g(H(x1))โ€ฆxn+1=g(H(xn))x_0 = g(seed) \\ x_1 = g(H(x_0)) \\ x_2 = g(H(x_1)) \\ \dots \\ x_{n+1} = g(H(x_n)) \\x0โ€‹=g(seed)x1โ€‹=g(H(x0โ€‹))x2โ€‹=g(H(x1โ€‹))โ€ฆxn+1โ€‹=g(H(xnโ€‹))

Where H:MโŸถTH:\mathcal{M} \longrightarrow \mathcal{T}H:MโŸถT is our hash function and g:TโŸถMg: \mathcal{T} \longrightarrow \mathcal{M} g:TโŸถM is a "sufficiently random" function which takes a hash value and produces a new. We define the composition of the functions to bef=Hโˆ˜g:TโŸถTf = H \circ g : \mathcal{T} \longrightarrow \mathcal{T} f=Hโˆ˜g:TโŸถT.

# TODO:
# have the two hash functions used in this chapter be the same

from Crypto.Hash import SHA256
from Crypto.Util.number import bytes_to_long, long_to_bytes

from tqdm.autonotebook import tqdm

# bits in hash output
n = 30

# H
def my_hash(x):
    x = bytes(x, 'ascii')
    h = SHA256.new()
    h.update(x)
    y = h.digest()
    y = bytes_to_long(y)
    y = y % (1<<n)
    y = int(y)
    return y

# g
def get_message(r):
    x = "Crypto{" + str(r) + "}"
    return x

# f
def f(r):
    return my_hash(get_message(r))

By the Birthday Paradox, we expect that the sequence will have a collision (where xi=xjx_i = x_jxiโ€‹=xjโ€‹ for two distinct values i,ji,ji,j) after O(N)O(\sqrt N)O(Nโ€‹)values. But once this occurs, then the sequence will begin to cycle, because xi+1=g(H(xi))=g(H(xj))=xj+1x_{i+1} = g(H(x_i)) = g(H(x_j)) = x_{j+1}xi+1โ€‹=g(H(xiโ€‹))=g(H(xjโ€‹))=xj+1โ€‹.

Therefore, we can detect that a collision has occurred by using standard cycle-detection algorithms, such as Floyd's tortoise and hare!

And finally, we can locate the first place in the sequence where the collision occurred, which will let us determine what the colliding inputs to the hash function are. This is done by determining how many iterations apart the colliding inputs are, and then stepping together one iteration at a time until the collision occurs.

For Floyd's tortoise and hare, this is done by noting that when we found our collision after nnn iterations, we were comparing H(xn)=H(x2n)H(x_{n}) = H(x_{2 n})H(xnโ€‹)=H(x2nโ€‹). And because the sequence is cyclic, if the first colliding input is xix_ixiโ€‹, then it collides withH(xi)=H(xi+n)H(x_{i}) = H(x_{i+n})H(xiโ€‹)=H(xi+nโ€‹). So we define the new sequence yi=xn+iy_i = x_{n+i}yiโ€‹=xn+iโ€‹, and step through the xix_ixiโ€‹ and yiy_iyiโ€‹ sequences together until we find our collision!

This is implemented in the following code snippet.

"""
initialization

This routine will find a hash collision in sqrt time with constant space.
"""

seed = 0

x0 = get_message(seed)
x = x0
y = f(x)

"""
detect collision
using Floyd / tortoise and hare cycle finding algorithm

expected number of iterations is ~ sqrt(pi/2) * 2^(n/2),
we run for up to 4 * 2^(n/2) iterations
"""
for i in tqdm(range(4 << (n//2))):
        
    if f(x) == f(y):
        break
        
    x = f(x)
    
    y = f(y)
    y = f(y)
    

"""
locate collision
"""
x = x0
y = f(y)


for j in tqdm(range(i)):
    if f(x) == f(y):
        break
    
    x = f(x)
    
    y = f(y)
    

m1 = get_message(x)
m2 = get_message(y)

assert my_hash(m1) == f(x)
assert my_hash(m2) == f(y)

print("[+] seeds for messages: {}, {}".format(x, y))
print("[+] messages: {}, {}".format(m1, m2))
print("[+] collided hashes of messages: {}, {}".format(my_hash(m1), my_hash(m2)))


# 31%    40391/131072 [00:03<00:08, 10666.20it/s]
# 30%    12032/40391 [00:00<00:02, 13112.15it/s]
# 
# [+] seeds for messages: 404842900, 254017312
# [+] messages: Crypto{404842900}, Crypto{254017312}
# [+] collided hashes of messages: 1022927209, 1022927209

Finally, there is a third algorithm for finding hash collisions in O(N)O(\sqrt N)O(Nโ€‹)time, namely the van Oorschot-Wiener algorithm based on Distinguished Points. While it does have additional storage requirements over Pollard's Rho, the main advantage of this algorithm is that it parallelizes extremely well, achieving O(Nm)O(\frac{\sqrt N}{m})O(mNโ€‹โ€‹)runtime when run on mmm processors.

Resources

  • https://en.wikipedia.org/wiki/Birthday_problem - wiki entry

  • https://en.wikipedia.org/wiki/Birthday_attack - wiki entry

  • https://www.youtube.com/watch?v=ofTb57aZHZs - vsauce2 video

  • van Oorschot-Wiener Parallel Collision Search with Cryptanalytic Applications

  • http://www.cs.umd.edu/~jkatz/imc/hash-erratum.pdf

  • https://crypto.stackexchange.com/questions/3295/how-does-a-birthday-attack-on-a-hashing-algorithm-work?rq=1

Isogenies

Motivation

Prerequisites: in this section we assume the reader is somewhat familiar with elliptic curves and begin by considering morphisms (maps) between elliptic curves.

Humans are fascinated with symmetries. The guiding star of theoretical physics is the study of dualities. How much one thing can be said to be another leads to strange and beautiful links between areas of mathematics that appear to be totally distinct.

A cruical piece of building this understanding is how one can map between objects which share structure. When we learn about topology, we are given the fun: "A doughnut is the same as a mug"; a statement which says within topology, we identify objects related by continuous functions.

Elliptic curves are beautiful mathematical objects. The fact that a geometric comes hand-in-hand with a algebraic group law is, to me, incredible. The study of isogenies is the study of maps (morphisms) between elliptic curves which preserves the origin. This condition is enough to preserve the group scheme of the elliptic curve.

In short, isogenies allow us to map between curves preserving their geometric properties (as projective varieties) and algebraic properties (the group associated with point addition).

Isogenies of Elliptic Curves

Definition: We say an isogeny ฯ•:E1โ†’E2\phi : E_1 \to E_2ฯ•:E1โ€‹โ†’E2โ€‹ between elliptic curves defined over a field kkkis a surjective morphism of curves which includes a group homomorphism E1(kห‰)โ†’E1(kห‰)E_1(\bar{k}) \to E_1(\bar{k})E1โ€‹(kห‰)โ†’E1โ€‹(kห‰)

References

  • https://arxiv.org/pdf/1711.04062.pdf

  • https://math.mit.edu/classes/18.783/2019/LectureNotes5.pdf

  • https://doc.sagemath.org/html/en/reference/arithmetic_curves/sage/schemes/elliptic_curves/ell_curve_isogeny.html

Sets and Functions

Rijndael Finite Field

A first time reader might skip this section and go directly to the description of the round transformations, then come back later (it is mostly useful to understand the construction of the operation MC and SB).

Each byte in AES is viewed as an element of a binary finite field of 256 elements, where it can always be represented as a polynomial of degree at most 7 with coefficients inF2\mathbf{F}_2F2โ€‹. The construction of the finite field is made as the quotient ringF2[x]/f(x)\mathbf{F}_2[x]/f(x)F2โ€‹[x]/f(x), wherefffis an irreducible polynomial of degree 8 inF2[x]\mathbf F_2[x]F2โ€‹[x]so the ring becomes a field.

In AES, the choice forfffis

f(x)=x8+x4+x3+x+1.f(x) = x^8 + x^4 + x^3 + x + 1.f(x)=x8+x4+x3+x+1.

We can check with SageMath that it is irreducible:

F2 = GF(2)
K.<x> = F2[]
f = x^8 + x^4 + x^3 + x + 1
f.is_irreducible()
# True

Matching Bytes as Finite Field Elements

A byte bbb is composed of 8 bits (b7,โ€ฆ,b0)2(b_7, \ldots, b_0)_2(b7โ€‹,โ€ฆ,b0โ€‹)2โ€‹ and is matched to a polynomial as

b7x7+b7x6+โ‹ฏ+b1x+b0.b_7x^7 + b_7 x^6 + \cdots + b_1 x + b_0.b7โ€‹x7+b7โ€‹x6+โ‹ฏ+b1โ€‹x+b0โ€‹.

For instance, take the byte 3a whose binary decomposition is (0,0,1,1,1,0,1,0)2(0, 0, 1, 1, 1, 0, 1, 0)_2(0,0,1,1,1,0,1,0)2โ€‹ and becomes the polynomial

0โ‹…x7+0โ‹…x6+1โ‹…x5+1โ‹…x4+1โ‹…x3+0โ‹…x2+1โ‹…x+0=x5+x4+x3+x.0\cdot x^7 + 0\cdot x^6 + 1\cdot x^5 + 1\cdot x^4 + 1\cdot x^3 + 0\cdot x^2 + 1\cdot x + 0 = x^5 + x^4 + x^3 + x.0โ‹…x7+0โ‹…x6+1โ‹…x5+1โ‹…x4+1โ‹…x3+0โ‹…x2+1โ‹…x+0=x5+x4+x3+x.

Polynomial Reduction

Polynomials of degree 8 or more can always be reduced, using the fact that in the finite field, we have f(x)=0f(x) = 0f(x)=0 , so we have the relation

x8=x4+x3+x+1x^8 = x^4 + x^3 + x + 1x8=x4+x3+x+1

Why not x8=โˆ’x4โˆ’x3โˆ’xโˆ’1x^8 = - x^4 - x^3 - x - 1x8=โˆ’x4โˆ’x3โˆ’xโˆ’1? In fact, that's also true, but the coefficient are in F2\mathbf F_2F2โ€‹ so the additive inverseโˆ’1-1โˆ’1 of 111 is itself.

In SageMath, this reduction can be produced in one of the following methods.

Method 1: Remainder of an Euclidean division by fff

(x^8 + x^6 + x^4 + 1) % f
# x^6 + x^3 + x

Method 2: Image in the quotient ring F2[x]/f(x)\mathbf{F}_2[x]/f(x)F2โ€‹[x]/f(x)

R = K.quotient(f)
R(x^8 + x^6 + x^4 + 1)
# xbar^6 + xbar^3 + xbar

Method 3: Using the Finite Field class of SageMath directly.

F.<x> = GF(2^8, modulus=x^8 + x^4 + x^3 + x + 1)
x^8 + x^6 + x^4 + 1
# x^6 + x^3 + x

On this page we use this last method. Also, this helper converts an element of the finite field to the hexadecimal representation of a byte, and could be useful in the examples:

def F_to_hex(a):
    return ZZ(a.integer_representation()).hex()

b = x^4 + x^3 + x + 1
F_to_hex(b)
# '1b'

Addition

The addition of two polynomials is done by adding the coefficients corresponding of each monomial:

โˆ‘i=07aixi+โˆ‘i=07bixi=โˆ‘i=07(ai+bi)xi.\sum_{i=0}^7 a_ix^i + \sum_{i=0}^7 b_ix^i = \sum_{i=0}^7(a_i + b_i)x^i.i=0โˆ‘7โ€‹aiโ€‹xi+i=0โˆ‘7โ€‹biโ€‹xi=i=0โˆ‘7โ€‹(aiโ€‹+biโ€‹)xi.

And as the addition of the coefficients is inF2\mathbf{F}_2F2โ€‹, it corresponds to the bitwise xor operation on the byte.

Multiplication

Multiplication of two polynomials is more complex (one example would be the Karatsuba algorithm, more efficient than the naive algorithm). For an implementation of AES, it is possible to only use the multiplication by xxx, whose byte representation is 02.

Letb7x7+โ‹ฏ+b1x+b0b_7x^7 + \cdots + b_1x + b_0b7โ€‹x7+โ‹ฏ+b1โ€‹x+b0โ€‹an element and we consider the multiplication byxxx:

xร—(b7x7+โ‹ฏ+b1x+b0)=b7x8+b6x7+โ‹ฏb1x2+b0x.x\times (b_7x^7 + \cdots + b_1x + b_0) = b_7x^8 + b_6x^7 + \cdots b_1 x^2 + b_0x.xร—(b7โ€‹x7+โ‹ฏ+b1โ€‹x+b0โ€‹)=b7โ€‹x8+b6โ€‹x7+โ‹ฏb1โ€‹x2+b0โ€‹x.

All coefficients are shifted to a monomial one degree higher. Then, there are two cases:

  • Ifb7b_7b7โ€‹is000, then we have a polynomial of degree at most 7 and we are done;

  • Ifb7b_7b7โ€‹is111, we can replacex8x^8x8byx4+x3+x+1x^4 + x^3 + x + 1x4+x3+x+1during the reduction phase:

xร—(x7+b6x6+โ‹ฏ+b1x+b0)=x8+b6x7+โ‹ฏb1x2+b0x=(x4+x3+x+1)+b6x7+โ‹ฏ+b1x2+b0x\begin{align*} x\times (x^7 + b_6x^6 + \cdots + b_1x + b_0) & = x^8 + b_6x^7 + \cdots b_1 x^2 + b_0x \\ & = (x^4 + x^3 + x + 1) + b_6x^7 + \cdots + b_1x^2 + b_0x \end{align*}xร—(x7+b6โ€‹x6+โ‹ฏ+b1โ€‹x+b0โ€‹)โ€‹=x8+b6โ€‹x7+โ‹ฏb1โ€‹x2+b0โ€‹x=(x4+x3+x+1)+b6โ€‹x7+โ‹ฏ+b1โ€‹x2+b0โ€‹xโ€‹

This can be used to implement a very efficient multiplication byxxxwith the byte representation:

  1. A bitwise shiftleft operation: (b << 1) & 0xff;

  2. Followed by a conditional addition with 1b if the top bit of bbb is 111.

Here an example in SageMath (we use the finite field construction of method 3):

b = x^7 + x^5 + x^4 + x^2 + 1
F_to_hex(b)
# 'b5'
(2*0xb5 & 0xff) ^^ 0x1b).hex() == F_to_hex(x*b)    # the xor in Sage is "^^"
# True

Probability Theory

Encryption

Author: Chuck_bartwoski

Introduction

A typical application of cryptography is secure communication. Informally a secure communication channel is one that provides both confidentiality and Integrity of the messages. In this section we investigate confidentiality, therefore we may assume that integrity is already guaranteed by some other means. (see section on integrity...#TODO)

We assume that two parties that want to communicate share a secret key kkk. Prior to sending a message, the sender encrypts the message with the secret key, this produces a ciphertext that is then sent. The receiver uses the same key to decrypt the message and recover the message.

Intuitively: A secure encryption scheme will prevent an eavesdropper to learn the content of the message since the ciphertext is unintelligible. The security requirement will be formalized later.

Formal definition

We introduce some notation first: We will use M\mathcal MM to denote the set of al possible message, K\mathcal KK is the set of all possible keys and C\mathcal CC is the set of ciphertexts.

A symmetric encryption scheme E\mathcal EEis a tuple of efficiently computable functions (KGen,ย Enc,ย Dec)(\text{KGen, Enc, Dec})(KGen,ย Enc,ย Dec).:

  • \text{KGen}: \diamond \xrightarrow $ \mathcal K Selects a key at random from the key space.

  • Enc:Mร—Kโ†ฆC\text{Enc}: \mathcal M \times \mathcal K \mapsto \mathcal CEnc:Mร—Kโ†ฆC. Encrypts the message mmm with the key kkk into a ciphertext c=Enc(m,k)c = \text{Enc}(m, k)c=Enc(m,k). Sometimes written as c=Enck(m)c = \text{Enc}_k(m)c=Enckโ€‹(m)

  • Dec:Cร—Kโ†ฆMร—{โŠฅ}\text{Dec}: \mathcal C \times \mathcal K \mapsto \mathcal M \times \{ \bot\}Dec:Cร—Kโ†ฆMร—{โŠฅ}. Decrypts the ciphertexts ccc with the key kkk into the message mmm or returns an error (โŠฅ\botโŠฅ). m=Dec(c,k)m = \text{Dec}(c, k)m=Dec(c,k). Sometimes written as m=Deck(c)m = \text{Dec}_k(c)m=Deckโ€‹(c)

ForE\mathcal EE to be useful we need that Dec(Enc(m,k),k)=m;โˆ€m,k\text{Dec}(\text{Enc}(m,k), k) = m; \forall m,kDec(Enc(m,k),k)=m;โˆ€m,k. This is also called correctness.

After all what's the point of confidentially sending a nice Christmas card to your grand children if they wont be able to read its content

TODO: security notions and examples

Groups

Authors: Ariana, Zademn Reviewed by:

Introduction

Modern cryptography is based on the assumption that some problems are hard (unfeasable to solve). Since the we do not have infinite computational power and storage we usually work with finite messages, keys and ciphertexts and we say they lay in some finite sets M,K\mathcal{M}, \mathcal{K}M,K and C\mathcal{C}C.

Furthermore, to get a ciphertext we usually perform some operations with the message and the key.

For example in AES128 K=M=C={0,1}128\mathcal{K} = \mathcal{M} = \mathcal{C} = \{0, 1\}^{128}K=M=C={0,1}128since the input, output and key spaces are 128 bits. We also have the encryption and decryption operations: Enc:Kร—Mโ†’CDec:Kร—Cโ†’MEnc: \mathcal{K} \times \mathcal{M} \to \mathcal{C} \\ Dec: \mathcal{K} \times \mathcal{C} \to \mathcal{M}Enc:Kร—Mโ†’CDec:Kร—Cโ†’M

The study of sets, and different types of operations on them is the target of abstract algebra. In this chapter we will learn the underlying building blocks of cryptosystems and some of the hard problems that the cryptosystems are based on.

Definition

A setGGGpaired with a binary operation โ‹…:Gร—Gโ†’G\cdot:G\times G\to Gโ‹…:Gร—Gโ†’Gis a group if the following requirements hold:

  • Closure: For all a,bโˆˆG:ย a, b \in G: \ a,bโˆˆG:ย  aโ‹…bโˆˆGa\cdot b \in Gaโ‹…bโˆˆG - Applying the operation keeps the element in the set

  • Associativity: For all a,b,cโˆˆG:a, b, c \in G: a,b,cโˆˆG: (aโ‹…b)โ‹…c=aโ‹…(bโ‹…c)(a \cdot b) \cdot c=a\cdot (b\cdot c)(aโ‹…b)โ‹…c=aโ‹…(bโ‹…c)

  • Identity: There exists an elementeโˆˆGe\in GeโˆˆGsuch that aโ‹…e=eโ‹…a=aa\cdot e=e\cdot a=aaโ‹…e=eโ‹…a=afor all aโˆˆGa\in GaโˆˆG

  • Inverse: For all elements aโˆˆGa\in GaโˆˆG, there exists some bโˆˆGb\in GbโˆˆGsuch that bโ‹…a=aโ‹…b=eb\cdot a=a\cdot b=ebโ‹…a=aโ‹…b=e. We usually denotebbbas aโˆ’1a^{-1}aโˆ’1

For nโˆˆZn\in\mathbb ZnโˆˆZ, ana^nanmeans aโ‹…aโ€ฆโ‹…aโŸnย times\underbrace{a\cdot a\dots{}\cdot a}_{n\text{ times}}nย timesaโ‹…aโ€ฆโ‹…aโ€‹โ€‹when n>0n>0n>0and (aโˆ’n)โˆ’1\left(a^{-n}\right)^{-1}(aโˆ’n)โˆ’1when n<0n<0n<0. For n=0n=0n=0, an=ea^n=ean=e.

If ab=baab=baab=ba, then โ‹…\cdotโ‹…is commutative and the group is called abelian. We often denote the group operation by +++instead of โ‹…\cdotโ‹…and we typically use nananainstead of ana^nan.

Remark

  • The identity element of a group GGG is also denoted with 1G1_G1Gโ€‹ or just 111 if only one groups is present

Examples of groups

Integers modulo nnn (remainders) under modular addition =(Z/nZ,+)= (\mathbb{Z} / n \mathbb{Z}, +)=(Z/nZ,+). Z/nZ={0,1,...,nโˆ’1}\mathbb{Z} / n \mathbb{Z} = \{0, 1, ..., n -1\}Z/nZ={0,1,...,nโˆ’1} Let's look if the group axioms are satisfied

  1. โœ“\checkmarkโœ“ โˆ€a,bโˆˆZ/nZย letย cโ‰กa+bโ€Šmodโ€Šn\forall a, b \in \mathbb{Z}/ n\mathbb{Z} \text{ let } c \equiv a + b \bmod nโˆ€a,bโˆˆZ/nZย letย cโ‰กa+bmodn. Because of the modulo reduction c<nโ‡’cโˆˆZ/nZc < n \Rightarrow c \in \mathbb{Z}/ n\mathbb{Z} c<nโ‡’cโˆˆZ/nZ

  2. โœ“\checkmarkโœ“Modular addition is associative

  3. โœ“\checkmark โœ“0+aโ‰กa+0โ‰กaโ€Šmodโ€Šnโ‡’00 + a \equiv a + 0 \equiv a \bmod n \Rightarrow 00+aโ‰กa+0โ‰กamodnโ‡’0 is the identity element

  4. โœ“\checkmarkโœ“โˆ€aโˆˆZ/nZ\forall a \in \mathbb{Z}/ n\mathbb{Z} โˆ€aโˆˆZ/nZwe take nโˆ’aโ€Šmodโ€Šnn - a \bmod nnโˆ’amodnto be the inverse of aaa. We check that

    a+nโˆ’aโ‰กnโ‰ก0โ€Šmodโ€Šna + n - a \equiv n \equiv 0 \bmod na+nโˆ’aโ‰กnโ‰ก0modn

    nโˆ’a+aโ‰กnโ‰ก0โ€Šmodโ€Šnn - a + a \equiv n \equiv 0 \bmod nnโˆ’a+aโ‰กnโ‰ก0modn

Therefore we can conclude that the integers mod nnn with the modular addition form a group.

Z5 = Zmod(5) # Technically it's a ring but we'll use the addition here
print(Z5.list())
# [0, 1, 2, 3, 4]

print(Z5.addition_table(names = 'elements'))
# +  0 1 2 3 4
#  +----------
# 0| 0 1 2 3 4
# 1| 1 2 3 4 0
# 2| 2 3 4 0 1
# 3| 3 4 0 1 2
# 4| 4 0 1 2 3

a, b = Z5(14), Z5(3)
print(a, b)
# 4 3
print(a + b)
# 2
print(a + 0)
# 4
print(a + (5 - a))
# 0

Example of non-groups

(Q,โ‹…)(\mathbb{Q}, \cdot)(Q,โ‹…) is not a group because we can find the element 000 that doesn't have an inverse for the identity 111. (Z,โ‹…)(\mathbb{Z}, \cdot)(Z,โ‹…)is not a group because we can find elements that don't have an inverse for the identity 111

Exercise

Is (Z/nZโˆ–{0},โ‹…)(\mathbb{Z} / n \mathbb{Z} \smallsetminus \{0\}, \cdot)(Z/nZโˆ–{0},โ‹…)a group? If yes why? If not, are there values for nnnthat make it a group?

sษนosแด‰สŒแด‰p uoษฏษฏoษ” puษ sวษฏแด‰ษนd ส‡noqษ สžuแด‰ษฅโ”ด :ส‡uแด‰H

Proprieties

  1. The identity of a group is unique

  2. The inverse of every element is unique

  3. โˆ€\forallโˆ€ aโˆˆGย :(aโˆ’1)โˆ’1=ga \in G \ : \left(a^{-1} \right) ^{-1} = gaโˆˆGย :(aโˆ’1)โˆ’1=g. The inverse of the inverse of the element is the element itself

  4. โˆ€a,bโˆˆG:\forall a, b \in G: โˆ€a,bโˆˆG: (ab)โˆ’1=bโˆ’1aโˆ’1(ab)^{-1} = b^{-1}a^{-1}(ab)โˆ’1=bโˆ’1aโˆ’1

    Proof: (ab)(bโˆ’1aโˆ’1)=a(bbโˆ’1)aโˆ’1=aaโˆ’1=e.(ab)(b^{โˆ’1}a^{โˆ’1}) =a(bb^{โˆ’1})a^{โˆ’1}=aa^{โˆ’1}= e.(ab)(bโˆ’1aโˆ’1)=a(bbโˆ’1)aโˆ’1=aaโˆ’1=e.

n = 11
Zn = Zmod(n)
a, b = Zn(5), Zn(7)
print(n - (a + b))
# 10
print((n - a) + (n - b))
# 10

Orders

In abstract algebra we have two notions of order: Group order and element order

Group order

The order of a group GGGis the number of the elements in that group. Notation: โˆฃGโˆฃ|G|โˆฃGโˆฃ

Element order

The order of an element aโˆˆGa \in GaโˆˆG is the smallest integer nnn such that an=1Ga^n = 1_Gan=1Gโ€‹. If such a number nnn doesn't exist we say the element has order โˆž\inftyโˆž. Notation: โˆฃaโˆฃ|a|โˆฃaโˆฃ

Z12 = Zmod(12) # Residues modulo 12
print(Z12.order()) # The additive order 
# 12
a, b= Z12(6), Z12(3)
print(a.order(), b.order())
# 2 4
print(a.order() * a)
# 0

print(ZZ.order()) # The integers under addition is a group of infinite order
# +Infinity

We said our messages lay in some group M\mathcal{M}M. The order of this group โˆฃMโˆฃ|\mathcal{M}|โˆฃMโˆฃ is the number of possible messages that we can have. For M={0,1}128\mathcal{M} = \{0,1\}^{128}M={0,1}128we have โˆฃMโˆฃ=2128|\mathcal{M}| = 2^{128}โˆฃMโˆฃ=2128 possible messages.

Let mโˆˆMm \in \mathcal{M}mโˆˆMbe some message. The order of mmm means how many different messages we can generate by applying the group operation on mmm

Subgroups

Definition

Let (G,โ‹…)(G, \cdot)(G,โ‹…) be a group. We say HHHis a subgroup of GGG if HHH is a subset of GGG and (H,โ‹…)(H, \cdot)(H,โ‹…)forms a group. Notation: Hโ‰คGH \leq GHโ‰คG

Proprieties

  1. The identity of GGG is also in H:H: H:1H=1G1_H = 1_G1Hโ€‹=1Gโ€‹

  2. The inverses of the elements in HHHare found in HHH

How to check Hโ‰คGH \leq GHโ‰คG? Let's look at a 2 step test

  1. Closed under operation: โˆ€a,bโˆˆHโ†’abโˆˆH\forall a, b \in H \to ab \in Hโˆ€a,bโˆˆHโ†’abโˆˆH

  2. Closed under inverses: โˆ€aโˆˆHโ†’aโˆ’1โˆˆH\forall a \in H \to a^{-1} \in Hโˆ€aโˆˆHโ†’aโˆ’1โˆˆH

Generators

Let GGGbe a group,gโˆˆGg \in GgโˆˆGan element and โˆฃgโˆฃ=n|g| = nโˆฃgโˆฃ=n. Consider the following set:

{1,g,g2,...,gnโˆ’1}=denotedโŸจgโŸฉ.\{1, g, g^2, ..., g^{n-1}\} \overset{\text{denoted}}{=} \langle g\rangle.{1,g,g2,...,gnโˆ’1}=denotedโŸจgโŸฉ.

This set paired the group operation form a subgroup of GGGgenerated by an element ggg.

Why do we care about subgroups? We praise the fact that some problems are hard because the numbers we use are huge and exhaustive space searches are too hard in practice.

Suppose we have a big secret values space GGGand we use an element gggto generate them.

If an elementgโˆˆGg \in GgโˆˆGwith a small order nnn is used then it can generate only nnn possible values and if nnn is small enough an attacker can do a brute force attack.

Example

For now, trust us that if given a prime ppp, a value gโˆˆZ/pZg \in \mathbb{Z} / p \mathbb{Z}gโˆˆZ/pZ and we compute y=gxโ€Šmodโ€Špy = g^x \bmod py=gxmodp for a secret xxx, finding xxx is a hard problem. We will tell you why a bit later.

p = 101 # prime
Zp = Zmod(p) 
H_list = Zp.multiplicative_subgroups() # Sage can get the subgroup generators for us
print(H_list)
# ((2,), (4,), (16,), (32,), (14,), (95,), (10,), (100,), ())

g1 = H_list[3][0] # Weak generator
print(g1, g1.multiplicative_order())
# 32 20

g2 = Zp(3) # Strong generator
print(g2, g2.multiplicative_order())
# 3 100


## Consider the following functions
def brute_force(g, p, secret_value):
    """
    Brute forces a secret value, returns number of attempts
    """
    for i in range(p-1):
        t = pow(g, i, p)
        if t == secret_value:
            break
    return i
    
def mean_attempts(g, p, num_keys):
    """
    Tries `num_keys` times to brute force and 
    returns the mean of the number of attempts
    """
    total_attempts = 0
    for _ in range(num_keys):
        k = random.randint(1, p-1)
        sv = pow(g, k, p) # sv = secret value
        total_attempts += brute_force(g, p, sv)
    return 1. * total_attempts / num_keys
    
## Let's try with our generators
print(mean_attempts(g1, p, 100)) # Weak generator
# 9.850
print(mean_attempts(g2, p, 100)) # Strong generator
# 49.200

Examples

// subgroups, quotient groups

// cyclic groups

Introduction

Lattices, also known as Minkowski's theory after Hermann Minkowski, or the geometry of numbers (deprecated!) allows the usage of geometrical tools (i.e. volumes) in number theory.

The intuitive notion of a lattice (perhaps surprisingly) matches its mathematical definition. For example, lattices are formed by

  • points on an infinite checkerboard;

  • centers of a hexagonal tessellation;

  • integers on the real number line.

The last example should hint at how we generalize this concept to arbitrary dimensions. In general, lattices consist of discrete points which appear at "regular intervals."

Definitions

A lattice LLL is a subgroup of Rn\mathbb{R}^nRngenerated by bib_ibiโ€‹, i.e.

L=โˆ‘i=1dZbi={โˆ‘i=1daibiโˆฃaiโˆˆZ}L=\sum_{i=1}^d\mathbb{Z} b_i = \left\{\left. \sum_{i=1}^d a_i b_i \right | a_i \in \mathbb{Z} \right\}L=i=1โˆ‘dโ€‹Zbiโ€‹={i=1โˆ‘dโ€‹aiโ€‹biโ€‹โ€‹aiโ€‹โˆˆZ}

where bib_ibiโ€‹ are linearly independent vectors. Collectively, {bi}i=1d\left\{b_i\right\}_{i=1}^d{biโ€‹}i=1dโ€‹ form a basis ofLLL.

We say a set of vectors viv_iviโ€‹are linearly independent if the only solution to the equation โˆ‘iaibi=0\sum_{i} a_i b_i = 0โˆ‘iโ€‹aiโ€‹biโ€‹=0 is when all aia_iaiโ€‹are zero.

Taking a step back, this definition should resemble that of a vector space, with one exception: scalars are integers! The discrete nature of lattices comes from this restriction.

Some more terminology from linear algebra will be useful. The dimension of a lattice, denoteddimโกL\dim LdimL, is ddd. A lattice is complete if d=nd=nd=n. Note that we can always choose a subspace of Rn\mathbb R^nRnsuch that the lattice is complete, namely the subspace generated by bib_ibiโ€‹.

The region

ฮฆ={โˆ‘i=1dxibiโˆฃ0โ‰คxi<1}\Phi=\left\{\left.\sum_{i=1}^dx_ib_i\right|0\leq x_i<1\right\}ฮฆ={i=1โˆ‘dโ€‹xiโ€‹biโ€‹โ€‹0โ‰คxiโ€‹<1}

is known as the fundamental mesh.

In the image above, we see the points of a lattice in R2\mathbb R^2R2. The red vectors are one set of basis vectors and the shaded region is the corresponding fundamental mesh. The green vectors also form another set of basis vectors with its corresponding fundamental mesh. We see here that the basis vectors and fundamental mesh is not unique to a lattice.

Although the fundamental mesh is not unique, it turns out that the (mmmdimensional) volume of the fundamental mesh is constant for any given lattice. Hence we can define the volume of a lattice as the volume of a fundamental mesh. However this definition can be hard to handle hence we provide an equivalent definition via determinants:

LetB\mathcal BBbe adร—nd\times ndร—nmatrix whose rows are given by the basis vectors. Then the volume of a fundamental mesh is given by

vol(L)=โˆฃdetโก(BBT)โˆฃ\text{vol}(L)=\sqrt{\left|\det\left(\mathcal B\mathcal B^T\right)\right|}vol(L)=โˆฃdet(BBT)โˆฃโ€‹

A subset XXXof Rn\mathbb R^nRnis known as centrally symmetric if xโˆˆXx\in XxโˆˆXimplies โˆ’xโˆˆX-x\in Xโˆ’xโˆˆX. It is convex if for any x,yโˆˆXx,y\in Xx,yโˆˆX, the line joining x,yx,yx,y is contained in XXX, i.e. {tx+(1โˆ’t)yโˆฃ0โ‰คtโ‰ค1}โŠ‚X\left\{tx+(1-t)y|0\leq t\leq1\right\}\subset X{tx+(1โˆ’t)yโˆฃ0โ‰คtโ‰ค1}โŠ‚X. Finally we can introduce the most important theorem about lattices, the Minkowski's Lattice Point Theorem:

Let LLLbe a complete lattice of dimensionnnn and XXXbe a centrally symmetric convex set. Suppose

vol(X)>2nvol(L)\text{vol}(X)>2^n\text{vol}(L)vol(X)>2nvol(L)

Then XXXcontains at least one nonzero point of LL L. This result is primarily used to prove the existence of lattice vectors.

Throughout this section, โˆฅvโˆฅ=โˆ‘ivi2\left\lVert v\right\rVert=\sqrt{\sum_iv_i^2}โˆฅvโˆฅ=โˆ‘iโ€‹vi2โ€‹โ€‹ denotes the โ„“2\ell_2โ„“2โ€‹norm and โŸจa,bโŸฉ=โˆ‘iaibi\langle a,b\rangle=\sum_ia_ib_iโŸจa,bโŸฉ=โˆ‘iโ€‹aiโ€‹biโ€‹ denotes the inner product.

Proof sketch of Minkowski's theorem

This proof is by some sort of a pigeonhole argument on volumes. Consider the set

12X={12xโˆฃxโˆˆX}\frac12X=\left\{\frac12x|x\in X\right\}21โ€‹X={21โ€‹xโˆฃxโˆˆX}

We have vol(12X)>vol(L)\text{vol}\left(\frac12 X\right)>\text{vol}(L)vol(21โ€‹X)>vol(L), hence the inclusion 12Xโ†’Rn/L\frac12X\to\mathbb R^n/L21โ€‹Xโ†’Rn/Lcannot be injective, thus we can find some x1=x2+โ„“x_1=x_2+\ellx1โ€‹=x2โ€‹+โ„“, x1,x2โˆˆ12X,โ„“โˆˆL,x1โ‰ x2x_1,x_2\in\frac12 X,\ell\in L,x_1\neq x_2x1โ€‹,x2โ€‹โˆˆ21โ€‹X,โ„“โˆˆL,x1โ€‹๎€ =x2โ€‹. Hence x1โˆ’x2โˆˆLx_1-x_2\in Lx1โ€‹โˆ’x2โ€‹โˆˆLis a nontrivial lattice point.

Exercises

1) Let LLLbe the lattice generated by B=(โˆ’1981โˆ’8โˆ’7)\mathcal B=\begin{pmatrix}-1&9&8\\1&-8&-7\end{pmatrix}B=(โˆ’11โ€‹9โˆ’8โ€‹8โˆ’7โ€‹)(take the rows as basis vectors).

  • Compute the volume of this lattice

  • Show that Bโ€ฒ=(101011)\mathcal B'=\begin{pmatrix}1&0&1\\0&1&1\end{pmatrix}Bโ€ฒ=(10โ€‹01โ€‹11โ€‹)generates the same lattice

  • Show that each row in C=(101022)\mathcal C=\begin{pmatrix}1&0&1\\0&2&2\end{pmatrix}C=(10โ€‹02โ€‹12โ€‹)is in the lattice butC\mathcal CCdoes not generate the lattice. This is one key difference from the case of linear algebra (over fields).

2) LetB,Bโ€ฒ\mathcal B,\mathcal B'B,Bโ€ฒbe dร—nd\times ndร—nmatrices whose row vectors are basis for lattices L,Lโ€ฒL,L'L,Lโ€ฒ. Both lattices are the same iff there exists some UโˆˆGLd(Z)U\in\text{GL}_d(\mathbb Z)UโˆˆGLdโ€‹(Z) such that Bโ€ฒ=UB\mathcal B'=U\mathcal BBโ€ฒ=UB. Find UUUfor problem 1. Note that GLd(Z)\text{GL}_d(\mathbb Z)GLdโ€‹(Z)is the group of invertible matrices with integer coefficients, meaning UUUand Uโˆ’1U^{-1}Uโˆ’1have integer coefficients.

3) Show that the condition in Minkowski's lattice point theorem is strict, i.e. for any complete latticeLLLof dimension nnn, we can find some centrally symmetric convex setXXXwithvol(X)=2nvol(L)\text{vol}(X)=2^n\text{vol}(L)vol(X)=2nvol(L)but the only lattice point inXXXis the origin.

4*) Letvvvbe the shortest nonzero vector for some lattice LLLwith dimensionnnn. Show that

โˆฅvโˆฅโ‰ค2ฯ€ฮ“(n2+1)1nvol(L)1n\left\lVert v\right\rVert\leq\frac2{\sqrt\pi}\Gamma\left(\frac n2+1\right)^{\frac1n}\text{vol}(L)^\frac1nโˆฅvโˆฅโ‰คฯ€โ€‹2โ€‹ฮ“(2nโ€‹+1)n1โ€‹vol(L)n1โ€‹

Lagrange's algorithm

Overview

Lagrange's algorithm, often incorrectly called Gaussian reduction, is the 2D analouge to the Euclidean algorithm and is used for lattice reduction. Intuitively, lattice reduction is the idea of finding a new basis that consists of shorter vectors. Before going into Lagrange's algorithm, we first recap the Euclidean algorithm:

def euclid(m,n):
    while n!=0:
        q = round(m/n)
        m -= q*n
        if abs(n) > abs(m):
            m, n = n, m
    return abs(m)

The algorithm primarily consists of two steps, a reduction step where the size of mmmis brought down by a multiple of nnnand a swapping step that ensures mmmis always the largest number. We can adapt this idea for lattices:

def lagrange(b1,b2):
    mu = 1
    while mu != 0:
        mu = round((b1*b2) / (b1*b1))
        b2 -= mu*b1
        if b1*b1 > b2*b2:
            b1, b2 = b2, b1
    return b1, b2

Here ฮผ\muฮผis actually the Gram-Schmidt coefficient ฮผ2,1\mu_{2,1}ฮผ2,1โ€‹and it turns out that this algorithm will always find the shortest possible basis! Using the basis

b1=(โˆ’1.8,1.2)b2=(โˆ’3.6,2.3)\begin{matrix} b_1&=&(-1.8,1.2)\\ b_2&=&(-3.6,2.3) \end{matrix}b1โ€‹b2โ€‹โ€‹==โ€‹(โˆ’1.8,1.2)(โˆ’3.6,2.3)โ€‹

the Lagrange reduction looks like

and here we see it clearly gives the shortest vectors.

Optimality proof

Let LLLbe a lattice. The basis b1,b2b_1,b_2b1โ€‹,b2โ€‹is defined to be the shortest for any other basis b1โ€ฒ,b2โ€ฒ,โˆฅb1โ€ฒโˆฅโ‰คโˆฅb2โ€ฒโˆฅb_1',b_2',\left\lVert b_1'\right\rVert\leq\left\lVert b_2'\right\rVertb1โ€ฒโ€‹,b2โ€ฒโ€‹,โˆฅb1โ€ฒโ€‹โˆฅโ‰คโˆฅb2โ€ฒโ€‹โˆฅ, we have โˆฅb1โˆฅโ‰คโˆฅb1โ€ฒโˆฅ\left\lVert b_1\right\rVert\leq\left\lVert b_1'\right\rVertโˆฅb1โ€‹โˆฅโ‰คโˆฅb1โ€ฒโ€‹โˆฅand โˆฅb2โˆฅโ‰คโˆฅb2โ€ฒโˆฅ\left\lVert b_2\right\rVert\leq\left\lVert b_2'\right\rVertโˆฅb2โ€‹โˆฅโ‰คโˆฅb2โ€ฒโ€‹โˆฅ. Note that this generally cannot be generalized to other dimensions, however in dimension 2, this is possible and is given by Lagrange's algorithm. The proof is a somewhat messy sequence of inequalities that eventually lead to the conclusion we want.

Let b1,b2b_1,b_2b1โ€‹,b2โ€‹be the output of the Lagrange reduction for some lattice LLL. To prove that Lagrange reduction gives the shortest basis, we first show that โˆฅb1โˆฅ\left\lVert b_1\right\rVertโˆฅb1โ€‹โˆฅis the shortest vector in LLL.

We know that โˆฃโŸจb1,b2โŸฉโˆฃโˆฅb1โˆฅ2โ‰ค12\frac{\left|\langle b_1,b_2\rangle\right|}{\left\lVert b_1\right\rVert^2}\le\frac12โˆฅb1โ€‹โˆฅ2โˆฃโŸจb1โ€‹,b2โ€‹โŸฉโˆฃโ€‹โ‰ค21โ€‹from the algorithm directly. Let v=mb1+nb2โˆˆLv=mb_1+nb_2\in Lv=mb1โ€‹+nb2โ€‹โˆˆLbe any element in LLL. We first show that โˆฅb1โˆฅโ‰คโˆฅvโˆฅ\left\lVert b_1\right\rVert\leq\left\lVert v\right\rVertโˆฅb1โ€‹โˆฅโ‰คโˆฅvโˆฅ:

โˆฅvโˆฅ2=โˆฅmb1+nb2โˆฅ2=m2โˆฅb1โˆฅ2+2mnโŸจb1,b2โŸฉ+n2โˆฅb2โˆฅ2โ‰ฅm2โˆฅb1โˆฅ2โˆ’โˆฃmnโˆฃโˆฅb1โˆฅ2+n2โˆฅb1โˆฅ2=(m2โˆ’โˆฃmnโˆฃ+n2)โˆฅb1โˆฅ2\begin{align*} \left\lVert v\right\rVert^2&=\left\lVert mb_1+nb_2\right\rVert^2\\ &=m^2\left\lVert b_1\right\rVert^2+2mn\langle b_1,b_2\rangle+n^2\left\lVert b_2\right\rVert^2\\ &\geq m^2\left\lVert b_1\right\rVert^2-|mn|\left\lVert b_1\right\rVert^2+n^2\left\lVert b_1\right\rVert^2\\ &=\left(m^2-|mn|+n^2\right)\left\lVert b_1\right\rVert^2\\ \end{align*}โˆฅvโˆฅ2โ€‹=โˆฅmb1โ€‹+nb2โ€‹โˆฅ2=m2โˆฅb1โ€‹โˆฅ2+2mnโŸจb1โ€‹,b2โ€‹โŸฉ+n2โˆฅb2โ€‹โˆฅ2โ‰ฅm2โˆฅb1โ€‹โˆฅ2โˆ’โˆฃmnโˆฃโˆฅb1โ€‹โˆฅ2+n2โˆฅb1โ€‹โˆฅ2=(m2โˆ’โˆฃmnโˆฃ+n2)โˆฅb1โ€‹โˆฅ2โ€‹

Since m2โˆ’mn+n2=(mโˆ’n2)2+34n2m^2-mn+n^2=\left(m-\frac n2\right)^2+\frac34n^2m2โˆ’mn+n2=(mโˆ’2nโ€‹)2+43โ€‹n2, this quantity is only 000when m=n=0m=n=0m=n=0and is a positive integer for all other cases, hence โˆฅvโˆฅโ‰ฅโˆฅb1โˆฅ\left\lVert v\right\rVert\geq\left\lVert b_1\right\rVertโˆฅvโˆฅโ‰ฅโˆฅb1โ€‹โˆฅand โˆฅb1โˆฅ\left\lVert b_1\right\rVertโˆฅb1โ€‹โˆฅis a shortest vector of LLL. Note that we can have multiple vectors with the same norm as b1b_1b1โ€‹, for instance โˆ’b1-b_1โˆ’b1โ€‹. So this is not a unique shortest vector.

Suppose there exists some basis b1โ€ฒ,b2โ€ฒb'_1,b'_2b1โ€ฒโ€‹,b2โ€ฒโ€‹for LLLsuch that โˆฅb1โ€ฒโˆฅโ‰คโˆฅb2โ€ฒโˆฅ\left\lVert b_1'\right\rVert\leq\left\lVert b_2'\right\rVertโˆฅb1โ€ฒโ€‹โˆฅโ‰คโˆฅb2โ€ฒโ€‹โˆฅ. We show that โˆฅb2โˆฅโ‰คโˆฅb2โ€ฒโˆฅ\left\lVert b_2\right\rVert\leq\left\lVert b_2'\right\rVertโˆฅb2โ€‹โˆฅโ‰คโˆฅb2โ€ฒโ€‹โˆฅ. Let b2โ€ฒ=mb1+nb2b_2'=mb_1+nb_2b2โ€ฒโ€‹=mb1โ€‹+nb2โ€‹.

If n=0n=0n=0, then b2โ€ฒ=ยฑb1b_2'=\pm b_1b2โ€ฒโ€‹=ยฑb1โ€‹as b1โ€ฒ,b2โ€ฒb_1',b_2'b1โ€ฒโ€‹,b2โ€ฒโ€‹must form a basis. This means that โˆฅb1โˆฅ=โˆฅb1โ€ฒโˆฅ=โˆฅb2โ€ฒโˆฅ\left\lVert b_1\right\rVert=\left\lVert b_1'\right\rVert=\left\lVert b_2'\right\rVertโˆฅb1โ€‹โˆฅ=โˆฅb1โ€ฒโ€‹โˆฅ=โˆฅb2โ€ฒโ€‹โˆฅ and by the inequality above, we must have ยฑb1โ€ฒ=b2\pm b_1'=b_2ยฑb1โ€ฒโ€‹=b2โ€‹or ยฑb1โ€ฒ=b1+b2\pm b_1'=b_1+b_2ยฑb1โ€ฒโ€‹=b1โ€‹+b2โ€‹. The first case tells us that โˆฅb1โ€ฒโˆฅ=โˆฅb2โˆฅ\left\lVert b'_1\right\rVert=\left\lVert b_2\right\rVertโˆฅb1โ€ฒโ€‹โˆฅ=โˆฅb2โ€‹โˆฅ. By squaring the second case, we get

โˆฅb1โ€ฒโˆฅ2=โˆฅb1+b2โˆฅ2โˆฅb1โ€ฒโˆฅ2=โˆฅb1โˆฅ2+2โŸจb1,b2โŸฉ+โˆฅb2โˆฅ20=2โŸจb1,b2โŸฉ+โˆฅb2โˆฅ2โˆฅb1โˆฅ2โ‰คโˆฅb2โˆฅ2\begin{align*} \left\lVert b'_1\right\rVert^2&=\left\lVert b_1+b_2\right\rVert^2\\ \left\lVert b'_1\right\rVert^2&=\left\lVert b_1\right\rVert^2+2\langle b_1,b_2\rangle+\left\lVert b_2\right\rVert^2\\ 0&=2\langle b_1,b_2\rangle+\left\lVert b_2\right\rVert^2\\ \left\lVert b_1\right\rVert^2&\leq\left\lVert b_2\right\rVert^2\\ \end{align*}โˆฅb1โ€ฒโ€‹โˆฅ2โˆฅb1โ€ฒโ€‹โˆฅ20โˆฅb1โ€‹โˆฅ2โ€‹=โˆฅb1โ€‹+b2โ€‹โˆฅ2=โˆฅb1โ€‹โˆฅ2+2โŸจb1โ€‹,b2โ€‹โŸฉ+โˆฅb2โ€‹โˆฅ2=2โŸจb1โ€‹,b2โ€‹โŸฉ+โˆฅb2โ€‹โˆฅ2โ‰คโˆฅb2โ€‹โˆฅ2โ€‹

but since โˆฅb1โˆฅ\left\lVert b_1\right\rVertโˆฅb1โ€‹โˆฅis the shortest vector, โˆฅb1โˆฅ=โˆฅb2โˆฅ\left\lVert b_1\right\rVert=\left\lVert b_2\right\rVertโˆฅb1โ€‹โˆฅ=โˆฅb2โ€‹โˆฅ.

Otherwise, we have m,nโ‰ 0m,n\neq0m,n๎€ =0 and m2โˆ’mn+n2โ‰ฅ1m^2-mn+n^2\geq1m2โˆ’mn+n2โ‰ฅ1, so

โˆฅb2โ€ฒโˆฅ2=m2โˆฅb1โˆฅ2+2mnโŸจb1,b2โŸฉ+n2โˆฅb2โˆฅ2โ‰ฅm2โˆฅb1โˆฅ2โˆ’โˆฃmnโˆฃโˆฅb1โˆฅ2+n2โˆฅb2โˆฅ2=n2(โˆฅb2โˆฅ2โˆ’โˆฅb1โˆฅ2)+(m2โˆ’โˆฃmnโˆฃ+n2)โˆฅb1โˆฅ2โ‰ฅ(n2โˆ’1)(โˆฅb2โˆฅ2โˆ’โˆฅb1โˆฅ2)+โˆฅb2โˆฅ2โ‰ฅโˆฅb2โˆฅ2\begin{align*} \left\lVert b'_2\right\rVert^2&=m^2\left\lVert b_1\right\rVert^2+2mn\langle b_1,b_2\rangle+n^2\left\lVert b_2\right\rVert^2\\ &\geq m^2\left\lVert b_1\right\rVert^2-|mn|\left\lVert b_1\right\rVert^2+n^2\left\lVert b_2\right\rVert^2\\ &=n^2\left(\left\lVert b_2\right\rVert^2-\left\lVert b_1\right\rVert^2\right)+\left(m^2-|mn|+n^2\right)\left\lVert b_1\right\rVert^2\\ &\geq\left(n^2-1\right)\left(\left\lVert b_2\right\rVert^2-\left\lVert b_1\right\rVert^2\right)+\left\lVert b_2\right\rVert^2\\ &\geq\left\lVert b_2\right\rVert^2 \end{align*}โˆฅb2โ€ฒโ€‹โˆฅ2โ€‹=m2โˆฅb1โ€‹โˆฅ2+2mnโŸจb1โ€‹,b2โ€‹โŸฉ+n2โˆฅb2โ€‹โˆฅ2โ‰ฅm2โˆฅb1โ€‹โˆฅ2โˆ’โˆฃmnโˆฃโˆฅb1โ€‹โˆฅ2+n2โˆฅb2โ€‹โˆฅ2=n2(โˆฅb2โ€‹โˆฅ2โˆ’โˆฅb1โ€‹โˆฅ2)+(m2โˆ’โˆฃmnโˆฃ+n2)โˆฅb1โ€‹โˆฅ2โ‰ฅ(n2โˆ’1)(โˆฅb2โ€‹โˆฅ2โˆ’โˆฅb1โ€‹โˆฅ2)+โˆฅb2โ€‹โˆฅ2โ‰ฅโˆฅb2โ€‹โˆฅ2โ€‹

Hence proving Lagrange's algorithm indeed gives us the shortest basis vectors.

Exercises

1) Show that the output of Lagrange's algorithm generate the same lattice as the input.

2) Find a case where โˆฅb1โˆฅ=โˆฅb2โˆฅ=โˆฅb1+b2โˆฅ\left\lVert b_1\right\rVert=\left\lVert b_2\right\rVert=\left\lVert b_1+b_2\right\rVertโˆฅb1โ€‹โˆฅ=โˆฅb2โ€‹โˆฅ=โˆฅb1โ€‹+b2โ€‹โˆฅ. Notice that the vectors here is the equality case for the bound given in Exercise 4 of the introduction, this actually tells us that the optimal lattice circle packing in 2D is given by this precise lattice! It turns out that this is actually the optimal circle packing in 2D but the proof is significantly more involved. (See https://arxiv.org/abs/1009.4322 for the details)

3*) Let ฮผ2,1=โŒŠฮผ2,1โŒ‰+ฮต=ฮผ+ฯต\mu_{2,1}=\lfloor\mu_{2,1}\rceil+\varepsilon=\mu+\epsilonฮผ2,1โ€‹=โŒŠฮผ2,1โ€‹โŒ‰+ฮต=ฮผ+ฯต, show that

โˆฅb2โˆฅ2โ‰ฅ((โˆฃฮผโˆฃโˆ’12)2โˆ’ฮต2)โˆฅb1โˆฅ2+โˆฅb2โˆ’ฮผb1โˆฅ\left\lVert b_2\right\rVert^2\geq\left(\left(|\mu|-\frac12\right)^2-\varepsilon^2\right)\left\lVert b_1\right\rVert^2+\left\lVert b_2-\mu b_1\right\rVertโˆฅb2โ€‹โˆฅ2โ‰ฅ((โˆฃฮผโˆฃโˆ’21โ€‹)2โˆ’ฮต2)โˆฅb1โ€‹โˆฅ2+โˆฅb2โ€‹โˆ’ฮผb1โ€‹โˆฅ

and show that โˆฃฮผโˆฃโ‰ฅ2|\mu|\geq2โˆฃฮผโˆฃโ‰ฅ2for all steps in the algorithm except the first and last, hence โˆฅb1โˆฅโˆฅb2โˆฅ\left\lVert b_1\right\rVert\left\lVert b_2\right\rVertโˆฅb1โ€‹โˆฅโˆฅb2โ€‹โˆฅdecreases by at least 3\sqrt33โ€‹ at each loop and the algorithm runs in polynomial time.

Hard lattice problems

This section is not complete. Help is needed with relevance + examples in cryptography, algorithms + hardness, relations between problems.

Also needs review from more experienced people.

Introduction

Now that we are comfortable with lattices we shall study why are they important to cryptography.

Like we said, when we construct cryptosystems we usually are looking for hard problems to base them on. The lattice world provides us with such problems such as the shortest vector problem or the closest vector problem.

What makes lattices even more special is that some cryptographic problems (which we will study in the next chapter) can be reduced to worst-case lattice problems which makes them crazy secure. Moreover, some problems are even secure against quantum computers.

But enough talk, let's get right into it!

Shortest vector problem + GapSVP

Before we go into any problems we must first define the concept of distance in a lattice.

Let:

  • L=L= L= Lattice

  • B=\mathcal B = B= the basis of the lattice

  • n=n = n=the dimension of the lattice

Distance function

Given some distance function (Example: Euclidean norm) the distance from a vector ttt to the lattice LLL is the distance from the vector to the closest point in the in lattice.

ฮผ(t,L)=minโกvโˆˆLโˆฅtโˆ’vโˆฅ\mu(t, L) = \underset{v \in \mathcal{L}}{\min}{\|t-v\|}ฮผ(t,L)=vโˆˆLminโ€‹โˆฅtโˆ’vโˆฅ

We will denote the length of the shortest vector with โˆฅvโˆฅ=ฮป1(L)\|v\| = \lambda_1(L)โˆฅvโˆฅ=ฮป1โ€‹(L)and the length of the next independent vectors in order with ฮปi(L)โ‡’ฮป1(L)โ‰คฮป2(L)โ‰ค...โ‰คฮปn(L)\lambda_i(L) \Rightarrow\lambda_1({L}) \leq \lambda_2({L}) \leq ... \leq \lambda_n({L})ฮปiโ€‹(L)โ‡’ฮป1โ€‹(L)โ‰คฮป2โ€‹(L)โ‰ค...โ‰คฮปnโ€‹(L)

Shortest vector problem

Given a lattice LLL and an arbitrary basis B\mathcal{B}B for it our task is to find the shortest vector vโˆˆLv \in LvโˆˆL.

Approximate SVP

We relax the SVP problem a bit. Given an arbitrary basis B\mathcal{B}Bfind a shortest nonzero lattice vector vโˆˆLv \in LvโˆˆLsuch that v<ฮณ(n)โ‹…ฮป1(L)v < \gamma(n)\cdot \lambda_1(L)v<ฮณ(n)โ‹…ฮป1โ€‹(L). Here ฮณ(n)>1\gamma(n) > 1ฮณ(n)>1is some approximation factor.

Decision SVP (GapSVP)

Given a lattice LLLwith a basis B\mathcal BB we must distinguish if ฮป1(L)โ‰ค1\lambda_1(L) \leq 1ฮป1โ€‹(L)โ‰ค1 or ฮป>ฮณ(n)\lambda > \gamma(n)ฮป>ฮณ(n)

Sage example

# We can find the shortest vector using the LLL algorithm
M = matrix([[-1, 2], [-2, 3]])
B = M.LLL()
print(B[0])
# (0, -1)

# Or we can use the Integer Lattice class
L = IntegerLattice(M)
L.shortest_vector()
# (-1, 0)

Closest Vector problem + GapCVP

Closest vector problem

Given a lattice LLL with an arbitrary basis B\mathcal BB and a vector wโˆˆRnw \in \mathbb{R}^nwโˆˆRn find the closest lattice vector to www vโˆˆL,โˆฅvโˆ’wโˆฅโ‰คฮผv \in {L}, \|v-w\| \leq \muvโˆˆL,โˆฅvโˆ’wโˆฅโ‰คฮผ

Approximate CVP

Given a lattice LLL with an arbitrary basis B\mathcal BB and a vector wโˆˆRnw \in \mathbb{R}^nwโˆˆRn find the closest lattice vector to www vโˆˆL,โˆฅvโˆ’wโˆฅ<ฮณ(n)โ‹…ฮผv \in {L}, \|v-w\| < \gamma(n) \cdot \muvโˆˆL,โˆฅvโˆ’wโˆฅ<ฮณ(n)โ‹…ฮผ

Decision CVP (GapCVP)

Given a lattice LLLwith a basis B\mathcal BB and a vector www we must decide if

  • There exists vโˆˆLv \in LvโˆˆLs.t โˆฅvโˆ’wโˆฅโ‰ค1\| v - w\| \leq 1โˆฅvโˆ’wโˆฅโ‰ค1

  • โˆ€vโˆˆL:โˆฅvโˆ’wโˆฅ>ฮณ(n)\forall v \in L: \|v - w\| > \gamma(n)โˆ€vโˆˆL:โˆฅvโˆ’wโˆฅ>ฮณ(n)

Sage example

M = matrix([[-1, 2], [-2, 3]])
L = IntegerLattice(M)

w = vector([1.8, 1.5])
L.closest_vector(w)
# (2.00000000000000, 2.00000000000000)

Bounded distance decoding

Given a lattice LLL with an arbitrary basis BBB, a vector wโˆˆRnw \in \mathbb{R}^nwโˆˆRn and a real number dโˆˆRd \in \mathbb{R}dโˆˆR find a lattice vector vโˆˆLv \in {L}vโˆˆL s.t โˆฅwโˆ’vโˆฅ<dโ‹…ฮป1(L)\|w-v\| < d \cdot \lambda_1({L})โˆฅwโˆ’vโˆฅ<dโ‹…ฮป1โ€‹(L)

Remark

  • If we have d<12d < \dfrac 12d<21โ€‹ the solution to the BDD problem is guaranteed to be unique.

Shortest independent vectors (SIVP)

Given a full rank lattice LLL with an arbitrary basis B\mathcal BBfind nnn linearly independent lattice vectors of length at most ฮปn(L)โ‡’maxโกiโˆฅviโˆฅโ‰คฮปn(L)\lambda_n(L) \Rightarrow \max_i\|v_i\| \leq \lambda_n(L)ฮปnโ€‹(L)โ‡’maxiโ€‹โˆฅviโ€‹โˆฅโ‰คฮปnโ€‹(L) or maxโกiโˆฃviโˆฃโ‰คฮณ(n)ฮปn(L)\max_i|v_i| \leq \gamma(n) \lambda_n(L)maxiโ€‹โˆฃviโ€‹โˆฃโ‰คฮณ(n)ฮปnโ€‹(L)for the approximate version.

Hardness of lattice problems

Resources

  • Pictures taken from https://simons.berkeley.edu/sites/default/files/docs/14953/intro.pdf and "Cryptography made simple - Nigel Smart" and edited a bit

  • Or generated by me

Interactive fun

Inspired by: https://crypto.katestange.net/lattice-tools/

Lattice + LLL + Fundamental mesh plot

@interact
def draw_lattice(v1x = input_box(label = "v1 x =", default = 1),
                 v1y = input_box(label = "v1 y =", default = 0),
                 v2x = input_box(label = "v2 x =", default = 0),
                 v2y = input_box(label = "v2 y =", default = 1),
                 box = 5, search = 10,
                 plot_LLL = True,
                 plot_C = True,
                 plot_F = True):

    v1 = vector((v1x, v1y))
    v2 = vector((v2x, v2y))
    vecs = []
    # Generate vectors
    for i in range(-search,search):
        for j in range(-search,search):
            vecs.append(i*v1 + j*v2)
    # Plot stuff
    G = Graphics()
    for p1 in vecs:
        x1, y1 = p1
        if x1 > -box and x1 < box and y1 > -box and y1 < box:
            G += point(p1, color = 'green', size = 30)
            G += line([p1, p1 + v2], linestyle = '--', alpha = .20)
            G += line([p1, p1 + v1], linestyle = '--', alpha = .20)
    G+= arrow((0, 0), v1, color = 'red', arrowsize = 2)
    G+= arrow((0, 0), v2, color = 'red', arrowsize = 2)
    G+= text('v1', v1 + .2 * v1, color = 'red')
    G+= text('v2', v2 + .2 * v2, color = 'red')
    
    # LLL
    if plot_LLL:
        v1_, v2_ = matrix([v1, v2]).LLL()
        G+= arrow((0, 0), v1_, color = 'purple', arrowsize = 2)
        G+= arrow((0, 0), v2_, color = 'purple', arrowsize = 2)
        if plot_C:
            G += circle(center = (0, 0), radius = norm(v1_) if norm(v1_) > norm(v2_) else norm(v2_), alpha = .5, color = 'purple')
    # Fundamental mesh
    if plot_F:
        F = polygon([[0, 0], v1, v1 + v2, v2], color='red', alpha = .1)
        G += F
    G.show(axes = False, figsize = (7, 7))

Lattice + CVP

@interact
def draw_cvp(v1x = input_box(label = "v1 x =", default = 1),
             v1y = input_box(label = "v1 y =", default = 0),
             v2x = input_box(label = "v2 x =", default = 0),
             v2y = input_box(label = "v2 y =", default = 1),
             wx = input_box(label = "w x =", default = 1.8),
             wy = input_box(label = "w y =", default = 1.7),
             box = 5, search = 10):

    v1 = vector((v1x, v1y))
    v2 = vector((v2x, v2y))
    print(v1, v2)
    vecs = []
    # Generate vectors
    for i in range(-search,search):
        for j in range(-search,search):
            vecs.append(i*v1 + j*v2)
    # Plot stuff
    G = Graphics()
    for p1 in vecs:
        x1, y1 = p1
        if x1 > -box and x1 < box and y1 > -box and y1 < box:
            G += point(p1, color = 'green', size = 30)
            G += line([p1, p1 + v2], linestyle = '--', alpha = .20)
            G += line([p1, p1 + v1], linestyle = '--', alpha = .20)
    G+= arrow((0, 0), v1, color = 'red', arrowsize = 2)
    G+= arrow((0, 0), v2, color = 'red', arrowsize = 2)
    G+= text('v1', v1 + .2 * v1, color = 'red')
    G+= text('v2', v2 + .2 * v2, color = 'red')         
    
    # Cvp
    L = IntegerLattice(matrix([v1, v2]))
    w = vector((wx, wy))
    t = L.closest_vector(w)
    G += point(w, color = 'purple', size = 30)
    G+= text('w', w + .2 * v1, color = 'purple')         

    G += point(t, color = 'red', size = 30)
    G+= text('t', t + .2 * v1, color = 'red')         
    G+= circle(center = w, radius=norm(t - w), color = 'purple', alpha = .5)
    G.show(axes = False, figsize = (7, 7))
@interact
def draw_dual(v1x = input_box(label = "v1 x =", default = 1),
                 v1y = input_box(label = "v1 y =", default = 0),
                 v2x = input_box(label = "v2 x =", default = 0),
                 v2y = input_box(label = "v2 y =", default = 1),
                 box = 3, search = 6,
                 plot_lattice_points = True,
                 plot_lattice_lines = True,
                 plot_dual_points = True,
                 plot_dual_lines = True):

    v1 = vector((v1x, v1y))
    v2 = vector((v2x, v2y))
    vecs = []
    v1_, v2_ = matrix([v1,v2]).inverse().T
    vecs_ = []
    # Generate vectors
    for i in range(-search,search):
        for j in range(-search,search):
            vecs.append(i*v1 + j*v2)
    for i in range(-search,search):
        for j in range(-search,search):
            vecs_.append(i*v1_ + j*v2_)
    # Plot stuff
    G = Graphics()
    for p1 in vecs:
        x1, y1 = p1
        if x1 > -box and x1 < box and y1 > -box and y1 < box:
            if plot_lattice_points:
                G += point(p1, color = 'green', size = 70)
            if plot_lattice_lines:
                G += line([p1, p1 + v2], linestyle = '--', alpha = .20, color = 'green')
                G += line([p1, p1 + v1], linestyle = '--', alpha = .20, color = 'green')
    if plot_lattice_lines:
        G+= arrow((0, 0), v1, color = 'green', arrowsize = 2)
        G+= arrow((0, 0), v2, color = 'green', arrowsize = 2)
        G+= text('v1', v1 + .2 * v1, color = 'green')
        G+= text('v2', v2 + .2 * v2, color = 'green')
    
    # Dual
    for p1 in vecs_:
        x1, y1 = p1
        if x1 > -box and x1 < box and y1 > -box and y1 < box:
            if plot_dual_points:
                G += point(p1, color = 'red', size = 25)
            if plot_dual_lines:
                G += line([p1, p1 + v2_], linestyle = '--', alpha = .20, color = 'red')
                G += line([p1, p1 + v1_], linestyle = '--', alpha = .20, color = 'red')
    if plot_dual_lines:
        G+= arrow((0, 0), v1_, color = 'red', arrowsize = 2)
        G+= arrow((0, 0), v2_, color = 'red', arrowsize = 2)
        G+= text('v1\'', v1_ + .2 * v1, color = 'red')
        G+= text('v2\'', v2_ + .2 * v2, color = 'red')
    
    G.show(axes = False, figsize = (7, 7))

Q-ary plots

# I'm not sure this does what is supposed to do
# but the plots are nice

from sage.modules.free_module_integer import IntegerLattice
@interact
def draw_qary(v1x = input_box(label = "v1 x =", default = 1),
                 v1y = input_box(label = "v1 y =", default = 0),
                 v2x = input_box(label = "v2 x =", default = 0),
                 v2y = input_box(label = "v2 y =", default = 1),
                 q = input_box(label = "q =", default = 5),
                 box = 7, search = 6,
                 plot_lattice_points = True,
                 plot_lattice_lines = True,
                 plot_qary_points = True,
                 plot_qary_lines = True):

    v1 = vector((v1x, v1y))
    v2 = vector((v2x, v2y))
    L = IntegerLattice(matrix([v1, v2]))
    vecs = []
    v1_ = v1.change_ring(Zmod(q))
    v2_ = v2.change_ring(Zmod(q))
    vecs_ = []
    # Generate vectors
    for i in range(-search,search):
        for j in range(-search,search):
            v = i*v1 + j*v2
            vecs.append(v)
            v = v.change_ring(Zmod(q)).change_ring(ZZ)
            if v not in vecs_:
                vecs_.append(v)
                
    # Lattice
    G = Graphics()
    for p1 in vecs:
        x1, y1 = p1
        if x1 > -box and x1 < box and y1 > -box and y1 < box:
            if plot_lattice_points:
                G += point(p1, color = 'green', size = 70)
            if plot_lattice_lines:
                G += line([p1, p1 + v2], linestyle = '--', alpha = .20, color = 'green')
                G += line([p1, p1 + v1], linestyle = '--', alpha = .20, color = 'green')
    if plot_lattice_lines:
        G+= arrow((0, 0), v1, color = 'green', arrowsize = 2)
        G+= arrow((0, 0), v2, color = 'green', arrowsize = 2)
        G+= text('v1', v1 + .2 * v1, color = 'green')
        G+= text('v2', v2 + .2 * v2, color = 'green')
    
    # qary
    for p1 in vecs_:
        p1 = p1
        x1, y1 = p1
        if x1 > -box and x1 < box and y1 > -box and y1 < box:
            if plot_qary_points:
                G += point(p1, color = 'red', size = 25)
            if plot_qary_lines:
                G += line([p1, p1 + v2_], linestyle = '--', alpha = .20, color = 'red')
                G += line([p1, p1 + v1_], linestyle = '--', alpha = .20, color = 'red')
    if plot_qary_lines:
        G+= arrow((0, 0), v1_, color = 'purple', arrowsize = 2)
        G+= arrow((0, 0), v2_, color = 'purple', arrowsize = 2)
        G+= text('v1\'', v1_.change_ring(ZZ) + .2 * v1, color = 'purple')
        G+= text('v2\'', v2_.change_ring(ZZ) + .2 * v2, color = 'purple')
    
    G.show(axes = False, figsize = (10, 10))

Short integer solutions (SIS)

Introduction

In this section we will study the short integer solution problem and a hashing algorithm that is based on this algorithm.

Short integer solution problem

Definition

Let SISn,m,q,ฮฒSIS_{n, m, q, \beta}SISn,m,q,ฮฒโ€‹ be a Short Integer Solution problem. We define it as such:

Given mmm uniformly random vectors aiโˆˆ(Z/qZ)na_iโˆˆ(\mathbb{Z}/q\mathbb Z)^naiโ€‹โˆˆ(Z/qZ)n, forming the columns of a matrix Aโˆˆ(Z/qZ)nร—mAโˆˆ(\mathbb{Z}/q\mathbb Z)^{nร—m}Aโˆˆ(Z/qZ)nร—m, find a nonzero integer vector zโˆˆZmzโˆˆ\mathbb{Z}^mzโˆˆZm of norm โ€–zโ€–โ‰คฮฒโ€–zโ€– โ‰คฮฒโ€–zโ€–โ‰คฮฒ (short) such that

fA(z)=Az=โˆ‘iaiโ‹…zi=0โˆˆ(Z/qZ)nz1a1โƒ—+z2a2โƒ—+...+zmamโƒ—=0f_A(z) = Az = \sum_i a_i \cdot z_i = 0 \in (\mathbb{Z}/q\mathbb Z)^n \\ z_1\vec{a_1} + z_2\vec{a_2} +...+ z_m\vec{a_m} = 0fAโ€‹(z)=Az=iโˆ‘โ€‹aiโ€‹โ‹…ziโ€‹=0โˆˆ(Z/qZ)nz1โ€‹a1โ€‹โ€‹+z2โ€‹a2โ€‹โ€‹+...+zmโ€‹amโ€‹โ€‹=0

Without the constraint ฮฒ\betaฮฒ the solution would be as simple as Gaussian elimination. Also we want ฮฒ<q\beta < qฮฒ<q otherwise z=(q,0,...,0)โˆˆZmz = (q,0, ..., 0) \in \mathbb{Z}^mz=(q,0,...,0)โˆˆZm would be a fine solution.

Notice that a solution zzz for AAA can be converted to a solution for the extension [AโˆฃAโ€ฒ][A| A'][AโˆฃAโ€ฒ] by appending 000s to zzz โ‡’\Rightarrowโ‡’

  • big mโ‡’m \Rightarrowmโ‡’ easy (the more vectors we are given, the easier the problem becomes)

  • big nโ‡’n \Rightarrownโ‡’ hard (the more dimension we work in the harder the problem becomes)

Solution existence is based on parameters set. One should think about them as follows:

  • nnn is the security parameter. The bigger it is the harder the problem becomes

  • mmm is set depending from application to application. Usually mโ‰ซnm \gg nmโ‰ซn

  • q=poly(n)q = \text{poly}(n)q=poly(n), think of it as q=O(n2)q = \mathcal{O}(n^2)q=O(n2)

  • ฮฒ=\beta = ฮฒ=the bound is set depending on application and ฮฒโ‰ชq\beta \ll qฮฒโ‰ชq

SIS as a SVP problem

// TODO

Ajtai's hashing function

  • Parameters: m,n,qโˆˆZm, n, q \in \mathbb{Z}m,n,qโˆˆZ, m>nlogโก2qm > n \log_2 qm>nlog2โ€‹q

  • Key: Aโˆˆ(Z/qZ)nร—mA \in (\mathbb{Z}/q\mathbb Z)^{n \times m}Aโˆˆ(Z/qZ)nร—m

  • Input: xโˆˆ{0,1}mโ‡’x \in \{0, 1\}^m \Rightarrowxโˆˆ{0,1}mโ‡’ Short vector

  • Output: fA(x)=Axโ€Šmodโ€Šq\boxed {f_A(x) = Ax \bmod q}fAโ€‹(x)=Axmodqโ€‹ where fA:{0,1}mโ†’(Z/qZ)nf_A : \{0, 1\}^m \to (\mathbb{Z}/q\mathbb Z)^nfAโ€‹:{0,1}mโ†’(Z/qZ)n

Hash function properties:

Compression

We know xโˆˆ{0,1}mโ‡’โˆฃXโˆฃ=2nx \in \{0, 1\}^m \Rightarrow |\mathcal{X}| = 2^nxโˆˆ{0,1}mโ‡’โˆฃXโˆฃ=2n and AxโˆˆY=(Z/qZ)nโ‡’โˆฃ(Z/qZ)nโˆฃ=qn=(2logโกq)nAx \in \mathcal Y = (\mathbb{Z}/q\mathbb Z)^n \Rightarrow |(\mathbb{Z}/q\mathbb Z)^n| = q^n = (2^{\log q})^nAxโˆˆY=(Z/qZ)nโ‡’โˆฃ(Z/qZ)nโˆฃ=qn=(2logq)n. Since we chose m>nlogโกqโ‡’โˆฃXโˆฃ>โˆฃYโˆฃm > n \log q \Rightarrow |\mathcal{X}| > |\mathcal{Y}| m>nlogqโ‡’โˆฃXโˆฃ>โˆฃYโˆฃ.

Collision resistance:

halp here

Sage example:

from Crypto.Util.number import long_to_bytes, bytes_to_long

n, m, q = 20, 40, 1009
set_random_seed(1337)
A = random_matrix(Zmod(q),n, m)

print(A.parent())
# Full MatrixSpace of 20 by 40 dense matrices over Ring of integers modulo 1009
print(A.lift().parent())
# Full MatrixSpace of 20 by 40 dense matrices over Integer Ring

msg = b'msg'
x = vector(Zmod(q), [int(i) for i in bin(bytes_to_long(msg))[2:].zfill(m)]) # pad message
print(len(x)
# 40

print(x.parent())
# Vector space of dimension 40 over Ring of integers modulo 1009

print(len(A * x))
# 20

Cryptanalysis

Inverting the function:

Given AAA and yyy find xโˆˆ{0,1}mx \in \{0, 1\}^mxโˆˆ{0,1}m such that Ax=yโ€Šmodโ€ŠqAx = y \bmod qAx=ymodq

Formulating as a lattice problem:

Find arbitrary ttt such that At=yโ€Šmodโ€ŠqAt = y \bmod qAt=ymodq

  • All solutions to Ax=yAx = yAx=y are of the form t+LโŠฅt + L^{\perp}t+LโŠฅ where LโŠฅ(A)={xโˆˆZm:Ax=0โˆˆ(Z/qZ)n}{L}^\perp(A) = \{x \in \mathbb{Z}^m : Ax = 0 \in (\mathbb{Z}/q\mathbb Z)^n \}LโŠฅ(A)={xโˆˆZm:Ax=0โˆˆ(Z/qZ)n}

  • So we need to find a short vector in t+LโŠฅ(A)t + {L}^{\perp}(A)t+LโŠฅ(A)

  • Equivalent, find vโˆˆLโŠฅ(A)v \in {L}^{\perp}(A)vโˆˆLโŠฅ(A) closest to ttt (CVP)

Hermite normal form

// TODO

Security Reduction

If somebody can explain the security bounds and reduction better, please do.

Resources

  • https://simons.berkeley.edu/sites/default/files/docs/14967/sis.pdf + https://www.youtube.com/watch?v=qZIjVX61NFc&list=PLgKuh-lKre10rqiTYqJi6P4UlBRMQtPn0&index=4

  • https://crypto.stanford.edu/cs355/18sp/lec9.pdf

  • https://eprint.iacr.org/2015/939.pdf - page 18

Lattices of interest

Needs review.

Introduction

In this chapter we will study some specific types of lattices that appear in cryptography. These will help us understand how certain problems we base our algorithms on reduce to other hard problems. They will also give insight about the geometry of lattices.

Intuitively, if we have a problem (1) in some lattice space we can reduce it to a hard problem (2) in another related lattice space. Then if we can prove that if solving problem (1) implies solving problem (2) then we can conclude that problem (1) is as hard as problem (2)

Understanding this chapter will strengthen the intuition for the fututre when we will study what breaking a lattice problem means and how to link it to another hard lattice problem.

Dual lattice

Let LโŠ‚RnL \subset \mathbb R^nLโŠ‚Rnbe a lattice. We define the dual of a lattice as the set of all vectors yโˆˆspan(L)y \in span(L)yโˆˆspan(L) such that yโ‹…xโˆˆZย y \cdot x \in \mathbb Z \ yโ‹…xโˆˆZย for all vectors xโˆˆLx \in LxโˆˆL:

Lโˆจ={yโˆˆspan(L):yโ‹…xโˆˆZย โˆ€ย xโˆˆL}L^\vee = \{y \in span(L) : y \cdot x \in \mathbb{Z} \ \forall \ x \in L\}Lโˆจ={yโˆˆspan(L):yโ‹…xโˆˆZย โˆ€ย xโˆˆL}

Note that the vectors in the dual lattice LโˆจL^\veeLโˆจ are not necessarily in the initial lattice LLL. They are spanned by the basis vectors of the lattice LLL.

Examples:

  1. (Zn)โˆจ=Zn(\mathbb Z^n) ^ \vee = \mathbb Z^n(Zn)โˆจ=Zn because the dot product of all vectors in Zn\mathbb Z^nZnstays in Zn\mathbb Z^nZn

  2. Scaling: (kโ‹…L)โˆจ=1kโ‹…L(k \cdot L)^\vee = \dfrac 1 k \cdot L(kโ‹…L)โˆจ=k1โ€‹โ‹…L Proof: If yโˆˆ(kL)โˆจโ‡’yโ‹…kx=k(xโ‹…y)โˆˆZย โˆ€ย xโˆˆLโ‡’yโˆˆ1kLโˆจy \in (kL)^\vee \Rightarrow y \cdot kx = k(x \cdot y) \in \mathbb{Z} \ \forall \ x \in L \Rightarrow y \in \dfrac 1 k L^\veeyโˆˆ(kL)โˆจโ‡’yโ‹…kx=k(xโ‹…y)โˆˆZย โˆ€ย xโˆˆLโ‡’yโˆˆk1โ€‹Lโˆจ If yโˆˆ(1kL)โˆจโ‡’yvโˆˆLโˆจโ‡’kyโ‹…x=k(xโ‹…y)=yโ‹…kxโˆˆZย โˆ€ย xย โˆˆLโ‡’yโˆˆ(kL)โˆจy \in \left (\dfrac 1 kL\right )^\vee \Rightarrow yv \in L^\vee \Rightarrow ky\cdot x = k(x \cdot y) = y \cdot kx \in \mathbb{Z} \ \forall \ x \ \in L \Rightarrow y \in (kL)^\veeyโˆˆ(k1โ€‹L)โˆจโ‡’yvโˆˆLโˆจโ‡’kyโ‹…x=k(xโ‹…y)=yโ‹…kxโˆˆZย โˆ€ย xย โˆˆLโ‡’yโˆˆ(kL)โˆจ

Plot: 2Z22\mathbb Z ^22Z2 - green, 12Z2\dfrac 1 2 \mathbb Z ^ 221โ€‹Z2 - red

Intuition: We can think of the dual lattice LโˆจL^\veeLโˆจ as some kind of inverse of the initial lattice LLL

Basis of the dual lattice

We will now focus on the problem of finding the basis BโˆจB^\veeBโˆจ of the dual lattice LโˆจL^\veeLโˆจgiven the lattice LLL and its basis BBB.

Reminder: We can think of the lattice LLL as a transformation given by its basis BโˆˆGLn(R)B \in GL_n(\mathbb R)BโˆˆGLnโ€‹(R)on Zn\mathbb Z^nZn.

We have the following equivalences:

yโˆˆLโˆจโ€…โ€ŠโŸบโ€…โ€Šyโ‹…xโˆˆZย โˆ€ย xโˆˆLโ€…โ€ŠโŸบโ€…โ€ŠBTyโˆˆZnโ€…โ€ŠโŸบโ€…โ€Šyโˆˆ(Bโˆ’1)Tโ‹…Zn\begin{align*} y \in L^\vee & \iff y \cdot x \in \mathbb Z \ \forall\ x \in L \\ & \iff B^Ty \in \mathbb{Z}^n \\ & \iff y \in (B^{-1})^T \cdot \mathbb Z^n \end{align*}yโˆˆLโˆจโ€‹โŸบyโ‹…xโˆˆZย โˆ€ย xโˆˆLโŸบBTyโˆˆZnโŸบyโˆˆ(Bโˆ’1)Tโ‹…Znโ€‹

Therefore Lโˆจ=(Bโˆ’1)Tโ‹…ZnL^\vee = (B^{-1})^T \cdot \mathbb Z^nLโˆจ=(Bโˆ’1)Tโ‹…Znso we have found a base for our dual lattice:

Bโˆจ=(Bโˆ’1)TโˆˆGLn(R)B^\vee = (B^{-1})^T \in GL_n(\mathbb{R})Bโˆจ=(Bโˆ’1)TโˆˆGLnโ€‹(R)
n = 5 # lattice dimension

B = sage.crypto.gen_lattice(m=n, q=11, seed=42)
B_dual = sage.crypto.gen_lattice(m=n,  q=11, seed=42, dual=True)

B_dual_ = (B.inverse().T * 11).change_ring(ZZ) # Scale up to integers
B_dual_.hermite_form() == B_dual.hermite_form() # Reduce form to compare
# True
  • https://en.wikipedia.org/wiki/Hermite_normal_form

Let's look at some plots. With green I will denote the original lattice and with red the dual. The scripts for the plots can be found in in the interactive fun section

Properties

  1. L1โІL2โ€…โ€ŠโŸบโ€…โ€ŠL2โˆจโІL1โˆจ{L}_1 \subseteq {L}_2 \iff {L}^\vee_2 \subseteq {L}^\vee_1L1โ€‹โІL2โ€‹โŸบL2โˆจโ€‹โІL1โˆจโ€‹

  2. (Lโˆจ)โˆจ=L=({L}^\vee)^\vee ={L} = (Lโˆจ)โˆจ=L=The dual of the dual is the initial lattice (to prove think of the basis of LโˆจL^\veeLโˆจ)

  3. detโก(Lโˆจ)=detโก(L)โˆ’1\det(L^\vee) = \det(L) ^{-1}det(Lโˆจ)=det(L)โˆ’1 (to prove think of the basis of LโˆจL^\veeLโˆจ)

  4. For xโˆˆL,yโˆˆLโˆจx \in {L}, y \in {L}^\veexโˆˆL,yโˆˆLโˆจconsider the vector dot product and addition - xโ‹…yโˆˆZx \cdot y \in \mathbb{Z}xโ‹…yโˆˆZ - x+yx + yx+y has no geometric meaning, they are in different spaces

Successive minima

We've seen that we can find the basis of the dual lattice given the basis of the original lattice. Let's look at another interesting quantity: the successive minima of a lattice LLL and its dual LโˆจL^\veeLโˆจ. Let's see what can we uncover about them.

We recommend to try and think about the problem for a few minutes before reading the conclusions.

What is ฮป1(2Z2)\lambda_1(2\mathbb Z^2)ฮป1โ€‹(2Z2)? What about ฮป1((2Z2)โˆจ)\lambda_1((2\mathbb Z^2)^\vee)ฮป1โ€‹((2Z2)โˆจ)? Can you see some patterns?

Reminder: We defined the successive minima of a lattice LLLas such:

ฮปi(L)=minโก(maxโก1โ‰คjโ‰คi(โˆฅvjโˆฅ):vjโˆˆLย areย linearlyย independent)\lambda_i(L)=\min\left(\max_{1\leq j\leq i}\left(\left\lVert v_j\right\rVert\right):v_j\in L\text{ are linearly independent}\right)ฮปiโ€‹(L)=min(1โ‰คjโ‰คimaxโ€‹(โˆฅvjโ€‹โˆฅ):vjโ€‹โˆˆLย areย linearlyย independent)

Claim 1:

ฮป1(L)โ‹…ฮป1(Lโˆจ)โ‰คn\lambda_1(L) \cdot \lambda_1(L^\vee) \leq nฮป1โ€‹(L)โ‹…ฮป1โ€‹(Lโˆจ)โ‰คn

Proof: By Minkowski's bound we know:

ฮป1(L)โ‰คnโ‹…detโก(L)1/n\lambda_1(L) \leq \sqrt{n} \cdot \det(L)^{1 / n}ฮป1โ€‹(L)โ‰คnโ€‹โ‹…det(L)1/n and ฮป1(Lโˆจ)โ‰คnโ‹…det(Lโˆจ)1/n=ndetโก(L)1/n\lambda_1(L^\vee) \leq \sqrt{n} \cdot det(L^\vee)^{1 / n} = \dfrac {\sqrt{n}} {\det(L)^{1/n}}ฮป1โ€‹(Lโˆจ)โ‰คnโ€‹โ‹…det(Lโˆจ)1/n=det(L)1/nnโ€‹โ€‹. By multiplying them we get the desired result.

From this result we can deduce that the minima of the LLL and LโˆจL^\veeLโˆจhave an inverse proportional relationship (If one is big, the other is small).

n = 5 # lattice dimension

B = sage.crypto.gen_lattice(m=n, q=11, seed=42)
B_dual = sage.crypto.gen_lattice(m = n,  q=11, seed=42, dual=True)

l1 = IntegerLattice(B).shortest_vector().norm().n() 
l2 = IntegerLattice(B_dual).shortest_vector().norm().n() / 11

print(l1 * l2 < n)
# True

Claim 2:

ฮป1(L)โ‹…ฮปn(Lโˆจ)โ‰ฅ1\lambda_1(L) \cdot \lambda_n(L^\vee) \geq 1ฮป1โ€‹(L)โ‹…ฮปnโ€‹(Lโˆจ)โ‰ฅ1

Proof:

Let xโˆˆLxโˆˆLxโˆˆL be such that โˆฅxโˆฅ=ฮป1(L)\|x\|=ฮป_1(L)โˆฅxโˆฅ=ฮป1โ€‹(L). Then take any set (y1,...,yn)(y_1, . . . , y_n)(y1โ€‹,...,ynโ€‹) of nnn linearly independent vectors in LโˆจL^\veeLโˆจ. Not all of them are orthogonal to xxx. Hence, there exists an iii such that yiโ‹…xโ‰ 0y_i \cdot x \neq 0yiโ€‹โ‹…x๎€ =0 . By the definition of the dual lattice, we have yiโ‹…xโˆˆZy_i \cdot x \in \mathbb Zyiโ€‹โ‹…xโˆˆZ and hence 1โ‰คyiโ‹…xโ‰คโˆฅyiโˆฅโ‹…โˆฅxโˆฅโ‰คฮป1โ‹…ฮปnโˆจ1 \leq y_i \cdot x \leq \|y_i\| \cdot \|x\| \leq \lambda_1 \cdot \lambda_n^\vee1โ‰คyiโ€‹โ‹…xโ‰คโˆฅyiโ€‹โˆฅโ‹…โˆฅxโˆฅโ‰คฮป1โ€‹โ‹…ฮปnโˆจโ€‹

n = 5 # lattice dimension

B = sage.crypto.gen_lattice(m=n, q=11, seed=42)
B_dual = sage.crypto.gen_lattice(m = n,  q=11, seed=42, dual=True)

l1 = IntegerLattice(B).shortest_vector().norm().n() 

B_dual_lll = B_dual.LLL()
lnd = 0
for v in B_dual_lll:
    lv = v.norm()
    if lv > lnd:
        lnd = lv
lnd = lnd.n() / 11

print(lnd * l1 > 1) 
# True

Geometry + Partitioning

// TODO

Q-ary lattices

We've seen that in cryptography we don't like to work with infinite sets (like Z\mathbb ZZ) and we limit them to some finite set using the โ€Šmodโ€Š\bmodmod operation (Zโ†’Z/qZ\mathbb Z \to \mathbb Z/ q\mathbb{Z}Zโ†’Z/qZ). We will apply the same principle to the lattices so let us define the concept of a q-ary lattice.

Definition:

For a number qโˆˆZ,ย qโ‰ฅ3q \in \mathbb{Z},\ q \geq 3qโˆˆZ,ย qโ‰ฅ3we call a lattice q-ary if

qZnโІLโІZnq\mathbb{Z}^n \subseteq {L} \subseteq \mathbb{Z}^nqZnโІLโІZn

Intuition:

  • qZnโІLq\mathbb{Z^n} \subseteq \mathcal{L}qZnโІL is periodic โ€Šmodโ€Šย q\bmod \ qmodย q

  • We use arithmetic โ€Šmodโ€Šย q\bmod \ qmodย q

We will now look at 2 more types of lattices that are q-ary. Let Aโˆˆ(Z/qZ)nร—mA \in (\mathbb{Z}/q\mathbb Z)^{n \times m}Aโˆˆ(Z/qZ)nร—m be a matrix with m>nm > nm>n. Consider the following lattices: Lq(A)={yโˆˆZm:y=ATxโ€Šmodโ€Šqโˆˆย forย someย xโˆˆZn}โŠ‚ZmL_q(A) = \{y \in \mathbb Z^m : y = A^Tx \bmod q \in \text{ for some } x \in \mathbb{Z}^n \} \subset \mathbb{Z^m}Lqโ€‹(A)={yโˆˆZm:y=ATxmodqโˆˆย forย someย xโˆˆZn}โŠ‚Zm LqโŠฅ(A)={yโˆˆZm:Ay=0โ€Šmodโ€Šq}โŠ‚ZmL^\perp_q(A) = \{y \in \mathbb Z^m : Ay = 0 \bmod q \} \subset \mathbb{Z^m}LqโŠฅโ€‹(A)={yโˆˆZm:Ay=0modq}โŠ‚Zm

Intuition:

  • Think of Lq(A)L_q(A)Lqโ€‹(A) as the image of the matrix AAA, the matrix spanned by the rows of AAA

  • Think of LqโŠฅ(A)L_q^\perp(A)LqโŠฅโ€‹(A) as the kernel of AAA modulo qqq. The set of solutions Ax=0Ax = 0Ax=0

Remark: If the same matrix AAA is used (AAA is fixed ) then Lq(A)โ‰ LqโŠฅ(A)L_q(A) \neq L_q^\perp(A)Lqโ€‹(A)๎€ =LqโŠฅโ€‹(A)

Claim:

Lq(A)L_q(A)Lqโ€‹(A) and LqโŠฅ(A)L_q^\perp(A)LqโŠฅโ€‹(A) are the dual of each other (up to scaling): Lq(A)=1qLqโŠฅ(A)L_q(A) = \dfrac 1 q L_q^\perp(A)Lqโ€‹(A)=q1โ€‹LqโŠฅโ€‹(A)

Proof:

Firstly we will show LqโŠฅ(A)โІq(Lq(A))โˆจL_q^\perp(A) \subseteq q(L_q(A))^\veeLqโŠฅโ€‹(A)โІq(Lqโ€‹(A))โˆจ

  • Let yโˆˆLqโŠฅ(A)โ‡’Ayโ‰ก0โ€Šmodโ€Šqโ€…โ€ŠโŸบโ€…โ€ŠAy=qzy \in L_q^\perp(A) \Rightarrow Ay \equiv 0 \bmod q \iff Ay = qzyโˆˆLqโŠฅโ€‹(A)โ‡’Ayโ‰ก0modqโŸบAy=qzfor some zโˆˆZmz \in \mathbb{Z}^mzโˆˆZm

  • Let yโ€ฒโˆˆLq(A)โ‡’yโ€ฒโ‰กATxโ€Šmodโ€Šqโ€…โ€ŠโŸบโ€…โ€Šyโ€ฒ=ATx+qzโ€ฒy' \in L_q(A)\Rightarrow y' \equiv A^Tx \bmod q \iff y' = A^Tx + qz'yโ€ฒโˆˆLqโ€‹(A)โ‡’yโ€ฒโ‰กATxmodqโŸบyโ€ฒ=ATx+qzโ€ฒ for some xโˆˆZn,ย zโ€ฒโˆˆZmx \in \mathbb Z^n, \ z' \in \mathbb Z^mxโˆˆZn,ย zโ€ฒโˆˆZm

Then we have:yโ‹…yโ€ฒ=yโ‹…(ATx+qzโ€ฒ)=yโ‹…ATx+q(yโ‹…zโ€ฒ)=AyโŸqzโ‹…x+q(yโ‹…zโ€ฒ)=qzโ‹…x+q(yโ‹…zโ€ฒ)y \cdot y' = y \cdot (A^Tx + qz') = y\cdot A^Tx + q (y \cdot z') = \underbrace{Ay}_{qz} \cdot x + q(y \cdot z') = qz \cdot x + q(y \cdot z')yโ‹…yโ€ฒ=yโ‹…(ATx+qzโ€ฒ)=yโ‹…ATx+q(yโ‹…zโ€ฒ)=qzAyโ€‹โ€‹โ‹…x+q(yโ‹…zโ€ฒ)=qzโ‹…x+q(yโ‹…zโ€ฒ)

โ‡’1qyโ‹…yโ€ฒโˆˆZโ‡’1qyโˆˆLq(A)โˆจ\Rightarrow \dfrac 1 q y \cdot y' \in \mathbb{Z} \Rightarrow \dfrac 1 q y\in L_q(A)^\veeโ‡’q1โ€‹yโ‹…yโ€ฒโˆˆZโ‡’q1โ€‹yโˆˆLqโ€‹(A)โˆจ

The second part is left as an exercise to the reader :D. Show LqโŠฅ(A)โЇq(Lq(A))โˆจL_q^\perp(A) \supseteq q(L_q(A))^\veeLqโŠฅโ€‹(A)โЇq(Lqโ€‹(A))โˆจ

Resources

  • https://cims.nyu.edu/~regev/teaching/lattices_fall_2004/ln/DualLattice.pdf

  • https://sp2.uni.lu/wp-content/uploads/sites/66/2019/06/DualLattice-Luca-Notarnicola.pdf

  • https://simons.berkeley.edu/sites/default/files/docs/14953/intro.pdf

  • https://cseweb.ucsd.edu/~daniele/papers/FOSAD11.pdf

Wiener's Attack

Wiener's attack is an attack on RSA that uses continued fractions to find the private exponent ddd when it's small (less than 13n4\frac{1}{3}\sqrt[4]{n}31โ€‹4nโ€‹, where nnn is the modulus). We know that when we pick the public exponent eee to be a small number and calcute its inverse dโ‰กeโˆ’1modโ€‰โ€‰ฯ•(n)d \equiv e^{-1} \mod \phi(n)dโ‰กeโˆ’1modฯ•(n)

Wiener's theorem

Wiener's attack is based on the following theorem:

Let n=pqn = pqn=pq, with q<p<2qq < p < 2qq<p<2q. Let d<13n4d < \frac{1}{3}\sqrt[4]{n}d<31โ€‹4nโ€‹. Given nnn and eee with edโ‰ก1modโ€‰โ€‰ฯ•(n)ed \equiv 1 \mod \phi(n)edโ‰ก1modฯ•(n), the attacker can efficiently recover ddd.

Some observations on RSA

In order to better understand Wiener's Attack, it may be useful to take note of certain properties of RSA:

We may start by noting that the congruence edโ‰ก1modโ€‰โ€‰ฯ•(n)ed \equiv 1 \mod \phi(n)edโ‰ก1modฯ•(n) can be written as the equality ed=kฯ•(n)+1ed = k\phi(n)+1ed=kฯ•(n)+1 for some value kkk, we may additionally note that ฯ•(n)=(pโˆ’1)(qโˆ’1)=pqโˆ’pโˆ’q+1\phi(n) = (p-1)(q-1) = pq - p - q + 1ฯ•(n)=(pโˆ’1)(qโˆ’1)=pqโˆ’pโˆ’q+1, since both ppp and qqq are much shorter than pq=npq = npq=n, we can say that ฯ•(n)โ‰ˆn\phi(n) \approx nฯ•(n)โ‰ˆn.

Dividing the former equation by dฯ•(n)d\phi(n)dฯ•(n) gives us eฯ•(n)=k+1d\frac{e}{\phi(n)} = \frac{k+1}{d}ฯ•(n)eโ€‹=dk+1โ€‹, and using the latter approximation, we can write this as enโ‰ˆkd\frac{e}{n} \approx \frac{k}{d}neโ€‹โ‰ˆdkโ€‹. Notice how the left-hand side of this equation is composed entirely of public information, this will become important later.

It is possible to quickly factor nnn by knowing nnn and ฯ•(n)\phi(n)ฯ•(n). Consider the quadratic polynomial (xโˆ’q)(xโˆ’p)(x-q)(x-p)(xโˆ’q)(xโˆ’p), this polynomial will have the roots ppp and qqq. Expanding it gives us x2โˆ’(p+q)x+pqx^2 - (p + q)x + pqx2โˆ’(p+q)x+pq, and substituting for the variables we know we can write this as x2โˆ’(nโˆ’ฯ•(n)+1)x+nx^2 - (n - \phi(n) + 1)x + nx2โˆ’(nโˆ’ฯ•(n)+1)x+n. Applying the quadratic formula gives us ppp and qqq: pโˆงq=โˆ’bยฑb2โˆ’4ac2ap \wedge q = \frac{-b \pm \sqrt{b^2-4ac}}{2a}pโˆงq=2aโˆ’bยฑb2โˆ’4acโ€‹โ€‹, where a=1a = 1a=1, b=nโˆ’ฯ•(n)+1b = n - \phi(n) + 1b=nโˆ’ฯ•(n)+1, and c=nc = nc=n.

Wiener's attack works by expanding en\frac{e}{n}neโ€‹ to a continued fraction and iterating through the terms to check various approximations of kd\frac{k}{d}dkโ€‹. In order to make this checking process more efficient, we can make a few observations (this part is optional):

  • Since ฯ•(n)\phi(n)ฯ•(n) is even, and eee and ddd are both by definition coprime to ฯ•(n)\phi(n)ฯ•(n), we know that ddd is odd.

  • Given the above equations and the values of eee, nnn, ddd, and kkk, we can solve for ฯ•(n)\phi(n)ฯ•(n) with the equation ฯ•(n)=edโˆ’1k\phi(n) = \frac{ed-1}{k}ฯ•(n)=kedโˆ’1โ€‹, thus we know that edโˆ’1ed-1edโˆ’1 has to be divisible by kkk.

  • If our ฯ•(n)\phi(n)ฯ•(n) is correct, the polynomial x2โˆ’(nโˆ’ฯ•(n)+1)x+nx^2 - (n - \phi(n) + 1)x + nx2โˆ’(nโˆ’ฯ•(n)+1)x+n will have roots ppp and qqq, which we can verify by checking if pq=npq = npq=n.

The Attack

Suppose we have the public key (n,e)(n, e)(n,e), this attack will determine ddd

  1. Convert the fraction en\frac{e}{n}neโ€‹ into a continued fraction [a0;a1,a2,โ€ฆ,akโˆ’2,akโˆ’1,ak][a_0;a_1,a_2, \ldots , a_{k-2},a_{k-1}, a_k][a0โ€‹;a1โ€‹,a2โ€‹,โ€ฆ,akโˆ’2โ€‹,akโˆ’1โ€‹,akโ€‹]

  2. Iterate over each convergent in the continued fraction: a01,a0+1a1,a0+1a1+1a2,ย โ€ฆ,a0+1a1+โ‹ฑakโˆ’2+1akโˆ’1,\frac{a_{0}}{1},a_{0} + \frac{1}{a_{1}},a_{0} + \frac{1}{a_{1} + \frac{1}{a_{2}}}, \ \ldots, a_{0} + \frac{1}{a_{1} + \frac{\ddots} {a_{k-2} + \frac{1}{a_{k-1}}}},1a0โ€‹โ€‹,a0โ€‹+a1โ€‹1โ€‹,a0โ€‹+a1โ€‹+a2โ€‹1โ€‹1โ€‹,ย โ€ฆ,a0โ€‹+a1โ€‹+akโˆ’2โ€‹+akโˆ’1โ€‹1โ€‹โ‹ฑโ€‹1โ€‹,

  3. Check if the convergent is kd\frac{k}{d}dkโ€‹ by doing the following:

    • Set the numerator to be kkk and denominator to be ddd

    • Check if ddd is odd, if not, move on to the next convergent

    • Check if edโ‰ก1modโ€‰โ€‰ked \equiv 1 \mod kedโ‰ก1modk, if not, move on to the next convergent

    • Set ฯ•(n)=edโˆ’1k\phi(n) = \frac{ed-1}{k}ฯ•(n)=kedโˆ’1โ€‹ and find the roots of the polynomial x2โˆ’(nโˆ’ฯ•(n)+1)x+nx^2 - (n - \phi(n) + 1)x + nx2โˆ’(nโˆ’ฯ•(n)+1)x+n

    • If the roots of the polynomial are integers, then we've found ddd. (If not, move on to the next convergent)

  4. If all convergents have been tried, and none of them work, then the given RSA parameters are not vulnerable to Wiener's attack.

Here's a sage implementation to play around with:

from Crypto.Util.number import long_to_bytes

def wiener(e, n):
    # Convert e/n into a continued fraction
    cf = continued_fraction(e/n)
    convergents = cf.convergents()
    for kd in convergents:
        k = kd.numerator()
        d = kd.denominator()
        # Check if k and d meet the requirements
        if k == 0 or d%2 == 0 or e*d % k != 1:
            continue
        phi = (e*d - 1)/k
        # Create the polynomial
        x = PolynomialRing(RationalField(), 'x').gen()
        f = x^2 - (n-phi+1)*x + n
        roots = f.roots()
        # Check if polynomial as two roots
        if len(roots) != 2:
            continue
        # Check if roots of the polynomial are p and q
        p,q = int(roots[0][0]), int(roots[1][0])
        if p*q == n:
            return d
    return None
# Test to see if our attack works
if __name__ == '__main__':
    n = 6727075990400738687345725133831068548505159909089226909308151105405617384093373931141833301653602476784414065504536979164089581789354173719785815972324079
    e = 4805054278857670490961232238450763248932257077920876363791536503861155274352289134505009741863918247921515546177391127175463544741368225721957798416107743
    c = 5928120944877154092488159606792758283490469364444892167942345801713373962617628757053412232636219967675256510422984948872954949616521392542703915478027634
    d = wiener(e,n)
    assert not d is None, "Wiener's attack failed :("
    print(long_to_bytes(int(pow(c,d,n))).decode())

//TODO: Proof of Wiener's theorem

Automation

The Python module owiener simplifies the scripting process of Wiener's attack:

Here is a Wiener's attack template:

#!/usr/bin/env python3
import owiener
from Crypto.Util.number import long_to_bytes

#--------Data--------#

N = <N>
e = <e>
c = <c>

#--------Wiener's attack--------#

d = owiener.attack(e, N)

if d:
    m = pow(c, d, N)
    flag = long_to_bytes(m).decode()
    print(flag)
else:
    print("Wiener's Attack failed.")

Boneh-Durfee Attack

What is Boneh-Durfee Attack

Boneh-Durfee attack is an extension of Wiener's attack. That is, it also attacks on low private component dddwith a further relaxed condition. If dddsatisfies:

d<N0.292d < N^{0.292} d<N0.292

Then we can use Boneh-Durfee attack to retrive ddd

this, using a graphical directed point of view, can be seen as:

{E,n}โ†’d<N0.292P{d}\{E, n\} \xrightarrow[d < N^{0.292}]{P} \{d\} {E,n}Pd<N0.292โ€‹{d}

Consider d<Nid < N^{i}d<Nifor first, see that

1=ed+kฯ•(N)21=ed + \frac{k \phi(N)}{2}\\ 1=ed+2kฯ•(N)โ€‹

As stated above, the RSA's totient function can be espressed as:

ฯ•(N)=(pโˆ’1)(qโˆ’1)=Nโˆ’qโˆ’p+1 \phi(N) = (p-1)(q-1) = N-q-p+1ฯ•(N)=(pโˆ’1)(qโˆ’1)=Nโˆ’qโˆ’p+1

continuing with the equation, we see that

1=ed+k(N+12โˆ’p+q2)1 = ed + k(\frac{N+1}{2}-\frac{p+q}{2} )1=ed+k(2N+1โ€‹โˆ’2p+qโ€‹)

and if we decide to consider x=N+12x = \frac{N+1}{2} x=2N+1โ€‹and y=p+q2y = \frac{p+q}{2} y=2p+qโ€‹, we will have:

1=ed+k(x+y)1 = ed + k(x+y)1=ed+k(x+y)

At this point, finding dddis equivalent to find the 2 small solutions xxxand yyyto the congruence

f(x,y)โ‰กk(x+y)โ‰ก1ย (modย e)k(x+y)โ‰ก1(ย modย e)f(x,y) \equiv k(x+y) \equiv 1 \space (mod \space e) \\ k(x + y) \equiv 1 (\space mod \space e)f(x,y)โ‰กk(x+y)โ‰ก1ย (modย e)k(x+y)โ‰ก1(ย modย e)

now let s=โˆ’p+q2s = -\frac{p+q}{2}s=โˆ’2p+qโ€‹and A=N+12A = \frac{N+1}{2}A=2N+1โ€‹this will preserve the scomposed ฯ•(N)\phi(N) ฯ•(N)subtraction

k(A+s)โ‰ก1(ย modย e)k(A+s) \equiv 1 (\space mod \space e)k(A+s)โ‰ก1(ย modย e)

consider e=Nฮฑe=N^{\alpha}e=Nฮฑ(with any ฮฑ\alphaฮฑ), we deduct that ฮฑ\alphaฮฑmust be really closed to 111because eeeis in the same order of the length of NNN(so e=Nโˆผ1โˆ’e=N^{\sim 1^{-}}e=Nโˆผ1โˆ’), we will get

โˆฃsโˆฃ<2N=p+q2<2N=2e12ฮฑโˆผeโˆฃkโˆฃ<2edฯ•(N)โ‰ค3edN<3e1+ฮฑ+1ฮฑ<ei| s | < 2\sqrt{N} = \\ \frac{p+q}{2} < 2\sqrt{N} =2e^{\frac{1}{2\alpha}} \sim \sqrt{e} \\ |k| < \frac{2ed}{\phi{(N)}} \leq\frac{3ed}{N}< 3e^{1+\frac{\alpha+1}{\alpha}} < e^{i}โˆฃsโˆฃ<2Nโ€‹=2p+qโ€‹<2Nโ€‹=2e2ฮฑ1โ€‹โˆผeโ€‹โˆฃkโˆฃ<ฯ•(N)2edโ€‹โ‰คN3edโ€‹<3e1+ฮฑฮฑ+1โ€‹<ei

Sage Implementation

AES

Advanced Encryption Standard

Introduction

The Advanced Encryption Standard most known as AES is one of the most used ciphers nowadays. Created by Vinent Rijmen and Joan Daemen under the name Rijndael, it won the NIST competition that resulted in its standardization in 2001 to replace older algorithms such as DES (and its variant 3DES). In fact, it is six times faster than 3DES.

AES encrypts a block of 16 bytes only at a time, though ciphertexts tend to be much longer. To accomodate this, cipherexts are cut in blocks of 16 bytes using an operating mode [see future section on mode]. We only focus on the encryption of a single block.

The array of 16 bytes(p0,โ€ฆ,p15)(p_0,\ldots,p_{15})(p0โ€‹,โ€ฆ,p15โ€‹)are arranged from up to bottom, column by column in4ร—44 \times 44ร—4matrix. During the encryption, the state of this matrix changes and results in a 16-bytes ciphertext(c0,โ€ฆ,c15)(c_0,\ldots,c_{15})(c0โ€‹,โ€ฆ,c15โ€‹)whose output can be read following the same ordering:

AES encryption.

A key is involved and three sizes are possible: 128, 192, or 256 bits. Depending of the size, there are a few differences which will be explained later. For now, it is sufficient to know that round keys are derived from this master key.

Our interest is to look at what goes inside the transformation between the plaintext and the ciphertext. Basically, there are four operations on the state matrix, each important for the security of AES:

  • AK: add round key;

  • SR: shift row;

  • SB: substitution box;

  • MC: MixColumn.

All these operations are executed a several number of times in what are called rounds to mix the plaintext enough. A look on the flow of an encryption is given in the figure below.

Rounds of AES.

Two particular cases can be noticed:

  • the first round is preceded by an additional AK;

  • last round is missing MC.

The number of rounds NR is different depending on the master key length:

Key length

Number of rounds

128

10

192

12

256

14

Introduction / overview

Authors: Zademn Reviewed by:

Introduction

Another desired propriety of our cryptographic protocols is data / message integrity. This propriety assures that during a data transfer the data has not been modified.

Suppose Alice has a new favourite game and wants to send it to Bob. How can Bob be sure that the file he receives is the same as the one Alice intended to send? One would say to run the game and see. But what if the game is a malware? What if there are changes that are undetectable to the human eye?

Hashes are efficient algorithms to check if two files are the same based on the data they contain. The slightest change (a single bit) would change the hash completely.

On the internet, when you download, files you often see a number near the download button called the hash of that file. If you download that file, recalculate the hash locally and obtain the same hash you can be sure that the data you downloaded is the intended one.

Another use for hashes is storing passwords. We don't want to store plaintext passwords because in case of a breach the attacker will know our password. If we hash them he will have to reverse the hash (or find a collision) to use our password. Luckily the hashes are very hard to reverse and collision resistant by definition and construction.

Note that hashes need a secure channel for communication. Alice must have a secure way to send her hash to Bob. If Eve intercepts Alice's message and hash she can impersonate Alice by changing the file, computing the hash and sending them to Bob. Hashes do not provide authenticity.

Definitions and Formalism

Definition - Hash

A hash is an efficient deterministic function that takes an arbitrary length input and produces a fixed length output (digest, hash). Let H:MโŸถTH:\mathcal{M} \longrightarrow \mathcal{T}H:MโŸถT be a function where

  • M\mathcal{M}M = message space

  • T\mathcal{T}T = digest space

Desired proprieties

  • Deterministic

  • Fast to compute

  • Small changes change the hash completely

  • Preimage, second preimage and collision resistance (Explained below)

How to use a hash:

  • Suppose you want to check if Alice and Bob have the same version of some file (File integrity)

    • They compute H(a),H(b)H(a), H(b)H(a),H(b)

    • They check if H(a)=H(b)H(a) = H(b)H(a)=H(b)

Figure 1.
from hashlib import sha256
m1 = b"Some file"
m2 = b"Some file"
sha256(m1).digest() == sha256(m2).digest() # -> True

Proprieties

  • Preimage Image Resistance

  • Second Preimage resistance

  • Resistant to collisions

1. Preimage Resistance

The hash function must be a one way function. Given tโˆˆTt \in \mathcal{T}tโˆˆT find mโˆˆMm \in \mathcal{M}mโˆˆM s.t H(m)=tH(m) = tH(m)=t

Intuition

It should be unfeasible to reverse a hash function (O(2l)\mathcal{O}(2^l)O(2l) time where lll is the number of output bits)

This propriety prevents an attacker to find the original message from a hash

2. Second Preimage Resistance

Given mmm it should be hard to find mโ€ฒโ‰ mm' \neq mmโ€ฒ๎€ =m with H(mโ€ฒ)=H(m)H(m') = H(m)H(mโ€ฒ)=H(m)

Attack game

An adversary A\mathcal{A}A is given a message mmm and outputs a message mโ€ฒโ‰ mm' \neq mmโ€ฒ๎€ =m.

A\mathcal{A}A wins the game if he finds H(m)=H(mโ€ฒ)H(m) = H(m')H(m)=H(mโ€ฒ)

His advantage is Pr[Aย findsย aย secondย preimage]Pr[\mathcal{A} \text{ finds a second preimage}]Pr[Aย findsย aย secondย preimage] where Pr(โ‹…)Pr(\cdot)Pr(โ‹…)is a probability

Figure 2. Security game - second preimage resistance
  • In practice a hash function with lll bits output should need 2l2^l2l queries before one can find a second preimage

  • This propriety prevents an attacker to substitute a message with another and get the same hash

3. Hash Collisions

Intuition

A hash collision happens when we have two different messages that have the same hash

Why do we care about hash collisions?

  • Since hashes are used to fastly verify a message integrity if two messages have the same hash then we can replace one with another => We can play with data

  • Now, we want to hash big files and big messages so โˆฃMโˆฃ>>โˆฃTโˆฃ|\mathcal{M}| >> |\mathcal{T}|โˆฃMโˆฃ>>โˆฃTโˆฃ => It would appear that hash collisions are possible

  • Natural collisions are normal to happen and we consider them improbable if T\mathcal{T}T is big enough (SHA256โ‡’T=\text{SHA256} \Rightarrow T =SHA256โ‡’T= {0,1}256\{0,1\}^{256}{0,1}256)

  • Yet, we don't want hash collisions to be computable

    • We don't want an attacker to be able to craft collisions or find collisions given a message

Let's throw some definitions

Attack game

An adversary A\mathcal{A}A outputs two messages m0โ‰ m1m_0 \neq m_1m0โ€‹๎€ =m1โ€‹

A\mathcal{A}A wins the game if he finds H(m0)=H(m1)H(m_0) = H(m_1)H(m0โ€‹)=H(m1โ€‹)

His advantage is Pr[Adversaryย findsย aย collision]Pr[\text{Adversary finds a collision}]Pr[Adversaryย findsย aย collision]

Figure 3. Security game - Collision resistance

Security

A hash function HHH is collision resistant if for all efficient and explicit adversaries the advantage is negligible

Intuition

We know hash collisions exist (therefore an efficient adversary must exist) and that is easy to prove therefore we request an explicit algorithm that finds these collisions

This propriety makes it difficult for an attacker to find 2 input values with the same hash

Difference from 2nd preimage

  • There is a fundamental difference in how hard it is to break collision resistance and second-preimage resistance.

    • Breaking collision-resistance is like inviting more people into the room until the room contains 2 people with the same birthday.

    • Breaking second-preimage resistance is like inviting more people into the room until the room contains another person with your birthday.

  • One of these fundamentally takes longer than the other

Implications

Lemma 1

Assuming a function HHH is preimage resistant for every element of the range of HHH is a weaker assumption than assuming it is either collision resistant or second preimage resistant.

Note

  • Provisional implication

  • https://crypto.stackexchange.com/questions/10602/why-does-second-pre-image-resistance-imply-pre-image-resistance?rq=1

  • https://crypto.stackexchange.com/questions/9684/pre-image-resistant-but-not-2nd-pre-image-resistant

Lemma 2

Assuming a function is second preimage resistant is a weaker assumption than assuming it is collision resistant.

Resources

  • https://en.wikipedia.org/wiki/Cryptographic_hash_function - Wikipedia entry

  • https://www.youtube.com/watch?v=b4b8ktEV4Bg - Computerphile

  • https://www.tutorialspoint.com/cryptography/cryptography_hash_functions.htm

  • https://www.cs.ucdavis.edu/~rogaway/papers/relates.pdf - Good read for more details

Bibliography

  • Figure 1 - Wikipedia

Round Transformations

This page gives a description of the four operations that compose a round of AES. Each has been designed to satisfy criterias, one of them is that all must be invertible.

Add Round Key

This is the only operation that involves a key. It is obvious that omitting it would mean no encryption.

Round keys are derived from the master key (see the Key Schedule section) and are all composed of 16 bytes. We simply xor byte by byte the state by the bytes of the round key in the according position.

AK: each byte is xored with a byte of the round key in the same position.

Its inverse is itself: if we xor again, we get back the original value of the state.

Mix Columns

A major goal of MC is the diffusion property: each byte has an impact on the whole column, so a modification propagates to other positions.

This operation mixes each column of the state independently from each other: each byte of the column is replaced by a (slightly different) combination of the four bytes of the column.

Let (a0,a1,a2,a3)(a_0, a_1, a_2, a_3)(a0โ€‹,a1โ€‹,a2โ€‹,a3โ€‹) the quadruplet of elements of a column, the operation MC is done by multiplying with a matrix MMM.

MC: each column is multiplied by a matrix.

The calculations are performed in the finite field. If you are not familiar enough with the notions, you can skip to the next part and retain that this operation is also invertible using another matrix.

This matrix is circulant: each row is the same as the one above but is shifted by one column. So we can construct it in one line of SageMath (recall that the bytes 02 and 03 correspond respectively to xxxand x+1x+1x+1 in the field):

# we construct the matrix
# (we use the finite field F constructed in the previous page)
M = Matrix.circulant([x, x + 1, 1, 1])
M
# [    x x + 1     1     1]
# [    1     x x + 1     1]
# [    1     1     x x + 1]
# [x + 1     1     1     x]

# We multiply a column
col1 = vector([F.random_element() for i in range(4)])
col1
# (x^6 + x + 1, x^7 + x^4 + x^2, x^6 + x^4 + x^3 + x^2, x^7 + x^6 + x^4 + x^3 + x^2)
col2 = M*col1
col2
# (x^7 + x^5 + 1, x^6 + x^3, x^4, x^7 + x^5 + x^3 + x^2 + x)

Inverse of Mix Column

It is needed to reverse MC for the decryption process. Fortunately, there exists a matrix NNN such that Mร—N=Nร—M=IdM\times N = N \times M = \textrm{Id}Mร—N=Nร—M=Id, the identity matrix.

N = M^-1
N
# [x^3 + x^2 + x   x^3 + x + 1 x^3 + x^2 + 1       x^3 + 1]
# [      x^3 + 1 x^3 + x^2 + x   x^3 + x + 1 x^3 + x^2 + 1]
# [x^3 + x^2 + 1       x^3 + 1 x^3 + x^2 + x   x^3 + x + 1]
# [  x^3 + x + 1 x^3 + x^2 + 1       x^3 + 1 x^3 + x^2 + x]

# hexadecimal representation
for row in N:
    print([F_to_hex(a) for a in row])
# ['e', 'b', 'd', '9']
# ['9', 'e', 'b', 'd']
# ['d', '9', 'e', 'b']
# ['b', 'd', '9', 'e']

col3 = N*col2
col3 == col1
# True

We remark that the coefficient of the matrix are less friendly for the inverse operation as it involves polynomial of higher degree. This means that the decryption is a bit slower.

Shift Rows

The goal of shifting rows is reinforce the diffusion property: the bytes of a column are shifted so they are all positioned on different columns. Combined with MC, then a one byte modification will have an effect to the whole state after several rounds: this is the Avalanche effect.

This operation shifts the rows of the state in the following manner:

SR: each is shifted by a different offset to the left.

The rows are shifted from top to bottom respectively by an offset of 0, 1, 2 or 3 columns to the left. Bytes that overflow on the left are put back to the right of the row.

The inverse is almost the same: the rows are shifted to the right instead by the same offsets and exceeding bytes are put back to the left.

Small exercise: to what extent would be the impact on the security of AES if no shifting were present?

Substitution Box

Last, but not least, the SB design criterias is to bring the confusion property to make correlation between a plaintext and a ciphertext as small as possible.

The precedent operations shuffle the plaintext in such a way that any modification of a byte has an impact to the whole state after several rounds. Though, this is not enough as those operations are linear: it means that the ciphertext could be expressed as linear equations from the plaintext and the master key. From a known couple plaintext/ciphertext it would be easy to solve the system and find the key.

The substitution box is the operation that breaks the linearity: each byte of the state is replaced by another following the table below.

00

01

02

03

04

05

06

07

08

09

0a

0b

0c

0d

0e

0f

00

63

7c

77

7b

f2

6b

6f

c5

30

01

67

2b

fe

d7

ab

76

10

ca

82

c9

7d

fa

59

47

f0

ad

d4

a2

af

9c

a4

72

c0

20

b7

fd

93

26

36

3f

f7

cc

34

a5

e5

f1

71

d8

31

15

30

04

c7

23

c3

18

96

05

9a

07

12

80

e2

eb

27

b2

75

40

09

83

2c

1a

1b

6e

5a

a0

52

3b

d6

b3

29

e3

2f

84

50

53

d1

00

ed

20

fc

b1

5b

6a

cb

be

39

4a

4c

58

cf

60

d0

ef

aa

fb

43

4d

33

85

45

f9

02

7f

50

3c

9f

a8

70

51

a3

40

8f

92

9d

38

f5

bc

b6

da

21

10

ff

f3

d2

80

cd

0c

13

ec

5f

97

44

17

c4

a7

7e

3d

64

5d

19

73

90

60

81

4f

dc

22

2a

90

88

46

ee

b8

14

de

5e

0b

db

a0

e0

32

3a

0a

49

06

24

5c

c2

d3

ac

62

91

95

e4

79

b0

e7

c8

37

6d

8d

d5

4e

a9

6c

56

f4

ea

65

7a

ae

08

c0

ba

78

25

2e

1c

a6

b4

c6

e8

dd

74

1f

4b

bd

8b

8a

d0

70

3e

b5

66

48

03

f6

0e

61

35

57

b9

86

c1

1d

9e

e0

e1

f8

98

11

69

d9

8e

94

9b

1e

87

e9

ce

55

28

df

f0

8c

a1

89

0d

bf

e6

42

68

41

99

2d

0f

b0

54

bb

16

If 3b is the input, its output is on row 30 and column 0b and is the byte e2.

Let sbox the name of this table, then for any bytes b1 and b2, we have

sbox(b1โŠ•b2)โ‰ sbox(b1)โŠ•sbox(b2)\texttt{sbox}(\texttt{b1} \oplus \texttt{b2}) \neq \texttt{sbox}(\texttt{b1}) \oplus \texttt{sbox}(\texttt{b2})sbox(b1โŠ•b2)๎€ =sbox(b1)โŠ•sbox(b2)

which is the desired property.

Though, this is not enough and the design of the sbox is made to include a sufficient algebraic complexity. The construction of the sbox table is done in two steps:

  1. An elementaaais replaced by b=aโˆ’1b = a^{-1}b=aโˆ’1 (000 has no inverse and is mapped to 000);

  2. An affine transformation on the coefficients of aaa:

[1000111111000111111000111111000111111000011111000011111000011111]โ‹…[b0b1b2b3b4b5b6b7]+[11000110]\begin{bmatrix} 1 & 0 & 0 & 0 & 1 & 1 & 1 & 1 \\ 1 & 1 & 0 & 0 & 0 & 1 & 1 & 1 \\ 1 & 1 & 1 & 0 & 0 & 0 & 1 & 1 \\ 1 & 1 & 1 & 1 & 0 & 0 & 0 & 1 \\ 1 & 1 & 1 & 1 & 1 & 0 & 0 & 0 \\ 0 & 1 & 1 & 1 & 1 & 1 & 0 & 0 \\ 0 & 0 & 1 & 1 & 1 & 1 & 1 & 0 \\ 0 & 0 & 0 & 1 & 1 & 1 & 1 & 1 \end{bmatrix} \cdot \begin{bmatrix} b_0 \\ b_1 \\ b_2 \\ b_3 \\ b_4 \\ b_5 \\ b_6 \\ b_7 \end{bmatrix} + \begin{bmatrix} 1 \\ 1 \\ 0 \\ 0 \\ 0 \\ 1 \\ 1 \\ 0 \end{bmatrix}โ€‹11111000โ€‹01111100โ€‹00111110โ€‹00011111โ€‹10001111โ€‹11000111โ€‹11100011โ€‹11110001โ€‹โ€‹โ‹…โ€‹b0โ€‹b1โ€‹b2โ€‹b3โ€‹b4โ€‹b5โ€‹b6โ€‹b7โ€‹โ€‹โ€‹+โ€‹11000110โ€‹โ€‹

The table we gave above has been construted with SageMath and applying the two steps:

def construct_sbox():
    mat = Matrix.circulant(vector(GF(2), [1,0,0,0,1,1,1,1]))
    sbox = []
    for a in range(256):
        # convert a byte value to field element
        b = sum(((a >> i) & 1)*x^i for i in range(8))
        # first step: map to inverse
        if b != 0:
        b = b^-1
        # second step:
        # affine transformation using a vector space over GF(2)
        b = mat*vector(b) + vector(GF(2), [1, 1, 0, 0, 0, 1, 1, 0])
        # convert the vector as an integer in [0, 255]
        sbox.append(sum(ZZ(b[i]) << i for i in range(8)))
    return sbox

sbox = construct_sbox()
for i in range(16):
    print([f'{a:02x}' for a in sbox[16*i : 16*(i + 1)]])
# ['63', '7c', '77', '7b', 'f2', '6b', '6f', 'c5', '30', '01', '67', '2b', 'fe', 'd7', 'ab', '76']
# ['ca', '82', 'c9', '7d', 'fa', '59', '47', 'f0', 'ad', 'd4', 'a2', 'af', '9c', 'a4', '72', 'c0']
# ['b7', 'fd', '93', '26', '36', '3f', 'f7', 'cc', '34', 'a5', 'e5', 'f1', '71', 'd8', '31', '15']
# ['04', 'c7', '23', 'c3', '18', '96', '05', '9a', '07', '12', '80', 'e2', 'eb', '27', 'b2', '75']
# ['09', '83', '2c', '1a', '1b', '6e', '5a', 'a0', '52', '3b', 'd6', 'b3', '29', 'e3', '2f', '84']
# ['53', 'd1', '00', 'ed', '20', 'fc', 'b1', '5b', '6a', 'cb', 'be', '39', '4a', '4c', '58', 'cf']
# ['d0', 'ef', 'aa', 'fb', '43', '4d', '33', '85', '45', 'f9', '02', '7f', '50', '3c', '9f', 'a8']
# ['51', 'a3', '40', '8f', '92', '9d', '38', 'f5', 'bc', 'b6', 'da', '21', '10', 'ff', 'f3', 'd2']
# ['cd', '0c', '13', 'ec', '5f', '97', '44', '17', 'c4', 'a7', '7e', '3d', '64', '5d', '19', '73']
# ['60', '81', '4f', 'dc', '22', '2a', '90', '88', '46', 'ee', 'b8', '14', 'de', '5e', '0b', 'db']
# ['e0', '32', '3a', '0a', '49', '06', '24', '5c', 'c2', 'd3', 'ac', '62', '91', '95', 'e4', '79']
# ['e7', 'c8', '37', '6d', '8d', 'd5', '4e', 'a9', '6c', '56', 'f4', 'ea', '65', '7a', 'ae', '08']
# ['ba', '78', '25', '2e', '1c', 'a6', 'b4', 'c6', 'e8', 'dd', '74', '1f', '4b', 'bd', '8b', '8a']
# ['70', '3e', 'b5', '66', '48', '03', 'f6', '0e', '61', '35', '57', 'b9', '86', 'c1', '1d', '9e']
# ['e1', 'f8', '98', '11', '69', 'd9', '8e', '94', '9b', '1e', '87', 'e9', 'ce', '55', '28', 'df']
# ['8c', 'a1', '89', '0d', 'bf', 'e6', '42', '68', '41', '99', '2d', '0f', 'b0', '54', 'bb', '16']

The inverse of the table is simple to produce: we only need to reverse the match between an input and its output.

Exercise: write the inverse of the substitution box in SageMath using the inverse of the affine transformation.

Isogeny and Ramanujan Graphs

I (Jack) know nothing about this. At all. But it will need to be talked about.

  • Isogeny graph (general definition, degree, duals...).

  • Starting vertex (Brรถker's algorithm).

  • Isogeny Volcanos: Sutherland might be a good source .

  • Supersingular isogeny graphs

    • Size, everything is defined over GF(p^2). (*as long as the degree divides (p+1)^2 or (p-1)^2).

    • Random walks are probably the best motivation to define Ramanujanness, and are directly applicable to cryptography. A (perhaps too large) source is Hoory-Linial-Wigderson.

    • Consequence from Ramanujan + random walk convergence: O(log p) diameter.

https://arxiv.org/abs/1208.5370
owiener
Boneh-Durfee attack Sage implementation
GitHub - orisano/owiener: A Python3 implementation of the Wiener attack on RSAGitHub
RSA-and-LLL-attacks/boneh_durfee.sage at master ยท mimoo/RSA-and-LLL-attacksGitHub
Logo
Logo