From 500f50f1c895fd1f2d73a1a57f7b6455651a43c2 Mon Sep 17 00:00:00 2001 From: Kris Kwiatkowski Date: Tue, 11 Sep 2018 10:52:25 +0100 Subject: [PATCH] 503 --- msr/include/P503_api.h | 107 +++++++++ msr/lib/intel/libsidh503.a | Bin 0 -> 119830 bytes msr/lib/{ => intel}/libsidh751.a | Bin src/runner503.go | 365 +++++++++++++++++++++++++++++++ src/{runner.go => runner751.go} | 2 +- 5 files changed, 473 insertions(+), 1 deletion(-) create mode 100644 msr/include/P503_api.h create mode 100644 msr/lib/intel/libsidh503.a rename msr/lib/{ => intel}/libsidh751.a (100%) create mode 100644 src/runner503.go rename src/{runner.go => runner751.go} (99%) diff --git a/msr/include/P503_api.h b/msr/include/P503_api.h new file mode 100644 index 0000000..9c32a63 --- /dev/null +++ b/msr/include/P503_api.h @@ -0,0 +1,107 @@ +/******************************************************************************************** +* SIDH: an efficient supersingular isogeny cryptography library +* +* Abstract: API header file for P503 +*********************************************************************************************/ + +#ifndef __P503_API_H__ +#define __P503_API_H__ + + +/*********************** Key encapsulation mechanism API ***********************/ + +#define CRYPTO_SECRETKEYBYTES 434 // MSG_BYTES + SECRETKEY_B_BYTES + CRYPTO_PUBLICKEYBYTES bytes +#define CRYPTO_PUBLICKEYBYTES 378 +#define CRYPTO_BYTES 16 +#define CRYPTO_CIPHERTEXTBYTES 402 // CRYPTO_PUBLICKEYBYTES + MSG_BYTES bytes + +// Algorithm name +#define CRYPTO_ALGNAME "SIKEp503" + +// SIKE's key generation +// It produces a private key sk and computes the public key pk. +// Outputs: secret key sk (CRYPTO_SECRETKEYBYTES = 434 bytes) +// public key pk (CRYPTO_PUBLICKEYBYTES = 378 bytes) +int crypto_kem_keypair_SIKEp503(unsigned char *pk, unsigned char *sk); + +// SIKE's encapsulation +// Input: public key pk (CRYPTO_PUBLICKEYBYTES = 378 bytes) +// Outputs: shared secret ss (CRYPTO_BYTES = 16 bytes) +// ciphertext message ct (CRYPTO_CIPHERTEXTBYTES = 402 bytes) +int crypto_kem_enc_SIKEp503(unsigned char *ct, unsigned char *ss, const unsigned char *pk); + +// SIKE's decapsulation +// Input: secret key sk (CRYPTO_SECRETKEYBYTES = 434 bytes) +// ciphertext message ct (CRYPTO_CIPHERTEXTBYTES = 402 bytes) +// Outputs: shared secret ss (CRYPTO_BYTES = 16 bytes) +int crypto_kem_dec_SIKEp503(unsigned char *ss, const unsigned char *ct, const unsigned char *sk); + + +// Encoding of keys for KEM-based isogeny system "SIKEp503" (wire format): +// ---------------------------------------------------------------------- +// Elements over GF(p503) are encoded in 63 octets in little endian format (i.e., the least significant octet is located in the lowest memory address). +// Elements (a+b*i) over GF(p503^2), where a and b are defined over GF(p503), are encoded as {a, b}, with a in the lowest memory portion. +// +// Private keys sk consist of the concatenation of a 24-byte random value, a value in the range [0, 2^252-1] and the public key pk. In the SIKE API, +// private keys are encoded in 434 octets in little endian format. +// Public keys pk consist of 3 elements in GF(p503^2). In the SIKE API, pk is encoded in 378 octets. +// Ciphertexts ct consist of the concatenation of a public key value and a 24-byte value. In the SIKE API, ct is encoded in 378 + 24 = 402 octets. +// Shared keys ss consist of a value of 16 octets. + + +/*********************** Ephemeral key exchange API ***********************/ + +#define SIDH_SECRETKEYBYTES 32 +#define SIDH_PUBLICKEYBYTES 378 +#define SIDH_BYTES 126 + +// SECURITY NOTE: SIDH supports ephemeral Diffie-Hellman key exchange. It is NOT secure to use it with static keys. +// See "On the Security of Supersingular Isogeny Cryptosystems", S.D. Galbraith, C. Petit, B. Shani and Y.B. Ti, in ASIACRYPT 2016, 2016. +// Extended version available at: http://eprint.iacr.org/2016/859 + +// Generation of Alice's secret key +// Outputs random value in [0, 2^250 - 1] to be used as Alice's private key +void random_mod_order_A_SIDHp503(unsigned char* random_digits); + +// Generation of Bob's secret key +// Outputs random value in [0, 2^Floor(Log(2,3^159)) - 1] to be used as Bob's private key +void random_mod_order_B_SIDHp503(unsigned char* random_digits); + +// Alice's ephemeral public key generation +// Input: a private key PrivateKeyA in the range [0, 2^250 - 1], stored in 32 bytes. +// Output: the public key PublicKeyA consisting of 3 GF(p503^2) elements encoded in 378 bytes. +int EphemeralKeyGeneration_A_SIDHp503(const unsigned char* PrivateKeyA, unsigned char* PublicKeyA); + +// Bob's ephemeral key-pair generation +// It produces a private key PrivateKeyB and computes the public key PublicKeyB. +// The private key is an integer in the range [0, 2^Floor(Log(2,3^159)) - 1], stored in 32 bytes. +// The public key consists of 3 GF(p503^2) elements encoded in 378 bytes. +int EphemeralKeyGeneration_B_SIDHp503(const unsigned char* PrivateKeyB, unsigned char* PublicKeyB); + +// Alice's ephemeral shared secret computation +// It produces a shared secret key SharedSecretA using her secret key PrivateKeyA and Bob's public key PublicKeyB +// Inputs: Alice's PrivateKeyA is an integer in the range [0, 2^250 - 1], stored in 32 bytes. +// Bob's PublicKeyB consists of 3 GF(p503^2) elements encoded in 378 bytes. +// Output: a shared secret SharedSecretA that consists of one element in GF(p503^2) encoded in 126 bytes. +int EphemeralSecretAgreement_A_SIDHp503(const unsigned char* PrivateKeyA, const unsigned char* PublicKeyB, unsigned char* SharedSecretA); + +// Bob's ephemeral shared secret computation +// It produces a shared secret key SharedSecretB using his secret key PrivateKeyB and Alice's public key PublicKeyA +// Inputs: Bob's PrivateKeyB is an integer in the range [0, 2^Floor(Log(2,3^159)) - 1], stored in 32 bytes. +// Alice's PublicKeyA consists of 3 GF(p503^2) elements encoded in 378 bytes. +// Output: a shared secret SharedSecretB that consists of one element in GF(p503^2) encoded in 126 bytes. +int EphemeralSecretAgreement_B_SIDHp503(const unsigned char* PrivateKeyB, const unsigned char* PublicKeyA, unsigned char* SharedSecretB); + + +// Encoding of keys for KEX-based isogeny system "SIDHp503" (wire format): +// ---------------------------------------------------------------------- +// Elements over GF(p503) are encoded in 63 octets in little endian format (i.e., the least significant octet is located in the lowest memory address). +// Elements (a+b*i) over GF(p503^2), where a and b are defined over GF(p503), are encoded as {a, b}, with a in the lowest memory portion. +// +// Private keys PrivateKeyA and PrivateKeyB can have values in the range [0, 2^250-1] and [0, 2^252-1], resp. In the SIDH API, private keys are encoded +// in 32 octets in little endian format. +// Public keys PublicKeyA and PublicKeyB consist of 3 elements in GF(p503^2). In the SIDH API, they are encoded in 378 octets. +// Shared keys SharedSecretA and SharedSecretB consist of one element in GF(p503^2). In the SIDH API, they are encoded in 126 octets. + + +#endif \ No newline at end of file diff --git a/msr/lib/intel/libsidh503.a b/msr/lib/intel/libsidh503.a new file mode 100644 index 0000000000000000000000000000000000000000..af26fd542073ed76580e9fc1ef8aafd8290ff6d9 GIT binary patch literal 119830 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≷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

u1zR8cyEaxFZhzP2 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 literal 0 HcmV?d00001 diff --git a/msr/lib/libsidh751.a b/msr/lib/intel/libsidh751.a similarity index 100% rename from msr/lib/libsidh751.a rename to msr/lib/intel/libsidh751.a diff --git a/src/runner503.go b/src/runner503.go new file mode 100644 index 0000000..733be6f --- /dev/null +++ b/src/runner503.go @@ -0,0 +1,365 @@ +package main + +/* +#cgo CFLAGS: -I../msr/include +#cgo LDFLAGS: -L../msr/lib/intel -lsidh503 -lsidh751 +#include +*/ +import "C" +import "fmt" +import rand "crypto/rand" +import sidh "github.com/cloudflare/p751sidh/sidh" +import sike "github.com/cloudflare/p751sidh/sike" +import "unsafe" +import "runtime" + +const ( + GSKsz = 24+32 // 56=(MSG+KeySize). + CSKsz = 434 // 56+public key size, which MSR concatenates with secret key + PKsz = 378 + CTsz = 24+378 + SSsz = 16 +) + +func FailNow() { + pc := make([]uintptr, 10) // at least 1 entry needed + runtime.Callers(2, pc) + f := runtime.FuncForPC(pc[0]) + file, line := f.FileLine(pc[0]) + fmt.Printf("%s:%d %s\n", file, line, f.Name()) + panic(0) +} + +// Helpers for byte convertion +// ------------------------------ + +// cBytes must be initialized to proper size +func convBytesGoToC(goBytes []byte, cBytes []C.uchar) { + for i,v:=range(goBytes) { + cBytes[i] = C.uchar(v) + } +} + +// goBytes must be initialized to proper size +func convBytesCToGo(cBytes []C.uchar, goBytes []byte) { + copy(goBytes, C.GoBytes(unsafe.Pointer(&cBytes[0]), C.int(len(cBytes)))) +} + +// Helpers for key generation +func keygenMsr() (*sidh.PublicKey, *sidh.PrivateKey) { + var prvKey = sidh.NewPrivateKey(sidh.FP_503, sidh.KeyVariant_SIKE) + var pubKey = sidh.NewPublicKey(sidh.FP_503, sidh.KeyVariant_SIKE) + var msrPK [PKsz]C.uchar + var msrSK [CSKsz]C.uchar + + if C.crypto_kem_keypair_SIKEp503(&msrPK[0], &msrSK[0]) != 0 { + panic(0) + } + + if prvKey.Import(C.GoBytes(unsafe.Pointer(&msrSK[0]), GSKsz)) != nil { + panic(0) + } + + if pubKey.Import(C.GoBytes(unsafe.Pointer(&msrPK[0]), PKsz)) != nil { + panic(0) + } + + return pubKey, prvKey +} + +func keygenCf() (*sidh.PublicKey, *sidh.PrivateKey) { + var prvKey = sidh.NewPrivateKey(sidh.FP_503, sidh.KeyVariant_SIKE) + + err := prvKey.Generate(rand.Reader) + if err!=nil { + fmt.Errorf("ERR: Generate private key for CF failed") + } + return prvKey.GeneratePublicKey(),prvKey +} + +// MSR keygen +// CF Encapsulate +// MSR Decapsulate +func test_msrK_cfE_msrD() { + var cCT [CTsz]C.uchar + var cSS [SSsz]C.uchar + var cSK [CSKsz]C.uchar + + pubKey, prvKey := keygenMsr() + gCT, gSS, err := sike.Encapsulate(rand.Reader, pubKey) + if err != nil { + panic(0) + } + convBytesGoToC(gCT, cCT[:]) + convBytesGoToC(prvKey.Export(), cSK[:]) + convBytesGoToC(pubKey.Export(), cSK[56:]) + if C.crypto_kem_dec_SIKEp503(&cSS[0], &cCT[0], &cSK[0]) != 0 { + panic(0) + } + for i:=0; i */ import "C"