mirror of
https://github.com/henrydcase/nobs.git
synced 2024-11-29 10:21:23 +00:00
303 lines
9.3 KiB
Go
303 lines
9.3 KiB
Go
package sidh
|
|
|
|
import (
|
|
. "github.com/henrydcase/nobs/dh/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
|
|
}
|