Skip to content

Commit

Permalink
Add PQClean falcon512 implementation
Browse files Browse the repository at this point in the history
Signed-off-by: eum602 <[email protected]>
  • Loading branch information
eum602 committed May 5, 2024
1 parent 0702f1d commit bee79f3
Show file tree
Hide file tree
Showing 17 changed files with 11,729 additions and 5 deletions.
10 changes: 5 additions & 5 deletions EIPS/eip-7619.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,15 @@ Include a precompiled signature verification function using Falcon-512. Falcon-5

## Motivation

The advent of quantum computing threatens blockchain protocols and networks because they utilize non-quantum resistant cryptographic algorithms. When quantum computers become robust enough to run Shor’s algorithm (a quantum algorithm to find the prime factos of an integer) on a large scale, the most used asymmetric algorithms, utilized for digital signatures and message encryption, such as RSA, (EC)DSA, and (EC)DH, will be no longer secure. Quantum computers will be able to break them within a short period of time. Today, there are hundreds of billions of dollars denominated in cryptocurrencies and other digital assets that rely on blockchain ledgers as well as thousands of blockchain-based applications storing value in blockchain networks. Cryptocurrencies and blockchain-based applications require solutions that guarantee quantum resistance in order to preserve the integrity of data and assets in these public and immutable ledgers. Most proposals for quantum-resistant blockchain networks are theoretical, require large QKD (quantum key distribution, a secure communication method that implements a cryptographic protocol involving components of quantum mechanics) networks, or propose new quantum-resistant blockchain protocols to be built from scratch. This EIP is pioneer in proposing a solution compatible with current EVM blockchain protocols. It presents a simple mechanism to add a NIST-compliant post-quantum signature to blockchain transactions, making them quantum-resistant even when ECC (elliptic curve cryptography) cryptography becomes vulnerable against attacks by quantum computers. We have developed a Solidity implementation for the on-chain verification of this signatures, which does not scale due to the required high amount of gas. This is why **this EIP is proposing a pre-compiled smart contract** that allows to verify post-quantum signatures in a scalable manner.
The advent of quantum computing threatens blockchain protocols and networks because they utilize non-quantum resistant cryptographic algorithms. When quantum computers become robust enough to run Shor’s algorithm (a quantum algorithm to find the prime factors of an integer) on a large scale, the most used asymmetric algorithms, utilized for digital signatures and message encryption, such as RSA, (EC)DSA, and (EC)DH, will be no longer secure. Quantum computers will be able to break them within a short period of time. Today, there are hundreds of billions of dollars denominated in cryptocurrencies and other digital assets that rely on blockchain ledgers as well as thousands of blockchain-based applications storing value in blockchain networks. Cryptocurrencies and blockchain-based applications require solutions that guarantee quantum resistance in order to preserve the integrity of data and assets in these public and immutable ledgers. Most proposals for quantum-resistant blockchain networks are theoretical, require large QKD (quantum key distribution, a secure communication method that implements a cryptographic protocol involving components of quantum mechanics) networks, or propose new quantum-resistant blockchain protocols to be built from scratch. This EIP is pioneer in proposing a solution compatible with current EVM blockchain protocols. It presents a simple mechanism to add a NIST-compliant post-quantum signature to blockchain transactions, making them quantum-resistant even when ECC (elliptic curve cryptography) cryptography becomes vulnerable against attacks by quantum computers. We have developed a Solidity implementation for the on-chain verification of this signatures, which does not scale due to the required high amount of gas. This is why **this EIP is proposing a pre-compiled smart contract** that allows to verify post-quantum signatures in a scalable manner.

## Specification

A clean implementation for Falcon-512 algorithm can be found at [PQClean-Falcon-512](https://github.com/PQClean/PQClean/commit/8e220a87308154d48fdfac40abbb191ac7fce06a)
A clean implementation for Falcon-512 algorithm was brought from PQClean: [PQClean-Falcon-512](../assets/eip-7619/pqclean-implementation/verify-signature.c)

The precompiled signature verification function runs at address `0x65`. The required inputs are:

- `message` - an arbitrary nummber of bytes representing the message that was signed
- `message` - an arbitrary number of bytes representing the message that was signed
- `public key` - Falcon Public key of 897 bytes
- `signature` - 666 bytes (max size)

Expand Down Expand Up @@ -117,12 +117,12 @@ Intel(R) Core(TM) i7-10750H CPU @ 2.60GHz
Based on [100 test vectors with valid signatures](../assets/eip-7619/bench_vectors.md) a benchmark of 5 seconds, for each test vector, was performed, considering the following:

- the average time per operation (ns/op),
- each verctor size increases in 33 bytes
- each vector size increases in 33 bytes
- Ecrecover is well tested

Benchmark results [here](../assets/eip-7619/benchmark_results.md)

Then the 100 BenchmarkPrecompiledFalcon512 results were approximated to a linear equation dependent on the number of bytes in each test vector. From the aproximation it was concluded that 1465 units of gas is the base requirement for any falcon-512 signature validation and 6 gas per word is additionally required.
Then the 100 BenchmarkPrecompiledFalcon512 results were approximated to a linear equation dependent on the number of bytes in each test vector. From the approximation it was concluded that 1465 units of gas is the base requirement for any falcon-512 signature validation and 6 gas per word is additionally required.

## Backwards Compatibility

Expand Down
2 changes: 2 additions & 0 deletions assets/eip-7619/pqclean-implementation/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
*.o
libfalcon-512_clean.a
22 changes: 22 additions & 0 deletions assets/eip-7619/pqclean-implementation/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Based on PQClean https://github.com/PQClean/PQClean/tree/master/crypto_sign/falcon-512/clean
# This Makefile can be used with GNU Make or BSD Make

LIB=libfalcon-512_clean.a

SOURCES = codec.c common.c fft.c fpr.c keygen.c pqclean.c rng.c sign.c verify-signature.c
OBJECTS = codec.o common.o fft.o fpr.o keygen.o pqclean.o rng.o sign.o verify-signature.o
HEADERS = api.h fpr.h inner.h

CFLAGS=-std=c99 -O2 -W -Wall -Wconversion -Wextra -Wpedantic -Wvla -Werror -Wmissing-prototypes -Wredundant-decls -I../../../common $(EXTRAFLAGS)

all: $(LIB)

%.o: %.c $(HEADERS)
$(CC) $(CFLAGS) -c -o $@ $<

$(LIB): $(OBJECTS)
$(AR) -r $@ $(OBJECTS)

clean:
$(RM) $(OBJECTS)
$(RM) $(LIB)
83 changes: 83 additions & 0 deletions assets/eip-7619/pqclean-implementation/api.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
// Based on PQClean https://github.com/PQClean/PQClean/tree/master/crypto_sign/falcon-512/clean
#ifndef PQCLEAN_FALCON512_CLEAN_API_H
#define PQCLEAN_FALCON512_CLEAN_API_H

#include <stddef.h>
#include <stdint.h>

#define PQCLEAN_FALCON512_CLEAN_CRYPTO_SECRETKEYBYTES 1281
#define PQCLEAN_FALCON512_CLEAN_CRYPTO_PUBLICKEYBYTES 897
#define PQCLEAN_FALCON512_CLEAN_CRYPTO_BYTES 752

#define PQCLEAN_FALCON512_CLEAN_CRYPTO_ALGNAME "Falcon-512"

#define PQCLEAN_FALCONPADDED512_CLEAN_CRYPTO_BYTES 666 // used in signature verification

/*
* Generate a new key pair. Public key goes into pk[], private key in sk[].
* Key sizes are exact (in bytes):
* public (pk): PQCLEAN_FALCON512_CLEAN_CRYPTO_PUBLICKEYBYTES
* private (sk): PQCLEAN_FALCON512_CLEAN_CRYPTO_SECRETKEYBYTES
*
* Return value: 0 on success, -1 on error.
*/
int PQCLEAN_FALCON512_CLEAN_crypto_sign_keypair(
uint8_t *pk, uint8_t *sk);

/*
* Compute a signature on a provided message (m, mlen), with a given
* private key (sk). Signature is written in sig[], with length written
* into *siglen. Signature length is variable; maximum signature length
* (in bytes) is PQCLEAN_FALCON512_CLEAN_CRYPTO_BYTES.
*
* sig[], m[] and sk[] may overlap each other arbitrarily.
*
* Return value: 0 on success, -1 on error.
*/
int PQCLEAN_FALCON512_CLEAN_crypto_sign_signature(
uint8_t *sig, size_t *siglen,
const uint8_t *m, size_t mlen, const uint8_t *sk);

/*
* Verify a signature (sig, siglen) on a message (m, mlen) with a given
* public key (pk).
*
* sig[], m[] and pk[] may overlap each other arbitrarily.
*
* Return value: 0 on success, -1 on error.
*/
int PQCLEAN_FALCON512_CLEAN_crypto_sign_verify(
const uint8_t *sig, size_t siglen,
const uint8_t *m, size_t mlen, const uint8_t *pk);

/*
* Compute a signature on a message and pack the signature and message
* into a single object, written into sm[]. The length of that output is
* written in *smlen; that length may be larger than the message length
* (mlen) by up to PQCLEAN_FALCON512_CLEAN_CRYPTO_BYTES.
*
* sm[] and m[] may overlap each other arbitrarily; however, sm[] shall
* not overlap with sk[].
*
* Return value: 0 on success, -1 on error.
*/
int PQCLEAN_FALCON512_CLEAN_crypto_sign(
uint8_t *sm, size_t *smlen,
const uint8_t *m, size_t mlen, const uint8_t *sk);

/*
* Open a signed message object (sm, smlen) and verify the signature;
* on success, the message itself is written into m[] and its length
* into *mlen. The message is shorter than the signed message object,
* but the size difference depends on the signature value; the difference
* may range up to PQCLEAN_FALCON512_CLEAN_CRYPTO_BYTES.
*
* m[], sm[] and pk[] may overlap each other arbitrarily.
*
* Return value: 0 on success, -1 on error.
*/
int PQCLEAN_FALCON512_CLEAN_crypto_sign_open(
uint8_t *m, size_t *mlen,
const uint8_t *sm, size_t smlen, const uint8_t *pk);

#endif
Loading

0 comments on commit bee79f3

Please sign in to comment.