forked from microsoft/PQCrypto-SIDH
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsike.c
94 lines (75 loc) · 3.8 KB
/
sike.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
/********************************************************************************************
* SIDH: an efficient supersingular isogeny cryptography library
*
* Abstract: supersingular isogeny key encapsulation (SIKE) protocol
*********************************************************************************************/
#include <string.h>
#include "sha3/fips202.h"
int crypto_kem_keypair(unsigned char *pk, unsigned char *sk)
{ // SIKE's key generation
// Outputs: secret key sk (CRYPTO_SECRETKEYBYTES = MSG_BYTES + SECRETKEY_B_BYTES + CRYPTO_PUBLICKEYBYTES bytes)
// public key pk (CRYPTO_PUBLICKEYBYTES bytes)
// Generate lower portion of secret key sk <- s||SK
randombytes(sk, MSG_BYTES);
random_mod_order_B(sk + MSG_BYTES);
// Generate public key pk
EphemeralKeyGeneration_B(sk + MSG_BYTES, pk);
// Append public key pk to secret key sk
memcpy(&sk[MSG_BYTES + SECRETKEY_B_BYTES], pk, CRYPTO_PUBLICKEYBYTES);
return 0;
}
int crypto_kem_enc(unsigned char *ct, unsigned char *ss, const unsigned char *pk)
{ // SIKE's encapsulation
// Input: public key pk (CRYPTO_PUBLICKEYBYTES bytes)
// Outputs: shared secret ss (CRYPTO_BYTES bytes)
// ciphertext message ct (CRYPTO_CIPHERTEXTBYTES = CRYPTO_PUBLICKEYBYTES + MSG_BYTES bytes)
unsigned char ephemeralsk[SECRETKEY_A_BYTES];
unsigned char jinvariant[FP2_ENCODED_BYTES];
unsigned char h[MSG_BYTES];
unsigned char temp[CRYPTO_CIPHERTEXTBYTES+MSG_BYTES];
// Generate ephemeralsk <- G(m||pk) mod oA
randombytes(temp, MSG_BYTES);
memcpy(&temp[MSG_BYTES], pk, CRYPTO_PUBLICKEYBYTES);
shake256(ephemeralsk, SECRETKEY_A_BYTES, temp, CRYPTO_PUBLICKEYBYTES+MSG_BYTES);
ephemeralsk[SECRETKEY_A_BYTES - 1] &= MASK_ALICE;
// Encrypt
EphemeralKeyGeneration_A(ephemeralsk, ct);
EphemeralSecretAgreement_A(ephemeralsk, pk, jinvariant);
shake256(h, MSG_BYTES, jinvariant, FP2_ENCODED_BYTES);
for (int i = 0; i < MSG_BYTES; i++) {
ct[i + CRYPTO_PUBLICKEYBYTES] = temp[i] ^ h[i];
}
// Generate shared secret ss <- H(m||ct)
memcpy(&temp[MSG_BYTES], ct, CRYPTO_CIPHERTEXTBYTES);
shake256(ss, CRYPTO_BYTES, temp, CRYPTO_CIPHERTEXTBYTES+MSG_BYTES);
return 0;
}
int crypto_kem_dec(unsigned char *ss, const unsigned char *ct, const unsigned char *sk)
{ // SIKE's decapsulation
// Input: secret key sk (CRYPTO_SECRETKEYBYTES = MSG_BYTES + SECRETKEY_B_BYTES + CRYPTO_PUBLICKEYBYTES bytes)
// ciphertext message ct (CRYPTO_CIPHERTEXTBYTES = CRYPTO_PUBLICKEYBYTES + MSG_BYTES bytes)
// Outputs: shared secret ss (CRYPTO_BYTES bytes)
unsigned char ephemeralsk_[SECRETKEY_A_BYTES];
unsigned char jinvariant_[FP2_ENCODED_BYTES];
unsigned char h_[MSG_BYTES];
unsigned char c0_[CRYPTO_PUBLICKEYBYTES];
unsigned char temp[CRYPTO_CIPHERTEXTBYTES+MSG_BYTES];
// Decrypt
EphemeralSecretAgreement_B(sk + MSG_BYTES, ct, jinvariant_);
shake256(h_, MSG_BYTES, jinvariant_, FP2_ENCODED_BYTES);
for (int i = 0; i < MSG_BYTES; i++) {
temp[i] = ct[i + CRYPTO_PUBLICKEYBYTES] ^ h_[i];
}
// Generate ephemeralsk_ <- G(m||pk) mod oA
memcpy(&temp[MSG_BYTES], &sk[MSG_BYTES + SECRETKEY_B_BYTES], CRYPTO_PUBLICKEYBYTES);
shake256(ephemeralsk_, SECRETKEY_A_BYTES, temp, CRYPTO_PUBLICKEYBYTES+MSG_BYTES);
ephemeralsk_[SECRETKEY_A_BYTES - 1] &= MASK_ALICE;
// Generate shared secret ss <- H(m||ct) or output ss <- H(s||ct)
EphemeralKeyGeneration_A(ephemeralsk_, c0_);
if (memcmp(c0_, ct, CRYPTO_PUBLICKEYBYTES) != 0) {
memcpy(temp, sk, MSG_BYTES);
}
memcpy(&temp[MSG_BYTES], ct, CRYPTO_CIPHERTEXTBYTES);
shake256(ss, CRYPTO_BYTES, temp, CRYPTO_CIPHERTEXTBYTES+MSG_BYTES);
return 0;
}