WIP
This commit is contained in:
parent
bbec636c3e
commit
8379648ba4
116
consts.go
116
consts.go
@ -1,122 +1,6 @@
|
|||||||
package sike
|
package sike
|
||||||
|
|
||||||
// I keep it bool in order to be able to apply logical NOT
|
|
||||||
type KeyVariant uint
|
|
||||||
|
|
||||||
// Representation of an element of the base field F_p.
|
|
||||||
//
|
|
||||||
// No particular meaning is assigned to the representation -- it could represent
|
|
||||||
// an element in Montgomery form, or not. Tracking the meaning of the field
|
|
||||||
// element is left to higher types.
|
|
||||||
type Fp [FP_WORDS]uint64
|
|
||||||
|
|
||||||
// Represents an intermediate product of two elements of the base field F_p.
|
|
||||||
type FpX2 [2 * FP_WORDS]uint64
|
|
||||||
|
|
||||||
// Represents an element of the extended field Fp^2 = Fp(x+i)
|
|
||||||
type Fp2 struct {
|
|
||||||
A Fp
|
|
||||||
B Fp
|
|
||||||
}
|
|
||||||
|
|
||||||
type DomainParams struct {
|
|
||||||
// P, Q and R=P-Q base points
|
|
||||||
Affine_P, Affine_Q, Affine_R Fp2
|
|
||||||
// Size of a compuatation strategy for x-torsion group
|
|
||||||
IsogenyStrategy []uint32
|
|
||||||
// Max size of secret key for x-torsion group
|
|
||||||
SecretBitLen uint
|
|
||||||
// Max size of secret key for x-torsion group
|
|
||||||
SecretByteLen uint
|
|
||||||
}
|
|
||||||
|
|
||||||
type SidhParams struct {
|
|
||||||
Id uint8
|
|
||||||
// Bytelen of P
|
|
||||||
Bytelen int
|
|
||||||
// The public key size, in bytes.
|
|
||||||
PublicKeySize int
|
|
||||||
// The shared secret size, in bytes.
|
|
||||||
SharedSecretSize int
|
|
||||||
// 2- and 3-torsion group parameter definitions
|
|
||||||
A, B DomainParams
|
|
||||||
// Precomputed identity element in the Fp2 in Montgomery domain
|
|
||||||
OneFp2 Fp2
|
|
||||||
// Precomputed 1/2 in the Fp2 in Montgomery domain
|
|
||||||
HalfFp2 Fp2
|
|
||||||
// Length of SIKE secret message. Must be one of {24,32,40},
|
|
||||||
// depending on size of prime field used (see [SIKE], 1.4 and 5.1)
|
|
||||||
MsgLen int
|
|
||||||
// Length of SIKE ephemeral KEM key (see [SIKE], 1.4 and 5.1)
|
|
||||||
KemSize int
|
|
||||||
// Size of a ciphertext returned by encapsulation in bytes
|
|
||||||
CiphertextSize int
|
|
||||||
}
|
|
||||||
|
|
||||||
// Stores curve projective parameters equivalent to A/C. Meaning of the
|
|
||||||
// values depends on the context. When working with isogenies over
|
|
||||||
// subgroup that are powers of:
|
|
||||||
// * three then (A:C) ~ (A+2C:A-2C)
|
|
||||||
// * four then (A:C) ~ (A+2C: 4C)
|
|
||||||
// See Appendix A of SIKE for more details
|
|
||||||
type CurveCoefficientsEquiv struct {
|
|
||||||
A Fp2
|
|
||||||
C Fp2
|
|
||||||
}
|
|
||||||
|
|
||||||
// A point on the projective line P^1(F_{p^2}).
|
|
||||||
//
|
|
||||||
// This represents a point on the Kummer line of a Montgomery curve. The
|
|
||||||
// curve is specified by a ProjectiveCurveParameters struct.
|
|
||||||
type ProjectivePoint struct {
|
|
||||||
X Fp2
|
|
||||||
Z Fp2
|
|
||||||
}
|
|
||||||
|
|
||||||
// Base type for public and private key. Used mainly to carry domain
|
|
||||||
// parameters.
|
|
||||||
type key struct {
|
|
||||||
// Domain parameters of the algorithm to be used with a key
|
|
||||||
params *SidhParams
|
|
||||||
// Flag indicates wether corresponds to 2-, 3-torsion group or SIKE
|
|
||||||
keyVariant KeyVariant
|
|
||||||
}
|
|
||||||
|
|
||||||
// Defines operations on private key
|
|
||||||
type PrivateKey struct {
|
|
||||||
key
|
|
||||||
// Secret key
|
|
||||||
Scalar []byte
|
|
||||||
// Used only by KEM
|
|
||||||
S []byte
|
|
||||||
}
|
|
||||||
|
|
||||||
// Defines operations on public key
|
|
||||||
type PublicKey struct {
|
|
||||||
key
|
|
||||||
affine_xP Fp2
|
|
||||||
affine_xQ Fp2
|
|
||||||
affine_xQmP Fp2
|
|
||||||
}
|
|
||||||
|
|
||||||
// A point on the projective line P^1(F_{p^2}).
|
|
||||||
//
|
|
||||||
// This is used to work projectively with the curve coefficients.
|
|
||||||
type ProjectiveCurveParameters struct {
|
|
||||||
A Fp2
|
|
||||||
C Fp2
|
|
||||||
}
|
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// First 2 bits identify SIDH variant third bit indicates
|
|
||||||
// wether key is a SIKE variant (set) or SIDH (not set)
|
|
||||||
|
|
||||||
// 001 - SIDH: corresponds to 2-torsion group
|
|
||||||
KeyVariant_SIDH_A KeyVariant = 1 << 0
|
|
||||||
// 010 - SIDH: corresponds to 3-torsion group
|
|
||||||
KeyVariant_SIDH_B = 1 << 1
|
|
||||||
// 110 - SIKE
|
|
||||||
KeyVariant_SIKE = 1<<2 | KeyVariant_SIDH_B
|
|
||||||
// Number of uint64 limbs used to store field element
|
// Number of uint64 limbs used to store field element
|
||||||
FP_WORDS = 8
|
FP_WORDS = 8
|
||||||
)
|
)
|
||||||
|
80
sike.go
80
sike.go
@ -7,6 +7,13 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// n can is max 320-bit (see 1.4 of [SIKE])
|
||||||
|
MaxMsgLen = 40
|
||||||
|
MaxSharedSecretSize = 188
|
||||||
|
MaxSecretByteLenA = 47
|
||||||
|
)
|
||||||
|
|
||||||
var cshakeG, cshakeH, cshakeF *shake.CShake
|
var cshakeG, cshakeH, cshakeF *shake.CShake
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@ -52,7 +59,7 @@ func zeroize(fp *Fp2) {
|
|||||||
//
|
//
|
||||||
// The output byte slice must be at least 2*bytelen(p) bytes long.
|
// The output byte slice must be at least 2*bytelen(p) bytes long.
|
||||||
func convFp2ToBytes(output []byte, fp2 *Fp2) {
|
func convFp2ToBytes(output []byte, fp2 *Fp2) {
|
||||||
if len(output) < 2*Params.Bytelen {
|
if len(output) < Params.SharedSecretSize {
|
||||||
panic("output byte slice too short")
|
panic("output byte slice too short")
|
||||||
}
|
}
|
||||||
var a Fp2
|
var a Fp2
|
||||||
@ -72,7 +79,7 @@ func convFp2ToBytes(output []byte, fp2 *Fp2) {
|
|||||||
//
|
//
|
||||||
// It is an error to call this function if the input byte slice is less than 2*bytelen(p) bytes long.
|
// It is an error to call this function if the input byte slice is less than 2*bytelen(p) bytes long.
|
||||||
func convBytesToFp2(fp2 *Fp2, input []byte) {
|
func convBytesToFp2(fp2 *Fp2, input []byte) {
|
||||||
if len(input) < 2*Params.Bytelen {
|
if len(input) < Params.SharedSecretSize {
|
||||||
panic("input byte slice too short")
|
panic("input byte slice too short")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -369,8 +376,8 @@ func deriveSecretB(ss []byte, prv *PrivateKey, pub *PublicKey) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func generateCiphertext(ctext []byte, skA *PrivateKey, pkA, pkB *PublicKey, ptext []byte) error {
|
func generateCiphertext(ctext []byte, skA *PrivateKey, pkA, pkB *PublicKey, ptext []byte) error {
|
||||||
var n [40]byte // OZAPTF n can is max 320-bit (see 1.4 of [SIKE])
|
var n [MaxMsgLen]byte
|
||||||
var j [126]byte
|
var j [MaxSharedSecretSize]byte
|
||||||
var ptextLen = len(ptext)
|
var ptextLen = len(ptext)
|
||||||
|
|
||||||
if pkB.keyVariant != KeyVariant_SIKE {
|
if pkB.keyVariant != KeyVariant_SIKE {
|
||||||
@ -383,7 +390,7 @@ func generateCiphertext(ctext []byte, skA *PrivateKey, pkA, pkB *PublicKey, ptex
|
|||||||
}
|
}
|
||||||
|
|
||||||
cshakeF.Reset()
|
cshakeF.Reset()
|
||||||
cshakeF.Write(j[:2*Params.Bytelen])
|
cshakeF.Write(j[:Params.SharedSecretSize])
|
||||||
cshakeF.Read(n[:ptextLen])
|
cshakeF.Read(n[:ptextLen])
|
||||||
for i, _ := range ptext {
|
for i, _ := range ptext {
|
||||||
n[i] ^= ptext[i]
|
n[i] ^= ptext[i]
|
||||||
@ -447,12 +454,9 @@ func (pub *PublicKey) Size() int {
|
|||||||
|
|
||||||
// Exports currently stored key. In case structure hasn't been filled with key data
|
// Exports currently stored key. In case structure hasn't been filled with key data
|
||||||
// returned byte string is filled with zeros.
|
// returned byte string is filled with zeros.
|
||||||
func (prv *PrivateKey) Export() []byte {
|
func (prv *PrivateKey) Export(out []byte) {
|
||||||
// OZAPTF
|
copy(out, prv.S)
|
||||||
ret := make([]byte, len(prv.Scalar)+len(prv.S))
|
copy(out[len(prv.S):], prv.Scalar)
|
||||||
copy(ret, prv.S)
|
|
||||||
copy(ret[len(prv.S):], prv.Scalar)
|
|
||||||
return ret
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Size returns size of the private key in bytes
|
// Size returns size of the private key in bytes
|
||||||
@ -579,7 +583,7 @@ func encrypt(ctext []byte, rng io.Reader, pub *PublicKey, ptext []byte) error {
|
|||||||
// Constant time
|
// Constant time
|
||||||
func decrypt(n []byte, prv *PrivateKey, ctext []byte) (int, error) {
|
func decrypt(n []byte, prv *PrivateKey, ctext []byte) (int, error) {
|
||||||
var c1_len int
|
var c1_len int
|
||||||
var j [2 * 63]byte // OZAPTF: 63
|
var j [MaxSharedSecretSize]byte
|
||||||
var pk_len = prv.params.PublicKeySize
|
var pk_len = prv.params.PublicKeySize
|
||||||
|
|
||||||
if prv.keyVariant != KeyVariant_SIKE {
|
if prv.keyVariant != KeyVariant_SIKE {
|
||||||
@ -604,7 +608,7 @@ func decrypt(n []byte, prv *PrivateKey, ctext []byte) (int, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
cshakeF.Reset()
|
cshakeF.Reset()
|
||||||
cshakeF.Write(j[:2*Params.Bytelen])
|
cshakeF.Write(j[:Params.SharedSecretSize])
|
||||||
cshakeF.Read(n[:c1_len])
|
cshakeF.Read(n[:c1_len])
|
||||||
for i, _ := range n[:c1_len] {
|
for i, _ := range n[:c1_len] {
|
||||||
n[i] ^= ctext[pk_len+i]
|
n[i] ^= ctext[pk_len+i]
|
||||||
@ -616,8 +620,8 @@ func decrypt(n []byte, prv *PrivateKey, ctext []byte) (int, error) {
|
|||||||
func (kem *KEM) Allocate(rng io.Reader) {
|
func (kem *KEM) Allocate(rng io.Reader) {
|
||||||
kem.allocated = true
|
kem.allocated = true
|
||||||
kem.rng = rng
|
kem.rng = rng
|
||||||
kem.msg = make([]byte, 24)
|
kem.msg = make([]byte, Params.MsgLen)
|
||||||
kem.secretBytes = make([]byte, 32)
|
kem.secretBytes = make([]byte, Params.A.SecretByteLen)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (kem *KEM) Reset() {
|
func (kem *KEM) Reset() {
|
||||||
@ -638,30 +642,22 @@ func (kem *KEM) SharedSecretSize() int {
|
|||||||
return Params.KemSize
|
return Params.KemSize
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
|
||||||
// See [SIKE], 1.4
|
|
||||||
MaxMsgLen = 40
|
|
||||||
MaxPublicKey = 378
|
|
||||||
)
|
|
||||||
|
|
||||||
// Encapsulation receives the public key and generates SIKE ciphertext and shared secret.
|
// Encapsulation receives the public key and generates SIKE ciphertext and shared secret.
|
||||||
// The generated ciphertext is used for authentication.
|
// The generated ciphertext is used for authentication.
|
||||||
// The rng must be cryptographically secure PRNG.
|
// The rng must be cryptographically secure PRNG.
|
||||||
// Error is returned in case PRNG fails or wrongly formated input was provided.
|
// Error is returned in case PRNG fails or wrongly formated input was provided.
|
||||||
func (kem *KEM) Encapsulate(ciphertext, secret []byte, pub *PublicKey) error {
|
func (kem *KEM) Encapsulate(ciphertext, secret []byte, pub *PublicKey) error {
|
||||||
if !kem.allocated {
|
var buf [3 * MaxSharedSecretSize]byte
|
||||||
panic("KEM unallocated")
|
|
||||||
}
|
|
||||||
|
|
||||||
// OZAPTF: MaxBuf: 3*SharedSecretSize
|
|
||||||
var buf [3 * 126]byte
|
|
||||||
|
|
||||||
var skA = PrivateKey{
|
var skA = PrivateKey{
|
||||||
key: key{
|
key: key{
|
||||||
params: &Params,
|
params: &Params,
|
||||||
keyVariant: KeyVariant_SIDH_A},
|
keyVariant: KeyVariant_SIDH_A},
|
||||||
Scalar: kem.secretBytes}
|
Scalar: kem.secretBytes}
|
||||||
|
|
||||||
|
if !kem.allocated {
|
||||||
|
panic("KEM unallocated")
|
||||||
|
}
|
||||||
|
|
||||||
// Generate ephemeral value
|
// Generate ephemeral value
|
||||||
_, err := io.ReadFull(kem.rng, kem.msg[:])
|
_, err := io.ReadFull(kem.rng, kem.msg[:])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -671,7 +667,7 @@ func (kem *KEM) Encapsulate(ciphertext, secret []byte, pub *PublicKey) error {
|
|||||||
pub.Export(buf[:])
|
pub.Export(buf[:])
|
||||||
cshakeG.Reset()
|
cshakeG.Reset()
|
||||||
cshakeG.Write(kem.msg)
|
cshakeG.Write(kem.msg)
|
||||||
cshakeG.Write(buf[:])
|
cshakeG.Write(buf[:3*Params.SharedSecretSize])
|
||||||
cshakeG.Read(skA.Scalar)
|
cshakeG.Read(skA.Scalar)
|
||||||
|
|
||||||
// Ensure bitlength is not bigger then to 2^e2-1
|
// Ensure bitlength is not bigger then to 2^e2-1
|
||||||
@ -696,16 +692,15 @@ func (kem *KEM) Encapsulate(ciphertext, secret []byte, pub *PublicKey) error {
|
|||||||
// Decapsulation may fail in case input is wrongly formated.
|
// Decapsulation may fail in case input is wrongly formated.
|
||||||
// Constant time for properly initialized input.
|
// Constant time for properly initialized input.
|
||||||
func (kem *KEM) Decapsulate(secret []byte, prv *PrivateKey, pub *PublicKey, ctext []byte) error {
|
func (kem *KEM) Decapsulate(secret []byte, prv *PrivateKey, pub *PublicKey, ctext []byte) error {
|
||||||
// Resulting shared secret
|
var m [MaxMsgLen]byte
|
||||||
var c0 [3 * 126]byte
|
var r [MaxSecretByteLenA]byte
|
||||||
var r [32]byte // OZAPTF: to change
|
var pkBytes [3 * MaxSharedSecretSize]byte
|
||||||
var keyBuf [3 * 126]byte
|
|
||||||
var m [40]byte // OZAPTF: to change
|
|
||||||
var skA = PrivateKey{
|
var skA = PrivateKey{
|
||||||
key: key{
|
key: key{
|
||||||
params: &Params,
|
params: &Params,
|
||||||
keyVariant: KeyVariant_SIDH_A},
|
keyVariant: KeyVariant_SIDH_A},
|
||||||
Scalar: kem.secretBytes}
|
Scalar: kem.secretBytes}
|
||||||
|
var pkA = NewPublicKey(KeyVariant_SIDH_A)
|
||||||
|
|
||||||
c1_len, err := decrypt(m[:], prv, ctext)
|
c1_len, err := decrypt(m[:], prv, ctext)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -714,21 +709,18 @@ func (kem *KEM) Decapsulate(secret []byte, prv *PrivateKey, pub *PublicKey, ctex
|
|||||||
|
|
||||||
// r' = G(m'||pub)
|
// r' = G(m'||pub)
|
||||||
//var key = make([]byte, pub.Size()+2*Params.MsgLen)
|
//var key = make([]byte, pub.Size()+2*Params.MsgLen)
|
||||||
pub.Export(keyBuf[:])
|
pub.Export(pkBytes[:])
|
||||||
cshakeG.Reset()
|
cshakeG.Reset()
|
||||||
cshakeG.Write(m[:c1_len])
|
cshakeG.Write(m[:c1_len])
|
||||||
cshakeG.Write(keyBuf[:])
|
cshakeG.Write(pkBytes[:3*pub.params.SharedSecretSize])
|
||||||
cshakeG.Read(r[:])
|
cshakeG.Read(r[:pub.params.A.SecretByteLen])
|
||||||
// Ensure bitlength is not bigger than 2^e2-1
|
// Ensure bitlength is not bigger than 2^e2-1
|
||||||
r[len(r)-1] &= (1 << (pub.params.A.SecretBitLen % 8)) - 1
|
r[pub.params.A.SecretByteLen-1] &= (1 << (pub.params.A.SecretBitLen % 8)) - 1
|
||||||
|
|
||||||
// Never fails
|
// Never fails
|
||||||
skA.Import(r[:])
|
skA.Import(r[:pub.params.A.SecretByteLen])
|
||||||
|
|
||||||
// Never fails
|
|
||||||
pkA := NewPublicKey(KeyVariant_SIDH_A)
|
|
||||||
skA.GeneratePublicKey(pkA)
|
skA.GeneratePublicKey(pkA)
|
||||||
pkA.Export(c0[:])
|
pkA.Export(pkBytes[:])
|
||||||
|
|
||||||
// S is chosen at random when generating a key and unknown to other party. It
|
// S is chosen at random when generating a key and unknown to other party. It
|
||||||
// may seem weird, but it's correct. It is important that S is unpredictable
|
// may seem weird, but it's correct. It is important that S is unpredictable
|
||||||
@ -737,7 +729,7 @@ func (kem *KEM) Decapsulate(secret []byte, prv *PrivateKey, pub *PublicKey, ctex
|
|||||||
//
|
//
|
||||||
// See more details in "On the security of supersingular isogeny cryptosystems"
|
// See more details in "On the security of supersingular isogeny cryptosystems"
|
||||||
// (S. Galbraith, et al., 2016, ePrint #859).
|
// (S. Galbraith, et al., 2016, ePrint #859).
|
||||||
mask := subtle.ConstantTimeCompare(c0[:pub.params.PublicKeySize], ctext[:pub.params.PublicKeySize])
|
mask := subtle.ConstantTimeCompare(pkBytes[:pub.params.PublicKeySize], ctext[:pub.params.PublicKeySize])
|
||||||
cpick(mask, m[:c1_len], m[:c1_len], prv.S)
|
cpick(mask, m[:c1_len], m[:c1_len], prv.S)
|
||||||
cshakeH.Reset()
|
cshakeH.Reset()
|
||||||
cshakeH.Write(m[:c1_len])
|
cshakeH.Write(m[:c1_len])
|
||||||
|
@ -172,6 +172,7 @@ func testPrivateKeyBelowMax(t testing.TB) {
|
|||||||
func(v KeyVariant, dp *DomainParams) {
|
func(v KeyVariant, dp *DomainParams) {
|
||||||
var blen = int(dp.SecretByteLen)
|
var blen = int(dp.SecretByteLen)
|
||||||
var prv = NewPrivateKey(v)
|
var prv = NewPrivateKey(v)
|
||||||
|
var secretBytes = make([]byte, prv.Size())
|
||||||
|
|
||||||
// Calculate either (2^e2 - 1) or (2^s - 1); where s=ceil(log_2(3^e3)))
|
// Calculate either (2^e2 - 1) or (2^s - 1); where s=ceil(log_2(3^e3)))
|
||||||
maxSecertVal := big.NewInt(int64(dp.SecretBitLen))
|
maxSecertVal := big.NewInt(int64(dp.SecretBitLen))
|
||||||
@ -184,7 +185,7 @@ func testPrivateKeyBelowMax(t testing.TB) {
|
|||||||
checkErr(t, err, "Private key generation")
|
checkErr(t, err, "Private key generation")
|
||||||
|
|
||||||
// Convert to big-endian, as that's what expected by (*Int)SetBytes()
|
// Convert to big-endian, as that's what expected by (*Int)SetBytes()
|
||||||
secretBytes := prv.Export()
|
prv.Export(secretBytes)
|
||||||
for i := 0; i < int(blen/2); i++ {
|
for i := 0; i < int(blen/2); i++ {
|
||||||
tmp := secretBytes[i] ^ secretBytes[blen-i-1]
|
tmp := secretBytes[i] ^ secretBytes[blen-i-1]
|
||||||
secretBytes[i] = tmp ^ secretBytes[i]
|
secretBytes[i] = tmp ^ secretBytes[i]
|
||||||
@ -484,7 +485,8 @@ func TestNegativeKEMSameWrongResult(t *testing.T) {
|
|||||||
"pre-requisite for a test failed")
|
"pre-requisite for a test failed")
|
||||||
|
|
||||||
// second decapsulation must be done with same, but imported private key
|
// second decapsulation must be done with same, but imported private key
|
||||||
expSk := sk.Export()
|
var expSk = make([]byte, sk.Size())
|
||||||
|
sk.Export(expSk)
|
||||||
|
|
||||||
// creat new private key
|
// creat new private key
|
||||||
sk = NewPrivateKey(KeyVariant_SIKE)
|
sk = NewPrivateKey(KeyVariant_SIKE)
|
||||||
|
120
types.go
Normal file
120
types.go
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
package sike
|
||||||
|
|
||||||
|
// I keep it bool in order to be able to apply logical NOT
|
||||||
|
type KeyVariant uint
|
||||||
|
|
||||||
|
// Representation of an element of the base field F_p.
|
||||||
|
//
|
||||||
|
// No particular meaning is assigned to the representation -- it could represent
|
||||||
|
// an element in Montgomery form, or not. Tracking the meaning of the field
|
||||||
|
// element is left to higher types.
|
||||||
|
type Fp [FP_WORDS]uint64
|
||||||
|
|
||||||
|
// Represents an intermediate product of two elements of the base field F_p.
|
||||||
|
type FpX2 [2 * FP_WORDS]uint64
|
||||||
|
|
||||||
|
// Represents an element of the extended field Fp^2 = Fp(x+i)
|
||||||
|
type Fp2 struct {
|
||||||
|
A Fp
|
||||||
|
B Fp
|
||||||
|
}
|
||||||
|
|
||||||
|
type DomainParams struct {
|
||||||
|
// P, Q and R=P-Q base points
|
||||||
|
Affine_P, Affine_Q, Affine_R Fp2
|
||||||
|
// Size of a compuatation strategy for x-torsion group
|
||||||
|
IsogenyStrategy []uint32
|
||||||
|
// Max size of secret key for x-torsion group
|
||||||
|
SecretBitLen uint
|
||||||
|
// Max size of secret key for x-torsion group
|
||||||
|
SecretByteLen uint
|
||||||
|
}
|
||||||
|
|
||||||
|
type SidhParams struct {
|
||||||
|
Id uint8
|
||||||
|
// Bytelen of P
|
||||||
|
Bytelen int
|
||||||
|
// The public key size, in bytes.
|
||||||
|
PublicKeySize int
|
||||||
|
// The shared secret size, in bytes.
|
||||||
|
SharedSecretSize int
|
||||||
|
// 2- and 3-torsion group parameter definitions
|
||||||
|
A, B DomainParams
|
||||||
|
// Precomputed identity element in the Fp2 in Montgomery domain
|
||||||
|
OneFp2 Fp2
|
||||||
|
// Precomputed 1/2 in the Fp2 in Montgomery domain
|
||||||
|
HalfFp2 Fp2
|
||||||
|
// Length of SIKE secret message. Must be one of {24,32,40},
|
||||||
|
// depending on size of prime field used (see [SIKE], 1.4 and 5.1)
|
||||||
|
MsgLen int
|
||||||
|
// Length of SIKE ephemeral KEM key (see [SIKE], 1.4 and 5.1)
|
||||||
|
KemSize int
|
||||||
|
// Size of a ciphertext returned by encapsulation in bytes
|
||||||
|
CiphertextSize int
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stores curve projective parameters equivalent to A/C. Meaning of the
|
||||||
|
// values depends on the context. When working with isogenies over
|
||||||
|
// subgroup that are powers of:
|
||||||
|
// * three then (A:C) ~ (A+2C:A-2C)
|
||||||
|
// * four then (A:C) ~ (A+2C: 4C)
|
||||||
|
// See Appendix A of SIKE for more details
|
||||||
|
type CurveCoefficientsEquiv struct {
|
||||||
|
A Fp2
|
||||||
|
C Fp2
|
||||||
|
}
|
||||||
|
|
||||||
|
// A point on the projective line P^1(F_{p^2}).
|
||||||
|
//
|
||||||
|
// This represents a point on the Kummer line of a Montgomery curve. The
|
||||||
|
// curve is specified by a ProjectiveCurveParameters struct.
|
||||||
|
type ProjectivePoint struct {
|
||||||
|
X Fp2
|
||||||
|
Z Fp2
|
||||||
|
}
|
||||||
|
|
||||||
|
// Base type for public and private key. Used mainly to carry domain
|
||||||
|
// parameters.
|
||||||
|
type key struct {
|
||||||
|
// Domain parameters of the algorithm to be used with a key
|
||||||
|
params *SidhParams
|
||||||
|
// Flag indicates wether corresponds to 2-, 3-torsion group or SIKE
|
||||||
|
keyVariant KeyVariant
|
||||||
|
}
|
||||||
|
|
||||||
|
// Defines operations on private key
|
||||||
|
type PrivateKey struct {
|
||||||
|
key
|
||||||
|
// Secret key
|
||||||
|
Scalar []byte
|
||||||
|
// Used only by KEM
|
||||||
|
S []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
// Defines operations on public key
|
||||||
|
type PublicKey struct {
|
||||||
|
key
|
||||||
|
affine_xP Fp2
|
||||||
|
affine_xQ Fp2
|
||||||
|
affine_xQmP Fp2
|
||||||
|
}
|
||||||
|
|
||||||
|
// A point on the projective line P^1(F_{p^2}).
|
||||||
|
//
|
||||||
|
// This is used to work projectively with the curve coefficients.
|
||||||
|
type ProjectiveCurveParameters struct {
|
||||||
|
A Fp2
|
||||||
|
C Fp2
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
// First 2 bits identify SIDH variant third bit indicates
|
||||||
|
// wether key is a SIKE variant (set) or SIDH (not set)
|
||||||
|
|
||||||
|
// 001 - SIDH: corresponds to 2-torsion group
|
||||||
|
KeyVariant_SIDH_A KeyVariant = 1 << 0
|
||||||
|
// 010 - SIDH: corresponds to 3-torsion group
|
||||||
|
KeyVariant_SIDH_B = 1 << 1
|
||||||
|
// 110 - SIKE
|
||||||
|
KeyVariant_SIKE = 1<<2 | KeyVariant_SIDH_B
|
||||||
|
)
|
Loading…
Reference in New Issue
Block a user