mirror of
https://github.com/v2fly/v2ray-core.git
synced 2026-08-03 21:50:42 -04:00
move vendor to external
This commit is contained in:
+226
@@ -0,0 +1,226 @@
|
||||
package sidh
|
||||
|
||||
import (
|
||||
"errors"
|
||||
. "v2ray.com/core/external/github.com/cloudflare/sidh/internal/isogeny"
|
||||
"io"
|
||||
)
|
||||
|
||||
// I keep it bool in order to be able to apply logical NOT
|
||||
type KeyVariant uint
|
||||
|
||||
// Id's correspond to bitlength of the prime field characteristic
|
||||
// Currently FP_751 is the only one supported by this implementation
|
||||
const (
|
||||
FP_503 uint8 = iota
|
||||
FP_751
|
||||
FP_964
|
||||
maxPrimeFieldId
|
||||
)
|
||||
|
||||
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
|
||||
)
|
||||
|
||||
// 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 public key
|
||||
type PublicKey struct {
|
||||
key
|
||||
affine_xP Fp2Element
|
||||
affine_xQ Fp2Element
|
||||
affine_xQmP Fp2Element
|
||||
}
|
||||
|
||||
// Defines operations on private key
|
||||
type PrivateKey struct {
|
||||
key
|
||||
// Secret key
|
||||
Scalar []byte
|
||||
// Used only by KEM
|
||||
S []byte
|
||||
}
|
||||
|
||||
// Accessor to the domain parameters
|
||||
func (key *key) Params() *SidhParams {
|
||||
return key.params
|
||||
}
|
||||
|
||||
// Accessor to key variant
|
||||
func (key *key) Variant() KeyVariant {
|
||||
return key.keyVariant
|
||||
}
|
||||
|
||||
// NewPrivateKey initializes private key.
|
||||
// Usage of this function guarantees that the object is correctly initialized.
|
||||
func NewPrivateKey(id uint8, v KeyVariant) *PrivateKey {
|
||||
prv := &PrivateKey{key: key{params: Params(id), keyVariant: v}}
|
||||
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)
|
||||
}
|
||||
return prv
|
||||
}
|
||||
|
||||
// NewPublicKey initializes public key.
|
||||
// Usage of this function guarantees that the object is correctly initialized.
|
||||
func NewPublicKey(id uint8, v KeyVariant) *PublicKey {
|
||||
return &PublicKey{key: key{params: Params(id), keyVariant: v}}
|
||||
}
|
||||
|
||||
// Import clears content of the public key currently stored in the structure
|
||||
// and imports key stored in the byte string. Returns error in case byte string
|
||||
// size is wrong. Doesn't perform any validation.
|
||||
func (pub *PublicKey) Import(input []byte) error {
|
||||
if len(input) != pub.Size() {
|
||||
return errors.New("sidh: input to short")
|
||||
}
|
||||
op := CurveOperations{Params: pub.params}
|
||||
ssSz := pub.params.SharedSecretSize
|
||||
op.Fp2FromBytes(&pub.affine_xP, input[0:ssSz])
|
||||
op.Fp2FromBytes(&pub.affine_xQ, input[ssSz:2*ssSz])
|
||||
op.Fp2FromBytes(&pub.affine_xQmP, input[2*ssSz:3*ssSz])
|
||||
return nil
|
||||
}
|
||||
|
||||
// Exports currently stored key. In case structure hasn't been filled with key data
|
||||
// returned byte string is filled with zeros.
|
||||
func (pub *PublicKey) Export() []byte {
|
||||
output := make([]byte, pub.params.PublicKeySize)
|
||||
op := CurveOperations{Params: pub.params}
|
||||
ssSz := pub.params.SharedSecretSize
|
||||
op.Fp2ToBytes(output[0:ssSz], &pub.affine_xP)
|
||||
op.Fp2ToBytes(output[ssSz:2*ssSz], &pub.affine_xQ)
|
||||
op.Fp2ToBytes(output[2*ssSz:3*ssSz], &pub.affine_xQmP)
|
||||
return output
|
||||
}
|
||||
|
||||
// Size returns size of the public key in bytes
|
||||
func (pub *PublicKey) Size() int {
|
||||
return pub.params.PublicKeySize
|
||||
}
|
||||
|
||||
// Exports currently stored key. In case structure hasn't been filled with key data
|
||||
// returned byte string is filled with zeros.
|
||||
func (prv *PrivateKey) Export() []byte {
|
||||
ret := make([]byte, len(prv.Scalar)+len(prv.S))
|
||||
copy(ret, prv.S)
|
||||
copy(ret[len(prv.S):], prv.Scalar)
|
||||
return ret
|
||||
}
|
||||
|
||||
// Size returns size of the private key in bytes
|
||||
func (prv *PrivateKey) Size() int {
|
||||
tmp := len(prv.Scalar)
|
||||
if prv.Variant() == KeyVariant_SIKE {
|
||||
tmp += int(prv.params.MsgLen)
|
||||
}
|
||||
return tmp
|
||||
}
|
||||
|
||||
// Import clears content of the private key currently stored in the structure
|
||||
// and imports key from octet string. In case of SIKE, the random value 'S'
|
||||
// must be prepended to the value of actual private key (see SIKE spec for details).
|
||||
// Function doesn't import public key value to PrivateKey object.
|
||||
func (prv *PrivateKey) Import(input []byte) error {
|
||||
if len(input) != prv.Size() {
|
||||
return errors.New("sidh: input to short")
|
||||
}
|
||||
copy(prv.S, input[:len(prv.S)])
|
||||
copy(prv.Scalar, input[len(prv.S):])
|
||||
return nil
|
||||
}
|
||||
|
||||
// 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 {
|
||||
dp = &prv.params.A
|
||||
} else {
|
||||
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
|
||||
}
|
||||
|
||||
// Generates public key.
|
||||
//
|
||||
// Constant time.
|
||||
func (prv *PrivateKey) GeneratePublicKey() *PublicKey {
|
||||
if (prv.keyVariant & KeyVariant_SIDH_A) == KeyVariant_SIDH_A {
|
||||
return publicKeyGenA(prv)
|
||||
}
|
||||
return publicKeyGenB(prv)
|
||||
}
|
||||
|
||||
// Computes a shared secret which is a j-invariant. Function requires that pub has
|
||||
// different KeyVariant than prv. Length of returned output is 2*ceil(log_2 P)/8),
|
||||
// where P is a prime defining finite field.
|
||||
//
|
||||
// It's important to notice that each keypair must not be used more than once
|
||||
// to calculate shared secret.
|
||||
//
|
||||
// Function may return error. This happens only in case provided input is invalid.
|
||||
// Constant time for properly initialized private and public key.
|
||||
func DeriveSecret(prv *PrivateKey, pub *PublicKey) ([]byte, error) {
|
||||
|
||||
if (pub == nil) || (prv == nil) {
|
||||
return nil, errors.New("sidh: invalid arguments")
|
||||
}
|
||||
|
||||
if (pub.keyVariant == prv.keyVariant) || (pub.params.Id != prv.params.Id) {
|
||||
return nil, errors.New("sidh: public and private are incompatbile")
|
||||
}
|
||||
|
||||
if (prv.keyVariant & KeyVariant_SIDH_A) == KeyVariant_SIDH_A {
|
||||
return deriveSecretA(prv, pub), nil
|
||||
} else {
|
||||
return deriveSecretB(prv, pub), nil
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
package sidh
|
||||
|
||||
import (
|
||||
. "v2ray.com/core/external/github.com/cloudflare/sidh/internal/isogeny"
|
||||
p503 "v2ray.com/core/external/github.com/cloudflare/sidh/p503"
|
||||
p751 "v2ray.com/core/external/github.com/cloudflare/sidh/p751"
|
||||
)
|
||||
|
||||
// Keeps mapping: SIDH prime field ID to domain parameters
|
||||
var sidhParams = make(map[uint8]SidhParams)
|
||||
|
||||
// Params returns domain parameters corresponding to finite field and identified by
|
||||
// `id` provieded by the caller. Function panics in case `id` wasn't registered earlier.
|
||||
func Params(id uint8) *SidhParams {
|
||||
if val, ok := sidhParams[id]; ok {
|
||||
return &val
|
||||
}
|
||||
panic("sidh: SIDH Params ID unregistered")
|
||||
}
|
||||
|
||||
func init() {
|
||||
p503 := SidhParams{
|
||||
Id: FP_503,
|
||||
PublicKeySize: p503.P503_PublicKeySize,
|
||||
SharedSecretSize: p503.P503_SharedSecretSize,
|
||||
A: DomainParams{
|
||||
Affine_P: p503.P503_affine_PA,
|
||||
Affine_Q: p503.P503_affine_QA,
|
||||
Affine_R: p503.P503_affine_RA,
|
||||
SecretBitLen: p503.P503_SecretBitLenA,
|
||||
SecretByteLen: uint((p503.P503_SecretBitLenA + 7) / 8),
|
||||
IsogenyStrategy: p503.P503_AliceIsogenyStrategy[:],
|
||||
},
|
||||
B: DomainParams{
|
||||
Affine_P: p503.P503_affine_PB,
|
||||
Affine_Q: p503.P503_affine_QB,
|
||||
Affine_R: p503.P503_affine_RB,
|
||||
SecretBitLen: p503.P503_SecretBitLenB,
|
||||
SecretByteLen: uint((p503.P503_SecretBitLenB + 7) / 8),
|
||||
IsogenyStrategy: p503.P503_BobIsogenyStrategy[:],
|
||||
},
|
||||
OneFp2: p503.P503_OneFp2,
|
||||
HalfFp2: p503.P503_HalfFp2,
|
||||
MsgLen: 24,
|
||||
// SIKEp751 provides 128 bit of classical security ([SIKE], 5.1)
|
||||
KemSize: 16,
|
||||
Bytelen: p503.P503_Bytelen,
|
||||
Op: p503.FieldOperations(),
|
||||
}
|
||||
|
||||
p751 := SidhParams{
|
||||
Id: FP_751,
|
||||
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,
|
||||
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,
|
||||
IsogenyStrategy: p751.P751_BobIsogenyStrategy[:],
|
||||
SecretBitLen: p751.P751_SecretBitLenB,
|
||||
SecretByteLen: uint((p751.P751_SecretBitLenB + 7) / 8),
|
||||
},
|
||||
OneFp2: p751.P751_OneFp2,
|
||||
HalfFp2: p751.P751_HalfFp2,
|
||||
MsgLen: 32,
|
||||
// SIKEp751 provides 192 bit of classical security ([SIKE], 5.1)
|
||||
KemSize: 24,
|
||||
Bytelen: p751.P751_Bytelen,
|
||||
Op: p751.FieldOperations(),
|
||||
}
|
||||
|
||||
sidhParams[FP_503] = p503
|
||||
sidhParams[FP_751] = p751
|
||||
}
|
||||
+302
@@ -0,0 +1,302 @@
|
||||
package sidh
|
||||
|
||||
import (
|
||||
. "v2ray.com/core/external/github.com/cloudflare/sidh/internal/isogeny"
|
||||
)
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Functions for traversing isogeny trees acoording to strategy. Key type 'A' is
|
||||
//
|
||||
|
||||
// Traverses isogeny tree in order to compute xR, xP, xQ and xQmP needed
|
||||
// for public key generation.
|
||||
func traverseTreePublicKeyA(curve *ProjectiveCurveParameters, xR, phiP, phiQ, phiR *ProjectivePoint, pub *PublicKey) {
|
||||
var points = make([]ProjectivePoint, 0, 8)
|
||||
var indices = make([]int, 0, 8)
|
||||
var i, sidx int
|
||||
var op = CurveOperations{Params: pub.params}
|
||||
|
||||
cparam := op.CalcCurveParamsEquiv4(curve)
|
||||
phi := Newisogeny4(op.Params.Op)
|
||||
strat := pub.params.A.IsogenyStrategy
|
||||
stratSz := len(strat)
|
||||
|
||||
for j := 1; j <= stratSz; j++ {
|
||||
for i <= stratSz-j {
|
||||
points = append(points, *xR)
|
||||
indices = append(indices, i)
|
||||
|
||||
k := strat[sidx]
|
||||
sidx++
|
||||
op.Pow2k(xR, &cparam, 2*k)
|
||||
i += int(k)
|
||||
}
|
||||
|
||||
cparam = phi.GenerateCurve(xR)
|
||||
for k := 0; k < len(points); k++ {
|
||||
points[k] = phi.EvaluatePoint(&points[k])
|
||||
}
|
||||
|
||||
*phiP = phi.EvaluatePoint(phiP)
|
||||
*phiQ = phi.EvaluatePoint(phiQ)
|
||||
*phiR = phi.EvaluatePoint(phiR)
|
||||
|
||||
// pop xR from points
|
||||
*xR, points = points[len(points)-1], points[:len(points)-1]
|
||||
i, indices = int(indices[len(indices)-1]), indices[:len(indices)-1]
|
||||
}
|
||||
}
|
||||
|
||||
// Traverses isogeny tree in order to compute xR needed
|
||||
// for public key generation.
|
||||
func traverseTreeSharedKeyA(curve *ProjectiveCurveParameters, xR *ProjectivePoint, pub *PublicKey) {
|
||||
var points = make([]ProjectivePoint, 0, 8)
|
||||
var indices = make([]int, 0, 8)
|
||||
var i, sidx int
|
||||
var op = CurveOperations{Params: pub.params}
|
||||
|
||||
cparam := op.CalcCurveParamsEquiv4(curve)
|
||||
phi := Newisogeny4(op.Params.Op)
|
||||
strat := pub.params.A.IsogenyStrategy
|
||||
stratSz := len(strat)
|
||||
|
||||
for j := 1; j <= stratSz; j++ {
|
||||
for i <= stratSz-j {
|
||||
points = append(points, *xR)
|
||||
indices = append(indices, i)
|
||||
|
||||
k := strat[sidx]
|
||||
sidx++
|
||||
op.Pow2k(xR, &cparam, 2*k)
|
||||
i += int(k)
|
||||
}
|
||||
|
||||
cparam = phi.GenerateCurve(xR)
|
||||
for k := 0; k < len(points); k++ {
|
||||
points[k] = phi.EvaluatePoint(&points[k])
|
||||
}
|
||||
|
||||
// pop xR from points
|
||||
*xR, points = points[len(points)-1], points[:len(points)-1]
|
||||
i, indices = int(indices[len(indices)-1]), indices[:len(indices)-1]
|
||||
}
|
||||
}
|
||||
|
||||
// Traverses isogeny tree in order to compute xR, xP, xQ and xQmP needed
|
||||
// for public key generation.
|
||||
func traverseTreePublicKeyB(curve *ProjectiveCurveParameters, xR, phiP, phiQ, phiR *ProjectivePoint, pub *PublicKey) {
|
||||
var points = make([]ProjectivePoint, 0, 8)
|
||||
var indices = make([]int, 0, 8)
|
||||
var i, sidx int
|
||||
var op = CurveOperations{Params: pub.params}
|
||||
|
||||
cparam := op.CalcCurveParamsEquiv3(curve)
|
||||
phi := Newisogeny3(op.Params.Op)
|
||||
strat := pub.params.B.IsogenyStrategy
|
||||
stratSz := len(strat)
|
||||
|
||||
for j := 1; j <= stratSz; j++ {
|
||||
for i <= stratSz-j {
|
||||
points = append(points, *xR)
|
||||
indices = append(indices, i)
|
||||
|
||||
k := strat[sidx]
|
||||
sidx++
|
||||
op.Pow3k(xR, &cparam, k)
|
||||
i += int(k)
|
||||
}
|
||||
|
||||
cparam = phi.GenerateCurve(xR)
|
||||
for k := 0; k < len(points); k++ {
|
||||
points[k] = phi.EvaluatePoint(&points[k])
|
||||
}
|
||||
|
||||
*phiP = phi.EvaluatePoint(phiP)
|
||||
*phiQ = phi.EvaluatePoint(phiQ)
|
||||
*phiR = phi.EvaluatePoint(phiR)
|
||||
|
||||
// pop xR from points
|
||||
*xR, points = points[len(points)-1], points[:len(points)-1]
|
||||
i, indices = int(indices[len(indices)-1]), indices[:len(indices)-1]
|
||||
}
|
||||
}
|
||||
|
||||
// Traverses isogeny tree in order to compute xR, xP, xQ and xQmP needed
|
||||
// for public key generation.
|
||||
func traverseTreeSharedKeyB(curve *ProjectiveCurveParameters, xR *ProjectivePoint, pub *PublicKey) {
|
||||
var points = make([]ProjectivePoint, 0, 8)
|
||||
var indices = make([]int, 0, 8)
|
||||
var i, sidx int
|
||||
var op = CurveOperations{Params: pub.params}
|
||||
|
||||
cparam := op.CalcCurveParamsEquiv3(curve)
|
||||
phi := Newisogeny3(op.Params.Op)
|
||||
strat := pub.params.B.IsogenyStrategy
|
||||
stratSz := len(strat)
|
||||
|
||||
for j := 1; j <= stratSz; j++ {
|
||||
for i <= stratSz-j {
|
||||
points = append(points, *xR)
|
||||
indices = append(indices, i)
|
||||
|
||||
k := strat[sidx]
|
||||
sidx++
|
||||
op.Pow3k(xR, &cparam, k)
|
||||
i += int(k)
|
||||
}
|
||||
|
||||
cparam = phi.GenerateCurve(xR)
|
||||
for k := 0; k < len(points); k++ {
|
||||
points[k] = phi.EvaluatePoint(&points[k])
|
||||
}
|
||||
|
||||
// pop xR from points
|
||||
*xR, points = points[len(points)-1], points[:len(points)-1]
|
||||
i, indices = int(indices[len(indices)-1]), indices[:len(indices)-1]
|
||||
}
|
||||
}
|
||||
|
||||
// Generate a public key in the 2-torsion group
|
||||
func publicKeyGenA(prv *PrivateKey) (pub *PublicKey) {
|
||||
var xPA, xQA, xRA ProjectivePoint
|
||||
var xPB, xQB, xRB, xR ProjectivePoint
|
||||
var invZP, invZQ, invZR Fp2Element
|
||||
var tmp ProjectiveCurveParameters
|
||||
|
||||
pub = NewPublicKey(prv.params.Id, KeyVariant_SIDH_A)
|
||||
var op = CurveOperations{Params: pub.params}
|
||||
var phi = Newisogeny4(op.Params.Op)
|
||||
|
||||
// Load points for A
|
||||
xPA = ProjectivePoint{X: prv.params.A.Affine_P, Z: prv.params.OneFp2}
|
||||
xQA = ProjectivePoint{X: prv.params.A.Affine_Q, Z: prv.params.OneFp2}
|
||||
xRA = ProjectivePoint{X: prv.params.A.Affine_R, Z: prv.params.OneFp2}
|
||||
|
||||
// Load points for B
|
||||
xRB = ProjectivePoint{X: prv.params.B.Affine_R, Z: prv.params.OneFp2}
|
||||
xQB = ProjectivePoint{X: prv.params.B.Affine_Q, Z: prv.params.OneFp2}
|
||||
xPB = ProjectivePoint{X: prv.params.B.Affine_P, Z: prv.params.OneFp2}
|
||||
|
||||
// Find isogeny kernel
|
||||
tmp.C = pub.params.OneFp2
|
||||
xR = op.ScalarMul3Pt(&tmp, &xPA, &xQA, &xRA, prv.params.A.SecretBitLen, prv.Scalar)
|
||||
|
||||
// Reset params object and travers isogeny tree
|
||||
tmp.C = pub.params.OneFp2
|
||||
tmp.A.Zeroize()
|
||||
traverseTreePublicKeyA(&tmp, &xR, &xPB, &xQB, &xRB, pub)
|
||||
|
||||
// Secret isogeny
|
||||
phi.GenerateCurve(&xR)
|
||||
xPA = phi.EvaluatePoint(&xPB)
|
||||
xQA = phi.EvaluatePoint(&xQB)
|
||||
xRA = phi.EvaluatePoint(&xRB)
|
||||
op.Fp2Batch3Inv(&xPA.Z, &xQA.Z, &xRA.Z, &invZP, &invZQ, &invZR)
|
||||
|
||||
op.Params.Op.Mul(&pub.affine_xP, &xPA.X, &invZP)
|
||||
op.Params.Op.Mul(&pub.affine_xQ, &xQA.X, &invZQ)
|
||||
op.Params.Op.Mul(&pub.affine_xQmP, &xRA.X, &invZR)
|
||||
return
|
||||
}
|
||||
|
||||
// Generate a public key in the 3-torsion group
|
||||
func publicKeyGenB(prv *PrivateKey) (pub *PublicKey) {
|
||||
var xPB, xQB, xRB, xR ProjectivePoint
|
||||
var xPA, xQA, xRA ProjectivePoint
|
||||
var invZP, invZQ, invZR Fp2Element
|
||||
var tmp ProjectiveCurveParameters
|
||||
|
||||
pub = NewPublicKey(prv.params.Id, prv.keyVariant)
|
||||
var op = CurveOperations{Params: pub.params}
|
||||
var phi = Newisogeny3(op.Params.Op)
|
||||
|
||||
// Load points for B
|
||||
xRB = ProjectivePoint{X: prv.params.B.Affine_R, Z: prv.params.OneFp2}
|
||||
xQB = ProjectivePoint{X: prv.params.B.Affine_Q, Z: prv.params.OneFp2}
|
||||
xPB = ProjectivePoint{X: prv.params.B.Affine_P, Z: prv.params.OneFp2}
|
||||
|
||||
// Load points for A
|
||||
xPA = ProjectivePoint{X: prv.params.A.Affine_P, Z: prv.params.OneFp2}
|
||||
xQA = ProjectivePoint{X: prv.params.A.Affine_Q, Z: prv.params.OneFp2}
|
||||
xRA = ProjectivePoint{X: prv.params.A.Affine_R, Z: prv.params.OneFp2}
|
||||
|
||||
tmp.C = pub.params.OneFp2
|
||||
xR = op.ScalarMul3Pt(&tmp, &xPB, &xQB, &xRB, prv.params.B.SecretBitLen, prv.Scalar)
|
||||
|
||||
tmp.C = pub.params.OneFp2
|
||||
tmp.A.Zeroize()
|
||||
traverseTreePublicKeyB(&tmp, &xR, &xPA, &xQA, &xRA, pub)
|
||||
|
||||
phi.GenerateCurve(&xR)
|
||||
xPB = phi.EvaluatePoint(&xPA)
|
||||
xQB = phi.EvaluatePoint(&xQA)
|
||||
xRB = phi.EvaluatePoint(&xRA)
|
||||
op.Fp2Batch3Inv(&xPB.Z, &xQB.Z, &xRB.Z, &invZP, &invZQ, &invZR)
|
||||
|
||||
op.Params.Op.Mul(&pub.affine_xP, &xPB.X, &invZP)
|
||||
op.Params.Op.Mul(&pub.affine_xQ, &xQB.X, &invZQ)
|
||||
op.Params.Op.Mul(&pub.affine_xQmP, &xRB.X, &invZR)
|
||||
return
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Key agreement functions
|
||||
//
|
||||
|
||||
// Establishing shared keys in in 2-torsion group
|
||||
func deriveSecretA(prv *PrivateKey, pub *PublicKey) []byte {
|
||||
var sharedSecret = make([]byte, pub.params.SharedSecretSize)
|
||||
var cparam ProjectiveCurveParameters
|
||||
var xP, xQ, xQmP ProjectivePoint
|
||||
var xR ProjectivePoint
|
||||
var op = CurveOperations{Params: prv.params}
|
||||
var phi = Newisogeny4(op.Params.Op)
|
||||
|
||||
// Recover curve coefficients
|
||||
cparam.C = pub.params.OneFp2
|
||||
op.RecoverCoordinateA(&cparam, &pub.affine_xP, &pub.affine_xQ, &pub.affine_xQmP)
|
||||
|
||||
// Find kernel of the morphism
|
||||
xP = ProjectivePoint{X: pub.affine_xP, Z: pub.params.OneFp2}
|
||||
xQ = ProjectivePoint{X: pub.affine_xQ, Z: pub.params.OneFp2}
|
||||
xQmP = ProjectivePoint{X: pub.affine_xQmP, Z: pub.params.OneFp2}
|
||||
xR = op.ScalarMul3Pt(&cparam, &xP, &xQ, &xQmP, pub.params.A.SecretBitLen, prv.Scalar)
|
||||
|
||||
// Traverse isogeny tree
|
||||
traverseTreeSharedKeyA(&cparam, &xR, pub)
|
||||
|
||||
// Calculate j-invariant on isogeneus curve
|
||||
c := phi.GenerateCurve(&xR)
|
||||
op.RecoverCurveCoefficients4(&cparam, &c)
|
||||
op.Jinvariant(&cparam, sharedSecret)
|
||||
return sharedSecret
|
||||
}
|
||||
|
||||
// Establishing shared keys in in 3-torsion group
|
||||
func deriveSecretB(prv *PrivateKey, pub *PublicKey) []byte {
|
||||
var sharedSecret = make([]byte, pub.params.SharedSecretSize)
|
||||
var xP, xQ, xQmP ProjectivePoint
|
||||
var xR ProjectivePoint
|
||||
var cparam ProjectiveCurveParameters
|
||||
var op = CurveOperations{Params: prv.params}
|
||||
var phi = Newisogeny3(op.Params.Op)
|
||||
|
||||
// Recover curve coefficients
|
||||
cparam.C = pub.params.OneFp2
|
||||
op.RecoverCoordinateA(&cparam, &pub.affine_xP, &pub.affine_xQ, &pub.affine_xQmP)
|
||||
|
||||
// Find kernel of the morphism
|
||||
xP = ProjectivePoint{X: pub.affine_xP, Z: pub.params.OneFp2}
|
||||
xQ = ProjectivePoint{X: pub.affine_xQ, Z: pub.params.OneFp2}
|
||||
xQmP = ProjectivePoint{X: pub.affine_xQmP, Z: pub.params.OneFp2}
|
||||
xR = op.ScalarMul3Pt(&cparam, &xP, &xQ, &xQmP, pub.params.B.SecretBitLen, prv.Scalar)
|
||||
|
||||
// Traverse isogeny tree
|
||||
traverseTreeSharedKeyB(&cparam, &xR, pub)
|
||||
|
||||
// Calculate j-invariant on isogeneus curve
|
||||
c := phi.GenerateCurve(&xR)
|
||||
op.RecoverCurveCoefficients3(&cparam, &c)
|
||||
op.Jinvariant(&cparam, sharedSecret)
|
||||
return sharedSecret
|
||||
}
|
||||
Reference in New Issue
Block a user