Adding Javad's SIDH IQC implementation

This commit is contained in:
Shravan Mishra 2017-02-15 19:48:56 -05:00
parent 42d38a59f5
commit 6b6afa837f
36 changed files with 4018 additions and 8 deletions

View File

@ -18,6 +18,10 @@ if [[ ${ENABLE_NTRU} == 1 ]];then
enable_disable_str+=" --enable-ntru"
fi
if [[ ${ENABLE_SIDH_IQC_REF} == 1 ]];then
enable_disable_str+=" --enable-sidhiqc"
fi
./configure --enable-silent-rules ${enable_disable_str}
make clean
make

View File

@ -6,13 +6,14 @@ matrix:
include:
- os: linux
compiler: gcc
env: CC_OQS=gcc-4.8
env: CC_OQS=gcc-4.8 ENABLE_SIDH_IQC_REF=1
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- gcc-4.8
- libgmp-dev
before_install:
- sh .travis/install-clang-format-linux.sh
- os: linux
@ -52,9 +53,9 @@ matrix:
- bash download-and-build-ntru.sh
- os: osx
compiler: clang
env: CC_OQS=clang AES_NI=0 USE_OPENSSL=1 ENABLE_CODE_MCBITS=1 ENABLE_NTRU=1
before_install:
- brew install clang-format openssl libsodium
env: CC_OQS=clang AES_NI=0 USE_OPENSSL=1 ENABLE_CODE_MCBITS=1 ENABLE_NTRU=1 ENABLE_SIDH_IQC_REF=1
before_install:
- brew install clang-format openssl libsodium gmp
- bash download-and-build-ntru.sh
script:

View File

@ -30,6 +30,10 @@ liboqs_la_LIBADD += src/kex_ntru/libntru.la
liboqs_la_LIBADD += external/NTRUEncrypt-master/.libs/libntruencrypt.la
endif
if USE_SIDH_IQC
liboqs_la_LIBADD += src/kex_sidh_iqc_ref/libsidhiqc.la
endif
noinst_bin_PROGRAMS = test_rand test_kex test_aes
noinst_bindir=$(prefix)/tests
test_kex_LDADD = liboqs.la -lm
@ -42,6 +46,9 @@ endif
if USE_MCBITS
test_kex_LDADD += -lsodium
endif
if USE_SIDH_IQC
test_kex_LDADD += -lgmp
endif
test_aes_LDADD = liboqs.la -lm
test_aes_SOURCES = src/crypto/aes/test_aes.c
@ -101,6 +108,10 @@ endif
if USE_NTRU
$(LN_S) -f ../../src/kex_ntru/kex_ntru.h include/oqs
endif
if USE_SIDH_IQC
$(LN_S) -f ../../src/kex_sidh_iqc_ref/kex_sidh_iqc_ref.h include/oqs
$(LN_S) -f src/kex_sidh_iqc_ref/sample_params
endif
clean-local:
rm -f liboqs.a

View File

@ -69,14 +69,19 @@ ARG_ENABL_SET([ntru], [enable NTRU.])
AM_CONDITIONAL([ntru], [test "x$ntru" = xtrue])
AM_CONDITIONAL([USE_NTRU], [test "x$ntru" = xtrue])
ARG_ENABL_SET([sidhiqc], [enable SIDH-IQC.])
AM_CONDITIONAL([sidhiqc], [test "x$sidhiqc" = xtrue])
AM_CONDITIONAL([USE_SIDH_IQC], [test "x$sidhiqc" = xtrue])
AM_CPPFLAGS="-O3 -std=gnu11 -Wpedantic -Wall -Wextra -DCONSTANT_TIME"
AM_CPPFLAGS="-g -std=gnu11 -Wpedantic -Wall -Wextra -DCONSTANT_TIME"
AC_CANONICAL_HOST
# Check for which host we are on and setup a few things
# specifically based on the host
case $host_os in
darwin* )
OPENSSL_DIR=/usr/local/opt/openssl
GMP_DIR=/usr/local/opt/include
AM_CONDITIONAL([ON_DARWIN], [test xtrue = xtrue])
;;
linux*)
@ -92,7 +97,6 @@ case $host_os in
;;
esac
SRCDIR=" src/common src/crypto/aes src/kex src/crypto/rand src/crypto/sha3"
SRCDIR=${SRCDIR}" src/crypto/rand_urandom_aesctr src/crypto/rand_urandom_chacha20"
SRCDIR=${SRCDIR}" src/kex_rlwe_bcns15/"
@ -101,8 +105,6 @@ SRCDIR=${SRCDIR}" src/kex_lwe_frodo"
SRCDIR=${SRCDIR}" src/kex_rlwe_msrln16"
SRCDIR=${SRCDIR}" src/kex_sidh_cln16"
if test x"$ntru" = x"true"; then
AM_CPPFLAGS=${AM_CPPFLAGS}" -DENABLE_NTRU"
SRCDIR=${SRCDIR}" src/kex_ntru"
@ -121,6 +123,12 @@ if test x"$openssl" = x"true"; then
AM_CPPFLAGS=${AM_CPPFLAGS}" -DUSE_OPENSSL"
fi
if test x"$sidhiqc" = x"true"; then
AM_CPPFLAGS=${AM_CPPFLAGS}" -DENABLE_SIDH_IQC_REF"
SRCDIR=${SRCDIR}" src/kex_sidh_iqc_ref"
fi
AC_SUBST(AM_CPPFLAGS)
AC_SUBST(SRCDIR)
AC_SUBST(OPENSSL_DIR)
@ -128,7 +136,9 @@ AC_SUBST(USE_OPENSSL)
AC_SUBST(USE_AES_NI)
AC_SUBST(USE_NTRU)
AC_SUBST(USE_MCBITS)
AC_SUBST(USE_SIDH_IQC)
AC_SUBST(ON_DARWIN)
AC_SUBST(GMP_DIR)
AC_CONFIG_FILES([Makefile
@ -145,6 +155,7 @@ AC_CONFIG_FILES([Makefile
src/kex_sidh_cln16/Makefile
src/kex_code_mcbits/Makefile
src/kex_ntru/Makefile
src/kex_sidh_iqc_ref/Makefile
src/kex_lwe_frodo/Makefile])
AC_OUTPUT

View File

@ -14,6 +14,7 @@
#ifdef ENABLE_NTRU
#include <oqs/kex_ntru.h>
#endif
#include <oqs/kex_sidh_iqc_ref.h>
OQS_KEX *OQS_KEX_new(OQS_RAND *rand, enum OQS_KEX_alg_name alg_name, const uint8_t *seed, const size_t seed_len, const char *named_parameters) {
switch (alg_name) {
@ -43,6 +44,12 @@ OQS_KEX *OQS_KEX_new(OQS_RAND *rand, enum OQS_KEX_alg_name alg_name, const uint8
#else
assert(0);
#endif
case OQS_KEX_alg_sidh_iqc_ref:
#ifdef ENABLE_SIDH_IQC_REF
return OQS_KEX_sidh_iqc_ref_new(rand);
#else
assert(0);
#endif
default:
assert(0);

View File

@ -20,6 +20,7 @@ enum OQS_KEX_alg_name {
OQS_KEX_alg_sidh_cln16,
OQS_KEX_alg_code_mcbits,
OQS_KEX_alg_ntru,
OQS_KEX_alg_sidh_iqc_ref,
};
typedef struct OQS_KEX OQS_KEX;

View File

@ -25,6 +25,9 @@ struct kex_testcase kex_testcases[] = {
{OQS_KEX_alg_rlwe_msrln16, NULL, 0, NULL, "rlwe_msrln16", 0, 100},
{OQS_KEX_alg_lwe_frodo, (unsigned char *) "01234567890123456", 16, "recommended", "lwe_frodo_recommended", 0, 100},
{OQS_KEX_alg_sidh_cln16, NULL, 0, NULL, "sidh_cln16", 0, 10},
#ifdef ENABLE_SIDH_IQC_REF
{OQS_KEX_alg_sidh_iqc_ref, NULL, 0, NULL, "sidh_iqc_ref", 0, 10},
#endif
#ifdef ENABLE_CODE_MCBITS
{OQS_KEX_alg_code_mcbits, NULL, 0, NULL, "code_mcbits", 0, 25},
#endif

View File

@ -0,0 +1,10 @@
AUTOMAKE_OPTIONS = foreign
noinst_LTLIBRARIES = libsidhiqc.la
libsidhiqc_la_SOURCES = kex_sidh_iqc_ref.c sidh_elliptic_curve.c sidh_elliptic_curve_dlp.c sidh_isogeny.c
libsidhiqc_la_SOURCES += sidh_private_key.c sidh_public_key.c sidh_public_key_encryption.c sidh_public_key_validation.c
libsidhiqc_la_SOURCES += sidh_public_param.c sidh_quadratic_ext.c sidh_shared_key.c sidh_util.c
libsidhiqc_la_CPPFLAGS = -I../../include -I.-fPIC
libsidhiqc_la_CPPFLAGS += $(AM_CPPFLAGS) -I$(GMP_DIR)

View File

@ -0,0 +1,208 @@
#if defined(WINDOWS)
#define UNUSED
#else
#define UNUSED __attribute__((unused))
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "sidh_elliptic_curve.h"
#include "sidh_public_param.h"
#include "sidh_isogeny.h"
#include "sidh_private_key.h"
#include "sidh_public_key.h"
#include "sidh_shared_key.h"
#include "kex_sidh_iqc_ref.h"
OQS_KEX *OQS_KEX_sidh_iqc_ref_new(OQS_RAND *rand) {
OQS_KEX *k = malloc(sizeof(OQS_KEX));
if (k == NULL) {
return NULL;
}
// initialize
// char *input_params = "sample_params/public_params_771";
public_params_t *params =
(public_params_t *) malloc(2 * sizeof(public_params_t));
oqs_sidh_iqc_ref_public_params_init(params[0]);
oqs_sidh_iqc_ref_public_params_init(params[1]);
if (!oqs_sidh_iqc_ref_public_params_read(params[0], params[1], "sample_params/public_params_771"))
return NULL;
oqs_sidh_iqc_ref_fp_init_chararacteristic(params[0]->characteristic);
k->rand = rand;
k->method_name = strdup("SIDH IQC REFERENCE");
k->estimated_classical_security = 192;
k->estimated_quantum_security = 128;
k->seed = NULL;
k->seed_len = 0;
k->named_parameters = strdup("sample_params/public_params_771");
k->params = params;
k->ctx = NULL;
k->alice_0 = &OQS_KEX_sidh_iqc_ref_alice_0;
k->bob = &OQS_KEX_sidh_iqc_ref_bob;
k->alice_1 = &OQS_KEX_sidh_iqc_ref_alice_1;
k->alice_priv_free = &OQS_KEX_sidh_iqc_ref_alice_priv_free;
k->free = &OQS_KEX_sidh_iqc_ref_free;
return k;
}
int OQS_KEX_sidh_iqc_ref_alice_0(OQS_KEX *k, void **alice_priv,
uint8_t **alice_msg, size_t *alice_msg_len) {
public_params_t *params = (public_params_t *) k->params;
private_key_t Alice_private_key;
oqs_sidh_iqc_ref_private_key_init(Alice_private_key);
oqs_sidh_iqc_ref_private_key_generate(Alice_private_key, params[0]);
public_key_t Alice_public_key;
oqs_sidh_iqc_ref_public_key_init(Alice_public_key);
point_t kernel_gen;
oqs_sidh_iqc_ref_point_init(kernel_gen);
oqs_sidh_iqc_ref_private_key_compute_kernel_gen(kernel_gen, Alice_private_key,
params[0]->P, params[0]->Q,
params[0]->le, params[0]->E);
oqs_sidh_iqc_ref_public_key_generate(Alice_public_key, kernel_gen, params[0],
params[1]);
// sizes in bytes
uint32_t prime_size = (mpz_sizeinbase(characteristic, 2) + 7) / 8;
uint32_t private_key_size = 2 * prime_size;
uint32_t public_key_size = 12 * prime_size;
*alice_priv = NULL;
*alice_msg = NULL;
*alice_priv = malloc(private_key_size);
*alice_msg = malloc(public_key_size);
*alice_msg_len = public_key_size;
oqs_sidh_iqc_ref_private_key_to_bytes((uint8_t *) *alice_priv,
Alice_private_key, prime_size);
oqs_sidh_iqc_ref_public_key_to_bytes((uint8_t *) *alice_msg, Alice_public_key,
prime_size);
oqs_sidh_iqc_ref_private_key_clear(Alice_private_key);
oqs_sidh_iqc_ref_public_key_clear(Alice_public_key);
oqs_sidh_iqc_ref_point_clear(kernel_gen);
return 1;
}
int OQS_KEX_sidh_iqc_ref_bob(OQS_KEX *k, const uint8_t *alice_msg,
UNUSED const size_t alice_msg_len,
uint8_t **bob_msg, size_t *bob_msg_len,
uint8_t **key, size_t *key_len) {
public_params_t *params = (public_params_t *) k->params;
private_key_t Bob_private_key;
oqs_sidh_iqc_ref_private_key_init(Bob_private_key);
oqs_sidh_iqc_ref_private_key_generate(Bob_private_key, params[1]);
public_key_t Bob_public_key;
oqs_sidh_iqc_ref_public_key_init(Bob_public_key);
point_t kernel_gen;
oqs_sidh_iqc_ref_point_init(kernel_gen);
oqs_sidh_iqc_ref_private_key_compute_kernel_gen(kernel_gen, Bob_private_key,
params[1]->P, params[1]->Q,
params[1]->le, params[1]->E);
oqs_sidh_iqc_ref_public_key_generate(Bob_public_key, kernel_gen, params[1],
params[0]);
// sizes in bytes
uint32_t prime_size = (mpz_sizeinbase(characteristic, 2) + 7) / 8;
uint32_t public_key_size = 12 * prime_size;
uint32_t shared_key_size = 2 * prime_size;
*bob_msg = NULL;
*key = NULL;
*bob_msg = malloc(public_key_size);
*key = malloc(shared_key_size);
*bob_msg_len = public_key_size;
*key_len = shared_key_size;
oqs_sidh_iqc_ref_public_key_to_bytes((uint8_t *) *bob_msg, Bob_public_key,
prime_size);
public_key_t Alice_public_key;
oqs_sidh_iqc_ref_public_key_init(Alice_public_key);
oqs_sidh_iqc_ref_bytes_to_public_key(Alice_public_key, alice_msg, prime_size);
fp2_element_t Bob_shared_key;
oqs_sidh_iqc_ref_fp2_init(Bob_shared_key);
oqs_sidh_iqc_ref_shared_key_generate(Bob_shared_key, Alice_public_key,
Bob_private_key, params[1]);
oqs_sidh_iqc_ref_fp2_to_bytes((uint8_t *) *key, Bob_shared_key, prime_size);
oqs_sidh_iqc_ref_public_key_clear(Alice_public_key);
oqs_sidh_iqc_ref_private_key_clear(Bob_private_key);
oqs_sidh_iqc_ref_public_key_clear(Bob_public_key);
oqs_sidh_iqc_ref_point_clear(kernel_gen);
oqs_sidh_iqc_ref_fp2_clear(Bob_shared_key);
return 1;
}
int OQS_KEX_sidh_iqc_ref_alice_1(OQS_KEX *k, const void *alice_priv,
const uint8_t *bob_msg,
UNUSED const size_t bob_msg_len, uint8_t **key,
size_t *key_len) {
public_params_t *params = (public_params_t *) k->params;
// sizes in bytes
uint32_t prime_size = (mpz_sizeinbase(characteristic, 2) + 7) / 8;
uint32_t shared_key_size = 2 * prime_size;
*key = NULL;
*key_len = shared_key_size;
*key = malloc(shared_key_size);
private_key_t Alice_private_key;
oqs_sidh_iqc_ref_private_key_init(Alice_private_key);
oqs_sidh_iqc_ref_bytes_to_private_key(Alice_private_key, alice_priv,
prime_size);
public_key_t Bob_public_key;
oqs_sidh_iqc_ref_public_key_init(Bob_public_key);
oqs_sidh_iqc_ref_bytes_to_public_key(Bob_public_key, bob_msg, prime_size);
fp2_element_t Alice_shared_key;
oqs_sidh_iqc_ref_fp2_init(Alice_shared_key);
oqs_sidh_iqc_ref_shared_key_generate(Alice_shared_key, Bob_public_key,
Alice_private_key, params[0]);
oqs_sidh_iqc_ref_fp2_to_bytes((uint8_t *) *key, Alice_shared_key, prime_size);
oqs_sidh_iqc_ref_private_key_clear(Alice_private_key);
oqs_sidh_iqc_ref_public_key_clear(Bob_public_key);
oqs_sidh_iqc_ref_fp2_clear(Alice_shared_key);
return 1;
}
void OQS_KEX_sidh_iqc_ref_alice_priv_free(UNUSED OQS_KEX *k, void *alice_priv) {
if (alice_priv) {
free(alice_priv);
}
}
void OQS_KEX_sidh_iqc_ref_free(OQS_KEX *k) {
if (!k) {
return;
}
oqs_sidh_iqc_ref_public_params_clear(((public_params_t *) (k->params))[0]);
oqs_sidh_iqc_ref_public_params_clear(((public_params_t *) (k->params))[1]);
free(k->params);
k->ctx = NULL;
free(k->method_name);
k->method_name = NULL;
free(k);
}

View File

@ -0,0 +1,28 @@
#ifndef KEX_SIDH_IQC_REF_H
#define KEX_SIDH_IQC_REF_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stddef.h>
#include <stdint.h>
#include <oqs/kex.h>
#include <oqs/rand.h>
OQS_KEX *OQS_KEX_sidh_iqc_ref_new(OQS_RAND *rand);
int OQS_KEX_sidh_iqc_ref_alice_0(OQS_KEX *k, void **alice_priv, uint8_t **alice_msg, size_t *alice_msg_len);
int OQS_KEX_sidh_iqc_ref_bob(OQS_KEX *k, const uint8_t *alice_msg, const size_t alice_msg_len, uint8_t **bob_msg, size_t *bob_msg_len, uint8_t **key, size_t *key_len);
int OQS_KEX_sidh_iqc_ref_alice_1(OQS_KEX *k, const void *alice_priv, const uint8_t *bob_msg, const size_t bob_msg_len, uint8_t **key, size_t *key_len);
void OQS_KEX_sidh_iqc_ref_alice_priv_free(OQS_KEX *k, void *alice_priv);
void OQS_KEX_sidh_iqc_ref_free(OQS_KEX *k);
#ifdef __cplusplus
}
#endif
#endif /* KEX_SIDH_IQC_REF_H */

View File

@ -0,0 +1,10 @@
p : 13278338917780691403163453935679248163066204141424819568321422575495838416502783
E : y^2 = x^3 + (10146232096640085910917654383121220722483913358884738813297160334128811466415525*i+12561065565697579851239386918801659303795666601356542822684985096240783059294353)*x + (5173097881985929355869345579251684505584624561073144550698251610858120795396524*i+7107679418274528586696192790945059679329002947961173384005281572895084003568218)
lA: 2
eA: 130
PA: (1195124728519659060317276132092013999345554256425666367370465963951595701748339*i + 12098972036709468461769702810131237350914726908853501736574286596252384974205652, 9783772475920257416467468866150378267376245694752823265285613818169901942309758*i + 11347159712348451494564706572599934965946403356550033502368700150470499448870987)
QA: (13205817885805264818436305084890835188490919868599289846511015770901764583677253*i + 5747572646648472262100078852868099320898697620053049578554081522615552834142382, 11801682343040573989191884352262922625922977024975963745404870899756844108073781*i + 995065035530346107238957276796927946979246210950956147759509023538740100220494)
lB: 3
eB: 81
PB: (5344800255669587458309912385997503623935901519546261901204157001079956379346933*i + 4377688844822469620769951245537289173274736372423169606270308984109645753298367, 6652276474756696057821879367411351758786745790244544252917780253177388224676512*i + 6708409928090950067466623637647088247028372838873736207829979327577754417492323)
QB: (5394161621076087291764603321428338049084294313968048256313378341079709241759382*i + 11839282739753708776384780179031575074752559110018400195581350405443930573103478, 13250321748367194013481592159238890438519376028036613608154243555537109237538486*i + 5018156126061581597984382235576466750307112019427938373002833669914648135622879)

View File

@ -0,0 +1,10 @@
p : 60183678025727
E : y^2 = x^3 + (33377407586757 * i + 44218433491776) * x + (14267804413813 * i + 34113052821919)
lA: 2
eA: 22
PA: (3621292231555 * i + 37993208494088, 7444041801194 * i + 49342879615307)
QA: (42474562877393 * i + 53371276514445, 2096833973245 * i + 34935006825293)
lB: 3
eB: 15
PB: (15834791163149 * i + 48632673242917, 26787723276578 * i + 2080970701160)
QB: (41347477823487 * i + 16893996428645, 16353006256863 * i + 58871308637793)

View File

@ -0,0 +1,10 @@
p : 5646428529833603710854376801719732121889771686125102421349898409102848702003905102057129871853579459735758942656769724874115169484320460874488881525976727551
E : y^2 = x^3 + (749284552715987846148963973296050195126229569341142224654666772427960869882697237787535113296933915107646826510805251959952317725821624926383192023779227916*i+4450862168665197219135947325665108840719206715065697554561201799074300990784248608236935291171911258967881216685164820345027022153809546719817771293646383402)*x + (2090701186560231235295975659537182225064154823783034367876346818451609525370628921026656891712603865222854303410638520367213822274197422708317359681412801686*i+928331116130151780314451251635374082476545231185861659046556547242876069870814548070746611568992085667981514874929668958586384832118048434225604407758374282)
lA: 2
eA: 258
PA: (4099566244205693793351119863629118684504739011975746402268940060566068632610815266810397027797757094816929218567651253950072216325440815687610023993835084896*i + 1558017772998619899443036875935946235185689333987633624537644882488763783158554538347022310514300405167644627965823931934377803788161014061154800653636626931, 4309963503463625615680726988334053841208952164733703323705989592325431854359074218382917880219717866947948218257035199142577782828393068620191995480863080814*i + 371139087724151319343471759858355552237686119972572871121509307705868621618190178855645217401101942092226237837619601742237974591506374361483536984282167861)
QA: (1068668697541208179714192612921089347931894414290359842562082470165052062241629674686530102495737378212525479245784252461983051355518227298502808569246918728*i + 3439758296201500299118396242846510199830393172149382335887091564620130903972985332523718369650346601985540123834734249105539074407495456634862920938577617312, 1377114633894100174167466575056453645918713530999472681191914854993325497527119824352424425031078252594689770391880104513192317018010057467691025379460070671*i + 4932622986840321005380766859714312144000718130204073302754586852541324804616229501269099878044960212632820224170853684078869359092914886360672352750928115581)
lB: 3
eB: 161
PB: (1873601143875829767876930991819826178988629054425671567488176037109831662817961473686026144306947256312476316751547084289880741326649856082832561714610850944*i + 1560175318533519875886314144935322002014985257654221707041583923868859979591849198401249634353361077499233198751747045058302746944304448268907689086502178616, 4982994975025169124121736752171094366264972439763192439008272414941290947933013927951198144521578535758162978083130741822789277050594650669549067865269480720*i + 5276260709601376725929198456951440724276715138987805447686932240717621617089316893818094566900580557346731678327745302440662762271627385800896501795127323769)
QB: (697646709404910236660735870475422491121726200391885074740251760174191839071888445718446637282034941836922171390196797602747505117748596104805560163856490804*i + 3625576702015594834652275264908614642470435266304155762812699923280767886451566560460365242828862442624975825786369269113406701427398318872227046324990780609, 4066773540363717441440268891591433184568174886592697891244632377954091519594774358483000191238791345767299029423088482812653880802118173619454377886226640626*i + 4190003034380720563592676434553383980850520959077934081654167677748426947392920518786394581045699661017779519240551462796264093681413592624709890262004623150)

View File

@ -0,0 +1,11 @@
p : 9161191555982008052298538759697325872858383005444503030763917191888120427263653604739574602371851919945332710234806205297475768266460658683484318356498713773944703702864057467786913144364234277796785269800198817400814717913480036351
E : y^2 = x^3 + (834414288954992257633455994192711449929625512434805347027412475310171948875352369017186937444645005409828817983476510572586689796723205608064400704385270116308944492168385499542550868452776212626111499661118550170888024552876875729*i+6422246000772528873002015578224375300444670334298744905928223359513938843110113655634334268879522218663819121887750824098836054966064056104287198717041277477329053582144813207672147369924203318339728355843554541603191165928512397074)*x + (6952862402661321818296934608460489441319492072429008834217170925899505712694617760090534612163651714423387662001257443691685988562319647888954263195545834510820670121276853179853453135161349568882745925527747286264586000816122662211*i+1801461307959256058754493292728237821856779795303869606357346421878164668617118529630863155614277813374785952465141324739461376333648338471745996274618770379494305097783365807731152848487472399799827998470890201827624741461111844749)
lA: 2
eA: 386
PA: (8104593598414300086705087098908311675030394399959710332294184564762361863835814307651327024806690095568546280563692186849608460564606528773115207348687739021740029922619947714003573784888374548470687911506820492526985145356335776446*i + 632723349492681895135768435670357424582748082370711990704098097526814363254991414123449305576539513413267774301605548017161074510859073483979044361740779150098452314120335316096416597425252882878881588818896781804191220848731008911, 6034454472695438020325443031188950458345445112930585331722482288319997086142640364760979210290700670085317874428427766978327706213014073448960161802245001428613528860063394247112544226096847944993689243523414240839321526974724280084*i + 3376800547075148066131970733541260743185153743453912100162319249600572606491084521062090319658073231669236186390422247468127880255567740549554667385892315318084299520660699776774656198376921140804260118165199828142540405774846853362)
QA: (2765053530820933445180998871832795313413946616218824127593215418859013295660994609348273546952174346166291903038023352135058779784133949653750586420316372475215070348272866065120539728715859798970386824706592072979142529191135265323*i + 4732630024306258879927225136904171174931421517225731042645253305380470569884989406374249571295113204909266761424593068942210539695621294791558555039840356194123377363470161894673618251481432584334320864233790205509164494505329331140, 4708584843807409676003733183136845288008597122413250473476957203240325041335536376819164132204831789648003763063194049792870695914267484368767687682889171445457695974399304884657394666807097601382128550039198416659937221320896980595*i + 6104437072476030203734870744361913380396342850775889826642334399814339224961644051070388756974954400647041041004040997989961961816982978689836414675142946310418861822777207486737128660492374354598010889893873060781304652392500710082)
lB: 3
eB: 242
PB: (3723895349260758944309889666952259909100424286764560948312844268916772080039091215194337476636106420561414206591006321840112505108525982835492286766266110460566937541551059011352798312867785900902951383836578444811900436603779674156*i + 8743733696371247709279217014221258693400652288884395784267041686740452975091187425123471886102340505926375682973850553993788314479705338557349284829716634286210825839825870379330100097103593148671390855900137936801780665161878467993, 8424241650394632026078421716292833598872223719053431149109783663376931645995151278886785513466077121063748132909299925706619410172763350254899661370368971798311266097772796416940961537063436478392108549760549489321636110323643921123*i + 5374610701506876802640722880318277643810083668249556787469960695884056089879250039154916755196748541850985290281804798435130927222521567170894905772855374873224510597225929994186728464447646660504589278345473514974074045904197344273)
QB: (7981195513789185488304157075392399068225052449489399943063249773724560281912789833792310612686835775356813196319643714519912123781500389027567621573946130157326769787082613646934296091151487953874493791717298439146548339580934348575*i + 6959299245778867305112554827985507377113662771316265280990751282080086185858550157506531552361757479904416443825479048359163719118671413144273420888615839877660288012435298448942304481059091585291706567711227879486375625133765783910, 4336888647745442057861067196613721067586889048321014506728806821392030059558638097842307835657146159647787621123250859783441147632121339894258934458102109985684014691372520469809743302874968486912740925764328254939284436994206821845*i + 219245698132319235934495637714582743670714862281024333766283207034829039474459867538486706426384326703893620364910932534607493596118208826082598798090838576408297983032654112984263431060439529497966028364279027386883785406090014775)

View File

@ -0,0 +1,368 @@
/*
* Copyright (C) 2016 Javad Doliskani, javad.doliskani@uwaterloo.ca
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdlib.h>
#include "sidh_elliptic_curve.h"
#include "sidh_util.h"
#include <string.h>
void oqs_sidh_iqc_ref_elliptic_curve_init(elliptic_curve_t E) {
oqs_sidh_iqc_ref_fp2_init_set_si(E->a, 0, 1);
oqs_sidh_iqc_ref_fp2_init_set_si(E->b, 0, 1);
}
void oqs_sidh_iqc_ref_elliptic_curve_set(elliptic_curve_t E,
const elliptic_curve_t T) {
oqs_sidh_iqc_ref_fp2_set(E->a, T->a);
oqs_sidh_iqc_ref_fp2_set(E->b, T->b);
}
void oqs_sidh_iqc_ref_elliptic_curve_set_coeffs(elliptic_curve_t E,
const fp2_element_t a,
const fp2_element_t b) {
oqs_sidh_iqc_ref_fp2_set(E->a, a);
oqs_sidh_iqc_ref_fp2_set(E->b, b);
}
void oqs_sidh_iqc_ref_point_init(point_t P) {
oqs_sidh_iqc_ref_fp2_init(P->x);
oqs_sidh_iqc_ref_fp2_init(P->y);
oqs_sidh_iqc_ref_point_zero(P);
}
void oqs_sidh_iqc_ref_point_set_coordinates(point_t P,
const fp2_element_t x,
const fp2_element_t y,
int z) {
oqs_sidh_iqc_ref_fp2_set(P->x, x);
oqs_sidh_iqc_ref_fp2_set(P->y, y);
P->z = z;
}
void oqs_sidh_iqc_ref_point_set(point_t P,
const point_t Q) {
oqs_sidh_iqc_ref_point_set_coordinates(P, Q->x, Q->y, Q->z);
}
void oqs_sidh_iqc_ref_point_zero(point_t P) {
oqs_sidh_iqc_ref_fp2_zero(P->x);
oqs_sidh_iqc_ref_fp2_one(P->y);
P->z = 0;
}
int oqs_sidh_iqc_ref_point_is_zero(const point_t P) {
return P->z == 0;
}
void oqs_sidh_iqc_ref_point_negate(point_t P,
const point_t Q) {
oqs_sidh_iqc_ref_point_set(P, Q);
oqs_sidh_iqc_ref_fp2_negate(P->y, P->y);
}
int oqs_sidh_iqc_ref_point_has_order_2(const point_t P) {
return oqs_sidh_iqc_ref_fp2_is_zero(P->y);
}
void oqs_sidh_iqc_ref_elliptic_curve_clear(elliptic_curve_t E) {
oqs_sidh_iqc_ref_fp2_clear(E->a);
oqs_sidh_iqc_ref_fp2_clear(E->b);
}
void oqs_sidh_iqc_ref_point_clear(point_t P) {
oqs_sidh_iqc_ref_fp2_clear(P->x);
oqs_sidh_iqc_ref_fp2_clear(P->y);
}
int oqs_sidh_iqc_ref_point_equals(const point_t P,
const point_t Q) {
return oqs_sidh_iqc_ref_fp2_equals(P->x, Q->x) &&
oqs_sidh_iqc_ref_fp2_equals(P->y, Q->y) &&
(P->z == Q->z);
}
char *oqs_sidh_iqc_ref_elliptic_curve_get_str(const elliptic_curve_t E) {
char *result = "";
result = oqs_sidh_iqc_ref_concat(result, "y^2 = x^3");
if (!oqs_sidh_iqc_ref_fp2_is_zero(E->a)) {
result = oqs_sidh_iqc_ref_concat(result, " + (");
result = oqs_sidh_iqc_ref_concat(result, oqs_sidh_iqc_ref_fp2_get_str(E->a));
result = oqs_sidh_iqc_ref_concat(result, ")");
result = oqs_sidh_iqc_ref_concat(result, " * x");
}
if (!oqs_sidh_iqc_ref_fp2_is_zero(E->b)) {
result = oqs_sidh_iqc_ref_concat(result, " + (");
result = oqs_sidh_iqc_ref_concat(result, oqs_sidh_iqc_ref_fp2_get_str(E->b));
result = oqs_sidh_iqc_ref_concat(result, ")");
}
return result;
}
char *oqs_sidh_iqc_ref_point_get_str(const point_t P) {
char *result = "";
result = oqs_sidh_iqc_ref_concat(result, "(");
result = oqs_sidh_iqc_ref_concat(result, oqs_sidh_iqc_ref_fp2_get_str(P->x));
result = oqs_sidh_iqc_ref_concat(result, " : ");
result = oqs_sidh_iqc_ref_concat(result, oqs_sidh_iqc_ref_fp2_get_str(P->y));
result = oqs_sidh_iqc_ref_concat(result, " : ");
result = oqs_sidh_iqc_ref_concat(result, (P->z == 1 ? "1" : "0"));
result = oqs_sidh_iqc_ref_concat(result, ")");
return result;
}
void oqs_sidh_iqc_ref_point_add_with_lambda(point_t R,
const point_t P,
const point_t Q,
const fp2_element_t lambda) {
point_t result;
oqs_sidh_iqc_ref_point_init(result);
result->z = 1;
// x_R = lambda^2 - x_P - x_Q
oqs_sidh_iqc_ref_fp2_square(result->x, lambda);
oqs_sidh_iqc_ref_fp2_sub(result->x, result->x, P->x);
oqs_sidh_iqc_ref_fp2_sub(result->x, result->x, Q->x);
// y_R = lambda * (x_P - x_R) - y_P
oqs_sidh_iqc_ref_fp2_sub(result->y, P->x, result->x);
oqs_sidh_iqc_ref_fp2_mul(result->y, result->y, lambda);
oqs_sidh_iqc_ref_fp2_sub(result->y, result->y, P->y);
oqs_sidh_iqc_ref_point_set(R, result);
oqs_sidh_iqc_ref_point_clear(result);
}
void oqs_sidh_iqc_ref_point_double(point_t R,
const point_t P,
const elliptic_curve_t E) {
if (oqs_sidh_iqc_ref_point_is_zero(P)) {
oqs_sidh_iqc_ref_point_zero(R);
return;
}
// check if the point is of order 2
if (oqs_sidh_iqc_ref_point_has_order_2(P)) {
oqs_sidh_iqc_ref_point_zero(R);
return;
}
fp2_element_t temp;
fp2_element_t lambda;
oqs_sidh_iqc_ref_fp2_init(temp);
oqs_sidh_iqc_ref_fp2_init(lambda);
// lambda = (3(x_P)^2 + a) / (2y_p)
oqs_sidh_iqc_ref_fp2_square(lambda, P->x);
oqs_sidh_iqc_ref_fp2_mul_scaler_si(lambda, lambda, 3);
oqs_sidh_iqc_ref_fp2_add(lambda, lambda, E->a);
oqs_sidh_iqc_ref_fp2_mul_scaler_si(temp, P->y, 2);
oqs_sidh_iqc_ref_fp2_div(lambda, lambda, temp);
oqs_sidh_iqc_ref_point_add_with_lambda(R, P, P, lambda);
oqs_sidh_iqc_ref_fp2_clear(temp);
oqs_sidh_iqc_ref_fp2_clear(lambda);
}
void oqs_sidh_iqc_ref_point_add(point_t R,
const point_t P,
const point_t Q,
const elliptic_curve_t E) {
if (oqs_sidh_iqc_ref_point_is_zero(P)) {
oqs_sidh_iqc_ref_point_set(R, Q);
return;
}
if (oqs_sidh_iqc_ref_point_is_zero(Q)) {
oqs_sidh_iqc_ref_point_set(R, P);
return;
}
if (oqs_sidh_iqc_ref_fp2_equals(P->x, Q->x)) {
if (oqs_sidh_iqc_ref_fp2_equals(P->y, Q->y)) {
oqs_sidh_iqc_ref_point_double(R, P, E);
return;
}
oqs_sidh_iqc_ref_point_zero(R);
return;
}
fp2_element_t temp;
fp2_element_t lambda;
oqs_sidh_iqc_ref_fp2_init(temp);
oqs_sidh_iqc_ref_fp2_init(lambda);
// lambda = (y_Q - y_P) / (x_Q - x_P)
oqs_sidh_iqc_ref_fp2_sub(lambda, Q->y, P->y);
oqs_sidh_iqc_ref_fp2_sub(temp, Q->x, P->x);
oqs_sidh_iqc_ref_fp2_div(lambda, lambda, temp);
oqs_sidh_iqc_ref_point_add_with_lambda(R, P, Q, lambda);
oqs_sidh_iqc_ref_fp2_clear(temp);
oqs_sidh_iqc_ref_fp2_clear(lambda);
}
void oqs_sidh_iqc_ref_point_sub(point_t R,
const point_t P,
const point_t Q,
const elliptic_curve_t E) {
point_t temp;
oqs_sidh_iqc_ref_point_init(temp);
oqs_sidh_iqc_ref_point_negate(temp, Q);
oqs_sidh_iqc_ref_point_add(R, P, temp, E);
oqs_sidh_iqc_ref_point_clear(temp);
}
void oqs_sidh_iqc_ref_point_mul_scaler(point_t R,
const point_t P,
const mpz_t scaler,
const elliptic_curve_t E) {
if (mpz_cmp_ui(scaler, 0) == 0) {
oqs_sidh_iqc_ref_point_zero(R);
return;
}
if (mpz_cmp_ui(scaler, 1) == 0) {
oqs_sidh_iqc_ref_point_set(R, P);
return;
}
point_t R0;
point_t R1;
oqs_sidh_iqc_ref_point_init(R0);
oqs_sidh_iqc_ref_point_init(R1);
oqs_sidh_iqc_ref_point_set(R1, P);
long num_bits = mpz_sizeinbase(scaler, 2);
for (long i = 0; i < num_bits; i++) {
if (mpz_tstbit(scaler, i) == 1)
oqs_sidh_iqc_ref_point_add(R0, R0, R1, E);
oqs_sidh_iqc_ref_point_double(R1, R1, E);
}
if (mpz_sgn(scaler) < 0)
oqs_sidh_iqc_ref_point_negate(R0, R0);
oqs_sidh_iqc_ref_point_set(R, R0);
oqs_sidh_iqc_ref_point_clear(R0);
oqs_sidh_iqc_ref_point_clear(R1);
}
void oqs_sidh_iqc_ref_point_mul_scaler_si(point_t R,
const point_t P,
long scaler,
const elliptic_curve_t E) {
mpz_t temp;
mpz_init_set_si(temp, scaler);
oqs_sidh_iqc_ref_point_mul_scaler(R, P, temp, E);
mpz_clear(temp);
}
void oqs_sidh_iqc_ref_elliptic_curve_compute_j_inv(fp2_element_t j_inv,
const elliptic_curve_t E) {
fp2_element_t result;
fp2_element_t temp;
oqs_sidh_iqc_ref_fp2_init(result);
oqs_sidh_iqc_ref_fp2_init(temp);
oqs_sidh_iqc_ref_fp2_pow_ui(temp, E->a, 3);
oqs_sidh_iqc_ref_fp2_mul_scaler_si(temp, temp, 4);
oqs_sidh_iqc_ref_fp2_square(result, E->b);
oqs_sidh_iqc_ref_fp2_mul_scaler_si(result, result, 27);
oqs_sidh_iqc_ref_fp2_add(result, result, temp);
oqs_sidh_iqc_ref_fp2_inv(result, result);
oqs_sidh_iqc_ref_fp2_mul(result, result, temp);
oqs_sidh_iqc_ref_fp2_mul_scaler_si(result, result, 1728);
oqs_sidh_iqc_ref_fp2_set(j_inv, result);
oqs_sidh_iqc_ref_fp2_clear(result);
oqs_sidh_iqc_ref_fp2_clear(temp);
}
int oqs_sidh_iqc_ref_point_is_on_curve(const point_t P,
const elliptic_curve_t E) {
if (oqs_sidh_iqc_ref_point_is_zero(P))
return 1;
fp2_element_t temp_x;
oqs_sidh_iqc_ref_fp2_init(temp_x);
// compute x^3 + a * x + b = x * (x^2 + a) + b
oqs_sidh_iqc_ref_fp2_square(temp_x, P->x);
oqs_sidh_iqc_ref_fp2_add(temp_x, temp_x, E->a);
oqs_sidh_iqc_ref_fp2_mul(temp_x, temp_x, P->x);
oqs_sidh_iqc_ref_fp2_add(temp_x, temp_x, E->b);
fp2_element_t temp_y;
oqs_sidh_iqc_ref_fp2_init(temp_y);
oqs_sidh_iqc_ref_fp2_square(temp_y, P->y);
int result = oqs_sidh_iqc_ref_fp2_equals(temp_y, temp_x);
oqs_sidh_iqc_ref_fp2_clear(temp_x);
oqs_sidh_iqc_ref_fp2_clear(temp_y);
return result;
}
void oqs_sidh_iqc_ref_elliptic_curve_random_point(point_t P,
const elliptic_curve_t E) {
point_t result;
oqs_sidh_iqc_ref_point_init(result);
result->z = 1;
fp2_element_t temp_x;
oqs_sidh_iqc_ref_fp2_init(temp_x);
fp2_element_t temp_y;
oqs_sidh_iqc_ref_fp2_init(temp_y);
gmp_randstate_t randstate;
gmp_randinit_default(randstate);
while (1) {
oqs_sidh_iqc_ref_fp2_random(result->x, randstate);
// compute x^3 + a * x + b = x * (x^2 + a) + b
oqs_sidh_iqc_ref_fp2_square(temp_x, result->x);
oqs_sidh_iqc_ref_fp2_add(temp_x, temp_x, E->a);
oqs_sidh_iqc_ref_fp2_mul(temp_x, temp_x, result->x);
oqs_sidh_iqc_ref_fp2_add(temp_x, temp_x, E->b);
if (oqs_sidh_iqc_ref_fp2_is_square(temp_x)) {
oqs_sidh_iqc_ref_fp2_sqrt(result->y, temp_x);
break;
}
}
oqs_sidh_iqc_ref_point_set(P, result);
oqs_sidh_iqc_ref_point_clear(result);
oqs_sidh_iqc_ref_fp2_clear(temp_x);
oqs_sidh_iqc_ref_fp2_clear(temp_y);
gmp_randclear(randstate);
}

View File

@ -0,0 +1,259 @@
/*
* Copyright (C) 2016 Javad Doliskani, javad.doliskani@uwaterloo.ca
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef CURVE_H
#define CURVE_H
#include "sidh_quadratic_ext.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* Representation of the elliptic curve y^2 = x^3 + a * x^2 + b * x
*/
typedef struct {
fp2_element_t a;
fp2_element_t b;
} elliptic_curve_struct;
typedef elliptic_curve_struct elliptic_curve_t[1];
/**
* Representation of a point in the standard affine D+(z) of the
* plain projective projective space
*/
typedef struct {
fp2_element_t x;
fp2_element_t y;
int z;
} point_struct;
typedef point_struct point_t[1];
/**
* Initializes the input curve to y^2 = x^3 + x + 1.
* @param E
*/
void oqs_sidh_iqc_ref_elliptic_curve_init(elliptic_curve_t E);
/**
* Copies T into E
* @param E
* @param T
*/
void oqs_sidh_iqc_ref_elliptic_curve_set(elliptic_curve_t E,
const elliptic_curve_t T);
/**
* Sets the coefficients of E: y^2 = x^3 + a * x^2 + b * x.
* @param E
* @param a
* @param b
*/
void oqs_sidh_iqc_ref_elliptic_curve_set_coeffs(elliptic_curve_t E,
const fp2_element_t a,
const fp2_element_t b);
/**
* Initializes the point {@code P} to the zero point (0 : 1 : 0).
* @param P
*/
void oqs_sidh_iqc_ref_point_init(point_t P);
/**
* Sets the coordinates of the point {@code P}.
* @param P
* @param x
* @param y
* @param z
*/
void oqs_sidh_iqc_ref_point_set_coordinates(point_t P,
const fp2_element_t x,
const fp2_element_t y,
int z);
/**
* Copies {@code Q} into {@code P}
* @param P
* @param Q
*/
void oqs_sidh_iqc_ref_point_set(point_t P,
const point_t Q);
/**
* Sets the given point to zero.
* @param P
*/
void oqs_sidh_iqc_ref_point_zero(point_t P);
/**
* Checks if a given point is zero.
* @param P
* @return
*/
int oqs_sidh_iqc_ref_point_is_zero(const point_t P);
/**
* Sets {@code P} to {@code -Q} as a group element.
* @param P
* @param Q
*/
void oqs_sidh_iqc_ref_point_negate(point_t P,
const point_t Q);
/**
* Checks if 2 * {@code P} = 0.
* @param P
* @return
*/
int oqs_sidh_iqc_ref_point_has_order_2(const point_t P);
/**
* Frees the memory allocated to {@code E}.
* @param E
*/
void oqs_sidh_iqc_ref_elliptic_curve_clear(elliptic_curve_t E);
/**
* Frees the memory allocated to {@code P}.
* @param P
*/
void oqs_sidh_iqc_ref_point_clear(point_t P);
/**
* Checks if {@code P = Q}.
* @param P
* @param Q
* @return 1 if the points are equal, 0 otherwise
*/
int oqs_sidh_iqc_ref_point_equals(const point_t P,
const point_t Q);
/**
* @param E
* @return A string representation of {@code E}
*/
char *oqs_sidh_iqc_ref_elliptic_curve_get_str(const elliptic_curve_t E);
/**
* @param P
* @return A string representation of {@code P}
*/
char *oqs_sidh_iqc_ref_point_get_str(const point_t P);
/**
* Sets {@code R = P + Q} on {@code E}.
* @param R
* @param P
* @param Q
* @param E
*/
void oqs_sidh_iqc_ref_point_add(point_t R,
const point_t P,
const point_t Q,
const elliptic_curve_t E);
/**
* Sets {@code R = P - Q}.
* @param R
* @param P
* @param Q
* @param E
*/
void oqs_sidh_iqc_ref_point_sub(point_t R,
const point_t P,
const point_t Q,
const elliptic_curve_t E);
/**
* Sets {@code R = P + Q} on {@code E}.
* @param R
* @param P
* @param Q
* @param lambda The slope of the line passing through {@code P, Q}
*/
void oqs_sidh_iqc_ref_point_add_with_lambda(point_t R,
const point_t P,
const point_t Q,
const fp2_element_t lambda);
/**
* Sets {@code R = 2 * P} on {@code E}.
* @param R
* @param P
* @param E
*/
void oqs_sidh_iqc_ref_point_double(point_t R,
const point_t P,
const elliptic_curve_t E);
/**
* Sets {@code R = scaler * P} on {@code E}.
* @param R
* @param P
* @param scaler
* @param E
*/
void oqs_sidh_iqc_ref_point_mul_scaler(point_t R,
const point_t P,
const mpz_t scaler,
const elliptic_curve_t E);
/**
* {@link oqs_sidh_iqc_ref_point_mul_scaler}
* @param R
* @param P
* @param scaler
* @param E
*/
void oqs_sidh_iqc_ref_point_mul_scaler_si(point_t R,
const point_t P,
long scaler,
const elliptic_curve_t E);
/**
* Computes the j-invariant of {@code E}.
* @param j_inv
* @param E
*/
void oqs_sidh_iqc_ref_elliptic_curve_compute_j_inv(fp2_element_t j_inv,
const elliptic_curve_t E);
/**
* Checks if the point {@code P} is on the curve {@code E}.
* @param P
* @param E
* @return 1 if the point is on the curve, 0 otherwise
*/
int oqs_sidh_iqc_ref_point_is_on_curve(const point_t P,
const elliptic_curve_t E);
/**
* Generates a random point on the curve {@code E}.
* @param P the generated random point.
* @param E
*/
void oqs_sidh_iqc_ref_elliptic_curve_random_point(point_t P,
const elliptic_curve_t E);
#ifdef __cplusplus
}
#endif
#endif /* CURVE_H */

View File

@ -0,0 +1,114 @@
/*
* Copyright (C) 2016 Javad Doliskani, javad.doliskani@uwaterloo.ca
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "sidh_elliptic_curve_dlp.h"
#include <stdio.h>
void oqs_sidh_iqc_ref_elliptic_curve_prime_power_dlp(mpz_t x,
const point_t P,
const point_t Q,
const elliptic_curve_t E,
long l,
long e) {
mpz_t exponent1;
mpz_t exponent2;
point_t temp_P;
point_t temp_Q;
point_t temp_R;
point_t PP;
mpz_init(exponent1);
mpz_init(exponent2);
oqs_sidh_iqc_ref_point_init(temp_P);
oqs_sidh_iqc_ref_point_init(temp_Q);
oqs_sidh_iqc_ref_point_init(temp_R);
oqs_sidh_iqc_ref_point_init(PP);
int ladic_rep[e];
mpz_ui_pow_ui(exponent1, l, e - 1);
// PP = l^(e - 1) * P once and for all
oqs_sidh_iqc_ref_point_mul_scaler(PP, P, exponent1, E);
// compute the first ladic coefficient
oqs_sidh_iqc_ref_point_mul_scaler(temp_Q, Q, exponent1, E);
long ladic_coeff = oqs_sidh_iqc_ref_elliptic_curve_prime_dlp(PP, temp_Q, E, l);
for (int j = 1; j < e; j++) {
if (ladic_coeff >= 0) {
ladic_rep[j - 1] = ladic_coeff;
} else {
break;
}
mpz_ui_pow_ui(exponent2, l, j - 1);
mpz_mul_ui(exponent2, exponent2, ladic_rep[j - 1]);
mpz_divexact_ui(exponent1, exponent1, l);
oqs_sidh_iqc_ref_point_mul_scaler(temp_P, P, exponent2, E);
oqs_sidh_iqc_ref_point_add(temp_R, temp_R, temp_P, E);
oqs_sidh_iqc_ref_point_sub(temp_Q, Q, temp_R, E);
oqs_sidh_iqc_ref_point_mul_scaler(temp_Q, temp_Q, exponent1, E);
ladic_coeff = oqs_sidh_iqc_ref_elliptic_curve_prime_dlp(PP, temp_Q, E, l);
}
if (ladic_coeff >= 0) {
ladic_rep[e - 1] = ladic_coeff;
// set x = l_{e - 1}l^{e - 1} + ... + l_1l + l_0
mpz_set_ui(x, ladic_rep[e - 1]);
for (long i = e - 2; i >= 0; i--) {
mpz_mul_ui(x, x, l);
mpz_add_ui(x, x, ladic_rep[i]);
}
} else {
mpz_set_si(x, -1);
}
mpz_clear(exponent1);
mpz_clear(exponent2);
oqs_sidh_iqc_ref_point_clear(temp_P);
oqs_sidh_iqc_ref_point_clear(temp_Q);
oqs_sidh_iqc_ref_point_clear(temp_R);
oqs_sidh_iqc_ref_point_clear(PP);
}
long oqs_sidh_iqc_ref_elliptic_curve_prime_dlp(const point_t P,
const point_t Q,
const elliptic_curve_t E,
long l) {
if (oqs_sidh_iqc_ref_point_is_zero(Q))
return 0;
if (oqs_sidh_iqc_ref_point_equals(P, Q))
return 1;
point_t temp;
oqs_sidh_iqc_ref_point_init(temp);
oqs_sidh_iqc_ref_point_set(temp, P);
long result = -1;
for (long i = 2; i < l; i++) {
oqs_sidh_iqc_ref_point_add(temp, temp, P, E);
if (oqs_sidh_iqc_ref_point_equals(temp, Q)) {
result = i;
break;
}
}
oqs_sidh_iqc_ref_point_clear(temp);
return result;
}

View File

@ -0,0 +1,62 @@
/*
* Copyright (C) 2016 Javad Doliskani, javad.doliskani@uwaterloo.ca
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ELLIPTIC_CURVE_DLP_H
#define ELLIPTIC_CURVE_DLP_H
#include "sidh_elliptic_curve.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* Computes the discrete logarithm {@code P = x * Q} in a group of order
* {@code l^e} generated by {@code P}. The PohligHellman algorithm is used.
* @param x the discrete logarithm if it exists, or -1 otherwise
* @param P the generator of the cyclic group
* @param Q an element in the the group generated by {@code P}
* @param E
* @param l a prime number
* @param e a positive integer
*/
void oqs_sidh_iqc_ref_elliptic_curve_prime_power_dlp(mpz_t x,
const point_t P,
const point_t Q,
const elliptic_curve_t E,
long l,
long e);
/**
* Computes the discrete logarithm {@code P = x * Q} in a group of order
* {@code l} generated by {@code P}.
* @param P the generator of the cyclic group
* @param Q an element in the the group generated by {@code P}
* @param E
* @param l a prime number
* @return the discrete logarithm if it exists, or -1 otherwise
*/
long oqs_sidh_iqc_ref_elliptic_curve_prime_dlp(const point_t P,
const point_t Q,
const elliptic_curve_t E,
long l);
#ifdef __cplusplus
}
#endif
#endif /* ELLIPTIC_CURVE_DLP_H */

View File

@ -0,0 +1,487 @@
/*
* Copyright (C) 2016 Javad Doliskani, javad.doliskani@uwaterloo.ca
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdlib.h>
#include <stdio.h>
#include "sidh_isogeny.h"
#include <math.h>
void oqs_sidh_iqc_ref_isogeny_init(isogeny_t isogeny,
long kernel_size) {
isogeny->kernel_size = 0;
isogeny->partition_size = 0;
oqs_sidh_iqc_ref_isogeny_set_kernel_size(isogeny, kernel_size);
long size = isogeny->partition_size;
isogeny->partition = (point_t *) malloc(size * sizeof(point_t));
isogeny->gx = (fp2_element_t *) malloc(size * sizeof(fp2_element_t));
isogeny->gy = (fp2_element_t *) malloc(size * sizeof(fp2_element_t));
isogeny->u = (fp2_element_t *) malloc(size * sizeof(fp2_element_t));
isogeny->v = (fp2_element_t *) malloc(size * sizeof(fp2_element_t));
oqs_sidh_iqc_ref_elliptic_curve_init(isogeny->domain);
oqs_sidh_iqc_ref_elliptic_curve_init(isogeny->codomain);
for (long i = 0; i < size; i++) {
oqs_sidh_iqc_ref_point_init(isogeny->partition[i]);
oqs_sidh_iqc_ref_fp2_init(isogeny->gx[i]);
oqs_sidh_iqc_ref_fp2_init(isogeny->gy[i]);
oqs_sidh_iqc_ref_fp2_init(isogeny->u[i]);
oqs_sidh_iqc_ref_fp2_init(isogeny->v[i]);
}
}
void oqs_sidh_iqc_ref_isogeny_clear(isogeny_t isogeny) {
oqs_sidh_iqc_ref_elliptic_curve_clear(isogeny->domain);
oqs_sidh_iqc_ref_elliptic_curve_clear(isogeny->codomain);
for (long i = 0; i < isogeny->partition_size; i++) {
oqs_sidh_iqc_ref_point_clear(isogeny->partition[i]);
oqs_sidh_iqc_ref_fp2_clear(isogeny->gx[i]);
oqs_sidh_iqc_ref_fp2_clear(isogeny->gy[i]);
oqs_sidh_iqc_ref_fp2_clear(isogeny->u[i]);
oqs_sidh_iqc_ref_fp2_clear(isogeny->v[i]);
}
free(isogeny->partition);
free(isogeny->gx);
free(isogeny->gy);
free(isogeny->u);
free(isogeny->v);
}
void oqs_sidh_iqc_ref_isogeny_compute(isogeny_t isogeny,
const point_t kernel_gen) {
oqs_sidh_iqc_ref_isogeny_partition_kernel(isogeny->partition,
isogeny->partition_size,
kernel_gen,
isogeny->domain);
long size = isogeny->partition_size;
// compute gx_P = 3 * x_P^2 + a
for (long i = 0; i < size; i++) {
oqs_sidh_iqc_ref_fp2_square(isogeny->gx[i], isogeny->partition[i]->x);
oqs_sidh_iqc_ref_fp2_mul_scaler_si(isogeny->gx[i], isogeny->gx[i], 3);
oqs_sidh_iqc_ref_fp2_add(isogeny->gx[i], isogeny->gx[i], isogeny->domain->a);
}
// compute gy_P = -2y_P
for (long i = 0; i < size; i++) {
oqs_sidh_iqc_ref_fp2_mul_scaler_si(isogeny->gy[i], isogeny->partition[i]->y, -2);
}
// compute v_P = gx_P or 2gx_P
for (long i = 0; i < size; i++) {
if (oqs_sidh_iqc_ref_point_has_order_2(isogeny->partition[i]))
oqs_sidh_iqc_ref_fp2_set(isogeny->v[i], isogeny->gx[i]);
else
oqs_sidh_iqc_ref_fp2_mul_scaler_si(isogeny->v[i], isogeny->gx[i], 2);
}
// compute u_P = gy_P^2
for (long i = 0; i < size; i++) {
oqs_sidh_iqc_ref_fp2_square(isogeny->u[i], isogeny->gy[i]);
}
// compute the codomain curve
fp2_element_t v;
fp2_element_t w;
fp2_element_t temp;
oqs_sidh_iqc_ref_fp2_init(v);
oqs_sidh_iqc_ref_fp2_init(w);
oqs_sidh_iqc_ref_fp2_init(temp);
for (long i = 0; i < size; i++) {
oqs_sidh_iqc_ref_fp2_add(v, v, isogeny->v[i]);
oqs_sidh_iqc_ref_fp2_mul(temp, isogeny->v[i], isogeny->partition[i]->x);
oqs_sidh_iqc_ref_fp2_add(temp, isogeny->u[i], temp);
oqs_sidh_iqc_ref_fp2_add(w, w, temp);
}
oqs_sidh_iqc_ref_fp2_mul_scaler_si(v, v, 5);
oqs_sidh_iqc_ref_fp2_sub(v, isogeny->domain->a, v);
oqs_sidh_iqc_ref_fp2_mul_scaler_si(w, w, 7);
oqs_sidh_iqc_ref_fp2_sub(w, isogeny->domain->b, w);
oqs_sidh_iqc_ref_elliptic_curve_set_coeffs(isogeny->codomain, v, w);
oqs_sidh_iqc_ref_fp2_clear(v);
oqs_sidh_iqc_ref_fp2_clear(w);
oqs_sidh_iqc_ref_fp2_clear(temp);
}
void oqs_sidh_iqc_ref_isogeny_partition_kernel(point_t *partition,
long partition_size,
const point_t kernel_gen,
const elliptic_curve_t E) {
oqs_sidh_iqc_ref_point_set(partition[0], kernel_gen);
for (long i = 1; i < partition_size; i++) {
oqs_sidh_iqc_ref_point_add(partition[i], partition[i - 1], kernel_gen, E);
}
}
void oqs_sidh_iqc_ref_isogeny_set_kernel_size(isogeny_t isogeny,
long kernel_size) {
long current_size = isogeny->kernel_size;
if (current_size != 0 && current_size <= kernel_size)
return;
current_size = isogeny->partition_size;
isogeny->kernel_size = kernel_size;
if (kernel_size % 2 == 0)
isogeny->partition_size = kernel_size / 2;
else
isogeny->partition_size = (kernel_size - 1) / 2;
// clear the the unused memory after shrinking
for (long i = isogeny->partition_size; i < current_size; i++) {
oqs_sidh_iqc_ref_point_clear(isogeny->partition[i]);
oqs_sidh_iqc_ref_fp2_clear(isogeny->gx[i]);
oqs_sidh_iqc_ref_fp2_clear(isogeny->gy[i]);
oqs_sidh_iqc_ref_fp2_clear(isogeny->u[i]);
oqs_sidh_iqc_ref_fp2_clear(isogeny->v[i]);
}
}
void oqs_sidh_iqc_ref_isogeny_evaluate_velu(point_t Q,
const isogeny_t isogeny,
const point_t P) {
if (oqs_sidh_iqc_ref_point_is_zero(P)) {
oqs_sidh_iqc_ref_point_zero(Q);
return;
}
long size = isogeny->partition_size;
fp2_element_t temp1;
fp2_element_t temp2;
fp2_element_t temp3;
oqs_sidh_iqc_ref_fp2_init(temp1);
oqs_sidh_iqc_ref_fp2_init(temp2);
oqs_sidh_iqc_ref_fp2_init(temp3);
point_t result;
oqs_sidh_iqc_ref_point_init(result);
oqs_sidh_iqc_ref_point_set(result, P);
for (long i = 0; i < size; i++) {
oqs_sidh_iqc_ref_fp2_sub(temp1, P->x, isogeny->partition[i]->x);
// check if the point is in the kernel
if (oqs_sidh_iqc_ref_fp2_is_zero(temp1)) {
oqs_sidh_iqc_ref_point_zero(result);
break;
}
// 1 / (x - x_P)
oqs_sidh_iqc_ref_fp2_inv(temp1, temp1);
// add 1 / (x - x_P) * (v_P + u_P / (x - x_P)) to x
oqs_sidh_iqc_ref_fp2_mul(temp2, isogeny->u[i], temp1);
oqs_sidh_iqc_ref_fp2_add(temp2, temp2, isogeny->v[i]);
oqs_sidh_iqc_ref_fp2_mul(temp2, temp2, temp1);
oqs_sidh_iqc_ref_fp2_add(result->x, result->x, temp2);
// v_P * (y - y_P) - gx_P * gy_P
oqs_sidh_iqc_ref_fp2_sub(temp2, P->y, isogeny->partition[i]->y);
oqs_sidh_iqc_ref_fp2_mul(temp2, temp2, isogeny->v[i]);
oqs_sidh_iqc_ref_fp2_mul(temp3, isogeny->gx[i], isogeny->gy[i]);
oqs_sidh_iqc_ref_fp2_sub(temp2, temp2, temp3);
// 2 * u_P * y / (x - x_P)
oqs_sidh_iqc_ref_fp2_mul(temp3, isogeny->u[i], P->y);
oqs_sidh_iqc_ref_fp2_mul_scaler_si(temp3, temp3, 2);
oqs_sidh_iqc_ref_fp2_mul(temp3, temp3, temp1);
oqs_sidh_iqc_ref_fp2_add(temp3, temp3, temp2);
oqs_sidh_iqc_ref_fp2_square(temp1, temp1);
oqs_sidh_iqc_ref_fp2_mul(temp3, temp3, temp1);
oqs_sidh_iqc_ref_fp2_sub(result->y, result->y, temp3);
}
oqs_sidh_iqc_ref_point_set(Q, result);
oqs_sidh_iqc_ref_point_clear(result);
oqs_sidh_iqc_ref_fp2_clear(temp1);
oqs_sidh_iqc_ref_fp2_clear(temp2);
oqs_sidh_iqc_ref_fp2_clear(temp3);
}
void oqs_sidh_iqc_ref_isogeny_evaluate_kohel(point_t Q,
const isogeny_t isogeny,
const point_t P) {
fp2_element_t ix1;
fp2_element_t ix2;
fp2_element_t ix3;
fp2_element_t temp1;
fp2_element_t temp2;
fp2_element_t temp3;
fp2_element_t sigma1;
oqs_sidh_iqc_ref_fp2_init(ix1);
oqs_sidh_iqc_ref_fp2_init(ix2);
oqs_sidh_iqc_ref_fp2_init(ix3);
oqs_sidh_iqc_ref_fp2_init(temp1);
oqs_sidh_iqc_ref_fp2_init(temp2);
oqs_sidh_iqc_ref_fp2_init(temp3);
oqs_sidh_iqc_ref_fp2_init(sigma1);
point_t result;
oqs_sidh_iqc_ref_point_init(result);
oqs_sidh_iqc_ref_point_set(result, P);
long size = isogeny->partition_size;
for (long i = 0; i < size; i++) {
oqs_sidh_iqc_ref_fp2_add(sigma1, sigma1, isogeny->partition[i]->x);
oqs_sidh_iqc_ref_fp2_sub(temp1, P->x, isogeny->partition[i]->x);
// check if the point is in the kernel
if (oqs_sidh_iqc_ref_fp2_is_zero(temp1)) {
oqs_sidh_iqc_ref_point_zero(result);
break;
}
// 1 / (x - x_P)
oqs_sidh_iqc_ref_fp2_inv(temp1, temp1);
// 1 / (x - x_P)^2
oqs_sidh_iqc_ref_fp2_square(temp2, temp1);
// 1 / (x - x_P)^3
oqs_sidh_iqc_ref_fp2_mul(temp3, temp2, temp1);
if (!oqs_sidh_iqc_ref_point_has_order_2(isogeny->partition[i])) {
oqs_sidh_iqc_ref_fp2_add(temp1, temp1, temp1);
oqs_sidh_iqc_ref_fp2_add(temp2, temp2, temp2);
oqs_sidh_iqc_ref_fp2_add(temp3, temp3, temp3);
oqs_sidh_iqc_ref_fp2_add(sigma1, sigma1, isogeny->partition[i]->x);
}
oqs_sidh_iqc_ref_fp2_add(ix1, ix1, temp1);
oqs_sidh_iqc_ref_fp2_add(ix2, ix2, temp2);
oqs_sidh_iqc_ref_fp2_add(ix3, ix3, temp3);
}
if (!oqs_sidh_iqc_ref_point_is_zero(result)) {
fp2_element_t u1;
fp2_element_t u2;
oqs_sidh_iqc_ref_fp2_init(u1);
oqs_sidh_iqc_ref_fp2_init(u2);
// 3 * x^2 + a
oqs_sidh_iqc_ref_fp2_square(u1, P->x);
oqs_sidh_iqc_ref_fp2_mul_scaler_si(u1, u1, 3);
oqs_sidh_iqc_ref_fp2_add(u1, u1, isogeny->domain->a);
// 2 * y^2
oqs_sidh_iqc_ref_fp2_square(u2, P->y);
oqs_sidh_iqc_ref_fp2_mul_scaler_si(u2, u2, 2);
// compute the first coordinate
oqs_sidh_iqc_ref_fp2_mul_scaler_si(result->x, P->x, isogeny->kernel_size);
oqs_sidh_iqc_ref_fp2_sub(result->x, result->x, sigma1);
oqs_sidh_iqc_ref_fp2_mul(temp1, u1, ix1);
oqs_sidh_iqc_ref_fp2_sub(result->x, result->x, temp1);
oqs_sidh_iqc_ref_fp2_mul(temp1, u2, ix2);
oqs_sidh_iqc_ref_fp2_add(result->x, result->x, temp1);
// compute the second coordinate
oqs_sidh_iqc_ref_fp2_mul_scaler_si(temp1, P->x, -6);
oqs_sidh_iqc_ref_fp2_mul(result->y, temp1, ix1);
oqs_sidh_iqc_ref_fp2_add_ui(result->y, result->y, isogeny->kernel_size);
oqs_sidh_iqc_ref_fp2_mul_scaler_si(temp1, u1, 3);
oqs_sidh_iqc_ref_fp2_mul(temp1, temp1, ix2);
oqs_sidh_iqc_ref_fp2_add(result->y, result->y, temp1);
oqs_sidh_iqc_ref_fp2_mul_scaler_si(temp1, u2, -2);
oqs_sidh_iqc_ref_fp2_mul(temp1, temp1, ix3);
oqs_sidh_iqc_ref_fp2_add(result->y, result->y, temp1);
oqs_sidh_iqc_ref_fp2_mul(result->y, result->y, P->y);
oqs_sidh_iqc_ref_fp2_clear(u1);
oqs_sidh_iqc_ref_fp2_clear(u2);
}
oqs_sidh_iqc_ref_point_set(Q, result);
oqs_sidh_iqc_ref_point_clear(result);
oqs_sidh_iqc_ref_fp2_clear(ix1);
oqs_sidh_iqc_ref_fp2_clear(ix2);
oqs_sidh_iqc_ref_fp2_clear(ix3);
oqs_sidh_iqc_ref_fp2_clear(temp1);
oqs_sidh_iqc_ref_fp2_clear(temp2);
oqs_sidh_iqc_ref_fp2_clear(temp3);
oqs_sidh_iqc_ref_fp2_clear(sigma1);
}
void oqs_sidh_iqc_ref_isogeny_evaluate_naive(elliptic_curve_t E,
point_t *points,
long num_points,
const point_t kernel_gen,
long l,
long e,
long isogeny_jump) {
point_t temp_gen;
oqs_sidh_iqc_ref_point_init(temp_gen);
oqs_sidh_iqc_ref_point_set(temp_gen, kernel_gen);
mpz_t le;
mpz_init(le);
mpz_ui_pow_ui(le, l, e);
long kernel_size = 0;
if (e <= isogeny_jump)
kernel_size = mpz_get_si(le);
else
kernel_size = (long) pow(l, isogeny_jump);
isogeny_t isogeny;
oqs_sidh_iqc_ref_isogeny_init(isogeny, kernel_size);
oqs_sidh_iqc_ref_elliptic_curve_set(isogeny->domain, E);
long i = 0;
while (i < e) {
mpz_divexact_ui(le, le, kernel_size);
oqs_sidh_iqc_ref_isogeny_evaluate_naive_helper(isogeny,
E,
points,
num_points,
temp_gen,
le);
i += isogeny_jump;
if ((e - i > 0) && (e - i) < isogeny_jump) {
kernel_size = (long) pow(l, e - i);
oqs_sidh_iqc_ref_isogeny_set_kernel_size(isogeny, kernel_size);
}
}
oqs_sidh_iqc_ref_point_clear(temp_gen);
mpz_clear(le);
oqs_sidh_iqc_ref_isogeny_clear(isogeny);
}
void oqs_sidh_iqc_ref_isogeny_evaluate_naive_curve(elliptic_curve_t E,
const point_t kernel_gen,
long l,
long e,
long isogeny_jump) {
oqs_sidh_iqc_ref_isogeny_evaluate_naive(E, NULL, 0, kernel_gen, l, e, isogeny_jump);
}
void oqs_sidh_iqc_ref_isogeny_evaluate_naive_helper(isogeny_t isogeny,
elliptic_curve_t E,
point_t *points,
long num_points,
point_t kernel_gen,
const mpz_t le) {
point_t K;
oqs_sidh_iqc_ref_point_init(K);
oqs_sidh_iqc_ref_point_mul_scaler(K, kernel_gen, le, E);
oqs_sidh_iqc_ref_isogeny_compute(isogeny, K);
oqs_sidh_iqc_ref_isogeny_evaluate_kohel(kernel_gen, isogeny, kernel_gen);
for (long i = 0; i < num_points; i++) {
oqs_sidh_iqc_ref_isogeny_evaluate_kohel(points[i], isogeny, points[i]);
}
oqs_sidh_iqc_ref_elliptic_curve_set(E, isogeny->codomain);
oqs_sidh_iqc_ref_elliptic_curve_set(isogeny->domain, isogeny->codomain);
oqs_sidh_iqc_ref_point_clear(K);
}
void oqs_sidh_iqc_ref_isogeny_evaluate_strategy_rec(elliptic_curve_t E,
point_t *points,
long num_points,
point_t *kernel_gens,
long num_gens,
long l,
long e,
float ratio) {
if (e == 1) {
isogeny_t isogeny;
long kernel_size = (long) pow(l, e);
oqs_sidh_iqc_ref_isogeny_init(isogeny, kernel_size);
oqs_sidh_iqc_ref_elliptic_curve_set(isogeny->domain, E);
oqs_sidh_iqc_ref_isogeny_compute(isogeny, kernel_gens[num_gens - 1]);
oqs_sidh_iqc_ref_elliptic_curve_set(E, isogeny->codomain);
for (long i = 0; i < num_points; i++) {
oqs_sidh_iqc_ref_isogeny_evaluate_velu(points[i], isogeny, points[i]);
}
for (long i = 0; i < num_gens - 1; i++) {
oqs_sidh_iqc_ref_isogeny_evaluate_velu(kernel_gens[i],
isogeny,
kernel_gens[i]);
}
oqs_sidh_iqc_ref_isogeny_clear(isogeny);
return;
}
long r = (long) (ratio * e);
mpz_t exponent;
mpz_init(exponent);
mpz_ui_pow_ui(exponent, l, r);
oqs_sidh_iqc_ref_point_mul_scaler(kernel_gens[num_gens],
kernel_gens[num_gens - 1],
exponent, E);
oqs_sidh_iqc_ref_isogeny_evaluate_strategy_rec(E, points, num_points, kernel_gens,
num_gens + 1, l, e - r, ratio);
oqs_sidh_iqc_ref_isogeny_evaluate_strategy_rec(E, points, num_points, kernel_gens,
num_gens, l, r, ratio);
mpz_clear(exponent);
}
void oqs_sidh_iqc_ref_isogeny_evaluate_strategy(elliptic_curve_t E,
point_t *points,
long num_points,
const point_t kernel_gen,
long l,
long e,
float ratio) {
point_t *kernel_gens = (point_t *) malloc(e * sizeof(point_t));
for (long i = 0; i < e; i++)
oqs_sidh_iqc_ref_point_init(kernel_gens[i]);
oqs_sidh_iqc_ref_point_set(kernel_gens[0], kernel_gen);
oqs_sidh_iqc_ref_isogeny_evaluate_strategy_rec(E, points, num_points,
kernel_gens, 1, l, e, ratio);
for (long i = 0; i < e; i++)
oqs_sidh_iqc_ref_point_clear(kernel_gens[i]);
free(kernel_gens);
}
void oqs_sidh_iqc_ref_isogeny_evaluate_strategy_curve(elliptic_curve_t E,
const point_t kernel_gen,
long l,
long e,
float ratio) {
oqs_sidh_iqc_ref_isogeny_evaluate_strategy(E, NULL, 0, kernel_gen, l, e, ratio);
}

View File

@ -0,0 +1,232 @@
/*
* Copyright (C) 2016 Javad Doliskani, javad.doliskani@uwaterloo.ca
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ISOGENY_H
#define ISOGENY_H
#include "sidh_elliptic_curve.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* Representation of an isogeny between two elliptic curve
*/
typedef struct {
// Let the kernel K of the isogeny (excluding the zero point) be the union
// of F and G such that R \in F if and only if -R \in G for all points
// R \in K. Then the partition is F.
point_t *partition;
fp2_element_t *gx;
fp2_element_t *gy;
fp2_element_t *u;
fp2_element_t *v;
elliptic_curve_t domain;
elliptic_curve_t codomain;
long partition_size;
long kernel_size;
} isogeny_struct;
typedef isogeny_struct isogeny_t[1];
/**
* Initializes the isogeny {@code isogeny}.
* @param isogeny
* @param kernel_size
*/
void oqs_sidh_iqc_ref_isogeny_init(isogeny_t isogeny,
long kernel_size);
/**
* Frees the memory allocated to {@code isogeny}.
* @param isogeny
*/
void oqs_sidh_iqc_ref_isogeny_clear(isogeny_t isogeny);
/**
* Computes the isogeny from the kernel generated by {@code kernel_gen}.
* @param isogeny
* @param kernel_gen
*/
void oqs_sidh_iqc_ref_isogeny_compute(isogeny_t isogeny,
const point_t kernel_gen);
/**
* Evaluates {@code isogeny} at the point {@code P}, using Velu's formulas.
* @param Q The result of the evaluation {@code isogeny(P)}
* @param isogeny
* @param P
*/
void oqs_sidh_iqc_ref_isogeny_evaluate_velu(point_t Q,
const isogeny_t isogeny,
const point_t P);
/**
* Evaluates {@code isogeny} at the point {@code P}, using Kohel's formulas.
* @param Q The result of the evaluation {@code isogeny(P)}
* @param isogeny
* @param P
*/
void oqs_sidh_iqc_ref_isogeny_evaluate_kohel(point_t Q,
const isogeny_t isogeny,
const point_t P);
/**
* Computes the partition for the isogeny generated by {@code kernel_gen}.
* @see isogeny_struct.
* @param partition
* @param partition_size
* @param kernel_gen
* @param E
*/
void oqs_sidh_iqc_ref_isogeny_partition_kernel(point_t *partition,
long partition_size,
const point_t kernel_gen,
const elliptic_curve_t E);
/**
* Sets the kernel size for {@code isogeny}. The new kernel size is assumed
* to be smaller than the current kernel size.
* @param isogeny
* @param kernel_size
*/
void oqs_sidh_iqc_ref_isogeny_set_kernel_size(isogeny_t isogeny,
long kernel_size);
/**
* Computes the images of the elliptic curve {@code E} and the points
* {@code points} through the isogeny with kernel generated by the point
* {@code kernel_gen}. The size of the kernel is {@code l^e}.
* @param E
* @param points
* @param num_points
* @param kernel_gen
* @param l
* @param e the length of the chain of l-isogenies
* @param isogeny_jump the number of successive l-isogenies that should
* be computed at once. For example, if {@code isogeny_jump = 2} then a
* chain of l-isogenies of length e is computed by doing e / 2 {l^2-isogenies}.
*/
void oqs_sidh_iqc_ref_isogeny_evaluate_naive(elliptic_curve_t E,
point_t *points,
long num_points,
const point_t kernel_gen,
long l,
long e,
long isogeny_jump);
/**
* Computes the images of the elliptic curve {@code E} through the isogeny
* with kernel generated by the point {@code kernel_gen}.
* {@link oqs_sidh_iqc_ref_isogeny_evaluate_naive}
* @param E
* @param kernel_gen
* @param l
* @param e
* @param isogeny_jump
*/
void oqs_sidh_iqc_ref_isogeny_evaluate_naive_curve(elliptic_curve_t E,
const point_t kernel_gen,
long l,
long e,
long isogeny_jump);
/**
* A helper method for {@link oqs_sidh_iqc_ref_isogeny_evaluate_naive}. All the arguments except
* {@code num_points, le} will be pushed through the isogeny. For example
* {@code E} will be the codomain of the isogeny. This method should not be
* called directly.
* @param isogeny
* @param E
* @param points
* @param num_points
* @param kernel_gen
* @param le
*/
void oqs_sidh_iqc_ref_isogeny_evaluate_naive_helper(isogeny_t isogeny,
elliptic_curve_t E,
point_t *points,
long num_points,
point_t kernel_gen,
const mpz_t le);
/**
* The recursion for {@link oqs_sidh_iqc_ref_isogeny_evaluate_strategy}.
* @param E
* @param points see {@link oqs_sidh_iqc_ref_isogeny_evaluate_strategy}
* @param num_points see {@link oqs_sidh_iqc_ref_isogeny_evaluate_strategy}
* @param kernel_gens contains the previous kernels computed while going down
* the recursion tree.
* @param num_gens number of elements in {@code kernel_gens}
* @param l
* @param e
* @param ratio see {@link oqs_sidh_iqc_ref_isogeny_evaluate_strategy}
*/
void oqs_sidh_iqc_ref_isogeny_evaluate_strategy_rec(elliptic_curve_t E,
point_t *points,
long num_points,
point_t *kernel_gens,
long num_gens,
long l,
long e,
float ratio);
/**
* This method implements the optimal strategy approach proposed in the paper
* De Feo, Luca, David Jao, and Jérôme Plût. "Towards quantum-resistant
* cryptosystems from supersingular elliptic curve isogenies".
* @param E
* @param points the points to be evaluated through the isogeny
* @param num_points number of points in {@code points}
* @param kernel_gen the generator of the kernel of the isogeny
* @param l
* @param e
* @param ratio a float in the range (0, 1). This indicates the portions of
* the computation that is done through point multiplication and isogeny
* evaluation. The larger values of {@code ratio} means more multiplication
* and less isogeny evaluation.
*/
void oqs_sidh_iqc_ref_isogeny_evaluate_strategy(elliptic_curve_t E,
point_t *points,
long num_points,
const point_t kernel_gen,
long l,
long e,
float ratio);
/**
* The same as {@link oqs_sidh_iqc_ref_isogeny_evaluate_strategy} except there is no point
* to evaluate through the isogeny. This method simply calls
* {@link oqs_sidh_iqc_ref_isogeny_evaluate_strategy} with {@code points = NULL, num_points = 0}.
* @param E
* @param kernel_gen
* @param l
* @param e
* @param ratio
*/
void oqs_sidh_iqc_ref_isogeny_evaluate_strategy_curve(elliptic_curve_t E,
const point_t kernel_gen,
long l,
long e,
float ratio);
#ifdef __cplusplus
}
#endif
#endif /* ISOGENY_H */

View File

@ -0,0 +1,102 @@
/*
* Copyright (C) 2016 Javad Doliskani, javad.doliskani@uwaterloo.ca
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "sidh_private_key.h"
#include "sidh_util.h"
#include "sidh_public_param.h"
#include <stdio.h>
void oqs_sidh_iqc_ref_private_key_init(private_key_t private_key) {
mpz_inits(private_key->m, private_key->n, NULL);
}
void oqs_sidh_iqc_ref_private_key_clear(private_key_t private_key) {
mpz_clears(private_key->m, private_key->n, NULL);
}
void oqs_sidh_iqc_ref_private_key_generate(private_key_t private_key,
const public_params_t params) {
gmp_randstate_t randstate;
gmp_randinit_default(randstate);
mpz_t seed;
mpz_init(seed);
oqs_sidh_iqc_ref_get_random_mpz(seed);
gmp_randseed(randstate, seed);
while (1) {
mpz_urandomm(private_key->m, randstate, params->le);
mpz_urandomm(private_key->n, randstate, params->le);
if (!mpz_divisible_ui_p(private_key->m, params->l))
break;
if (!mpz_divisible_ui_p(private_key->n, params->l)) {
mpz_swap(private_key->m, private_key->n);
break;
}
}
gmp_randclear(randstate);
mpz_clear(seed);
}
void oqs_sidh_iqc_ref_private_key_compute_kernel_gen(
point_t gen, const private_key_t private_key, const point_t P,
const point_t Q, const mpz_t le, const elliptic_curve_t E) {
mpz_t temp_m;
mpz_t temp_n;
mpz_init_set(temp_m, private_key->m);
mpz_init_set(temp_n, private_key->n);
point_t result;
oqs_sidh_iqc_ref_point_init(result);
mpz_invert(temp_m, temp_m, le);
mpz_mul(temp_n, temp_m, temp_n);
mpz_mod(temp_n, temp_n, le);
oqs_sidh_iqc_ref_point_mul_scaler(result, Q, temp_n, E);
oqs_sidh_iqc_ref_point_add(result, result, P, E);
oqs_sidh_iqc_ref_point_set(gen, result);
mpz_clears(temp_m, temp_n, NULL);
oqs_sidh_iqc_ref_point_clear(result);
}
void oqs_sidh_iqc_ref_private_key_print(const private_key_t private_key) {
printf("m: %s\n", mpz_get_str(NULL, 10, private_key->m));
printf("n: %s\n", mpz_get_str(NULL, 10, private_key->n));
}
void oqs_sidh_iqc_ref_private_key_to_bytes(uint8_t *bytes,
const private_key_t private_key,
long prime_size) {
for (long i = 0; i < 2 * prime_size; i++)
bytes[i] = 0;
mpz_export(bytes, NULL, -1, 1, 0, 0, private_key->m);
mpz_export(bytes + prime_size, NULL, -1, 1, 0, 0, private_key->n);
}
void oqs_sidh_iqc_ref_bytes_to_private_key(private_key_t private_key,
const uint8_t *bytes,
long prime_size) {
mpz_set_ui(private_key->m, 0);
mpz_set_ui(private_key->n, 0);
mpz_import(private_key->m, prime_size, -1, 1, 0, 0, bytes);
mpz_import(private_key->n, prime_size, -1, 1, 0, 0, bytes + prime_size);
}

View File

@ -0,0 +1,106 @@
/*
* Copyright (C) 2016 Javad Doliskani, javad.doliskani@uwaterloo.ca
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PRIVATE_KEY_H
#define PRIVATE_KEY_H
#include "sidh_elliptic_curve.h"
#include "sidh_public_param.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* Representation of the private key in oqs_sidh_iqc_ref
*/
typedef struct {
mpz_t m;
mpz_t n;
} private_key_struct;
typedef private_key_struct private_key_t[1];
/**
* Initializes the private-key.
* @param private_key
*/
void oqs_sidh_iqc_ref_private_key_init(private_key_t private_key);
/**
* Frees the memory allocated to the private-key.
* @param private_key
*/
void oqs_sidh_iqc_ref_private_key_clear(private_key_t private_key);
/**
* Generates the private-key. It is guaranteed that {@code private_key->m}
* is comprime to {@code params->l}.
* @param private_key
* @param params
*/
void oqs_sidh_iqc_ref_private_key_generate(private_key_t private_key,
const public_params_t params);
/**
* Computes a generator for th kernel generated by {@code gen = m * P + n * Q}.
* It is assumed that {@code m} is invertible modulo {@code le}.
* @param gen
* @param P one of the generators of the l^e torsion.
* @param Q one of the generators of the l^e torsion.
* @param private_key
* @param le
* @param E
*/
void oqs_sidh_iqc_ref_private_key_compute_kernel_gen(point_t gen,
const private_key_t private_key,
const point_t P,
const point_t Q,
const mpz_t le,
const elliptic_curve_t E);
/**
* Converts a private-key to an array of bytes.
* @param bytes
* @param private_key
* @param prime_size
*/
void oqs_sidh_iqc_ref_private_key_to_bytes(uint8_t *bytes,
const private_key_t private_key,
long prime_size);
/**
* Converts an array of bytes to a private-key.
* @param private_key
* @param bytes
* @param prime_size
*/
void oqs_sidh_iqc_ref_bytes_to_private_key(private_key_t private_key,
const uint8_t *bytes,
long prime_size);
/**
* Prints {@code private_key} to the standard output.
* @param private_key
*/
void oqs_sidh_iqc_ref_private_key_print(const private_key_t private_key);
#ifdef __cplusplus
}
#endif
#endif /* PRIVATE_KEY_H */

View File

@ -0,0 +1,113 @@
/*
* Copyright (C) 2016 Javad Doliskani, javad.doliskani@uwaterloo.ca
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "sidh_public_key.h"
#include "sidh_isogeny.h"
#include "sidh_private_key.h"
#include <stdio.h>
#include <math.h>
void oqs_sidh_iqc_ref_public_key_init(public_key_t public_key) {
oqs_sidh_iqc_ref_elliptic_curve_init(public_key->E);
oqs_sidh_iqc_ref_point_init(public_key->P);
oqs_sidh_iqc_ref_point_init(public_key->Q);
}
void oqs_sidh_iqc_ref_public_key_clear(public_key_t public_key) {
oqs_sidh_iqc_ref_elliptic_curve_clear(public_key->E);
oqs_sidh_iqc_ref_point_clear(public_key->P);
oqs_sidh_iqc_ref_point_clear(public_key->Q);
}
void oqs_sidh_iqc_ref_public_key_generate(public_key_t public_key,
const point_t kernel_gen,
const public_params_t paramsA,
const public_params_t paramsB) {
point_t points[2];
oqs_sidh_iqc_ref_point_init(points[0]);
oqs_sidh_iqc_ref_point_init(points[1]);
oqs_sidh_iqc_ref_elliptic_curve_set(public_key->E, paramsA->E);
oqs_sidh_iqc_ref_point_set(points[0], paramsB->P);
oqs_sidh_iqc_ref_point_set(points[1], paramsB->Q);
oqs_sidh_iqc_ref_isogeny_evaluate_strategy(public_key->E,
points,
2,
kernel_gen,
paramsA->l,
paramsA->e,
0.5);
// oqs_sidh_iqc_ref_isogeny_evaluate_naive(public_key->E,
// points,
// 2,
// kernel_gen,
// paramsA->l,
// paramsA->e,
// 10);
oqs_sidh_iqc_ref_point_set(public_key->P, points[0]);
oqs_sidh_iqc_ref_point_set(public_key->Q, points[1]);
oqs_sidh_iqc_ref_point_clear(points[0]);
oqs_sidh_iqc_ref_point_clear(points[1]);
}
void oqs_sidh_iqc_ref_public_key_print(const public_key_t public_key) {
printf("E: %s\n", oqs_sidh_iqc_ref_elliptic_curve_get_str(public_key->E));
printf("P: %s\n", oqs_sidh_iqc_ref_point_get_str(public_key->P));
printf("Q: %s\n", oqs_sidh_iqc_ref_point_get_str(public_key->Q));
}
void oqs_sidh_iqc_ref_public_key_to_bytes(uint8_t *bytes,
const public_key_t public_key,
long prime_size) {
long index = 0;
oqs_sidh_iqc_ref_fp2_to_bytes(bytes + index, public_key->E->a, prime_size);
index += 2 * prime_size;
oqs_sidh_iqc_ref_fp2_to_bytes(bytes + index, public_key->E->b, prime_size);
index += 2 * prime_size;
oqs_sidh_iqc_ref_fp2_to_bytes(bytes + index, public_key->P->x, prime_size);
index += 2 * prime_size;
oqs_sidh_iqc_ref_fp2_to_bytes(bytes + index, public_key->P->y, prime_size);
index += 2 * prime_size;
oqs_sidh_iqc_ref_fp2_to_bytes(bytes + index, public_key->Q->x, prime_size);
index += 2 * prime_size;
oqs_sidh_iqc_ref_fp2_to_bytes(bytes + index, public_key->Q->y, prime_size);
}
void oqs_sidh_iqc_ref_bytes_to_public_key(public_key_t public_key,
const uint8_t *bytes,
long prime_size) {
long index = 0;
oqs_sidh_iqc_ref_bytes_to_fp2(public_key->E->a, bytes + index, prime_size);
index += 2 * prime_size;
oqs_sidh_iqc_ref_bytes_to_fp2(public_key->E->b, bytes + index, prime_size);
index += 2 * prime_size;
oqs_sidh_iqc_ref_bytes_to_fp2(public_key->P->x, bytes + index, prime_size);
index += 2 * prime_size;
oqs_sidh_iqc_ref_bytes_to_fp2(public_key->P->y, bytes + index, prime_size);
index += 2 * prime_size;
oqs_sidh_iqc_ref_bytes_to_fp2(public_key->Q->x, bytes + index, prime_size);
index += 2 * prime_size;
oqs_sidh_iqc_ref_bytes_to_fp2(public_key->Q->y, bytes + index, prime_size);
public_key->P->z = 1;
public_key->Q->z = 1;
}

View File

@ -0,0 +1,94 @@
/*
* Copyright (C) 2016 Javad Doliskani, javad.doliskani@uwaterloo.ca
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PUBLIC_KEY_H
#define PUBLIC_KEY_H
#include "sidh_public_param.h"
#include "sidh_private_key.h"
#include "sidh_isogeny.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* Representation of the public key in oqs_sidh_iqc_ref
*/
typedef struct {
elliptic_curve_t E;
point_t P;
point_t Q;
} public_key_struct;
typedef public_key_struct public_key_t[1];
/**
* Initializes the public-key.
* @param public_key
*/
void oqs_sidh_iqc_ref_public_key_init(public_key_t public_key);
/**
* Frees the memory allocated to the public-key.
* @param public_key
*/
void oqs_sidh_iqc_ref_public_key_clear(public_key_t public_key);
/**
* Generates the public-key
* @param public_key
* @param kernel_gen a generator for the kernel of the isogeny
* @param paramsA own params
* @param paramsB other's params
*/
void oqs_sidh_iqc_ref_public_key_generate(public_key_t public_key,
const point_t kernel_gen,
const public_params_t paramsA,
const public_params_t paramsB);
/**
* Prints {@code public_key} to the standard output.
* @param public_key
*/
void oqs_sidh_iqc_ref_public_key_print(const public_key_t public_key);
/**
* Converts a public-key to a byte array.
* @param bytes
* @param public_key
* @param prime_size
*/
void oqs_sidh_iqc_ref_public_key_to_bytes(uint8_t *bytes,
const public_key_t public_key,
long prime_size);
/**
* Converts a byte array to a public-key.
* @param public_key
* @param bytes
* @param prime_size
*/
void oqs_sidh_iqc_ref_bytes_to_public_key(public_key_t public_key,
const uint8_t *bytes,
long prime_size);
#ifdef __cplusplus
}
#endif
#endif /* PUBLIC_KEY_H */

View File

@ -0,0 +1,158 @@
/*
* Copyright (C) 2016 Javad Doliskani, javad.doliskani@uwaterloo.ca
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "sidh_public_key_encryption.h"
#include "sidh_public_key.h"
#include "sidh_util.h"
#include "sidh_shared_key.h"
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
void oqs_sidh_iqc_ref_public_key_ciphertext_init(ciphertext_t ciphertext) {
oqs_sidh_iqc_ref_elliptic_curve_init(ciphertext->E);
oqs_sidh_iqc_ref_point_init(ciphertext->P);
oqs_sidh_iqc_ref_point_init(ciphertext->Q);
ciphertext->size = 0;
}
void oqs_sidh_iqc_ref_public_key_ciphertext_clear(ciphertext_t ciphertext) {
oqs_sidh_iqc_ref_elliptic_curve_clear(ciphertext->E);
oqs_sidh_iqc_ref_point_clear(ciphertext->P);
oqs_sidh_iqc_ref_point_clear(ciphertext->Q);
free(ciphertext->content);
ciphertext->size = 0;
}
void oqs_sidh_iqc_ref_public_key_plaintext_init(plaintext_t plaintext) {
plaintext->size = 0;
}
void oqs_sidh_iqc_ref_public_key_plaintext_clear(plaintext_t plaintext) {
plaintext->size = 0;
}
int oqs_sidh_iqc_ref_public_key_pad_plaintext(plaintext_t result,
const plaintext_t raw) {
long key_size = public_key_get_key_size();
long max_msg_size = key_size - 1;
if (raw->size > key_size) {
printf("\nMessage too large. It should be less than %ld bytes.\n",
max_msg_size);
return -1;
}
// pad the message
char *new_content = (char *) malloc(max_msg_size);
memset(new_content, 0, max_msg_size);
memcpy(new_content, raw->content, raw->size);
result->content = new_content;
result->size = max_msg_size;
return 1;
}
void oqs_sidh_iqc_ref_public_key_encrypt(ciphertext_t ciphertext,
const plaintext_t plaintext,
const public_key_t public_keyA,
const public_params_t paramsA,
const public_params_t paramsB) {
private_key_t private_key_temp;
oqs_sidh_iqc_ref_private_key_init(private_key_temp);
oqs_sidh_iqc_ref_private_key_generate(private_key_temp, paramsB);
point_t kernel_gen;
oqs_sidh_iqc_ref_point_init(kernel_gen);
oqs_sidh_iqc_ref_private_key_compute_kernel_gen(kernel_gen,
private_key_temp,
paramsB->P,
paramsB->Q,
paramsB->le,
paramsB->E);
public_key_t public_key_temp;
oqs_sidh_iqc_ref_public_key_init(public_key_temp);
oqs_sidh_iqc_ref_public_key_generate(public_key_temp, kernel_gen, paramsB, paramsA);
fp2_element_t shared_key;
oqs_sidh_iqc_ref_fp2_init(shared_key);
oqs_sidh_iqc_ref_shared_key_generate(shared_key, public_keyA, private_key_temp, paramsB);
char *hash = oqs_sidh_iqc_ref_public_key_encryption_hash(shared_key, plaintext->size);
ciphertext->content = oqs_sidh_iqc_ref_array_xor(plaintext->content,
hash, plaintext->size);
ciphertext->size = plaintext->size;
oqs_sidh_iqc_ref_elliptic_curve_set(ciphertext->E, public_key_temp->E);
oqs_sidh_iqc_ref_point_set(ciphertext->P, public_key_temp->P);
oqs_sidh_iqc_ref_point_set(ciphertext->Q, public_key_temp->Q);
oqs_sidh_iqc_ref_private_key_clear(private_key_temp);
oqs_sidh_iqc_ref_point_clear(kernel_gen);
oqs_sidh_iqc_ref_public_key_clear(public_key_temp);
oqs_sidh_iqc_ref_fp2_clear(shared_key);
free(hash);
}
void oqs_sidh_iqc_ref_public_key_decrypt(plaintext_t plaintext,
const ciphertext_t ciphertext,
const private_key_t private_keyA,
const public_params_t paramsA) {
public_key_t public_key_temp;
oqs_sidh_iqc_ref_public_key_init(public_key_temp);
oqs_sidh_iqc_ref_elliptic_curve_set(public_key_temp->E, ciphertext->E);
oqs_sidh_iqc_ref_point_set(public_key_temp->P, ciphertext->P);
oqs_sidh_iqc_ref_point_set(public_key_temp->Q, ciphertext->Q);
fp2_element_t shared_key;
oqs_sidh_iqc_ref_fp2_init(shared_key);
oqs_sidh_iqc_ref_shared_key_generate(shared_key, public_key_temp, private_keyA, paramsA);
char *hash = oqs_sidh_iqc_ref_public_key_encryption_hash(shared_key, ciphertext->size);
plaintext->content = oqs_sidh_iqc_ref_array_xor(ciphertext->content, hash,
ciphertext->size);
plaintext->size = ciphertext->size;
oqs_sidh_iqc_ref_public_key_clear(public_key_temp);
oqs_sidh_iqc_ref_fp2_clear(shared_key);
free(hash);
}
const mp_limb_t *mpz_limbs_read(const mpz_t x);
char *oqs_sidh_iqc_ref_public_key_encryption_hash(const fp2_element_t value,
long size) {
// compute the size of value in chars
long size_a = labs(mpz_size(value->a)) * sizeof(mp_limb_t);
long size_b = labs(mpz_size(value->b)) * sizeof(mp_limb_t);
char *hash = (char *) malloc(size);
memcpy(hash, (char *) mpz_limbs_read(value->a), size_a);
memcpy(hash + size_a, (char *) mpz_limbs_read(value->b), size_b);
return hash;
}
long public_key_get_key_size() {
// the key size is twice as large as the base prime.
long key_size = 2 * labs(mpz_size(characteristic)) * sizeof(mp_limb_t);
return key_size;
}

View File

@ -0,0 +1,132 @@
/*
* Copyright (C) 2016 Javad Doliskani, javad.doliskani@uwaterloo.ca
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PUBLIC_KEY_ENCRYPTION_H
#define PUBLIC_KEY_ENCRYPTION_H
#include "sidh_elliptic_curve.h"
#include "sidh_public_key.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* Representation of ciphertext in oqs_sidh_iqc_ref
*/
typedef struct {
elliptic_curve_t E;
point_t P;
point_t Q;
char *content;
// size of the content field
long size;
} ciphertext_struct;
/**
* Representation of plaintext in oqs_sidh_iqc_ref
*/
typedef struct {
char *content;
// size of the content field
long size;
} plaintext_struct;
typedef ciphertext_struct ciphertext_t[1];
typedef plaintext_struct plaintext_t[1];
/**
* Initializes the ciphertext.
* @param ciphertext
*/
void oqs_sidh_iqc_ref_public_key_ciphertext_init(ciphertext_t ciphertext);
/**
* Frees the memory allocated to {@code ciphertext}.
* @param ciphertext
*/
void oqs_sidh_iqc_ref_public_key_ciphertext_clear(ciphertext_t ciphertext);
/**
* Initializes the plaintext.
* @param plaintext
*/
void oqs_sidh_iqc_ref_public_key_plaintext_init(plaintext_t plaintext);
/**
* Frees the memory allocated to {@code plaintext}.
* @param plaintext
*/
void oqs_sidh_iqc_ref_public_key_plaintext_clear(plaintext_t plaintext);
/**
* Pads a given plain text for encryption.
* @param result the prepared plaintext
* @param raw the given plaintext
* @return 1 if successful, and -1 otherwise
*/
int oqs_sidh_iqc_ref_public_key_pad_plaintext(plaintext_t result,
const plaintext_t raw);
/**
* Encrypts the {@code plaintext} using {@code public_key}.
* @param ciphertext the generated cipher
* @param plaintext
* @param public_keyA other's public-key
* @param paramsA other's public params
* @param paramsB own pubic params
*/
void oqs_sidh_iqc_ref_public_key_encrypt(ciphertext_t ciphertext,
const plaintext_t plaintext,
const public_key_t public_keyA,
const public_params_t paramsA,
const public_params_t paramsB);
/**
* Decrypts the {@code ciphertext} using {@code private_key}.
* @param plaintext the result
* @param ciphertext the given ciphertext
* @param private_keyA
* @param paramsA the public parameters associated to the owner of
* the private-key
*/
void oqs_sidh_iqc_ref_public_key_decrypt(plaintext_t plaintext,
const ciphertext_t ciphertext,
const private_key_t private_keyA,
const public_params_t paramsA);
/**
* Computes the hash of {@code value}
* @param value
* @param size size of the output hash
* @return the hash
*/
char *oqs_sidh_iqc_ref_public_key_encryption_hash(const fp2_element_t value,
long size);
/**
* @return the key-size in bytes
*/
long public_key_get_key_size();
#ifdef __cplusplus
}
#endif
#endif /* PUBLIC_KEY_ENCRYPTION_H */

View File

@ -0,0 +1,106 @@
/*
* Copyright (C) 2016 Javad Doliskani, javad.doliskani@uwaterloo.ca
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "sidh_public_key_validation.h"
#include "sidh_elliptic_curve_dlp.h"
#include <stdio.h>
int oqs_sidh_iqc_ref_public_key_is_valid(const public_key_t public_key,
const public_params_t params) {
if (!oqs_sidh_iqc_ref_public_key_check_order(public_key->P, public_key->E, params))
return 0;
if (!oqs_sidh_iqc_ref_public_key_check_order(public_key->Q, public_key->E, params))
return 0;
if (!oqs_sidh_iqc_ref_public_key_check_dependency(public_key, params))
return 0;
if (!oqs_sidh_iqc_ref_public_key_check_curve(public_key->E))
return 0;
return 1;
}
int oqs_sidh_iqc_ref_public_key_check_order(const point_t P,
const elliptic_curve_t E,
const public_params_t params) {
mpz_t order;
point_t temp;
mpz_init_set(order, params->le);
oqs_sidh_iqc_ref_point_init(temp);
int result = 0;
mpz_divexact_ui(order, order, params->l);
oqs_sidh_iqc_ref_point_mul_scaler(temp, P, order, E);
if (!oqs_sidh_iqc_ref_point_is_zero(temp)) {
oqs_sidh_iqc_ref_point_mul_scaler_si(temp, temp, params->l, E);
if (oqs_sidh_iqc_ref_point_is_zero(temp))
result = 1;
}
mpz_clear(order);
oqs_sidh_iqc_ref_point_clear(temp);
return result;
}
int oqs_sidh_iqc_ref_public_key_check_dependency(const public_key_t public_key,
const public_params_t params) {
mpz_t x;
mpz_init(x);
int result = 0;
oqs_sidh_iqc_ref_elliptic_curve_prime_power_dlp(x,
public_key->P,
public_key->Q,
public_key->E,
params->l,
params->e);
if (mpz_cmp_si(x, -1) == 0) {
oqs_sidh_iqc_ref_elliptic_curve_prime_power_dlp(x,
public_key->Q,
public_key->P,
public_key->E,
params->l,
params->e);
if (mpz_cmp_si(x, -1) == 0)
result = 1;
}
mpz_clear(x);
return result;
}
int oqs_sidh_iqc_ref_public_key_check_curve(const elliptic_curve_t E) {
point_t temp;
mpz_t exponent;
oqs_sidh_iqc_ref_point_init(temp);
mpz_init_set(exponent, characteristic);
mpz_add_ui(exponent, exponent, 1);
oqs_sidh_iqc_ref_elliptic_curve_random_point(temp, E);
oqs_sidh_iqc_ref_point_mul_scaler(temp, temp, exponent, E);
int result = oqs_sidh_iqc_ref_point_is_zero(temp);
oqs_sidh_iqc_ref_point_clear(temp);
mpz_clear(exponent);
return result;
}

View File

@ -0,0 +1,72 @@
/*
* Copyright (C) 2016 Javad Doliskani, javad.doliskani@uwaterloo.ca
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PUBLIC_KEY_VALIDATION_H
#define PUBLIC_KEY_VALIDATION_H
#include "sidh_elliptic_curve.h"
#include "sidh_public_key.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* Check if a given public-key is valid.
* @param public_key
* @param params the other party's public parameters from which
* the public-key is generated.
* @return 1 if the public-key is valid, 0 otherwise
*/
int oqs_sidh_iqc_ref_public_key_is_valid(const public_key_t public_key,
const public_params_t params);
/**
* Checks if {@code P} has the exact order l^e where l, e are given in
* {@code params}.
* @param P
* @param E
* @param params
* @return 1 if {@code P} has order l^e, 0 otherwise
*/
int oqs_sidh_iqc_ref_public_key_check_order(const point_t P,
const elliptic_curve_t E,
const public_params_t params);
/**
* Checks if the two point in {@code public-key} are linearly independent.
* @param public_key
* @param params
* @return 1 if the points are linearly independent, 0 otherwise
*/
int oqs_sidh_iqc_ref_public_key_check_dependency(const public_key_t public_key,
const public_params_t params);
/**
* Checks if a given is valid supersingular curve. A curve is considered
* valid if it has order (p + 1)^2 where p is the characteristic. The test
* is done probabilistically.
* @param E
* @return 1 if the curve is valid, 0 otherwise.
*/
int oqs_sidh_iqc_ref_public_key_check_curve(const elliptic_curve_t E);
#ifdef __cplusplus
}
#endif
#endif /* PUBLIC_KEY_VALIDATION_H */

View File

@ -0,0 +1,100 @@
/*
* Copyright (C) 2016 Javad Doliskani, javad.doliskani@uwaterloo.ca
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include "sidh_public_param.h"
void oqs_sidh_iqc_ref_public_params_init(public_params_t params) {
mpz_init(params->characteristic);
oqs_sidh_iqc_ref_elliptic_curve_init(params->E);
oqs_sidh_iqc_ref_point_init(params->P);
oqs_sidh_iqc_ref_point_init(params->Q);
mpz_init(params->le);
}
int oqs_sidh_iqc_ref_public_params_read(public_params_t paramsA,
public_params_t paramsB,
const char *file_name) {
FILE *input;
input = fopen(file_name, "r");
if (!input) {
printf("No such file!\n");
return 0;
}
fp2_element_t a;
fp2_element_t b;
oqs_sidh_iqc_ref_fp2_init(a);
oqs_sidh_iqc_ref_fp2_init(b);
gmp_fscanf(input, "p : %Zd \n", paramsA->characteristic);
mpz_set(paramsB->characteristic, paramsA->characteristic);
gmp_fscanf(input,
"E : y^2 = x^3 + (%Zd * i + %Zd) * x + (%Zd * i + %Zd) \n",
a->a, a->b, b->a, b->b);
oqs_sidh_iqc_ref_elliptic_curve_set_coeffs(paramsA->E, a, b);
oqs_sidh_iqc_ref_elliptic_curve_set(paramsB->E, paramsA->E);
gmp_fscanf(input, "lA: %ld \n", &paramsA->l);
gmp_fscanf(input, "eA: %ld \n", &paramsA->e);
mpz_ui_pow_ui(paramsA->le, paramsA->l, paramsA->e);
gmp_fscanf(input,
"PA: (%Zd * i + %Zd, %Zd * i + %Zd) \n",
a->a, a->b, b->a, b->b);
oqs_sidh_iqc_ref_point_set_coordinates(paramsA->P, a, b, 1);
gmp_fscanf(input,
"QA: (%Zd * i + %Zd, %Zd * i + %Zd) \n",
a->a, a->b, b->a, b->b);
oqs_sidh_iqc_ref_point_set_coordinates(paramsA->Q, a, b, 1);
gmp_fscanf(input, "lB: %ld \n", &paramsB->l);
gmp_fscanf(input, "eB: %ld \n", &paramsB->e);
mpz_ui_pow_ui(paramsB->le, paramsB->l, paramsB->e);
gmp_fscanf(input,
"PB: (%Zd * i + %Zd, %Zd * i + %Zd) \n",
a->a, a->b, b->a, b->b);
oqs_sidh_iqc_ref_point_set_coordinates(paramsB->P, a, b, 1);
gmp_fscanf(input,
"QB: (%Zd * i + %Zd, %Zd * i + %Zd) \n",
a->a, a->b, b->a, b->b);
oqs_sidh_iqc_ref_point_set_coordinates(paramsB->Q, a, b, 1);
fclose(input);
oqs_sidh_iqc_ref_fp2_clear(a);
oqs_sidh_iqc_ref_fp2_clear(b);
return 1;
}
void oqs_sidh_iqc_ref_public_params_print(const public_params_t params,
int print_torsion) {
if (print_torsion != 1) {
printf("p : %s\n", mpz_get_str(NULL, 10, params->characteristic));
printf("E : %s\n", oqs_sidh_iqc_ref_elliptic_curve_get_str(params->E));
}
printf("lA: %ld\n", params->l);
printf("eA: %ld\n", params->e);
printf("PA: %s\n", oqs_sidh_iqc_ref_point_get_str(params->P));
printf("QA: %s\n", oqs_sidh_iqc_ref_point_get_str(params->Q));
}
void oqs_sidh_iqc_ref_public_params_clear(public_params_t params) {
mpz_clear(params->characteristic);
oqs_sidh_iqc_ref_elliptic_curve_clear(params->E);
oqs_sidh_iqc_ref_point_clear(params->P);
oqs_sidh_iqc_ref_point_clear(params->Q);
mpz_clear(params->le);
}

View File

@ -0,0 +1,85 @@
/*
* Copyright (C) 2016 Javad Doliskani, javad.doliskani@uwaterloo.ca
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PUBLIC_PARAM_H
#define PUBLIC_PARAM_H
#include "sidh_elliptic_curve.h"
#include "sidh_quadratic_ext.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* Representation of the public parameters in oqs_sidh_iqc_ref
*/
typedef struct {
// the characteristic
mpz_t characteristic;
elliptic_curve_t E;
unsigned long l;
unsigned long e;
// a generator for the l^e torsion subgroup of E
point_t P;
point_t Q;
// l^e, precomputed
mpz_t le;
} public_params_struct;
typedef public_params_struct public_params_t[1];
/**
* Initializes the public parameters.
* @param params
*/
void oqs_sidh_iqc_ref_public_params_init(public_params_t params);
/**
* Reads the public parameters from file named {@code file_name}.
* @param paramsA
* @param paramsB
* @param file_name
* @return 1 if the parameters are read successfully, and 0 otherwise.
*/
int oqs_sidh_iqc_ref_public_params_read(public_params_t paramsA,
public_params_t paramsB,
const char *file_name);
/**
* Prints the public parameters to the standard output.
* @param params
* @param torsion if it is 1 only the torsion parameters are printed
*/
void oqs_sidh_iqc_ref_public_params_print(const public_params_t params,
int print_torsion);
/**
* Frees the memory allocated to {@code params}.
* @param params
*/
void oqs_sidh_iqc_ref_public_params_clear(public_params_t params);
#ifdef __cplusplus
}
#endif
#endif /* PUBLIC_PARAM_H */

View File

@ -0,0 +1,443 @@
/*
* Copyright (C) 2016 Javad Doliskani, javad.doliskani@uwaterloo.ca
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "sidh_quadratic_ext.h"
#include "sidh_util.h"
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
void oqs_sidh_iqc_ref_fp_init_chararacteristic_ui(long p) {
mpz_init_set_ui(characteristic, p);
}
void oqs_sidh_iqc_ref_fp_init_chararacteristic_str(const char *value) {
mpz_init_set_str(characteristic, value, 10);
}
void oqs_sidh_iqc_ref_fp_init_chararacteristic(const mpz_t p) {
mpz_init_set(characteristic, p);
}
void oqs_sidh_iqc_ref_fp_set(mpz_t x, const mpz_t a) {
mpz_mod(x, a, characteristic);
}
void oqs_sidh_iqc_ref_fp_add(mpz_t x, const mpz_t a, const mpz_t b) {
mpz_add(x, a, b);
mpz_mod(x, x, characteristic);
}
void oqs_sidh_iqc_ref_fp_add_ui(mpz_t x, const mpz_t a, unsigned long b) {
mpz_add_ui(x, a, b);
mpz_mod(x, x, characteristic);
}
void oqs_sidh_iqc_ref_fp_sub(mpz_t x, const mpz_t a, const mpz_t b) {
mpz_sub(x, a, b);
mpz_mod(x, x, characteristic);
}
void oqs_sidh_iqc_ref_fp_sub_ui(mpz_t x, const mpz_t a, unsigned long b) {
mpz_sub_ui(x, a, b);
mpz_mod(x, x, characteristic);
}
void oqs_sidh_iqc_ref_fp_mul(mpz_t x, const mpz_t a, const mpz_t b) {
mpz_mul(x, a, b);
mpz_mod(x, x, characteristic);
}
void oqs_sidh_iqc_ref_fp_mul_si(mpz_t x, const mpz_t a, long b) {
mpz_mul_si(x, a, b);
mpz_mod(x, x, characteristic);
}
void oqs_sidh_iqc_ref_fp_inv(mpz_t x, const mpz_t a) {
mpz_invert(x, a, characteristic);
}
void oqs_sidh_iqc_ref_fp_div(mpz_t x, const mpz_t a, const mpz_t b) {
oqs_sidh_iqc_ref_fp_inv(x, b);
oqs_sidh_iqc_ref_fp_mul(x, a, x);
}
void oqs_sidh_iqc_ref_fp_neg(mpz_t x, const mpz_t a) {
oqs_sidh_iqc_ref_fp_sub(x, characteristic, a);
}
void oqs_sidh_iqc_ref_fp_sqrt(mpz_t x, const mpz_t a) {
mpz_t exponent;
mpz_init(exponent);
// compute (p + 1) / 4
mpz_add_ui(exponent, characteristic, 1);
mpz_divexact_ui(exponent, exponent, 4);
mpz_powm(x, a, exponent, characteristic);
mpz_clear(exponent);
}
//////////////// fp2 methods //////////////////////////
void oqs_sidh_iqc_ref_fp2_init(fp2_element_t x) { mpz_inits(x->a, x->b, NULL); }
void oqs_sidh_iqc_ref_fp2_init_set_si(fp2_element_t x, long a, long b) {
mpz_init_set_si(x->a, a);
mpz_init_set_si(x->b, b);
}
void oqs_sidh_iqc_ref_fp2_init_set_str(fp2_element_t x, const char *a,
const char *b) {
mpz_init_set_str(x->a, a, 10);
mpz_init_set_str(x->b, b, 10);
}
void oqs_sidh_iqc_ref_fp2_init_set(fp2_element_t x, const fp2_element_t a) {
mpz_init_set(x->a, a->a);
mpz_init_set(x->b, a->b);
}
void oqs_sidh_iqc_ref_fp2_clear(fp2_element_t x) {
mpz_clears(x->a, x->b, NULL);
}
void oqs_sidh_iqc_ref_fp2_set(fp2_element_t x, const fp2_element_t b) {
mpz_set(x->a, b->a);
mpz_set(x->b, b->b);
}
void oqs_sidh_iqc_ref_fp2_zero(fp2_element_t x) {
mpz_set_si(x->a, 0);
mpz_set_si(x->b, 0);
}
void oqs_sidh_iqc_ref_fp2_one(fp2_element_t x) {
mpz_set_si(x->a, 0);
mpz_set_si(x->b, 1);
}
char *oqs_sidh_iqc_ref_fp2_get_str(const fp2_element_t a) {
if (mpz_cmp_si(a->a, 0) == 0 && mpz_cmp_si(a->b, 0) == 0) {
return "0";
}
if (mpz_cmp_si(a->a, 0) == 0) {
return mpz_get_str(NULL, 10, a->b);
}
char *result = "";
if (mpz_cmp_si(a->b, 0) == 0) {
result = oqs_sidh_iqc_ref_concat(result, mpz_get_str(NULL, 10, a->a));
result = oqs_sidh_iqc_ref_concat(result, " * i");
return result;
}
result = oqs_sidh_iqc_ref_concat(result, mpz_get_str(NULL, 10, a->a));
result = oqs_sidh_iqc_ref_concat(result, " * i + ");
result = oqs_sidh_iqc_ref_concat(result, mpz_get_str(NULL, 10, a->b));
return result;
}
void oqs_sidh_iqc_ref_fp2_add(fp2_element_t x, const fp2_element_t a,
const fp2_element_t b) {
oqs_sidh_iqc_ref_fp_add(x->a, a->a, b->a);
oqs_sidh_iqc_ref_fp_add(x->b, a->b, b->b);
}
void oqs_sidh_iqc_ref_fp2_add_ui(fp2_element_t x, const fp2_element_t a,
unsigned long b) {
oqs_sidh_iqc_ref_fp_add_ui(x->b, a->b, b);
oqs_sidh_iqc_ref_fp_set(x->a, a->a);
}
void oqs_sidh_iqc_ref_fp2_sub(fp2_element_t x, const fp2_element_t a,
const fp2_element_t b) {
oqs_sidh_iqc_ref_fp_sub(x->a, a->a, b->a);
oqs_sidh_iqc_ref_fp_sub(x->b, a->b, b->b);
}
void oqs_sidh_iqc_ref_fp2_sub_ui(fp2_element_t x, const fp2_element_t a,
unsigned long b) {
oqs_sidh_iqc_ref_fp_sub_ui(x->b, a->b, b);
oqs_sidh_iqc_ref_fp_set(x->a, a->a);
}
void oqs_sidh_iqc_ref_fp2_mul(fp2_element_t x, const fp2_element_t a,
const fp2_element_t b) {
mpz_t temp1;
mpz_t temp2;
mpz_init(temp1);
mpz_init(temp2);
fp2_element_t result;
oqs_sidh_iqc_ref_fp2_init(result);
// (a + b) * (c + d)
oqs_sidh_iqc_ref_fp_add(temp1, a->a, a->b);
oqs_sidh_iqc_ref_fp_add(temp2, b->a, b->b);
oqs_sidh_iqc_ref_fp_mul(result->a, temp1, temp2);
// a * c
oqs_sidh_iqc_ref_fp_mul(temp1, a->a, b->a);
// b * d
oqs_sidh_iqc_ref_fp_mul(temp2, a->b, b->b);
oqs_sidh_iqc_ref_fp_sub(result->a, result->a, temp1);
oqs_sidh_iqc_ref_fp_sub(result->a, result->a, temp2);
oqs_sidh_iqc_ref_fp_sub(result->b, temp2, temp1);
oqs_sidh_iqc_ref_fp2_set(x, result);
mpz_clear(temp1);
mpz_clear(temp2);
oqs_sidh_iqc_ref_fp2_clear(result);
}
void oqs_sidh_iqc_ref_fp2_square(fp2_element_t x, const fp2_element_t a) {
mpz_t temp1;
mpz_t temp2;
mpz_init(temp1);
mpz_init(temp2);
fp2_element_t result;
oqs_sidh_iqc_ref_fp2_init(result);
// (b + a) * (b - a)
oqs_sidh_iqc_ref_fp_add(temp1, a->a, a->b);
oqs_sidh_iqc_ref_fp_sub(temp2, a->b, a->a);
oqs_sidh_iqc_ref_fp_mul(result->b, temp1, temp2);
// 2 * a * b
oqs_sidh_iqc_ref_fp_mul(result->a, a->a, a->b);
oqs_sidh_iqc_ref_fp_mul_si(result->a, result->a, 2);
oqs_sidh_iqc_ref_fp2_set(x, result);
mpz_clear(temp1);
mpz_clear(temp2);
oqs_sidh_iqc_ref_fp2_clear(result);
}
void oqs_sidh_iqc_ref_fp2_pow_ui(fp2_element_t x, const fp2_element_t a,
unsigned long n) {
mpz_t temp_n;
mpz_init_set_ui(temp_n, n);
oqs_sidh_iqc_ref_fp2_pow(x, a, temp_n);
mpz_clear(temp_n);
}
void oqs_sidh_iqc_ref_fp2_pow(fp2_element_t x, const fp2_element_t a,
const mpz_t n) {
if (mpz_cmp_ui(n, 0) == 0) {
oqs_sidh_iqc_ref_fp2_one(x);
return;
}
fp2_element_t temp1;
fp2_element_t temp2;
oqs_sidh_iqc_ref_fp2_init_set_si(temp1, 0, 1);
oqs_sidh_iqc_ref_fp2_init_set(temp2, a);
long num_bits = mpz_sizeinbase(n, 2);
for (long i = 0; i < num_bits; i++) {
if (mpz_tstbit(n, i) == 1)
oqs_sidh_iqc_ref_fp2_mul(temp1, temp1, temp2);
oqs_sidh_iqc_ref_fp2_square(temp2, temp2);
}
oqs_sidh_iqc_ref_fp2_set(x, temp1);
oqs_sidh_iqc_ref_fp2_clear(temp1);
oqs_sidh_iqc_ref_fp2_clear(temp2);
}
void oqs_sidh_iqc_ref_fp2_conjugate(fp2_element_t x, const fp2_element_t a) {
oqs_sidh_iqc_ref_fp2_set(x, a);
oqs_sidh_iqc_ref_fp_neg(x->a, x->a);
}
void oqs_sidh_iqc_ref_fp2_negate(fp2_element_t x, const fp2_element_t a) {
oqs_sidh_iqc_ref_fp2_set(x, a);
oqs_sidh_iqc_ref_fp_neg(x->a, x->a);
oqs_sidh_iqc_ref_fp_neg(x->b, x->b);
}
void oqs_sidh_iqc_ref_fp2_mul_scaler(fp2_element_t x, const fp2_element_t a,
const mpz_t scaler) {
oqs_sidh_iqc_ref_fp_mul(x->a, a->a, scaler);
oqs_sidh_iqc_ref_fp_mul(x->b, a->b, scaler);
}
void oqs_sidh_iqc_ref_fp2_mul_scaler_si(fp2_element_t x, const fp2_element_t a,
long scaler) {
oqs_sidh_iqc_ref_fp_mul_si(x->a, a->a, scaler);
oqs_sidh_iqc_ref_fp_mul_si(x->b, a->b, scaler);
}
void oqs_sidh_iqc_ref_fp2_inv(fp2_element_t x, const fp2_element_t a) {
mpz_t temp;
fp2_element_t result;
mpz_init(temp);
oqs_sidh_iqc_ref_fp2_init(result);
oqs_sidh_iqc_ref_fp2_conjugate(result, a);
oqs_sidh_iqc_ref_fp2_norm(temp, a);
oqs_sidh_iqc_ref_fp_inv(temp, temp);
oqs_sidh_iqc_ref_fp2_mul_scaler(result, result, temp);
oqs_sidh_iqc_ref_fp2_set(x, result);
mpz_clear(temp);
oqs_sidh_iqc_ref_fp2_clear(result);
}
void oqs_sidh_iqc_ref_fp2_div(fp2_element_t x, const fp2_element_t a,
const fp2_element_t b) {
fp2_element_t result;
oqs_sidh_iqc_ref_fp2_init(result);
oqs_sidh_iqc_ref_fp2_inv(result, b);
oqs_sidh_iqc_ref_fp2_mul(result, a, result);
oqs_sidh_iqc_ref_fp2_set(x, result);
oqs_sidh_iqc_ref_fp2_clear(result);
}
int oqs_sidh_iqc_ref_fp2_is_zero(const fp2_element_t a) {
return !mpz_cmp_si(a->a, 0) && !mpz_cmp_si(a->b, 0);
}
int oqs_sidh_iqc_ref_fp2_is_one(const fp2_element_t a) {
return !mpz_cmp_si(a->a, 0) && !mpz_cmp_si(a->b, 1);
}
int oqs_sidh_iqc_ref_fp2_equals(const fp2_element_t a, const fp2_element_t b) {
return (mpz_cmp(a->a, b->a) == 0) && (mpz_cmp(a->b, b->b) == 0);
}
void oqs_sidh_iqc_ref_fp2_random(fp2_element_t x, gmp_randstate_t randstate) {
mpz_urandomm(x->a, randstate, characteristic);
mpz_urandomm(x->b, randstate, characteristic);
}
void oqs_sidh_iqc_ref_fp2_sqrt(fp2_element_t x, const fp2_element_t a) {
mpz_t exponent;
fp2_element_t temp_a;
fp2_element_t b;
fp2_element_t c;
fp2_element_t beta;
mpz_t base_root;
gmp_randstate_t randstate;
mpz_init(exponent);
oqs_sidh_iqc_ref_fp2_init(temp_a);
oqs_sidh_iqc_ref_fp2_init(b);
oqs_sidh_iqc_ref_fp2_init(c);
oqs_sidh_iqc_ref_fp2_init(beta);
mpz_init(base_root);
gmp_randinit_default(randstate);
// compute (p - 1) / 2
mpz_sub_ui(exponent, characteristic, 1);
mpz_divexact_ui(exponent, exponent, 2);
while (oqs_sidh_iqc_ref_fp2_is_zero(b)) {
oqs_sidh_iqc_ref_fp2_random(c, randstate);
oqs_sidh_iqc_ref_fp2_square(temp_a, c);
oqs_sidh_iqc_ref_fp2_mul(temp_a, temp_a, a);
// compute 1 + temp_a^((p - 1) / 2)
oqs_sidh_iqc_ref_fp2_pow(b, temp_a, exponent);
oqs_sidh_iqc_ref_fp2_add_ui(b, b, 1);
}
// compute temp_a * b^2
oqs_sidh_iqc_ref_fp2_square(beta, b);
oqs_sidh_iqc_ref_fp2_mul(beta, beta, temp_a);
// beta is now in the prime field
oqs_sidh_iqc_ref_fp_sqrt(base_root, beta->b);
oqs_sidh_iqc_ref_fp2_inv(b, b);
oqs_sidh_iqc_ref_fp2_mul_scaler(b, b, base_root);
oqs_sidh_iqc_ref_fp2_div(x, b, c);
mpz_clear(exponent);
oqs_sidh_iqc_ref_fp2_clear(temp_a);
oqs_sidh_iqc_ref_fp2_clear(b);
oqs_sidh_iqc_ref_fp2_clear(c);
oqs_sidh_iqc_ref_fp2_clear(beta);
mpz_clear(base_root);
gmp_randclear(randstate);
}
int oqs_sidh_iqc_ref_fp2_is_square(const fp2_element_t a) {
mpz_t exponent;
mpz_t norm;
fp2_element_t temp;
mpz_init(exponent);
mpz_init(norm);
oqs_sidh_iqc_ref_fp2_init(temp);
// a^((p - 1) / 2)
mpz_sub_ui(exponent, characteristic, 1);
mpz_divexact_ui(exponent, exponent, 2);
oqs_sidh_iqc_ref_fp2_pow(temp, a, exponent);
oqs_sidh_iqc_ref_fp2_norm(norm, temp);
int result = (mpz_cmp_si(norm, 1) == 0);
mpz_clear(exponent);
mpz_clear(norm);
oqs_sidh_iqc_ref_fp2_clear(temp);
return result;
}
void oqs_sidh_iqc_ref_fp2_norm(mpz_t x, const fp2_element_t a) {
mpz_t temp1;
mpz_t temp2;
mpz_inits(temp1, temp2, NULL);
oqs_sidh_iqc_ref_fp_mul(temp1, a->a, a->a);
oqs_sidh_iqc_ref_fp_mul(temp2, a->b, a->b);
oqs_sidh_iqc_ref_fp_add(temp1, temp1, temp2);
mpz_set(x, temp1);
mpz_clears(temp1, temp2, NULL);
}
void oqs_sidh_iqc_ref_fp2_to_bytes(uint8_t *bytes, const fp2_element_t a,
long prime_size) {
for (long i = 0; i < 2 * prime_size; i++)
bytes[i] = 0;
mpz_export(bytes, NULL, -1, 1, 0, 0, a->a);
mpz_export(bytes + prime_size, NULL, -1, 1, 0, 0, a->b);
}
void oqs_sidh_iqc_ref_bytes_to_fp2(fp2_element_t a, const uint8_t *bytes,
long prime_size) {
oqs_sidh_iqc_ref_fp2_zero(a);
mpz_import(a->a, prime_size, -1, 1, 0, 0, bytes);
mpz_import(a->b, prime_size, -1, 1, 0, 0, bytes + prime_size);
}

View File

@ -0,0 +1,445 @@
/*
* Copyright (C) 2016 Javad Doliskani, javad.doliskani@uwaterloo.ca
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef FP2_H
#define FP2_H
#include <gmp.h>
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
mpz_t characteristic;
/**
* Representation of elements of the quadratic extension F_(p^2)
* of F_p. We assume F_(p^2) is represented by the quotient
* F_p[X] / (X^2 + 1) which requires X^2 + 1 to be irreducible over F_p.
* The elements are therefore of the form a * i + b where i^2 = -1.
*/
typedef struct {
mpz_t a;
mpz_t b;
} fp2_element_struct;
typedef fp2_element_struct fp2_element_t[1];
//////////////// fp methods //////////////////////////
/**
* {@link oqs_sidh_iqc_ref_init_chararacteristic}
* @param p
*/
void oqs_sidh_iqc_ref_fp_init_chararacteristic_ui(long p);
/**
* {@link oqs_sidh_iqc_ref_init_chararacteristic}
* @param value
*/
void oqs_sidh_iqc_ref_fp_init_chararacteristic_str(const char *value);
/**
* Initializes the characteristic to {@code p}.
* @param p
*/
void oqs_sidh_iqc_ref_fp_init_chararacteristic(const mpz_t p);
/**
* Sets {@code x = a}.
* @param x
* @param a
*/
void oqs_sidh_iqc_ref_fp_set(mpz_t x, const mpz_t a);
/**
* Sets {@code x = a + b}.
* @param x
* @param a
* @param b
*/
void oqs_sidh_iqc_ref_fp_add(mpz_t x,
const mpz_t a,
const mpz_t b);
/**
* {@link oqs_sidh_iqc_ref_fp_add}.
* @param x
* @param a
* @param b
*/
void oqs_sidh_iqc_ref_fp_add_ui(mpz_t x,
const mpz_t a,
unsigned long b);
/**
* Sets {@code x = a - b}.
* @param x
* @param a
* @param b
*/
void oqs_sidh_iqc_ref_fp_sub(mpz_t x,
const mpz_t a,
const mpz_t b);
/**
* {@link oqs_sidh_iqc_ref_fp_sub}
* @param x
* @param a
* @param b
*/
void oqs_sidh_iqc_ref_fp_sub_ui(mpz_t x,
const mpz_t a,
unsigned long b);
/**
* Sets {@code x = a * b}.
* @param x
* @param a
* @param b
*/
void oqs_sidh_iqc_ref_fp_mul(mpz_t x,
const mpz_t a,
const mpz_t b);
/**
* {@link oqs_sidh_iqc_ref_fp_mul}
* @param x
* @param a
* @param b
*/
void oqs_sidh_iqc_ref_fp_mul_si(mpz_t x,
const mpz_t a,
long b);
/**
* Sets {@code x = 1 / a}. This is possible only if {@code a} is
* prime to the characteristic.
* @param x
* @param a
*/
void oqs_sidh_iqc_ref_fp_inv(mpz_t x,
const mpz_t a);
/**
* Sets {x = a / b}. @see fp_inv.
* @param x
* @param a
* @param b
*/
void oqs_sidh_iqc_ref_fp_div(mpz_t x,
const mpz_t a,
const mpz_t b);
/**
* Sets {@code x = -a}.
* @param x
* @param a
*/
void oqs_sidh_iqc_ref_fp_neg(mpz_t x,
const mpz_t a);
/**
* Computes the square root of {@code a}.
* This method works only for p = 3 mod 4.
* @param x the square root
* @param a
*/
void oqs_sidh_iqc_ref_fp_sqrt(mpz_t x,
const mpz_t a);
//////////////// fp2 methods //////////////////////////
/**
* Initializes {@code x} to zero.
* @param x
*/
void oqs_sidh_iqc_ref_fp2_init(fp2_element_t x);
/**
* Initializes {@code x} to {@code a * i + b}.
* @param x
* @param a
* @param b
*/
void oqs_sidh_iqc_ref_fp2_init_set_si(fp2_element_t x,
long a,
long b);
/**
* {@link oqs_sidh_iqc_ref_fp2_init_set_si}.
* @param x
* @param a
* @param b
*/
void oqs_sidh_iqc_ref_fp2_init_set_str(fp2_element_t x,
const char *a,
const char *b);
/**
* Initializes {@code x} to {@code a}.
* @param x
* @param a
*/
void oqs_sidh_iqc_ref_fp2_init_set(fp2_element_t x,
const fp2_element_t a);
/**
* Frees the memory allocated to {@code x}.
* @param x
*/
void oqs_sidh_iqc_ref_fp2_clear(fp2_element_t x);
/**
* Copies {@code a} into {@code x}.
* @param x
* @param b
*/
void oqs_sidh_iqc_ref_fp2_set(fp2_element_t x,
const fp2_element_t b);
/**
* Sets {@code a = 0}
* @param x
*/
void oqs_sidh_iqc_ref_fp2_zero(fp2_element_t x);
/**
* Sets {@code x = 1}.
* @param x
*/
void oqs_sidh_iqc_ref_fp2_one(fp2_element_t x);
/**
* @param a
* @return the string representation of {@code a}
*/
char *oqs_sidh_iqc_ref_fp2_get_str(const fp2_element_t a);
/**
* Sets {@code x = a + b}.
* @param x
* @param a
* @param b
*/
void oqs_sidh_iqc_ref_fp2_add(fp2_element_t x,
const fp2_element_t a,
const fp2_element_t b);
/**
* {@link oqs_sidh_iqc_ref_fp2_add}
* @param x
* @param a
* @param b
*/
void oqs_sidh_iqc_ref_fp2_add_ui(fp2_element_t x,
const fp2_element_t a,
unsigned long b);
/**
* Sets {@code x = a - b}.
* @param x
* @param a
* @param b
*/
void oqs_sidh_iqc_ref_fp2_sub(fp2_element_t x,
const fp2_element_t a,
const fp2_element_t b);
/**
* {@link oqs_sidh_iqc_ref_fp2_sub}
* @param x
* @param a
* @param b
*/
void oqs_sidh_iqc_ref_fp2_sub_ui(fp2_element_t x,
const fp2_element_t a,
unsigned long b);
/**
* Sets {@code x = a * b}.
* @param x
* @param a
* @param b
*/
void oqs_sidh_iqc_ref_fp2_mul(fp2_element_t x,
const fp2_element_t a,
const fp2_element_t b);
/**
* Sets {@code x = a^2}.
* @param x
* @param a
*/
void oqs_sidh_iqc_ref_fp2_square(fp2_element_t x,
const fp2_element_t a);
/**
* {@link oqs_sidh_iqc_ref_fp2_pow}
*/
void oqs_sidh_iqc_ref_fp2_pow_ui(fp2_element_t x,
const fp2_element_t a,
unsigned long n);
/**
* Sets {@code x = a^n}.
* @param x
* @param a
* @param n
*/
void oqs_sidh_iqc_ref_fp2_pow(fp2_element_t x,
const fp2_element_t a,
const mpz_t n);
/**
* Sets {@code x = 1 / a}.
* @param x
* @param a
*/
void oqs_sidh_iqc_ref_fp2_inv(fp2_element_t x,
const fp2_element_t a);
/**
* Sets {@code x = a / b}.
* @param x
* @param a
* @param b
*/
void oqs_sidh_iqc_ref_fp2_div(fp2_element_t x,
const fp2_element_t a,
const fp2_element_t b);
/**
* Sets {@code x = -u * i + v} where {@code a = u * i + v}.
* @param x
* @param a
*/
void oqs_sidh_iqc_ref_fp2_conjugate(fp2_element_t x,
const fp2_element_t a);
/**
* Sets {@code x = -a}.
* @param x
* @param a
*/
void oqs_sidh_iqc_ref_fp2_negate(fp2_element_t x,
const fp2_element_t a);
/**
* Sets {@code x = a * scaler}.
* @param x
* @param a
* @param scaler
*/
void oqs_sidh_iqc_ref_fp2_mul_scaler(fp2_element_t x,
const fp2_element_t a,
const mpz_t scaler);
/**
* {@link oqs_sidh_iqc_ref_fp2_mul_scaler}
* @param x
* @param a
* @param scaler
*/
void oqs_sidh_iqc_ref_fp2_mul_scaler_si(fp2_element_t x,
const fp2_element_t a,
long scaler);
/**
* Checks if {@code a} is zero.
* @param a
* @return 1 if {@code a == 0}, and 0 otherwise
*/
int oqs_sidh_iqc_ref_fp2_is_zero(const fp2_element_t a);
/**
* Checks if {@code a} is one.
* @param a
* @return 1 if {@code a == 1}, and 0 otherwise
*/
int oqs_sidh_iqc_ref_fp2_is_one(const fp2_element_t a);
/**
* Checks if {@code a == b}.
* @param a
* @param b
* @return 1 if {@code a == b}, and 0 otherwise.
*/
int oqs_sidh_iqc_ref_fp2_equals(const fp2_element_t a,
const fp2_element_t b);
/**
* Generates a random element in the quadratic extension.
* @param x the generated random element
* @param randstate
*/
void oqs_sidh_iqc_ref_fp2_random(fp2_element_t x,
gmp_randstate_t randstate);
/**
* Computes the square root of {@code a}.
* The algorithm is based on
* Doliskani & Schost, Taking Roots over High Extensions of Finite Fields, 2011.
* It works for any characteristic, but since it uses {@link oqs_sidh_iqc_ref_fp_sqrt} for
* base-case square root, it is limited to p = 3 mod 4.
* @param x the square root
* @param a
*/
void oqs_sidh_iqc_ref_fp2_sqrt(fp2_element_t x,
const fp2_element_t a);
/**
* Checks if {@code a} is a square.
* @param a
* @return 1 if {@code a} is a square, 0 otherwise
*/
int oqs_sidh_iqc_ref_fp2_is_square(const fp2_element_t a);
/**
* Computes the norm of {@code x = b * i + c} which is b^2 + c^2.
* @param x the computed norm
* @param a
*/
void oqs_sidh_iqc_ref_fp2_norm(mpz_t x,
const fp2_element_t a);
/**
* Converts bytes an fp2 element to a byte array.
* @param bytes
* @param a
* @param prime_size
*/
void oqs_sidh_iqc_ref_fp2_to_bytes(uint8_t *bytes,
const fp2_element_t a,
long prime_size);
/**
* Converts a byte array to an fp2 element.
* @param a
* @param bytes
* @param prime_size
*/
void oqs_sidh_iqc_ref_bytes_to_fp2(fp2_element_t a,
const uint8_t *bytes,
long prime_size);
#ifdef __cplusplus
}
#endif
#endif /* FP2_H */

View File

@ -0,0 +1,47 @@
/*
* Copyright (C) 2016 Javad Doliskani, javad.doliskani@uwaterloo.ca
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "sidh_shared_key.h"
#include "sidh_isogeny.h"
void oqs_sidh_iqc_ref_shared_key_generate(fp2_element_t shared_key,
const public_key_t public_key,
const private_key_t private_key,
const public_params_t params) {
point_t kernel_gen;
oqs_sidh_iqc_ref_point_init(kernel_gen);
// compute a generator for the kernel of the isogeny
oqs_sidh_iqc_ref_private_key_compute_kernel_gen(kernel_gen,
private_key,
public_key->P,
public_key->Q,
params->le,
public_key->E);
elliptic_curve_t E;
oqs_sidh_iqc_ref_elliptic_curve_init(E);
oqs_sidh_iqc_ref_elliptic_curve_set(E, public_key->E);
oqs_sidh_iqc_ref_isogeny_evaluate_strategy_curve(E, kernel_gen, params->l, params->e, 0.5);
// oqs_sidh_iqc_ref_isogeny_evaluate_naive_curve(E, kernel_gen, params->l, params->e, 3);
oqs_sidh_iqc_ref_elliptic_curve_compute_j_inv(shared_key, E);
oqs_sidh_iqc_ref_point_clear(kernel_gen);
oqs_sidh_iqc_ref_elliptic_curve_clear(E);
}

View File

@ -0,0 +1,44 @@
/*
* Copyright (C) 2016 Javad Doliskani, javad.doliskani@uwaterloo.ca
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef SHARED_KEY_H
#define SHARED_KEY_H
#include "sidh_private_key.h"
#include "sidh_public_key.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* Generates the shared-key.
* @param shared_key the generated shared-key
* @param public_key other's public-key
* @param private_key own private-key
* @param params own parameters
*/
void oqs_sidh_iqc_ref_shared_key_generate(fp2_element_t shared_key,
const public_key_t public_key,
const private_key_t private_key,
const public_params_t params);
#ifdef __cplusplus
}
#endif
#endif /* SHARED_KEY_H */

View File

@ -0,0 +1,54 @@
/*
* Copyright (C) 2016 Javad Doliskani, javad.doliskani@uwaterloo.ca
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdlib.h>
#include <stdio.h>
#include <gmp.h>
#include <time.h>
#include <oqs/rand.h>
#include "sidh_util.h"
char *oqs_sidh_iqc_ref_concat(char *str1, const char *str2) {
char *temp = (char *) malloc(strlen(str1) + strlen(str2) + 1);
strcpy(temp, str1);
strcat(temp, str2);
return temp;
}
char *oqs_sidh_iqc_ref_get_random_str(int num_bytes) {
char *rand_value = (char *) malloc(num_bytes);
OQS_RAND *rand = OQS_RAND_new(OQS_RAND_alg_urandom_chacha20);
OQS_RAND_n(rand, (uint8_t *) rand_value, num_bytes);
return rand_value;
}
void oqs_sidh_iqc_ref_get_random_mpz(mpz_t x) {
int num_bytes = 20;
char *a = oqs_sidh_iqc_ref_get_random_str(num_bytes);
mpz_import(x, num_bytes, 1, sizeof(char), 0, 0, a);
}
char *oqs_sidh_iqc_ref_array_xor(const char *array1, const char *array2,
long lenght) {
char *result = (char *) malloc(lenght);
for (long i = 0; i < lenght; i++)
result[i] = array1[i] ^ array2[i];
return result;
}

View File

@ -0,0 +1,62 @@
/*
* Copyright (C) 2016 Javad Doliskani, javad.doliskani@uwaterloo.ca
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef UTIL_H
#define UTIL_H
#include <string.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* Concatenates two strings.
* @param str1
* @param str2
* @return the concatenation of {@code str1, str2}
*/
char *oqs_sidh_iqc_ref_concat(char *str1,
const char *str2);
/**
* Generates a random char array of length {@code num_bytes}.
* @param num_bytes
* @return a random char array of length {@code num_bytes}
*/
char *oqs_sidh_iqc_ref_get_random_str(int num_bytes);
/**
* @param x a randomly generated 160bit integer
*/
void oqs_sidh_iqc_ref_get_random_mpz(mpz_t x);
/**
* @param array1
* @param array2
* @param lenght
* @return the bitwise xor of the two arrays
*/
char *oqs_sidh_iqc_ref_array_xor(const char *array1,
const char *array2,
long lenght);
#ifdef __cplusplus
}
#endif
#endif /* UTIL_H */