Преглед изворни кода

Refactor private key generation

Private key generation can take advantage of the fact that keyspace for
secret key is (0, 2^x - 1), for some possitivite value of 'x' (see SIKE,
1.3.8). It means that all bytes in the secret key, but the last one, can
take any value between <0x00,0xFF>. Similarily for the last byte, but
generation needs to chop off some bits, to make sure generated value is
an element of a key-space.
Assuming uniform distribution of bytes generated by RNG, secret key is
still chosen uniformly at random, but there is no need to maintain field
specific assembly code.
trials/PERF
Henry Case пре 6 година
committed by Kris Kwiatkowski
родитељ
комит
e5cb7382ac
11 измењених фајлова са 85 додато и 297 уклоњено
  1. +4
    -6
      internal/isogeny/types.go
  2. +0
    -6
      p751/consts.go
  3. +32
    -10
      sidh/api.go
  4. +4
    -5
      sidh/params.go
  5. +0
    -66
      sidh/sidh.go
  6. +0
    -70
      sidh/sidh_amd64.s
  7. +0
    -13
      sidh/sidh_decl.go
  8. +0
    -52
      sidh/sidh_generic.go
  9. +38
    -60
      sidh/sidh_test.go
  10. +6
    -8
      sike/sike.go
  11. +1
    -1
      sike/sike_test.go

+ 4
- 6
internal/isogeny/types.go Прегледај датотеку

@@ -25,20 +25,18 @@ type Fp2Element struct {
type DomainParams struct {
// P, Q and R=P-Q base points
Affine_P, Affine_Q, Affine_R Fp2Element
// Max size of secret key for x-torsion group
SecretBitLen uint
// MaskBytes
MaskBytes []byte
// 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 PrimeFieldId
// Bytelen of P
Bytelen int
// The secret key size, in bytes.
SecretKeySize int
// The public key size, in bytes.
PublicKeySize int
// The shared secret size, in bytes.


+ 0
- 6
p751/consts.go Прегледај датотеку

@@ -15,12 +15,6 @@ const (
P751_SecretBitLenA = 372
// Size of secret key for 3-torsion group, corresponds to log_2(3^e3)
P751_SecretBitLenB = 379
// Corresponds to (8 - e2 % 8). Used for ensuring bitlength equal to e2
P751_MaskAliceByte1 = 0x00
P751_MaskAliceByte2 = 0x0f
P751_MaskAliceByte3 = 0xfe
// Corresponds to (8 - e3 % 8). Used for ensuring bitlength equal to e3
P751_MaskBobByte = 0x03
// Sample rate to obtain a value in [0,3^238]
P751_SampleRate = 102
// P751 bytelen ceil(751/8)


+ 32
- 10
sidh/api.go Прегледај датотеку

@@ -2,8 +2,8 @@ package sidh

import (
"errors"
. "github.com/cloudflare/p751sidh/internal/isogeny"
"io"
. "github.com/cloudflare/p751sidh/internal/isogeny"
)

// Id's correspond to bitlength of the prime field characteristic
@@ -67,7 +67,11 @@ func (key *key) Variant() KeyVariant {
// Usage of this function guarantees that the object is correctly initialized.
func NewPrivateKey(id PrimeFieldId, v KeyVariant) *PrivateKey {
prv := &PrivateKey{key: key{params: Params(id), keyVariant: v}}
prv.Scalar = make([]byte, prv.params.SecretKeySize)
if (v & KeyVariant_SIDH_A) == KeyVariant_SIDH_A {
prv.Scalar = make([]byte, prv.params.A.SecretByteLen)
} else {
prv.Scalar = make([]byte, prv.params.B.SecretByteLen)
}
if v == KeyVariant_SIKE {
prv.S = make([]byte, prv.params.MsgLen)
}
@@ -123,7 +127,7 @@ func (prv *PrivateKey) Export() []byte {

// Size returns size of the private key in bytes
func (prv *PrivateKey) Size() int {
tmp := prv.params.SecretKeySize
tmp := len(prv.Scalar)
if prv.Variant() == KeyVariant_SIKE {
tmp += int(prv.params.MsgLen)
}
@@ -138,29 +142,47 @@ func (prv *PrivateKey) Import(input []byte) error {
if len(input) != prv.Size() {
return errors.New("sidh: input to short")
}
if len(prv.Scalar) != prv.params.SecretKeySize {
return errors.New("sidh: object wrongly initialized")
}
copy(prv.S, input[:len(prv.S)])
copy(prv.Scalar, input[len(prv.S):])
return nil
}

// Generates random private key for SIDH or SIKE. Returns error
// in case user provided RNG or memory initialization fails.
// Generates random private key for SIDH or SIKE. Generated value is
// formed as little-endian integer from key-space <2^(e2-1)..2^e2 - 1>
// for KeyVariant_A or <2^(s-1)..2^s - 1>, where s = floor(log_2(3^e3)),
// for KeyVariant_B.
//
// Returns error in case user provided RNG fails.
func (prv *PrivateKey) Generate(rand io.Reader) error {
var err error
var dp *DomainParams

if (prv.keyVariant & KeyVariant_SIDH_A) == KeyVariant_SIDH_A {
err = prv.generatePrivateKeyA(rand)
dp = &prv.params.A
} else {
err = prv.generatePrivateKeyB(rand)
dp = &prv.params.B
}

if prv.keyVariant == KeyVariant_SIKE && err == nil {
_, err = io.ReadFull(rand, prv.S)
}

// Private key generation takes advantage of the fact that keyspace for secret
// key is (0, 2^x - 1), for some possitivite value of 'x' (see SIKE, 1.3.8).
// It means that all bytes in the secret key, but the last one, can take any
// value between <0x00,0xFF>. Similarily for the last byte, but generation
// needs to chop off some bits, to make sure generated value is an element of
// a key-space.
_, err = io.ReadFull(rand, prv.Scalar)
if err != nil {
return err
}
prv.Scalar[len(prv.Scalar)-1] &= (1 << (dp.SecretBitLen % 8)) - 1
// Make sure scalar is SecretBitLen long. SIKE spec says that key
// space starts from 0, but I'm not confortable with having low
// value scalars used for private keys. It is still secrure as per
// table 5.1 in [SIKE].
prv.Scalar[len(prv.Scalar)-1] |= 1 << ((dp.SecretBitLen % 8) - 1)
return err
}



+ 4
- 5
sidh/params.go Прегледај датотеку

@@ -20,24 +20,23 @@ func Params(id PrimeFieldId) *SidhParams {
func init() {
p751 := SidhParams{
Id: FP_751,
SecretKeySize: p751.P751_SecretKeySize,
PublicKeySize: p751.P751_PublicKeySize,
SharedSecretSize: p751.P751_SharedSecretSize,
A: DomainParams{
Affine_P: p751.P751_affine_PA,
Affine_Q: p751.P751_affine_QA,
Affine_R: p751.P751_affine_RA,
SecretBitLen: p751.P751_SecretBitLenA,
MaskBytes: []byte{p751.P751_MaskAliceByte1, p751.P751_MaskAliceByte2, p751.P751_MaskAliceByte3},
IsogenyStrategy: p751.P751_AliceIsogenyStrategy[:],
SecretBitLen: p751.P751_SecretBitLenA,
SecretByteLen: uint((p751.P751_SecretBitLenA+7)/8),
},
B: DomainParams{
Affine_P: p751.P751_affine_PB,
Affine_Q: p751.P751_affine_QB,
Affine_R: p751.P751_affine_RB,
SecretBitLen: p751.P751_SecretBitLenB,
MaskBytes: []byte{p751.P751_MaskBobByte},
IsogenyStrategy: p751.P751_BobIsogenyStrategy[:],
SecretBitLen: p751.P751_SecretBitLenB,
SecretByteLen: uint((p751.P751_SecretBitLenB+7)/8),
},
OneFp2: p751.P751_OneFp2,
HalfFp2: p751.P751_HalfFp2,


+ 0
- 66
sidh/sidh.go Прегледај датотеку

@@ -1,9 +1,6 @@
package sidh

import (
"errors"
"io"

. "github.com/cloudflare/p751sidh/internal/isogeny"
)

@@ -159,69 +156,6 @@ func traverseTreeSharedKeyB(curve *ProjectiveCurveParameters, xR *ProjectivePoin
}
}

// -----------------------------------------------------------------------------
// Key generation functions
//

// Generate a private key for "Alice". Note that because this library does not
// implement SIDH validation, each keypair must be used for at most one
// shared secret computation.
func (prv *PrivateKey) generatePrivateKeyA(rand io.Reader) error {
_, err := io.ReadFull(rand, prv.Scalar)
if err != nil {
return err
}

// Bit-twiddle to ensure scalar is in 2*[0,2^371):
prv.Scalar[prv.params.SecretKeySize-1] = prv.params.A.MaskBytes[0]
prv.Scalar[prv.params.SecretKeySize-2] &= prv.params.A.MaskBytes[1] // clear high bits, so scalar < 2^372
prv.Scalar[0] &= prv.params.A.MaskBytes[2] // clear low bit, so scalar is even

// We actually want scalar in 2*(0,2^371), but the above procedure
// generates 0 with probability 2^(-371), which isn't worth checking
// for.
return nil
}

// Generate a private key for "Bob". Note that because this library does not
// implement SIDH validation, each keypair must be used for at most one
// shared secret computation.
func (prv *PrivateKey) generatePrivateKeyB(rand io.Reader) error {
// Perform rejection sampling to obtain a random value in [0,3^238]:
var ok uint8
for i := uint(0); i < prv.params.SampleRate; i++ {
_, err := io.ReadFull(rand, prv.Scalar)
if err != nil {
return err
}
// Mask the high bits to obtain a uniform value in [0,2^378):
// TODO: simply run it in loop, if rand distribution is uniform you surelly get non 0
// if not - better die, keep looping, hang, whatever, but don't generate secure key
prv.Scalar[prv.params.SecretKeySize-1] &= prv.params.B.MaskBytes[0]

// Accept if scalar < 3^238 (this happens w/ prob ~0.5828)
// TODO this is specific to P751
ok = checkLessThanThree238(prv.Scalar)
if ok == 0 {
break
}
}
// ok is nonzero if all sampleRate trials failed.
// This happens with probability 0.41719...^102 < 2^(-128), i.e., never
if ok != 0 {
// In case this happens user should retry. In practice it is highly
// improbable (< 2^-128).
return errors.New("sidh: private key generation failed")
}

// Multiply by 3 to get a scalar in 3*[0,3^238):
multiplyByThree(prv.Scalar)
// We actually want scalar in 2*(0,2^371), but the above procedure
// generates 0 with probability 2^(-371), which isn't worth checking
// for.
return nil
}

// Generate a public key in the 2-torsion group
func publicKeyGenA(prv *PrivateKey) (pub *PublicKey) {
var xPA, xQA, xRA ProjectivePoint


+ 0
- 70
sidh/sidh_amd64.s Прегледај датотеку

@@ -1,70 +0,0 @@
// +build amd64,!noasm

#include "textflag.h"

// Digits of 3^238 - 1
#define THREE238M1_0 $0xedcd718a828384f8
#define THREE238M1_1 $0x733b35bfd4427a14
#define THREE238M1_2 $0xf88229cf94d7cf38
#define THREE238M1_3 $0x63c56c990c7c2ad6
#define THREE238M1_4 $0xb858a87e8f4222c7
#define THREE238M1_5 $0x254c9c6b525eaf5

// Set result to zero if the input scalar is <= 3^238, otherwise result is 1.
// Scalar must be array of 48 bytes
// func checkLessThanThree238(s_base uintptr, s_len uint, s_cap uint) uint8
TEXT ·checkLessThanThree238(SB), NOSPLIT, $0-16
MOVQ scalar+0(FP), SI

XORQ AX, AX

// Set [R10,...,R15] = 3^238
MOVQ THREE238M1_0, R10
MOVQ THREE238M1_1, R11
MOVQ THREE238M1_2, R12
MOVQ THREE238M1_3, R13
MOVQ THREE238M1_4, R14
MOVQ THREE238M1_5, R15

// Set [R10,...,R15] = 3^238 - scalar
SUBQ (SI), R10
SBBQ 8(SI), R11
SBBQ 16(SI), R12
SBBQ 24(SI), R13
SBBQ 32(SI), R14
SBBQ 40(SI), R15

// Save borrow flag indicating 3^238 - scalar < 0 as a mask in AX (rax)
ADCB $0, AX
MOVB AX, ret+24(FP)

RET

// Multiply 48-byte scalar by 3 to get a scalar in 3*[0,3^238)
TEXT ·multiplyByThree(SB), NOSPLIT, $0-8
MOVQ scalar+0(FP), SI

// Set [R10,...,R15] = scalar
MOVQ (SI), R10
MOVQ 8(SI), R11
MOVQ 16(SI), R12
MOVQ 24(SI), R13
MOVQ 32(SI), R14
MOVQ 40(SI), R15

// Add scalar twice to compute 3*scalar
ADDQ R10, (SI)
ADCQ R11, (8)(SI)
ADCQ R12, (16)(SI)
ADCQ R13, (24)(SI)
ADCQ R14, (32)(SI)
ADCQ R15, (40)(SI)
ADDQ R10, (SI)
ADCQ R11, (8)(SI)
ADCQ R12, (16)(SI)
ADCQ R13, (24)(SI)
ADCQ R14, (32)(SI)
ADCQ R15, (40)(SI)

RET


+ 0
- 13
sidh/sidh_decl.go Прегледај датотеку

@@ -1,13 +0,0 @@
// +build amd64,!noasm

package sidh

// Set result to zero if the input scalar is <= 3^238, otherwise result is 1.
// Scalar must be array of 48 bytes. This function is specific to P751.
//go:noescape
func checkLessThanThree238(scalar []byte) uint8

// Multiply 48-byte scalar by 3 to get a scalar in 3*[0,3^238). This
// function is specific to P751.
//go:noescape
func multiplyByThree(scalar []byte)

+ 0
- 52
sidh/sidh_generic.go Прегледај датотеку

@@ -1,52 +0,0 @@
// +build !amd64 noasm

package sidh

var three238m1 = []uint8{
0xf8, 0x84, 0x83, 0x82, 0x8a, 0x71, 0xcd, 0xed,
0x14, 0x7a, 0x42, 0xd4, 0xbf, 0x35, 0x3b, 0x73,
0x38, 0xcf, 0xd7, 0x94, 0xcf, 0x29, 0x82, 0xf8,
0xd6, 0x2a, 0x7c, 0x0c, 0x99, 0x6c, 0xc5, 0x63,
0xc7, 0x22, 0x42, 0x8f, 0x7e, 0xa8, 0x58, 0xb8,
0xf5, 0xea, 0x25, 0xb5, 0xc6, 0xc9, 0x54, 0x02}

func addc8(cin, a, b uint8) (ret, cout uint8) {
t := a + cin
ret = b + t
cout = ((a & b) | ((a | b) & (^ret))) >> 7
return
}

func subc8(bIn, a, b uint8) (ret, bOut uint8) {
var tmp1 = a - b
ret = tmp1 - bIn
// Set bOut if bIn!=0 and tmp1==0 in constant time
bOut = bIn & (1 ^ ((tmp1 | uint8(0-tmp1)) >> 7))
// Constant time check if a<b
bOut |= (a ^ ((a ^ b) | (uint8(a-b) ^ b))) >> 7
return
}

// Set result to zero if the input scalar is <= 3^238, otherwise result is 1.
// Scalar must be array of 48 bytes. This function is specific to P751.
func checkLessThanThree238(scalar []byte) uint8 {
var borrow uint8
for i := 0; i < len(three238m1); i++ {
_, borrow = subc8(borrow, three238m1[i], scalar[i])
}
return borrow
}

// Multiply 48-byte scalar by 3 to get a scalar in 3*[0,3^238). This
// function is specific to P751.
func multiplyByThree(scalar []byte) {
var carry uint8
var dbl [48]uint8

for i := 0; i < len(scalar); i++ {
dbl[i], carry = addc8(carry, scalar[i], scalar[i])
}
for i := 0; i < len(scalar); i++ {
scalar[i], carry = addc8(carry, dbl[i], scalar[i])
}
}

+ 38
- 60
sidh/sidh_test.go Прегледај датотеку

@@ -4,6 +4,7 @@ import (
"bytes"
"crypto/rand"
"encoding/hex"
"math/big"
"testing"

. "github.com/cloudflare/p751sidh/internal/isogeny"
@@ -12,7 +13,7 @@ import (
const (
// PrA - Alice's Private Key: 2*randint(0,2^371)
PrA = "C09957CC83045FB4C3726384D784476ACB6FFD92E5B15B3C2D451BA063F1BD4CED8FBCF682A98DD0954D3" +
"7BCAF730E00"
"7BCAF730E"
// PrB - Bob's Private Key: 3*randint(0,3^238)
PrB = "393E8510E78A16D2DC1AACA9C9D17E7E78DB630881D8599C7040D05BB5557ECAE8165C45D5366ECB37B00" +
"969740AF201"
@@ -188,7 +189,7 @@ func TestRoundtripP751(t *testing.T) {

func TestKeyAgreementP751_AliceEvenNumber(t *testing.T) {
// even alice
prE := "C09957CC83045FB4C3726384D784476ACB6FFD92E5B15B3C2D451BA063F1BD4CED8FBCF682A98DD0954D37BCAF730F00"
prE := "C09957CC83045FB4C3726384D784476ACB6FFD92E5B15B3C2D451BA063F1BD4CED8FBCF682A98DD0954D37BCAF730F"
pkE := "8A2DE6FD963C475F7829B689C8B8306FC0917A39EBBC35CA171546269A85698FEC0379E2E1A3C567BE1B8EF5639F81F304889737E6CC444DBED4579DB204DC8C7928F5CBB1ECDD682A1B5C48C0DAF34208C06BF201BE4E6063B1BFDC42413B0537F8E76BEE645C1A24118301BAB17EB8D6E0F283BCB16EFB833E4BB3463953C93165A0DDAC55B385059F27FF7228486D0A733812C81C792BE9EC3A16A5DB0EB099EEA76AC0E59612251A3AD19F7CC567DA2AEBD7733171F48E471D17648692355164E27B515D2A47D7BA34B3B48A047BE7C09C4ABEE2FCC9ACA7396C8A8C9E73E29533FC7369094DFA7988778E55E53F309922C6E233F8F9C7936C3D29CEA640406FCA06450AA1978FF39F227BF06B1E072F1763447C6F513B23CDF3B0EC0379070AEE5A02D9AD8E0EB023461D631F4A9643A4C79921334945F6B33DDFC11D9703BD06B047B4DA404AB12EFD2C3A49E5C42D10DA063352748B21DE41C32A5693FE1C0DCAB111F4990CD58BECADB1892EE7A7E99C9DB4DA4E69C96E57138B99038BC9B877ECE75914EFB98DD08B9E4A2DCCB948A8F7D2F26678A9952BA0EFAB1E9CF6E51B557480DEC2BA30DE0FE4AFE30A6B30765EE75EF64F678316D81C72755AD2CFA0B8C7706B07BFA52FBC3DB84EF9E79796C0089305B1E13C78660779E0FF2A13820CE141104F976B1678990F85B2D3D2B89CD5BC4DD52603A5D24D3EFEDA44BAA0F38CDB75A220AF45EAB70F2799875D435CE50FC6315EDD4BB7AA7260AFD7CD0561B69B4FA3A817904322661C3108DA24"
testKeyAgreement(Params(FP_751), t, pkE, PkB, prE, PrB)
}
@@ -221,64 +222,41 @@ func TestImportExport(t *testing.T) {
}
}

func TestMultiplyByThree(t *testing.T) {
// sage: repr((3^238 -1).digits(256))
var three238minus1 = [48]byte{
248, 132, 131, 130, 138, 113, 205, 237, 20, 122, 66, 212, 191, 53, 59, 115, 56, 207,
215, 148, 207, 41, 130, 248, 214, 42, 124, 12, 153, 108, 197, 99, 199, 34, 66, 143,
126, 168, 88, 184, 245, 234, 37, 181, 198, 201, 84, 2}
// sage: repr((3*(3^238 -1)).digits(256))
var threeTimesThree238minus1 = [48]byte{
232, 142, 138, 135, 159, 84, 104, 201, 62, 110, 199, 124, 63, 161, 177, 89, 169, 109,
135, 190, 110, 125, 134, 233, 132, 128, 116, 37, 203, 69, 80, 43, 86, 104, 198, 173,
123, 249, 9, 41, 225, 192, 113, 31, 84, 93, 254, 6}

multiplyByThree(three238minus1[:])

for i := 0; i < 48; i++ {
if three238minus1[i] != threeTimesThree238minus1[i] {
t.Error("Digit", i, "error: found", three238minus1[i],
"expected", threeTimesThree238minus1[i])
}
}
}

func TestCheckLessThanThree238(t *testing.T) {
var three238minus1 = [48]byte{
248, 132, 131, 130, 138, 113, 205, 237, 20, 122, 66, 212, 191, 53, 59, 115,
56, 207, 215, 148, 207, 41, 130, 248, 214, 42, 124, 12, 153, 108, 197, 99,
199, 34, 66, 143, 126, 168, 88, 184, 245, 234, 37, 181, 198, 201, 84, 2}
var three238 = [48]byte{
249, 132, 131, 130, 138, 113, 205, 237, 20, 122, 66, 212, 191, 53, 59, 115,
56, 207, 215, 148, 207, 41, 130, 248, 214, 42, 124, 12, 153, 108, 197, 99, 199,
34, 66, 143, 126, 168, 88, 184, 245, 234, 37, 181, 198, 201, 84, 2}
var three238plus1 = [48]byte{250, 132, 131, 130, 138, 113, 205, 237, 20, 122, 66,
212, 191, 53, 59, 115, 56, 207, 215, 148, 207, 41, 130, 248, 214, 42, 124, 12,
153, 108, 197, 99, 199, 34, 66, 143, 126, 168, 88, 184, 245, 234, 37, 181, 198,
201, 84, 2}
// makes second 64-bit digits bigger than in three238. checks if carries are correctly propagated
var three238plus2power65 = [48]byte{249, 132, 131, 130, 138, 113, 205, 237, 22, 122,
66, 212, 191, 53, 59, 115, 56, 207, 215, 148, 207, 41, 130, 248, 214, 42, 124, 12,
153, 108, 197, 99, 199, 34, 66, 143, 126, 168, 88, 184, 245, 234, 37, 181, 198,
201, 84, 2}

var result uint8

result = checkLessThanThree238(three238minus1[:])
if result != 0 {
t.Error("expected 0, got", result)
}
result = checkLessThanThree238(three238[:])
if result != 1 {
t.Error("expected nonzero, got", result)
}
result = checkLessThanThree238(three238plus1[:])
if result != 1 {
t.Error("expected nonzero, got", result)
}
result = checkLessThanThree238(three238plus2power65[:])
if result != 1 {
t.Error("expected nonzero, got", result)
func testPrivateKeyBelowMax(t testing.TB, id PrimeFieldId) {
params := Params(id)
for variant,keySz:=range(
map[KeyVariant]*DomainParams {
KeyVariant_SIDH_A: &params.A,
KeyVariant_SIDH_B: &params.B}){

func(v KeyVariant, dp *DomainParams) {
var blen = int(dp.SecretByteLen)
var prv = NewPrivateKey(id, v)

// Calculate either (2^e2 - 1) or (2^s - 1); where s=ceil(log_2(3^e3)))
maxSecertVal := big.NewInt(int64(dp.SecretBitLen))
maxSecertVal.Exp(big.NewInt(int64(2)), maxSecertVal, nil)
maxSecertVal.Sub(maxSecertVal, big.NewInt(1))

// Do same test 1000 times
for i:=0; i<1000; i++ {
err := prv.Generate(rand.Reader)
checkErr(t, err, "Private key generation")

// Convert to big-endian, as that's what expected by (*Int)SetBytes()
secretBytes := prv.Export()
for i:=0; i<int(blen/2); i++ {
tmp := secretBytes[i] ^ secretBytes[blen-i-1]
secretBytes[i] = tmp ^ secretBytes[i]
secretBytes[blen-i-1] = tmp ^ secretBytes[blen-i-1]
}
prvBig := new(big.Int).SetBytes(secretBytes)
// Check if generated key is bigger then acceptable
if prvBig.Cmp(maxSecertVal) == 1 {
t.Error("Generated private key is wrong")
}
}
}(variant,keySz)
}
}



+ 6
- 8
sike/sike.go Прегледај датотеку

@@ -126,7 +126,7 @@ func Encapsulate(rng io.Reader, pub *PublicKey) (ctext []byte, secret []byte, er
// Buffer for random, secret message
var ptext = make([]byte, params.MsgLen)
// r = G(ptext||pub)
var r = make([]byte, params.SecretKeySize)
var r = make([]byte, params.A.SecretByteLen)
// Resulting shared secret
secret = make([]byte, params.KemSize)

@@ -141,9 +141,8 @@ func Encapsulate(rng io.Reader, pub *PublicKey) (ctext []byte, secret []byte, er
h.Write(pub.Export())
h.Read(r)

// cSHAKE256 implementation is byte oriented. Ensure bitlength is less then to E2
r[len(r)-1] &= params.A.MaskBytes[0]
r[len(r)-2] &= params.A.MaskBytes[1] // clear high bits, so scalar < 2*732
// cSHAKE256 implementation is byte oriented. Ensure bitlength is not bigger then to 2^e2-1
r[len(r)-1] &= (1 << (params.A.SecretBitLen % 8)) - 1

// (c0 || c1) = Enc(pkA, ptext; r)
skA := NewPrivateKey(params.Id, KeyVariant_SIDH_A)
@@ -173,7 +172,7 @@ func Encapsulate(rng io.Reader, pub *PublicKey) (ctext []byte, secret []byte, er
// Constant time for properly initialized input.
func Decapsulate(prv *PrivateKey, pub *PublicKey, ctext []byte) ([]byte, error) {
var params = pub.Params()
var r = make([]byte, params.SecretKeySize)
var r = make([]byte, params.A.SecretByteLen)
// Resulting shared secret
var secret = make([]byte, params.KemSize)
var skA = NewPrivateKey(params.Id, KeyVariant_SIDH_A)
@@ -189,9 +188,8 @@ func Decapsulate(prv *PrivateKey, pub *PublicKey, ctext []byte) ([]byte, error)
h.Write(pub.Export())
h.Read(r)

// cSHAKE256 implementation is byte oriented: Ensure bitlength is equal to E2
r[len(r)-1] &= params.A.MaskBytes[0]
r[len(r)-2] &= params.A.MaskBytes[1] // clear high bits, so scalar < 2*732
// cSHAKE256 implementation is byte oriented: Ensure bitlength is not bigger than 2^e2-1
r[len(r)-1] &= (1 << (params.A.SecretBitLen % 8)) - 1

// Never fails
skA.Import(r)


+ 1
- 1
sike/sike_test.go Прегледај датотеку

@@ -312,7 +312,7 @@ func TestSIKE_KAT(t *testing.T) {
// sk (secret key in test vector is concatenation of
// MSG + SECRET_BOB_KEY + PUBLIC_BOB_KEY. We use only MSG+SECRET_BOB_KEY
sk := readAndCheckLine(r)
sk = sk[:params.MsgLen+uint(params.SecretKeySize)]
sk = sk[:params.MsgLen+uint(params.B.SecretByteLen)]
// ct
ct := readAndCheckLine(r)
// ss


Loading…
Откажи
Сачувај