http://git-wip-us.apache.org/repos/asf/incubator-milagro-crypto/blob/85fabaa6/go/amcl-go/PAIR.go ---------------------------------------------------------------------- diff --git a/go/amcl-go/PAIR.go b/go/amcl-go/PAIR.go new file mode 100644 index 0000000..8a7de9f --- /dev/null +++ b/go/amcl-go/PAIR.go @@ -0,0 +1,541 @@ +/* +Licensed to the Apache Software Foundation (ASF) under one +or more contributor license agreements. See the NOTICE file +distributed with this work for additional information +regarding copyright ownership. The ASF licenses this file +to you under the Apache License, Version 2.0 (the +"License"); you may not use this file except in compliance +with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, +software distributed under the License is distributed on an +"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +KIND, either express or implied. See the License for the +specific language governing permissions and limitations +under the License. +*/ + +/* AMCL BN Curve Pairing functions */ + +package amcl + +//import "fmt" + +/* Line function */ +func line(A *ECP2, B *ECP2, Qx *FP, Qy *FP) *FP12 { + P := NewECP2() + + P.copy(A) + ZZ := NewFP2copy(P.getz()) + ZZ.sqr() + var D int + if A == B { + D = A.dbl() + } else { + D = A.add(B) + } + + if D < 0 { + return NewFP12int(1) + } + + Z3 := NewFP2copy(A.getz()) + + var a *FP4 + var b *FP4 + c := NewFP4int(0) + + if D == 0 { /* Addition */ + X := NewFP2copy(B.getx()) + Y := NewFP2copy(B.gety()) + T := NewFP2copy(P.getz()) + T.mul(Y) + ZZ.mul(T) + + NY := NewFP2copy(P.gety()) + NY.neg() + ZZ.add(NY) + Z3.pmul(Qy) + T.mul(P.getx()) + X.mul(NY) + T.add(X) + a = NewFP4fp2s(Z3, T) + ZZ.neg() + ZZ.pmul(Qx) + b = NewFP4fp2(ZZ) + } else { /* Doubling */ + X := NewFP2copy(P.getx()) + Y := NewFP2copy(P.gety()) + T := NewFP2copy(P.getx()) + T.sqr() + T.imul(3) + + Y.sqr() + Y.add(Y) + Z3.mul(ZZ) + Z3.pmul(Qy) + + X.mul(T) + X.sub(Y) + a = NewFP4fp2s(Z3, X) + T.neg() + ZZ.mul(T) + ZZ.pmul(Qx) + b = NewFP4fp2(ZZ) + } + return NewFP12fp4s(a, b, c) +} + +/* Optimal R-ate pairing */ +func ate(P *ECP2, Q *ECP) *FP12 { + f := NewFP2bigs(NewBIGints(CURVE_Fra), NewBIGints(CURVE_Frb)) + x := NewBIGints(CURVE_Bnx) + n := NewBIGcopy(x) + K := NewECP2() + var lv *FP12 + n.pmul(6) + n.dec(2) + n.norm() + P.affine() + Q.affine() + Qx := NewFPcopy(Q.getx()) + Qy := NewFPcopy(Q.gety()) + + A := NewECP2() + r := NewFP12int(1) + + A.copy(P) + nb := n.nbits() + + for i := nb - 2; i >= 1; i-- { + lv = line(A, A, Qx, Qy) + r.smul(lv) + + if n.bit(i) == 1 { + lv = line(A, P, Qx, Qy) + r.smul(lv) + } + r.sqr() + } + + lv = line(A, A, Qx, Qy) + r.smul(lv) + + /* R-ate fixup */ + + r.conj() + + K.copy(P) + K.frob(f) + A.neg() + lv = line(A, K, Qx, Qy) + r.smul(lv) + K.frob(f) + K.neg() + lv = line(A, K, Qx, Qy) + r.smul(lv) + + return r +} + +/* Optimal R-ate double pairing e(P,Q).e(R,S) */ +func ate2(P *ECP2, Q *ECP, R *ECP2, S *ECP) *FP12 { + f := NewFP2bigs(NewBIGints(CURVE_Fra), NewBIGints(CURVE_Frb)) + x := NewBIGints(CURVE_Bnx) + n := NewBIGcopy(x) + K := NewECP2() + var lv *FP12 + n.pmul(6) + n.dec(2) + n.norm() + P.affine() + Q.affine() + R.affine() + S.affine() + + Qx := NewFPcopy(Q.getx()) + Qy := NewFPcopy(Q.gety()) + Sx := NewFPcopy(S.getx()) + Sy := NewFPcopy(S.gety()) + + A := NewECP2() + B := NewECP2() + r := NewFP12int(1) + + A.copy(P) + B.copy(R) + nb := n.nbits() + + for i := nb - 2; i >= 1; i-- { + lv = line(A, A, Qx, Qy) + r.smul(lv) + lv = line(B, B, Sx, Sy) + r.smul(lv) + + if n.bit(i) == 1 { + lv = line(A, P, Qx, Qy) + r.smul(lv) + lv = line(B, R, Sx, Sy) + r.smul(lv) + } + r.sqr() + } + + lv = line(A, A, Qx, Qy) + r.smul(lv) + + lv = line(B, B, Sx, Sy) + r.smul(lv) + + /* R-ate fixup */ + r.conj() + + K.copy(P) + K.frob(f) + A.neg() + lv = line(A, K, Qx, Qy) + r.smul(lv) + K.frob(f) + K.neg() + lv = line(A, K, Qx, Qy) + r.smul(lv) + + K.copy(R) + K.frob(f) + B.neg() + lv = line(B, K, Sx, Sy) + r.smul(lv) + K.frob(f) + K.neg() + lv = line(B, K, Sx, Sy) + r.smul(lv) + + return r +} + +/* final exponentiation - keep separate for multi-pairings and to avoid thrashing stack */ +func fexp(m *FP12) *FP12 { + f := NewFP2bigs(NewBIGints(CURVE_Fra), NewBIGints(CURVE_Frb)) + x := NewBIGints(CURVE_Bnx) + r := NewFP12copy(m) + + /* Easy part of final exp */ + lv := NewFP12copy(r) + lv.inverse() + r.conj() + + r.mul(lv) + lv.copy(r) + r.frob(f) + r.frob(f) + r.mul(lv) + /* Hard part of final exp */ + lv.copy(r) + lv.frob(f) + x0 := NewFP12copy(lv) + x0.frob(f) + lv.mul(r) + x0.mul(lv) + x0.frob(f) + x1 := NewFP12copy(r) + x1.conj() + x4 := r.pow(x) + + x3 := NewFP12copy(x4) + x3.frob(f) + + x2 := x4.pow(x) + + x5 := NewFP12copy(x2) + x5.conj() + lv = x2.pow(x) + + x2.frob(f) + r.copy(x2) + r.conj() + + x4.mul(r) + x2.frob(f) + + r.copy(lv) + r.frob(f) + lv.mul(r) + + lv.usqr() + lv.mul(x4) + lv.mul(x5) + r.copy(x3) + r.mul(x5) + r.mul(lv) + lv.mul(x2) + r.usqr() + r.mul(lv) + r.usqr() + lv.copy(r) + lv.mul(x1) + r.mul(x0) + lv.usqr() + r.mul(lv) + r.reduce() + return r +} + +/* GLV method */ +func glv(e *BIG) []*BIG { + t := NewBIGint(0) + q := NewBIGints(CURVE_Order) + var u []*BIG + var v []*BIG + + for i := 0; i < 2; i++ { + t.copy(NewBIGints(CURVE_W[i])) // why not just t=new BIG(ROM.CURVE_W[i]); + d := mul(t, e) + v = append(v, NewBIGcopy(d.div(q))) + u = append(u, NewBIGint(0)) + } + u[0].copy(e) + for i := 0; i < 2; i++ { + for j := 0; j < 2; j++ { + t.copy(NewBIGints(CURVE_SB[j][i])) + t.copy(modmul(v[j], t, q)) + u[i].add(q) + u[i].sub(t) + u[i].mod(q) + } + } + return u +} + +/* Galbraith & Scott Method */ +func gs(e *BIG) []*BIG { + t := NewBIGint(0) + q := NewBIGints(CURVE_Order) + var u []*BIG + var v []*BIG + for i := 0; i < 4; i++ { + t.copy(NewBIGints(CURVE_WB[i])) + d := mul(t, e) + v = append(v, NewBIGcopy(d.div(q))) + u = append(u, NewBIGint(0)) + } + u[0].copy(e) + for i := 0; i < 4; i++ { + for j := 0; j < 4; j++ { + t.copy(NewBIGints(CURVE_BB[j][i])) + t.copy(modmul(v[j], t, q)) + u[i].add(q) + u[i].sub(t) + u[i].mod(q) + } + } + return u +} + +/* Multiply P by e in group G1 */ +func G1mul(P *ECP, e *BIG) *ECP { + var R *ECP + if USE_GLV { + P.affine() + R = NewECP() + R.copy(P) + Q := NewECP() + Q.copy(P) + q := NewBIGints(CURVE_Order) + cru := NewFPbig(NewBIGints(CURVE_Cru)) + t := NewBIGint(0) + u := glv(e) + Q.getx().mul(cru) + + np := u[0].nbits() + t.copy(modneg(u[0], q)) + nn := t.nbits() + if nn < np { + u[0].copy(t) + R.neg() + } + + np = u[1].nbits() + t.copy(modneg(u[1], q)) + nn = t.nbits() + if nn < np { + u[1].copy(t) + Q.neg() + } + + R = R.mul2(u[0], Q, u[1]) + + } else { + R = P.mul(e) + } + return R +} + +/* Multiply P by e in group G2 */ +func G2mul(P *ECP2, e *BIG) *ECP2 { + var R *ECP2 + if USE_GS_G2 { + var Q []*ECP2 + f := NewFP2bigs(NewBIGints(CURVE_Fra), NewBIGints(CURVE_Frb)) + q := NewBIGints(CURVE_Order) + u := gs(e) + + t := NewBIGint(0) + P.affine() + Q = append(Q, NewECP2()) + Q[0].copy(P) + for i := 1; i < 4; i++ { + Q = append(Q, NewECP2()) + Q[i].copy(Q[i-1]) + Q[i].frob(f) + } + for i := 0; i < 4; i++ { + np := u[i].nbits() + t.copy(modneg(u[i], q)) + nn := t.nbits() + if nn < np { + u[i].copy(t) + Q[i].neg() + } + } + R = mul4(Q, u) + + } else { + R = P.mul(e) + } + return R +} + +/* f=f^e */ +/* Note that this method requires a lot of RAM! Better to use compressed XTR method, see FP4.java */ +func GTpow(d *FP12, e *BIG) *FP12 { + var r *FP12 + if USE_GS_GT { + var g []*FP12 + f := NewFP2bigs(NewBIGints(CURVE_Fra), NewBIGints(CURVE_Frb)) + q := NewBIGints(CURVE_Order) + t := NewBIGint(0) + + u := gs(e) + + g = append(g, NewFP12copy(d)) + for i := 1; i < 4; i++ { + g = append(g, NewFP12int(0)) + g[i].copy(g[i-1]) + g[i].frob(f) + } + for i := 0; i < 4; i++ { + np := u[i].nbits() + t.copy(modneg(u[i], q)) + nn := t.nbits() + if nn < np { + u[i].copy(t) + g[i].conj() + } + } + r = pow4(g, u) + } else { + r = d.pow(e) + } + return r +} + +/* test group membership */ +/* with GT-Strong curve, now only check that m!=1, conj(m)*m==1, and m.m^{p^4}=m^{p^2} */ +func GTmember(m *FP12) bool { + if m.isunity() { + return false + } + r := NewFP12copy(m) + r.conj() + r.mul(m) + if !r.isunity() { + return false + } + + f := NewFP2bigs(NewBIGints(CURVE_Fra), NewBIGints(CURVE_Frb)) + + r.copy(m) + r.frob(f) + r.frob(f) + w := NewFP12copy(r) + w.frob(f) + w.frob(f) + w.mul(m) + if !GT_STRONG { + if !w.equals(r) { + return false + } + x := NewBIGints(CURVE_Bnx) + r.copy(m) + w = r.pow(x) + w = w.pow(x) + r.copy(w) + r.sqr() + r.mul(w) + r.sqr() + w.copy(m) + w.frob(f) + } + return w.equals(r) +} + +/* +func main() { + + Q:=NewECPbigs(NewBIGints(CURVE_Gx),NewBIGints(CURVE_Gy)) + P:=NewECP2fp2s(NewFP2bigs(NewBIGints(CURVE_Pxa),NewBIGints(CURVE_Pxb)),NewFP2bigs(NewBIGints(CURVE_Pya),NewBIGints(CURVE_Pyb))) + + r:=NewBIGints(CURVE_Order) + xa:=NewBIGints(CURVE_Pxa) + + fmt.Printf("P= "+P.toString()) + fmt.Printf("\n"); + fmt.Printf("Q= "+Q.toString()); + fmt.Printf("\n"); + + //m:=NewBIGint(17) + + e:=ate(P,Q) + fmt.Printf("\ne= "+e.toString()) + fmt.Printf("\n") + + e=fexp(e) + // e=GTpow(e,m); + + fmt.Printf("\ne= "+e.toString()) + fmt.Printf("\n"); + GLV:=glv(r) + + fmt.Printf("GLV[0]= "+GLV[0].toString()) + fmt.Printf("\n") + + fmt.Printf("GLV[0]= "+GLV[1].toString()) + fmt.Printf("\n") + + G:=NewECP(); G.copy(Q) + R:=NewECP2(); R.copy(P) + + + e=ate(R,Q) + e=fexp(e) + + e=GTpow(e,xa) + fmt.Printf("\ne= "+e.toString()); + fmt.Printf("\n") + + R=G2mul(R,xa) + e=ate(R,G) + e=fexp(e) + + fmt.Printf("\ne= "+e.toString()) + fmt.Printf("\n") + + G=G1mul(G,xa) + e=ate(P,G) + e=fexp(e) + fmt.Printf("\ne= "+e.toString()) + fmt.Printf("\n") +} +*/
http://git-wip-us.apache.org/repos/asf/incubator-milagro-crypto/blob/85fabaa6/go/amcl-go/RAND.go ---------------------------------------------------------------------- diff --git a/go/amcl-go/RAND.go b/go/amcl-go/RAND.go new file mode 100644 index 0000000..eb92107 --- /dev/null +++ b/go/amcl-go/RAND.go @@ -0,0 +1,187 @@ +/* +Licensed to the Apache Software Foundation (ASF) under one +or more contributor license agreements. See the NOTICE file +distributed with this work for additional information +regarding copyright ownership. The ASF licenses this file +to you under the Apache License, Version 2.0 (the +"License"); you may not use this file except in compliance +with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, +software distributed under the License is distributed on an +"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +KIND, either express or implied. See the License for the +specific language governing permissions and limitations +under the License. +*/ + +/* + * Cryptographic strong random number generator + * + * Unguessable seed -> SHA -> PRNG internal state -> SHA -> random numbers + * Slow - but secure + * + * See ftp://ftp.rsasecurity.com/pub/pdfs/bull-1.pdf for a justification + */ + +/* Marsaglia & Zaman Random number generator constants */ + +package amcl + +import ( + "sync" +) + +//import "fmt" + +const rand_NK int = 21 +const rand_NJ int = 6 +const rand_NV int = 8 + +type RAND struct { + sync.Mutex + ira [rand_NK]uint32 /* random number... */ + rndptr int + borrow uint32 + pool_ptr int + pool [32]byte +} + +/* Terminate and clean up */ +func (R *RAND) Clean() { /* kill internal state */ + R.pool_ptr = 0 + R.rndptr = 0 + for i := 0; i < 32; i++ { + R.pool[i] = 0 + } + for i := 0; i < rand_NK; i++ { + R.ira[i] = 0 + } + R.borrow = 0 +} + +func NewRAND() *RAND { + R := new(RAND) + R.Clean() + return R +} + +func (R *RAND) sbrand() uint32 { /* Marsaglia & Zaman random number generator */ + R.rndptr++ + if R.rndptr < rand_NK { + return R.ira[R.rndptr] + } + R.rndptr = 0 + k := rand_NK - rand_NJ + for i := 0; i < rand_NK; i++ { /* calculate next NK values */ + if k == rand_NK { + k = 0 + } + t := R.ira[k] + pdiff := t - R.ira[i] - R.borrow + if pdiff < t { + R.borrow = 0 + } + if pdiff > t { + R.borrow = 1 + } + R.ira[i] = pdiff + k++ + } + + return R.ira[0] +} + +func (R *RAND) sirand(seed uint32) { + var m uint32 = 1 + R.borrow = 0 + R.rndptr = 0 + R.ira[0] ^= seed + for i := 1; i < rand_NK; i++ { /* fill initialisation vector */ + in := (rand_NV * i) % rand_NK + R.ira[in] ^= m /* note XOR */ + t := m + m = seed - m + seed = t + } + + for i := 0; i < 10000; i++ { + R.sbrand() + } /* "warm-up" & stir the generator */ +} + +func (R *RAND) fill_pool() { + + sh := NewHASH() + for i := 0; i < 128; i++ { + sh.Process(byte(R.sbrand() & 0xff)) + } + R.pool = sh.Hash() + R.pool_ptr = 0 +} + +func pack(b [4]byte) uint32 { /* pack 4 bytes into a 32-bit Word */ + return (((uint32(b[3])) & 0xff) << 24) | ((uint32(b[2]) & 0xff) << 16) | ((uint32(b[1]) & 0xff) << 8) | (uint32(b[0]) & 0xff) +} + +/* Initialize RNG with some real entropy from some external source */ +func (R *RAND) Seed(rawlen int, raw []byte) { /* initialise from at least 128 byte string of raw random entropy */ + var b [4]byte + sh := NewHASH() + R.pool_ptr = 0 + + for i := 0; i < rand_NK; i++ { + R.ira[i] = 0 + } + + if rawlen > 0 { + for i := 0; i < rawlen; i++ { + sh.Process(raw[i]) + } + digest := sh.Hash() + + /* initialise PRNG from distilled randomness */ + + for i := 0; i < 8; i++ { + b[0] = digest[4*i] + b[1] = digest[4*i+1] + b[2] = digest[4*i+2] + b[3] = digest[4*i+3] + R.sirand(pack(b)) + } + } + R.fill_pool() +} + +/* get random byte */ +func (R *RAND) GetByte() byte { + R.Lock() + defer R.Unlock() + + r := R.pool[R.pool_ptr] + R.pool_ptr++ + + if R.pool_ptr >= 32 { + R.fill_pool() + } + return byte(r & 0xff) +} + +/* test main program */ +/* +func main() { + var raw [100]byte + rng:=NewRAND() + + rng.Clean() + for i:=0;i<100;i++ {raw[i]=byte(i)} + + rng.Seed(100,raw[:]) + + for i:=0;i<1000;i++ { + fmt.Printf("%03d ",rng.GetByte()) + } +} +*/ http://git-wip-us.apache.org/repos/asf/incubator-milagro-crypto/blob/85fabaa6/go/amcl-go/ROM.go ---------------------------------------------------------------------- diff --git a/go/amcl-go/ROM.go b/go/amcl-go/ROM.go new file mode 100644 index 0000000..0a4ceb9 --- /dev/null +++ b/go/amcl-go/ROM.go @@ -0,0 +1,353 @@ +/* +Licensed to the Apache Software Foundation (ASF) under one +or more contributor license agreements. See the NOTICE file +distributed with this work for additional information +regarding copyright ownership. The ASF licenses this file +to you under the Apache License, Version 2.0 (the +"License"); you may not use this file except in compliance +with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, +software distributed under the License is distributed on an +"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +KIND, either express or implied. See the License for the +specific language governing permissions and limitations +under the License. +*/ + +/* Fixed Data in ROM - Field and Curve parameters */ + +package amcl + +const NOT_SPECIAL int = 0 +const PSEUDO_MERSENNE int = 1 +const MONTGOMERY_FRIENDLY int = 2 +const WEIERSTRASS int = 0 +const EDWARDS int = 1 +const MONTGOMERY int = 2 + +const NLEN int = 5 +const DNLEN int = 2 * NLEN +const CHUNK int = 64 +const MODBYTES uint = 32 + +/*** Enter Some Field details here ***/ +// Curve 25519 +//const MODBITS uint=255 +//const MOD8 uint=5 +// NIST256 or Brainpool +//const MODBITS uint=256 +//const MOD8 uint=7 +// MF254 +//const MODBITS uint=254 +//const MOD8 uint=7 +// MS255 +//const MODBITS uint= 255 +//const MOD8 uint= 3 +// MF256 +//const MODBITS uint=256 +//const MOD8 uint=7 +// MS256 +//const MODBITS uint= 256 +//const MOD8 uint= 3 +// ANSSI +//const MODBITS uint= 256 +//const MOD8 uint= 3 +// BN Curve +const MODBITS uint = 254 /* Number of bits in Modulus */ +const MOD8 uint = 3 /* Modulus mod 8 */ + +/* Don't Modify from here... */ +const MASK int64 = ((int64(1) << BASEBITS) - 1) +const BASEBITS uint = 56 +const OMASK int64 = ((int64(-1)) << (MODBITS % BASEBITS)) +const HBITS uint = (BASEBITS / 2) +const HMASK int64 = ((int64(1) << HBITS) - 1) +const TBITS uint = MODBITS % BASEBITS // Number of active bits in top word +const TMASK int64 = (int64(1) << TBITS) - 1 +const FF_BITS int = 2048 /* Finite Field Size in bits - must be 256.2^n */ +const FFLEN int = (FF_BITS / 256) +const HFLEN int = (FFLEN / 2) /* Useful for half-size RSA private key operations */ + +const NEXCESS int = (1 << (uint(CHUNK) - BASEBITS - 1)) +const FEXCESS int64 = (int64(1) << (BASEBITS*uint(NLEN) - MODBITS)) + +// START SPECIFY FIELD DETAILS HERE +//********************************************************************************* +// Curve25519 Modulus +//const MODTYPE int=PSEUDO_MERSENNE +//var Modulus = [...]int64 {0xFFFFFFFFFFFFED,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0x7FFFFFFF} +//const MConst int64=0x13 +// NIST-256 Curve +//const MODTYPE int=NOT_SPECIAL +//var Modulus = [...]int64 {0xFFFFFFFFFFFFFF,0xFFFFFFFFFF,0x0,0x1000000,0xFFFFFFFF} +//const MConst int64=0x1 +// MF254 Modulus +//const MODTYPE int=MONTGOMERY_FRIENDLY +//var Modulus= [...]int64 {0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0x3F80FFFF} +//const MConst int64=0x3F810000 +// MS255 Modulus +//const MODTYPE int= 1 +//var Modulus= [...]int64 {0xFFFFFFFFFFFD03,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0x7FFFFFFF} +//const MConst int64=0x2FD +// MF256 Modulus +//const MODTYPE int= 2 +//var Modulus= [...]int64 {0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFA7FFFF} +//const MConst int64=0xFFA80000 +// MS256 Modulus +//const MODTYPE int= 1 +//var Modulus= [...]int64 {0xFFFFFFFFFFFF43,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFF} +//const MConst int64=0xBD +// Brainpool +//const MODTYPE int= NOT_SPECIAL +//var Modulus= [...]int64 {0x13481D1F6E5377,0xF623D526202820,0x909D838D726E3B,0xA1EEA9BC3E660A,0xA9FB57DB} +//const MConst int64 =0xA75590CEFD89B9 +// ANSSI +//const MODTYPE int= 0 +//var Modulus= [...]int64{0xFCF353D86E9C03,0xADBCABC8CA6DE8,0xE8CE42435B3961,0xB3AD58F10126D,0xF1FD178C} +//const MConst int64=0x97483A164E1155 +// BNCX Curve Modulus +const MODTYPE int = NOT_SPECIAL + +var Modulus = [...]int64{0x6623EF5C1B55B3, 0xD6EE18093EE1BE, 0x647A6366D3243F, 0x8702A0DB0BDDF, 0x24000000} + +const MConst int64 = 0x4E205BF9789E85 + +// BN Curve +//const MODTYPE int=NOT_SPECIAL +//var Modulus= [...]int64 {0x13,0x13A7,0x80000000086121,0x40000001BA344D,0x25236482} +//const MConst int64=0x435E50D79435E5 +// BNT Curve +//const MODTYPE int=NOT_SPECIAL +//var Modulus= [...]int64 {0x9DBBFEEEB4A713,0x555614F464BABE,0x3696F8D5F06E8A,0x6517014EFA0BAB,0x240120DB} +//const MConst int64=0xC5A872D914C4E5 +// BNT2 Curve +//const MODTYPE int=NOT_SPECIAL +//var Modulus= [...]int64 {0xB2DC2BB460A48B,0x93E428F0D651E8,0xF3B89D00081CF,0x410F5AADB74E20,0x24000482} +//const MConst int64=0xFE6A47A6505CDD + +// START SPECIFY CURVE DETAILS HERE +//********************************************************************************* + +// Ed25519 Curve +//const CURVETYPE int=EDWARDS +//const CURVE_A int = -1 +//var CURVE_B = [...]int64 {0xEB4DCA135978A3,0xA4D4141D8AB75,0x797779E8980070,0x2B6FFE738CC740,0x52036CEE} +//var CURVE_Order = [...]int64 {0x12631A5CF5D3ED,0xF9DEA2F79CD658,0x14DE,0x0,0x10000000} +//var CURVE_Gx = [...]int64 {0x562D608F25D51A,0xC7609525A7B2C9,0x31FDD6DC5C692C,0xCD6E53FEC0A4E2,0x216936D3} +//var CURVE_Gy = [...]int64 {0x66666666666658,0x66666666666666,0x66666666666666,0x66666666666666,0x66666666} + +// NIST-256 Curve +//const CURVETYPE int=WEIERSTRASS +//const CURVE_A int = -3 +//var CURVE_B = [...]int64 {0xCE3C3E27D2604B,0x6B0CC53B0F63B,0x55769886BC651D,0xAA3A93E7B3EBBD,0x5AC635D8} +//var CURVE_Order = [...]int64 {0xB9CAC2FC632551,0xFAADA7179E84F3,0xFFFFFFFFFFBCE6,0xFFFFFF,0xFFFFFFFF} +//var CURVE_Gx =[...]int64 {0xA13945D898C296,0x7D812DEB33A0F4,0xE563A440F27703,0xE12C4247F8BCE6,0x6B17D1F2} +//var CURVE_Gy =[...]int64 {0xB6406837BF51F5,0x33576B315ECECB,0x4A7C0F9E162BCE,0xFE1A7F9B8EE7EB,0x4FE342E2} + +// MF254 Modulus, Weierstrass Curve w-254-mont +//const CURVETYPE int= 0 +//const CURVE_A int = -3 +//var CURVE_B = [...]int64 {0xFFFFFFFFFFD08D,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0x3F80FFFF} +//var CURVE_Order=[...]int64 {0xA419C4AF8DF83F,0x8BEA0DA375C06F,0xFFFFFFFFFFEB81,0xFFFFFFFFFFFFFF,0x3F80FFFF} +//var CURVE_Gx =[...]int64 {0x2,0x0,0x0,0x0,0x0} +//var CURVE_Gy =[...]int64 {0x65DF37F90D4EBC,0x38E3F8511931AD,0x75BD778AEBDFB7,0x3B2E56014AE15A,0x140E3FD3} + +// MF254 Modulus, Edwards Curve ed-254-mont +//const CURVETYPE int= 1 +//const CURVE_A int= -1 +//var CURVE_B = [...]int64 {0x367B,0x0,0x0,0x0,0x0} +//var CURVE_Order=[...]int64 {0xF3D3FEC46E98C7,0x306C8BD62FB0EA,0xFFFFFFFFFFEB95,0xFFFFFFFFFFFFFF,0xFE03FFF} +//var CURVE_Gx =[...]int64 {0x1,0x0,0x0,0x0,0x0} +//var CURVE_Gy =[...]int64 {0x52D0FDAF2701E5,0x9A840E3212187C,0xD502363F4E3632,0xD6A4C335951D00,0x19F0E690} + +// MF254 Modulus, Montgomery Curve +//const CURVETYPE int=MONTGOMERY +//const CURVE_A int= -55790 +//var CURVE_B = [...]int64 {0x0,0x0,0x0,0x0,0x0} // not used +//var CURVE_Order=[...]int64 {0xF3D3FEC46E98C7,0x306C8BD62FB0EA,0xFFFFFFFFFFEB95,0xFFFFFFFFFFFFFF,0xFE03FFF} +//var CURVE_Gx =[...]int64 {0x3,0x0,0x0,0x0,0x0} +//var CURVE_Gy =[...]int64 {0x0,0x0,0x0,0x0,0x0} // not used + +// MS255 Modulus, Weierstrass Curve +//const CURVETYPE int= 0 +//const CURVE_A int= -3 +//var CURVE_B = [...]int64 {0xFFFFFFFFFFAB46,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0x7FFFFFFF} +//var CURVE_Order=[...]int64 {0x8FAC983C594AEB,0x38283AD2B3DFAB,0xFFFFFFFFFF864A,0xFFFFFFFFFFFFFF,0x7FFFFFFF} +//var CURVE_Gx =[...]int64 {0x1,0x0,0x0,0x0,0x0}; +//var CURVE_Gy =[...]int64 {0x33FF6769CB44BA,0xC78CDDFDA60D17,0xF9B2FF7D177DB6,0xEDBA7833921EBF,0x6F7A6AC0} + +// MS255 Modulus, Edwards Curve +//const CURVETYPE int= 1 +//const CURVE_A int= -1 +//var CURVE_B = [...]int64{0xEA97,0x0,0x0,0x0,0x0} +//var CURVE_Order=[...]int64{0x49D1ED0436EB75,0xA785EDA6832EAC,0xFFFFFFFFFFDCF1,0xFFFFFFFFFFFFFF,0x1FFFFFFF} +//var CURVE_Gx =[...]int64{0x4,0x0,0x0,0x0,0x0} +//var CURVE_Gy =[...]int64{0x2A255BD08736A0,0x4B8AED445A45BA,0xDD8E0C47E55291,0x4A7BB545EC254C,0x26CB7853} + +// MS255 Modulus, Montgomery Curve +//const CURVETYPE int=MONTGOMERY +//const CURVE_A int=-240222 +//var CURVE_B = [...]int64 {0x0,0x0,0x0,0x0,0x0} +//var CURVE_Order=[...]int64 {0x49D1ED0436EB75,0xA785EDA6832EAC,0xFFFFFFFFFFDCF1,0xFFFFFFFFFFFFFF,0x1FFFFFFF} +//var CURVE_Gx =[...]int64 {0x4,0x0,0x0,0x0,0x0} +//var CURVE_Gy =[...]int64 {0x0,0x0,0x0,0x0,0x0}; + +// MF256 Modulus, Weierstrass Curve +//const CURVETYPE int= 0 +//const CURVE_A int= -3 +//var CURVE_B = [...]int64 {0x14E6A,0x0,0x0,0x0,0x0} +//var CURVE_Order=[...]int64 {0x10C5E1A79857EB,0x7513E6E5074B9D,0xFFFFFFFFFFFC51,0xFFFFFFFFFFFFFF,0xFFA7FFFF} +//var CURVE_Gx =[...]int64 {0x1,0x0,0x0,0x0,0x0} +//var CURVE_Gy =[...]int64 {0x7954C2B724D2A,0x47EB8D94DC6610,0x26123DAE289569,0xBE1808CE7BABBA,0x20887C87} + +// MF256, Edwards Curve +//const CURVETYPE int= 1 +//const CURVE_A int= -1 +//var CURVE_B = [...]int64 {0x350A,0x0,0x0,0x0,0x0} +//var CURVE_Order=[...]int64 {0xD92EDED8EC7BAB,0xBBAFB86733C966,0xFFFFFFFFFFB154,0xFFFFFFFFFFFFFF,0x3FE9FFFF} +//var CURVE_Gx =[...]int64 {0x1,0x0,0x0,0x0,0x0} +//var CURVE_Gy =[...]int64 {0xEAA722F2F3C908,0x5E648DFEA68D7D,0xF3DB2C1AACA0C0,0xF8CC4D5AEAEBEE,0xDAD8D4F8} + +// MF256 Modulus, Montgomery Curve +//const CURVETYPE int=MONTGOMERY +//const CURVE_A int= -54314 +//var CURVE_B = [...]int64 {0x0,0x0,0x0,0x0,0x0} // not used +//var CURVE_Order=[...]int64 {0xD92EDED8EC7BAB,0xBBAFB86733C966,0xFFFFFFFFFFB154,0xFFFFFFFFFFFFFF,0x3FE9FFFF} +//var CURVE_Gx =[...]int64 {0x8,0x0,0x0,0x0,0x0} +//var CURVE_Gy =[...]int64 {0x0,0x0,0x0,0x0,0x0} // not used + +// MS256, Weierstrass Curve +//const CURVETYPE int= 0 +//const CURVE_A int= -3 +//var CURVE_B = [...]int64 {0x25581,0x0,0x0,0x0,0x0} +//var CURVE_Order=[...]int64 {0xAB20294751A825,0x8275EA265C6020,0xFFFFFFFFFFE43C,0xFFFFFFFFFFFFFF,0xFFFFFFFF} +//var CURVE_Gx =[...]int64 {0x1,0x0,0x0,0x0,0x0} +//var CURVE_Gy =[...]int64 {0xF46306C2B56C77,0x2F9375894EC10B,0x6CCEEEDD6BD02C,0xC1E466D7FC82C9,0x696F1853} + +// MS256, Edwards Curve +//const CURVETYPE int= 1 +//const CURVE_A int= -1 +//var CURVE_B = [...]int64 {0x3BEE,0x0,0x0,0x0,0x0} +//var CURVE_Order=[...]int64 {0xB84E6F1122B4AD,0xA55AD0A6BC64E5,0xFFFFFFFFFFBE6A,0xFFFFFFFFFFFFFF,0x3FFFFFFF} +//var CURVE_Gx =[...]int64 {0xD,0x0,0x0,0x0,0x0} +//var CURVE_Gy =[...]int64 {0x7F6FB5331CADBA,0x6D63824D303F70,0xB39FA046BFBE2A,0x2A1276DBA3D330,0x7D0AB41E} + +// MS256 Modulus, Montgomery Curve +//const CURVETYPE int=MONTGOMERY +//const CURVE_A int=-61370 +//var CURVE_B = [...]int64 {0x0,0x0,0x0,0x0,0x0} // not used +//var CURVE_Order= [...]int64 {0xB84E6F1122B4AD,0xA55AD0A6BC64E5,0xFFFFFFFFFFBE6A,0xFFFFFFFFFFFFFF,0x3FFFFFFF} +//var CURVE_Gx = [...]int64 {0xb,0x0,0x0,0x0,0x0} +//var CURVE_Gy = [...]int64 {0x0,0x0,0x0,0x0,0x0} // not used + +// Brainpool +//const CURVETYPE int= 0 +//const CURVE_A int= -3 +//var CURVE_B = [...]int64 {0xE58101FEE92B04,0xEBC4AF2F49256A,0x733D0B76B7BF93,0x30D84EA4FE66A7,0x662C61C4} +//var CURVE_Order= [...]int64 {0x1E0E82974856A7,0x7AA3B561A6F790,0x909D838D718C39,0xA1EEA9BC3E660A,0xA9FB57DB} +//var CURVE_Gx = [...]int64 {0xA191562E1305F4,0x42C47AAFBC2B79,0xB23A656149AFA1,0xC1CFE7B7732213,0xA3E8EB3C} +//var CURVE_Gy = [...]int64 {0xABE8F35B25C9BE,0xB6DE39D027001D,0xE14644417E69BC,0x3439C56D7F7B22,0x2D996C82} + +// ANSSI +//const CURVETYPE int= 0 +//const CURVE_A int= -3 +//var CURVE_B = [...]int64 {0x75ED967B7BB73F,0xC9AE4B1A18030,0x754A44C00FDFEC,0x5428A9300D4ABA,0xEE353FCA} +//var CURVE_Order=[...]int64 {0xFDD459C6D655E1,0x67E140D2BF941F,0xE8CE42435B53DC,0xB3AD58F10126D,0xF1FD178C} +//var CURVE_Gx =[...]int64 {0xC97A2DD98F5CFF,0xD2DCAF98B70164,0x4749D423958C27,0x56C139EB31183D,0xB6B3D4C3} +//var CURVE_Gy =[...]int64 {0x115A1554062CFB,0xC307E8E4C9E183,0xF0F3ECEF8C2701,0xC8B204911F9271,0x6142E0F7} + +// BNCX Curve + +const CURVETYPE int = WEIERSTRASS +const CURVE_A int = 0 + +var CURVE_B = [...]int64{0x2, 0x0, 0x0, 0x0, 0x0} +var CURVE_Order = [...]int64{0x11C0A636EB1F6D, 0xD6EE0CC906CEBE, 0x647A6366D2C43F, 0x8702A0DB0BDDF, 0x24000000} +var CURVE_Bnx = [...]int64{0x3C012B1, 0x40, 0x0, 0x0, 0x0} +var CURVE_Cru = [...]int64{0xE0931794235C97, 0xDF6471EF875631, 0xCA83F1440BD, 0x480000, 0x0} +var CURVE_Fra = [...]int64{0xD9083355C80EA3, 0x7326F173F8215B, 0x8AACA718986867, 0xA63A0164AFE18B, 0x1359082F} +var CURVE_Frb = [...]int64{0x8D1BBC06534710, 0x63C7269546C062, 0xD9CDBC4E3ABBD8, 0x623628A900DC53, 0x10A6F7D0} +var CURVE_Pxa = [...]int64{0x851CEEE4D2EC74, 0x85BFA03E2726C0, 0xF5C34BBB907C, 0x7053B256358B25, 0x19682D2C} +var CURVE_Pxb = [...]int64{0xA58E8B2E29CFE1, 0x97B0C209C30F47, 0x37A8E99743F81B, 0x3E19F64AA011C9, 0x1466B9EC} +var CURVE_Pya = [...]int64{0xFBFCEBCF0BE09F, 0xB33D847EC1B30C, 0x157DAEE2096361, 0x72332B8DD81E22, 0xA79EDD9} +var CURVE_Pyb = [...]int64{0x904B228898EE9D, 0x4EA569D2EDEBED, 0x512D8D3461C286, 0xECC4C09035C6E4, 0x6160C39} +var CURVE_Gx = [...]int64{0x6623EF5C1B55B2, 0xD6EE18093EE1BE, 0x647A6366D3243F, 0x8702A0DB0BDDF, 0x24000000} +var CURVE_Gy = [...]int64{0x1, 0x0, 0x0, 0x0, 0x0} +var CURVE_W = [2][5]int64{{0x546349162FEB83, 0xB40381200, 0x6000, 0x0, 0x0}, {0x7802561, 0x80, 0x0, 0x0, 0x0}} +var CURVE_SB = [2][2][5]int64{{{0x5463491DB010E4, 0xB40381280, 0x6000, 0x0, 0x0}, {0x7802561, 0x80, 0x0, 0x0, 0x0}}, {{0x7802561, 0x80, 0x0, 0x0, 0x0}, {0xBD5D5D20BB33EA, 0xD6EE0188CEBCBD, 0x647A6366D2643F, 0x8702A0DB0BDDF, 0x24000000}}} +var CURVE_WB = [4][5]int64{{0x1C2118567A84B0, 0x3C012B040, 0x2000, 0x0, 0x0}, {0xCDF995BE220475, 0x94EDA8CA7F9A36, 0x8702A0DC07E, 0x300000, 0x0}, {0x66FCCAE0F10B93, 0x4A76D4653FCD3B, 0x4381506E03F, 0x180000, 0x0}, {0x1C21185DFAAA11, 0x3C012B0C0, 0x2000, 0x0, 0x0}} +var CURVE_BB = [4][4][5]int64{{{0x11C0A6332B0CBD, 0xD6EE0CC906CE7E, 0x647A6366D2C43F, 0x8702A0DB0BDDF, 0x24000000}, {0x11C0A6332B0CBC, 0xD6EE0CC906CE7E, 0x647A6366D2C43F, 0x8702A0DB0BDDF, 0x24000000}, {0x11C0A6332B0CBC, 0xD6EE0CC906CE7E, 0x647A6366D2C43F, 0x8702A0DB0BDDF, 0x24000000}, {0x7802562, 0x80, 0x0, 0x0, 0x0}}, {{0x7802561, 0x80, 0x0, 0x0, 0x0}, {0x11C0A6332B0CBC, 0xD6EE0CC906CE7E, 0x647A6366D2C43F, 0x8702A0DB0BDDF, 0x24000000}, {0x11C0A6332B0CBD, 0xD6EE0CC906CE7E, 0x647A6366D2C43F, 0x8702A0DB0BDDF, 0x24000000}, {0x11C0A6332B0CBC, 0xD6EE0CC906CE7E, 0x647A6366D2C43F, 0x8702A0DB0BDDF, 0x24000000}}, {{0x7802562, 0x80, 0x0, 0x0, 0x0}, {0x7802561, 0x80, 0x0, 0x0, 0x0}, {0x7802561, 0x80, 0x0, 0x0, 0x0}, {0x7802561, 0x80, 0x0, 0x0, 0x0}}, {{0x3C012B2, 0x40, 0x0, 0x0, 0x0}, {0xF004AC2, 0x100, 0x0, 0x0, 0x0}, {0x11C0A62F6AFA0A, 0xD6EE0CC906CE3E, 0x647A6366D2C43F, 0x8702A0DB0BDDF, 0x24000000}, {0x3C012B2, 0x40, 0x0, 0x0, 0x0}}} + +// BN Curve +/* +const CURVETYPE int=WEIERSTRASS +const CURVE_A int= 0 +var CURVE_B = [...]int64 {0x2,0x0,0x0,0x0,0x0} +var CURVE_Order=[...]int64 {0xD,0x800000000010A1,0x8000000007FF9F,0x40000001BA344D,0x25236482} +var CURVE_Bnx=[...]int64 {0x80000000000001,0x40,0x0,0x0,0x0} +var CURVE_Cru=[...]int64 {0x80000000000007,0x6CD,0x40000000024909,0x49B362,0x0} +var CURVE_Fra=[...]int64 {0x7DE6C06F2A6DE9,0x74924D3F77C2E1,0x50A846953F8509,0x212E7C8CB6499B,0x1B377619} +var CURVE_Frb=[...]int64 {0x82193F90D5922A,0x8B6DB2C08850C5,0x2F57B96AC8DC17,0x1ED1837503EAB2,0x9EBEE69} +var CURVE_Pxa=[...]int64 {0xAB2C7935FD0CB4,0xE319E4FCC57C2B,0x24F6DF763B05A5,0xF55EA7EA335FB7,0x95B04D4} +var CURVE_Pxb=[...]int64 {0xA07D0790962455,0x86BE3D27AA5E38,0x89E05747F39D6D,0xC08347B49D42BF,0x5D4D8A7} +var CURVE_Pya=[...]int64 {0xADCE687A08A46C,0x2B30E98A4191F9,0x4C3784B1F16908,0x25E5313FA16D1C,0xABF2ABF} +var CURVE_Pyb=[...]int64 {0xDF88D405F306EC,0x82076ADD13A0E6,0x1E47819D6A5C04,0xE679DABDB38627,0x18769A87} +var CURVE_Gx =[...]int64 {0x12,0x13A7,0x80000000086121,0x40000001BA344D,0x25236482} +var CURVE_Gy =[...]int64 {0x1,0x0,0x0,0x0,0x0} +var CURVE_W=[2][5]int64{{0x3,0x80000000000204,0x6181,0x0,0x0},{0x1,0x81,0x0,0x0,0x0}} +var CURVE_SB=[2][2][5]int64 {{{0x4,0x80000000000285,0x6181,0x0,0x0},{0x1,0x81,0x0,0x0,0x0}},{{0x1,0x81,0x0,0x0,0x0},{0xA,0xE9D,0x80000000079E1E,0x40000001BA344D,0x25236482}}} +var CURVE_WB=[4][5]int64 {{0x80000000000000,0x80000000000040,0x2080,0x0,0x0},{0x80000000000005,0x54A,0x8000000001C707,0x312241,0x0},{0x80000000000003,0x800000000002C5,0xC000000000E383,0x189120,0x0},{0x80000000000001,0x800000000000C1,0x2080,0x0,0x0}} +var CURVE_BB=[4][4][5]int64 {{{0x8000000000000D,0x80000000001060,0x8000000007FF9F,0x40000001BA344D,0x25236482},{0x8000000000000C,0x80000000001060,0x8000000007FF9F,0x40000001BA344D,0x25236482},{0x8000000000000C,0x80000000001060,0x8000000007FF9F,0x40000001BA344D,0x25236482},{0x2,0x81,0x0,0x0,0x0}},{{0x1,0x81,0x0,0x0,0x0},{0x8000000000000C,0x80000000001060,0x8000000007FF9F,0x40000001BA344D,0x25236482},{0x8000000000000D,0x80000000001060,0x8000000007FF9F,0x40000001BA344D,0x25236482},{0x8000000000000C,0x80000000001060,0x8000000007FF9F,0x40000001BA344D,0x25236482}},{{0x2,0x81,0x0,0x0,0x0},{0x1,0x81,0x0,0x0,0x0},{0x1,0x81,0x0,0x0,0x0},{0x1,0x81,0x0,0x0,0x0}},{{0x80000000000002,0x40,0x0,0x0,0x0},{0x2,0x102,0x0,0x0,0x0},{0xA,0x80000000001020,0x8000000007FF9F,0x40000001BA344D,0x25236482},{0x80000000000002,0x40,0x0,0x0,0x0}}} +*/ + +// BNT Curve +/* +const CURVETYPE int=WEIERSTRASS +const CURVE_A int= 0 +var CURVE_B = [...]int64 {0x2,0x0,0x0,0x0,0x0} +var CURVE_Order=[...]int64 {0x75777E8D30210D,0xD43492B2CB363A,0x3696F8D5F00E88,0x6517014EFA0BAB,0x240120DB} +var CURVE_Bnx=[...]int64 {0x806000004081,0x40,0x0,0x0,0x0} +var CURVE_Cru=[...]int64 {0xEB53D5AB4FCD87,0x82A5F2BAB11FAD,0x47651504C9764C,0x4801B1,0x0} +var CURVE_Fra=[...]int64 {0xF5D14EADC80022,0x4904D6FACCE359,0xF190A13211BE6C,0xC9BBC4394F6509,0x1328A292} +var CURVE_Frb=[...]int64 {0xA7EAB040ECA6F1,0xC513DF997D764,0x450657A3DEB01E,0x9B5B3D15AAA6A1,0x10D87E48} +var CURVE_Pxa=[...]int64 {0x8987E2288E65BB,0xAD1CAA6313BE,0x325041548B7CCC,0x4C1339EBCC055,0x14483FCD} +var CURVE_Pxb=[...]int64 {0x67888808DBE2C0,0x7FE1F81E34853A,0xA631A51B57B95,0x384EC302DA3FC5,0x87F46B3} +var CURVE_Pya=[...]int64 {0x202C47E020CA1D,0xB4167E8399F36C,0xC6E5439F72C94C,0x102B0BD74A2C69,0x14E8C29C} +var CURVE_Pyb=[...]int64 {0xD8437C716628F2,0x27E167BCB7DC6B,0xA82C7572681D0A,0x62454BD1EDEC18,0x17AFE2A4} +var CURVE_Gx =[...]int64 {0x9DBBFEEEB4A712,0x555614F464BABE,0x3696F8D5F06E8A,0x6517014EFA0BAB,0x240120DB} +var CURVE_Gy =[...]int64 {0x1,0x0,0x0,0x0,0x0} +var CURVE_W=[2][5]int64{{0x26430061838403,0x81218241998384,0x6001,0x0,0x0},{0x100C000008101,0x80,0x0,0x0,0x0}} +var CURVE_SB=[2][2][5]int64 {{{0x2743C061840504,0x81218241998404,0x6001,0x0,0x0},{0x100C000008101,0x80,0x0,0x0,0x0}},{{0x100C000008101,0x80,0x0,0x0,0x0},{0x4F347E2BAC9D0A,0x5313107131B2B6,0x3696F8D5EFAE87,0x6517014EFA0BAB,0x240120DB}}} +var CURVE_WB=[4][5]int64 {{0x6140602080C080,0x806080C08880C1,0x2000,0x0,0x0},{0xB53904088C4A85,0xAD2FA352DC6C36,0xDA436358868EDE,0x300120,0x0},{0x5ADCB204464583,0x5697D1A96E363B,0x6D21B1AC43476F,0x180090,0x0},{0x62412020814181,0x806080C0888141,0x2000,0x0,0x0}} +var CURVE_BB=[4][4][5]int64 {{{0x74F71E8D2FE08D,0xD43492B2CB35FA,0x3696F8D5F00E88,0x6517014EFA0BAB,0x240120DB},{0x74F71E8D2FE08C,0xD43492B2CB35FA,0x3696F8D5F00E88,0x6517014EFA0BAB,0x240120DB},{0x74F71E8D2FE08C,0xD43492B2CB35FA,0x3696F8D5F00E88,0x6517014EFA0BAB,0x240120DB},{0x100C000008102,0x80,0x0,0x0,0x0}},{{0x100C000008101,0x80,0x0,0x0,0x0},{0x74F71E8D2FE08C,0xD43492B2CB35FA,0x3696F8D5F00E88,0x6517014EFA0BAB,0x240120DB},{0x74F71E8D2FE08D,0xD43492B2CB35FA,0x3696F8D5F00E88,0x6517014EFA0BAB,0x240120DB},{0x74F71E8D2FE08C,0xD43492B2CB35FA,0x3696F8D5F00E88,0x6517014EFA0BAB,0x240120DB}},{{0x100C000008102,0x80,0x0,0x0,0x0},{0x100C000008101,0x80,0x0,0x0,0x0},{0x100C000008101,0x80,0x0,0x0,0x0},{0x100C000008101,0x80,0x0,0x0,0x0}},{{0x806000004082,0x40,0x0,0x0,0x0},{0x2018000010202,0x100,0x0,0x0,0x0},{0x7476BE8D2FA00A,0xD43492B2CB35BA,0x3696F8D5F00E88,0x6517014EFA0BAB,0x240120DB},{0x806000004082,0x40,0x0,0x0,0x0}}} +*/ + +// BNT2 Curve +/* +const CURVETYPE int=WEIERSTRASS +const CURVE_A int= 0 +var CURVE_B = [...]int64 {0x2,0x0,0x0,0x0,0x0} +var CURVE_Order=[...]int64 {0xFB71A511AA2BF5,0x8DE127B73833D7,0xF3B89D00021CF,0x410F5AADB74E20,0x24000482} +var CURVE_Bnx=[...]int64 {0x20100608205,0x40,0x0,0x0,0x0} +var CURVE_Cru=[...]int64 {0x5027444866BD33,0x5B773016470EFB,0xC3617BECF23675,0x480006,0x0} +var CURVE_Fra=[...]int64 {0xB268C973AEF062,0xC69B33C3BCE492,0xF67FA37F195BBC,0x29E8CAB6BD0A41,0x124E0B8D} +var CURVE_Frb=[...]int64 {0x736240B1B429,0xCD48F52D196D56,0x18BBE650E72612,0x17268FF6FA43DE,0x11B1F8F5} +var CURVE_Pxa=[...]int64 {0xCC92399F40A3C8,0xCDA4E96611784A,0x7B056961706B35,0x9693C6318279D7,0x16FC17CF} +var CURVE_Pxb=[...]int64 {0x557A8AD8549540,0x6F7BE6F6510610,0x565907A95D17DB,0xBD5975909C8188,0x1EB5B500} +var CURVE_Pya=[...]int64 {0x7BECC514220513,0x4A78860E737B14,0x51B83935F12684,0x761422AA9D4DFA,0x1E8EE498} +var CURVE_Pyb=[...]int64 {0xB9328F577CE78E,0xB746E26FA5781F,0xA93DBC1FB8E27E,0xBAE33BDBA29D76,0x23CEF4CD} +var CURVE_Gx =[...]int64 {0xB2DC2BB460A48A,0x93E428F0D651E8,0xF3B89D00081CF,0x410F5AADB74E20,0x24000482} +var CURVE_Gy =[...]int64 {0x1,0x0,0x0,0x0,0x0} +var CURVE_W=[2][5]int64 {{0xB76282A1347083,0x60301399E1D10,0x6000,0x0,0x0},{0x40200C10409,0x80,0x0,0x0,0x0}} +var CURVE_SB=[2][2][5]int64 {{{0xB76684A1F5748C,0x60301399E1D90,0x6000,0x0,0x0},{0x40200C10409,0x80,0x0,0x0,0x0}},{{0x40200C10409,0x80,0x0,0x0,0x0},{0x440F227075BB72,0x87DE267D9A16C7,0xF3B89CFFFC1CF,0x410F5AADB74E20,0x24000482}}} +var CURVE_WB=[4][5]int64 {{0x9272D48A70A224,0x20100688A0945,0x2000,0x0,0x0},{0x5A572CF030EF19,0x9651763543721D,0x8240FD48A1B9A3,0x300004,0x0},{0xAD2C96F848B88F,0xCB28BB1AA1B92E,0x41207EA450DCD1,0x180002,0x0},{0x9276D68B31A62D,0x20100688A09C5,0x2000,0x0,0x0}} +var CURVE_BB=[4][4][5]int64 {{{0xFB6FA41149A9F1,0x8DE127B7383397,0xF3B89D00021CF,0x410F5AADB74E20,0x24000482},{0xFB6FA41149A9F0,0x8DE127B7383397,0xF3B89D00021CF,0x410F5AADB74E20,0x24000482},{0xFB6FA41149A9F0,0x8DE127B7383397,0xF3B89D00021CF,0x410F5AADB74E20,0x24000482},{0x40200C1040A,0x80,0x0,0x0,0x0}},{{0x40200C10409,0x80,0x0,0x0,0x0},{0xFB6FA41149A9F0,0x8DE127B7383397,0xF3B89D00021CF,0x410F5AADB74E20,0x24000482},{0xFB6FA41149A9F1,0x8DE127B7383397,0xF3B89D00021CF,0x410F5AADB74E20,0x24000482},{0xFB6FA41149A9F0,0x8DE127B7383397,0xF3B89D00021CF,0x410F5AADB74E20,0x24000482}},{{0x40200C1040A,0x80,0x0,0x0,0x0},{0x40200C10409,0x80,0x0,0x0,0x0},{0x40200C10409,0x80,0x0,0x0,0x0},{0x40200C10409,0x80,0x0,0x0,0x0}},{{0x20100608206,0x40,0x0,0x0,0x0},{0x80401820812,0x100,0x0,0x0,0x0},{0xFB6DA310E927EA,0x8DE127B7383357,0xF3B89D00021CF,0x410F5AADB74E20,0x24000482},{0x20100608206,0x40,0x0,0x0,0x0}}} +*/ + +const USE_GLV bool = true +const USE_GS_G2 bool = true +const USE_GS_GT bool = true +const GT_STRONG bool = true http://git-wip-us.apache.org/repos/asf/incubator-milagro-crypto/blob/85fabaa6/go/amcl-go/RSA.go ---------------------------------------------------------------------- diff --git a/go/amcl-go/RSA.go b/go/amcl-go/RSA.go new file mode 100644 index 0000000..5b1cf5b --- /dev/null +++ b/go/amcl-go/RSA.go @@ -0,0 +1,373 @@ +/* +Licensed to the Apache Software Foundation (ASF) under one +or more contributor license agreements. See the NOTICE file +distributed with this work for additional information +regarding copyright ownership. The ASF licenses this file +to you under the Apache License, Version 2.0 (the +"License"); you may not use this file except in compliance +with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, +software distributed under the License is distributed on an +"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +KIND, either express or implied. See the License for the +specific language governing permissions and limitations +under the License. +*/ + +/* RSA API high-level functions */ + +package amcl + +import "fmt" + +const RSA_RFS int = int(MODBYTES) * FFLEN + +type rsa_private_key struct { + p, q, dp, dq, c *FF +} + +func New_rsa_private_key(n int) *rsa_private_key { + SK := new(rsa_private_key) + SK.p = NewFFint(n) + SK.q = NewFFint(n) + SK.dp = NewFFint(n) + SK.dq = NewFFint(n) + SK.c = NewFFint(n) + return SK +} + +type rsa_public_key struct { + e int + n *FF +} + +func New_rsa_public_key(m int) *rsa_public_key { + PK := new(rsa_public_key) + PK.e = 0 + PK.n = NewFFint(m) + return PK +} + +func RSA_KEY_PAIR(rng *RAND, e int, PRIV *rsa_private_key, PUB *rsa_public_key) { /* IEEE1363 A16.11/A16.12 more or less */ + n := PUB.n.getlen() / 2 + t := NewFFint(n) + p1 := NewFFint(n) + q1 := NewFFint(n) + + for true { + PRIV.p.random(rng) + for PRIV.p.lastbits(2) != 3 { + PRIV.p.inc(1) + } + for !prime(PRIV.p, rng) { + PRIV.p.inc(4) + } + + p1.copy(PRIV.p) + p1.dec(1) + + if p1.cfactor(e) { + continue + } + break + } + + for true { + PRIV.q.random(rng) + for PRIV.q.lastbits(2) != 3 { + PRIV.q.inc(1) + } + for !prime(PRIV.q, rng) { + PRIV.q.inc(4) + } + + q1.copy(PRIV.q) + q1.dec(1) + + if q1.cfactor(e) { + continue + } + + break + } + + PUB.n = ff_mul(PRIV.p, PRIV.q) + PUB.e = e + + t.copy(p1) + t.shr() + PRIV.dp.set(e) + PRIV.dp.invmodp(t) + if PRIV.dp.parity() == 0 { + PRIV.dp.add(t) + } + PRIV.dp.norm() + + t.copy(q1) + t.shr() + PRIV.dq.set(e) + PRIV.dq.invmodp(t) + if PRIV.dq.parity() == 0 { + PRIV.dq.add(t) + } + PRIV.dq.norm() + + PRIV.c.copy(PRIV.p) + PRIV.c.invmodp(PRIV.q) + +} + +/* Mask Generation Function */ + +func RSA_MGF1(Z []byte, olen int, K []byte) { + H := NewHASH() + hlen := 32 + + var k int = 0 + for i := 0; i < len(K); i++ { + K[i] = 0 + } + + cthreshold := olen / hlen + if olen%hlen != 0 { + cthreshold++ + } + for counter := 0; counter < cthreshold; counter++ { + H.Process_array(Z) + H.Process_num(int32(counter)) + B := H.Hash() + + if k+hlen > olen { + for i := 0; i < olen%hlen; i++ { + K[k] = B[i] + k++ + } + } else { + for i := 0; i < hlen; i++ { + K[k] = B[i] + k++ + } + } + } +} + +func RSA_printBinary(array []byte) { + for i := 0; i < len(array); i++ { + fmt.Printf("%02x", array[i]) + } + fmt.Printf("\n") +} + +/* OAEP Message Encoding for Encryption */ +func RSA_OAEP_ENCODE(m []byte, rng *RAND, p []byte) []byte { + olen := RSA_RFS - 1 + mlen := len(m) + var f [RSA_RFS]byte + + H := NewHASH() + hlen := 32 + var SEED [32]byte + seedlen := hlen + if mlen > olen-hlen-seedlen-1 { + return nil + } + + var DBMASK [RSA_RFS - 1 - 32]byte + + if p != nil { + H.Process_array(p) + } + h := H.Hash() + for i := 0; i < hlen; i++ { + f[i] = h[i] + } + + slen := olen - mlen - hlen - seedlen - 1 + + for i := 0; i < slen; i++ { + f[hlen+i] = 0 + } + f[hlen+slen] = 1 + for i := 0; i < mlen; i++ { + f[hlen+slen+1+i] = m[i] + } + + for i := 0; i < seedlen; i++ { + SEED[i] = rng.GetByte() + } + RSA_MGF1(SEED[:], olen-seedlen, DBMASK[:]) + + for i := 0; i < olen-seedlen; i++ { + DBMASK[i] ^= f[i] + } + RSA_MGF1(DBMASK[:], seedlen, f[:]) + + for i := 0; i < seedlen; i++ { + f[i] ^= SEED[i] + } + + for i := 0; i < olen-seedlen; i++ { + f[i+seedlen] = DBMASK[i] + } + + /* pad to length RFS */ + d := 1 + for i := RSA_RFS - 1; i >= d; i-- { + f[i] = f[i-d] + } + for i := d - 1; i >= 0; i-- { + f[i] = 0 + } + return f[:] +} + +/* OAEP Message Decoding for Decryption */ +func RSA_OAEP_DECODE(p []byte, f []byte) []byte { + olen := RSA_RFS - 1 + + H := NewHASH() + hlen := 32 + var SEED [32]byte + seedlen := hlen + var CHASH [32]byte + + if olen < seedlen+hlen+1 { + return nil + } + var DBMASK [RSA_RFS - 1 - 32]byte + for i := 0; i < olen-seedlen; i++ { + DBMASK[i] = 0 + } + + if len(f) < RSA_RFS { + d := RSA_RFS - len(f) + for i := RSA_RFS - 1; i >= d; i-- { + f[i] = f[i-d] + } + for i := d - 1; i >= 0; i-- { + f[i] = 0 + } + } + + if p != nil { + H.Process_array(p) + } + h := H.Hash() + for i := 0; i < hlen; i++ { + CHASH[i] = h[i] + } + + x := f[0] + + for i := seedlen; i < olen; i++ { + DBMASK[i-seedlen] = f[i+1] + } + + RSA_MGF1(DBMASK[:], seedlen, SEED[:]) + for i := 0; i < seedlen; i++ { + SEED[i] ^= f[i+1] + } + RSA_MGF1(SEED[:], olen-seedlen, f) + for i := 0; i < olen-seedlen; i++ { + DBMASK[i] ^= f[i] + } + + comp := true + for i := 0; i < hlen; i++ { + if CHASH[i] != DBMASK[i] { + comp = false + } + } + + for i := 0; i < olen-seedlen-hlen; i++ { + DBMASK[i] = DBMASK[i+hlen] + } + + for i := 0; i < hlen; i++ { + SEED[i] = 0 + CHASH[i] = 0 + } + + var k int + for k = 0; ; k++ { + if k >= olen-seedlen-hlen { + return nil + } + if DBMASK[k] != 0 { + break + } + } + + t := DBMASK[k] + if !comp || x != 0 || t != 0x01 { + for i := 0; i < olen-seedlen; i++ { + DBMASK[i] = 0 + } + return nil + } + + var r = make([]byte, olen-seedlen-hlen-k-1) + + for i := 0; i < olen-seedlen-hlen-k-1; i++ { + r[i] = DBMASK[i+k+1] + } + + for i := 0; i < olen-seedlen; i++ { + DBMASK[i] = 0 + } + + return r +} + +/* destroy the Private Key structure */ +func RSA_PRIVATE_KEY_KILL(PRIV *rsa_private_key) { + PRIV.p.zero() + PRIV.q.zero() + PRIV.dp.zero() + PRIV.dq.zero() + PRIV.c.zero() +} + +/* RSA encryption with the public key */ +func RSA_ENCRYPT(PUB *rsa_public_key, F []byte, G []byte) { + n := PUB.n.getlen() + f := NewFFint(n) + + ff_fromBytes(f, F) + f.power(PUB.e, PUB.n) + f.toBytes(G) +} + +/* RSA decryption with the private key */ +func RSA_DECRYPT(PRIV *rsa_private_key, G []byte, F []byte) { + n := PRIV.p.getlen() + g := NewFFint(2 * n) + + ff_fromBytes(g, G) + jp := g.dmod(PRIV.p) + jq := g.dmod(PRIV.q) + + jp.skpow(PRIV.dp, PRIV.p) + jq.skpow(PRIV.dq, PRIV.q) + + g.zero() + g.dscopy(jp) + jp.mod(PRIV.q) + if ff_comp(jp, jq) > 0 { + jq.add(PRIV.q) + } + jq.sub(jp) + jq.norm() + + t := ff_mul(PRIV.c, jq) + jq = t.dmod(PRIV.q) + + t = ff_mul(jq, PRIV.p) + g.add(t) + g.norm() + + g.toBytes(F) +} http://git-wip-us.apache.org/repos/asf/incubator-milagro-crypto/blob/85fabaa6/go/amcl-go/UTILS.go ---------------------------------------------------------------------- diff --git a/go/amcl-go/UTILS.go b/go/amcl-go/UTILS.go new file mode 100644 index 0000000..b9b9ecb --- /dev/null +++ b/go/amcl-go/UTILS.go @@ -0,0 +1,45 @@ +/* +Licensed to the Apache Software Foundation (ASF) under one +or more contributor license agreements. See the NOTICE file +distributed with this work for additional information +regarding copyright ownership. The ASF licenses this file +to you under the Apache License, Version 2.0 (the +"License"); you may not use this file except in compliance +with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, +software distributed under the License is distributed on an +"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +KIND, either express or implied. See the License for the +specific language governing permissions and limitations +under the License. +*/ + +package amcl + +// Generate random six digit value +func GENERATE_OTP(rng *RAND) int { + OTP := 0 + mult := 1 + for i := 0; i < 6; i++ { + val := int(rng.GetByte()) + if val < 0 { + val = -val + } + val = val % 10 + OTP = val*mult + OTP + mult = mult * 10 + } + return OTP +} + +// Generate a random byte array +func GENERATE_RANDOM(rng *RAND, randomLen int) []byte { + random := make([]byte, randomLen) + for i := 0; i < randomLen; i++ { + random[i] = rng.GetByte() + } + return random +} http://git-wip-us.apache.org/repos/asf/incubator-milagro-crypto/blob/85fabaa6/go/amcl-go/UTILS_test.go ---------------------------------------------------------------------- diff --git a/go/amcl-go/UTILS_test.go b/go/amcl-go/UTILS_test.go new file mode 100644 index 0000000..17058cc --- /dev/null +++ b/go/amcl-go/UTILS_test.go @@ -0,0 +1,71 @@ +/* +Licensed to the Apache Software Foundation (ASF) under one +or more contributor license agreements. See the NOTICE file +distributed with this work for additional information +regarding copyright ownership. The ASF licenses this file +to you under the Apache License, Version 2.0 (the +"License"); you may not use this file except in compliance +with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, +software distributed under the License is distributed on an +"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +KIND, either express or implied. See the License for the +specific language governing permissions and limitations +under the License. +*/ + +package amcl + +import ( + "encoding/hex" + "fmt" + "testing" +) + +func TestGENERATE_OTP(t *testing.T) { + cases := []int{751847, 625436, 628111, 611804, 148564, 202193, 794783, 631944, 544480, 384313} + + // Seed value for Random Number Generator (RNG) + seedHex := "9e8b4178790cd57a5761c4a6f164ba72" + seed, err := hex.DecodeString(seedHex) + if err != nil { + fmt.Println("Error decoding seed value") + return + } + rng := NewRAND() + rng.Seed(len(seed), seed) + + // Generate the one time passwords + for _, want := range cases { + got := GENERATE_OTP(rng) + if got != want { + t.Errorf("One Time Passord %d != %d", got, want) + } + } +} + +func TestGENERATE_RANDOM(t *testing.T) { + cases := []string{"57d662d39b1b245da469e89c", "155babf8de4204e68a656f42", "727e1980e01f996d977a0a34", "7b6c39221d89546895153f10", "32e40e9ad6f50dab3f5ec63f", "f6962a1fc5add13277900871", "93ae541acd6dc3264c19a12a", "faf196291d0820c611d3fcd4", "ba0602f0f6df1908dbcffe5b", "9e93cf35ccd5141e367cf2fd"} + + // Seed value for Random Number Generator (RNG) + seedHex := "9e8b4178790cd57a5761c4a6f164ba72" + seed, err := hex.DecodeString(seedHex) + if err != nil { + fmt.Println("Error decoding seed value") + return + } + rng := NewRAND() + rng.Seed(len(seed), seed) + + // Generate the one time passwords + for _, want := range cases { + val := GENERATE_RANDOM(rng, 12) + got := hex.EncodeToString(val) + if got != want { + t.Errorf("One Time Passord %s != %s", got, want) + } + } +} http://git-wip-us.apache.org/repos/asf/incubator-milagro-crypto/blob/85fabaa6/go/amcl-go/crypto.go ---------------------------------------------------------------------- diff --git a/go/amcl-go/crypto.go b/go/amcl-go/crypto.go new file mode 100644 index 0000000..e2b8bbb --- /dev/null +++ b/go/amcl-go/crypto.go @@ -0,0 +1,222 @@ +/* +Licensed to the Apache Software Foundation (ASF) under one +or more contributor license agreements. See the NOTICE file +distributed with this work for additional information +regarding copyright ownership. The ASF licenses this file +to you under the Apache License, Version 2.0 (the +"License"); you may not use this file except in compliance +with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, +software distributed under the License is distributed on an +"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +KIND, either express or implied. See the License for the +specific language governing permissions and limitations +under the License. +*/ + +package amcl + +const EAS int = 16 +const EGS int = int(MODBYTES) +const EFS int = int(MODBYTES) +const HASH_BYTES int = 32 +const IVS int = 12 +const G1S = 2*EFS + 1 +const G2S = 4 * EFS +const GTS = 12 * EFS + +/* create random secret S. Use GO RNG */ +func MPIN_RANDOM_GENERATE_WRAP(RNG *RAND) (int, []byte) { + var S [EGS]byte + errorCode := MPIN_RANDOM_GENERATE(RNG, S[:]) + return errorCode, S[:] +} + +/* Extract Server Secret SS=S*Q where Q is fixed generator in G2 and S is master secret */ +func MPIN_GET_SERVER_SECRET_WRAP(S []byte) (int, []byte) { + var SS [G2S]byte + errorCode := MPIN_GET_SERVER_SECRET(S[:], SS[:]) + return errorCode, SS[:] +} + +/* R=R1+R2 in group G1 */ +func MPIN_RECOMBINE_G1_WRAP(R1 []byte, R2 []byte) (int, []byte) { + var R [G1S]byte + errorCode := MPIN_RECOMBINE_G1(R1[:], R2[:], R[:]) + return errorCode, R[:] +} + +/* W=W1+W2 in group G2 */ +func MPIN_RECOMBINE_G2_WRAP(W1 []byte, W2 []byte) (int, []byte) { + var W [G2S]byte + errorCode := MPIN_RECOMBINE_G2(W1[:], W2[:], W[:]) + return errorCode, W[:] +} + +/* Client secret CS=S*H(ID) where ID is client ID and S is master secret */ +/* CID is hashed externally */ +func MPIN_GET_CLIENT_SECRET_WRAP(S []byte, ID []byte) (int, []byte) { + var CS [G1S]byte + errorCode := MPIN_GET_CLIENT_SECRET(S[:], ID[:], CS[:]) + return errorCode, CS[:] +} + +/* Time Permit TP=S*(date|H(ID)) where S is master secret */ +func MPIN_GET_CLIENT_PERMIT_WRAP(date int, S []byte, ID []byte) (int, []byte) { + var TP [G1S]byte + errorCode := MPIN_GET_CLIENT_PERMIT(date, S[:], ID[:], TP[:]) + return errorCode, TP[:] +} + +/* Extract PIN from CS for identity CID to form TOKEN */ +func MPIN_EXTRACT_PIN_WRAP(ID []byte, PIN int, CS []byte) (int, []byte) { + CSIn := make([]byte, G1S) + copy(CSIn, CS) + errorCode := MPIN_EXTRACT_PIN(ID[:], PIN, CSIn[:]) + return errorCode, CSIn[:] +} + +/* One pass MPIN Client. Using GO RNG */ +func MPIN_CLIENT_WRAP(date, TimeValue, PIN int, RNG *RAND, ID, X, TOKEN, TP, MESSAGE []byte) (int, []byte, []byte, []byte, []byte, []byte) { + var Y [EGS]byte + var SEC [G1S]byte + var U [G1S]byte + var UT [G1S]byte + errorCode := MPIN_CLIENT(date, ID, RNG, X[:], PIN, TOKEN[:], SEC[:], U[:], UT[:], TP[:], MESSAGE, TimeValue, Y[:]) + return errorCode, X[:], Y[:], SEC[:], U[:], UT[:] +} + +// Precompute values for use by the client side of M-Pin Full +func MPIN_PRECOMPUTE_WRAP(TOKEN []byte, ID []byte) (int, []byte, []byte) { + var GT1 [GTS]byte + var GT2 [GTS]byte + errorCode := MPIN_PRECOMPUTE(TOKEN[:], ID[:], GT1[:], GT2[:]) + return errorCode, GT1[:], GT2[:] +} + +/* + W=x*H(G); + if RNG == NULL then X is passed in + if RNG != NULL the X is passed out + if typ=0 W=x*G where G is point on the curve, else W=x*M(G), where M(G) is mapping of octet G to point on the curve + Use GO RNG +*/ +func MPIN_GET_G1_MULTIPLE_WRAP(RNG *RAND, typ int, X, G []byte) (int, []byte, []byte) { + var Z [G1S]byte + errorCode := MPIN_GET_G1_MULTIPLE(RNG, typ, X[:], G[:], Z[:]) + return errorCode, X[:], Z[:] +} + +/* One pass MPIN Server */ +func MPIN_SERVER_WRAP(date int, TimeValue int, SS, U, UT, V, ID, MESSAGE []byte) (int, []byte, []byte, []byte, []byte, []byte) { + var HID [G1S]byte + var HTID [G1S]byte + var Y [EGS]byte + var E [GTS]byte + var F [GTS]byte + + errorCode := MPIN_SERVER(date, HID[:], HTID[:], Y[:], SS[:], U[:], UT[:], V[:], E[:], F[:], ID[:], MESSAGE[:], TimeValue) + + return errorCode, HID[:], HTID[:], Y[:], E[:], F[:] +} + +/* calculate common key on server side */ +/* Z=r.A - no time permits involved */ +func MPIN_SERVER_KEY_WRAP(Z, SS, W, U, UT []byte) (int, []byte) { + var SK [EAS]byte + errorCode := MPIN_SERVER_KEY(Z[:], SS[:], W[:], U[:], UT[:], SK[:]) + return errorCode, SK[:] +} + +/* calculate common key on client side */ +/* wCID = w.(A+AT) */ +func MPIN_CLIENT_KEY_WRAP(PIN int, GT1, GT2, R, X, T []byte) (int, []byte) { + var CK [EAS]byte + errorCode := MPIN_CLIENT_KEY(GT1[:], GT2[:], PIN, R[:], X[:], T[:], CK[:]) + return errorCode, CK[:] +} + +/* Extract big type PIN.hash(ID) from CS to form TOKEN */ +func MPIN_EXTRACT_BIG_PIN_WRAP(ID, PIN, CS []byte) (int, []byte) { + TOKEN := make([]byte, G1S) + pin := fromBytes(PIN) + P := ECP_fromBytes(CS) + if P.is_infinity() { + return MPIN_INVALID_POINT, TOKEN[:] + } + h := Hashit(0, ID) + R := mapit(h) + + R = R.mul(pin) + P.sub(R) + + P.toBytes(TOKEN) + + return 0, TOKEN[:] +} + +/* Add big type PIN.hash(ID) to TOKEN for identity ID to form CS */ +func MPIN_ADD_BIG_PIN_WRAP(ID, PIN, TOKEN []byte) (int, []byte) { + CS := make([]byte, G1S) + pin := fromBytes(PIN) + P := ECP_fromBytes(TOKEN) + if P.is_infinity() { + return MPIN_INVALID_POINT, CS[:] + } + h := Hashit(0, ID) + R := mapit(h) + + R = R.mul(pin) + P.add(R) + + P.toBytes(CS) + + return 0, CS[:] +} + +/* dst = a ^ b ^ c */ +func XORBytes(a, b, c []byte) ([]byte, int) { + n := len(a) + dst := make([]byte, n) + if (len(b) != n) || (len(c) != n) { + return dst[:], 1 + } + for i := 0; i < n; i++ { + dst[i] = a[i] ^ b[i] ^ c[i] + } + return dst[:], 0 +} + +/* Outputs H(CID) and H(T|H(CID)) for time permits. If no time permits set HID=HTID */ +func MPIN_SERVER_1_WRAP(date int, ID []byte) ([]byte, []byte) { + var HID [G1S]byte + var HTID [G1S]byte + MPIN_SERVER_1(date, ID, HID[:], HTID[:]) + return HID[:], HTID[:] +} + +/* Implement step 2 of MPin protocol on server side */ +func MPIN_SERVER_2_WRAP(date int, HID []byte, HTID []byte, Y []byte, SS []byte, U []byte, UT []byte, V []byte) (int, []byte, []byte) { + var E [12 * EFS]byte + var F [12 * EFS]byte + errorCode := MPIN_SERVER_2(date, HID[:], HTID[:], Y[:], SS[:], U[:], UT[:], V[:], E[:], F[:]) + return errorCode, E[:], F[:] +} + +/* Implement step 1 on client side of MPin protocol */ +func MPIN_CLIENT_1_WRAP(date int, ID []byte, rng *RAND, X []byte, PIN int, TOKEN []byte, TP []byte) (int, []byte, []byte, []byte, []byte) { + var SEC [G1S]byte + var U [G1S]byte + var UT [G1S]byte + errorCode := MPIN_CLIENT_1(date, ID[:], rng, X[:], PIN, TOKEN[:], SEC[:], U[:], UT[:], TP[:]) + return errorCode, X[:], SEC[:], U[:], UT[:] +} + +/* Implement step 2 on client side of MPin protocol */ +func MPIN_CLIENT_2_WRAP(X []byte, Y []byte, SEC []byte) (int, []byte) { + errorCode := MPIN_CLIENT_2(X[:], Y[:], SEC[:]) + return errorCode, SEC[:] +} http://git-wip-us.apache.org/repos/asf/incubator-milagro-crypto/blob/85fabaa6/go/amcl-go/crypto_test.go ---------------------------------------------------------------------- diff --git a/go/amcl-go/crypto_test.go b/go/amcl-go/crypto_test.go new file mode 100644 index 0000000..710204e --- /dev/null +++ b/go/amcl-go/crypto_test.go @@ -0,0 +1,1194 @@ +/* +Licensed to the Apache Software Foundation (ASF) under one +or more contributor license agreements. See the NOTICE file +distributed with this work for additional information +regarding copyright ownership. The ASF licenses this file +to you under the Apache License, Version 2.0 (the +"License"); you may not use this file except in compliance +with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, +software distributed under the License is distributed on an +"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +KIND, either express or implied. See the License for the +specific language governing permissions and limitations +under the License. +*/ + +package amcl + +import ( + "crypto/rand" + "encoding/hex" + "fmt" + mathrand "math/rand" + "testing" + + "github.com/stretchr/testify/assert" +) + +const nIter int = 1000 + +func TestCryptoGoodPIN(t *testing.T) { + want := 0 + // Assign the End-User an ID + IDstr := "[email protected]" + ID := []byte(IDstr) + + // Epoch time in days + date := 16660 + + // Epoch time in seconds + timeValue := 1439465203 + + // PIN variable to create token + PIN1 := 1234 + // PIN variable to authenticate + PIN2 := 1234 + + // Seed value for Random Number Generator (RNG) + seedHex := "9e8b4178790cd57a5761c4a6f164ba72" + seed, err := hex.DecodeString(seedHex) + if err != nil { + fmt.Println("Error decoding seed value") + return + } + rng := NewRAND() + rng.Seed(len(seed), seed) + + // Message to sign + var MESSAGE []byte + + // Generate Master Secret Share 1 + _, MS1 := MPIN_RANDOM_GENERATE_WRAP(rng) + + // Generate Master Secret Share 2 + _, MS2 := MPIN_RANDOM_GENERATE_WRAP(rng) + + // Either Client or TA calculates Hash(ID) + HCID := MPIN_HASH_ID(ID) + + // Generate server secret share 1 + _, SS1 := MPIN_GET_SERVER_SECRET_WRAP(MS1[:]) + + // Generate server secret share 2 + _, SS2 := MPIN_GET_SERVER_SECRET_WRAP(MS2[:]) + + // Combine server secret shares + _, SS := MPIN_RECOMBINE_G2_WRAP(SS1[:], SS2[:]) + + // Generate client secret share 1 + _, CS1 := MPIN_GET_CLIENT_SECRET_WRAP(MS1[:], HCID) + + // Generate client secret share 2 + _, CS2 := MPIN_GET_CLIENT_SECRET_WRAP(MS2[:], HCID) + + // Combine client secret shares + CS := make([]byte, G1S) + _, CS = MPIN_RECOMBINE_G1_WRAP(CS1[:], CS2[:]) + + // Generate time permit share 1 + _, TP1 := MPIN_GET_CLIENT_PERMIT_WRAP(date, MS1[:], HCID) + + // Generate time permit share 2 + _, TP2 := MPIN_GET_CLIENT_PERMIT_WRAP(date, MS2[:], HCID) + + // Combine time permit shares + _, TP := MPIN_RECOMBINE_G1_WRAP(TP1[:], TP2[:]) + + // Create token + _, TOKEN := MPIN_EXTRACT_PIN_WRAP(ID[:], PIN1, CS[:]) + + // Send U, UT, V, timeValue and Message to server + var X [EGS]byte + _, _, _, V, U, UT := MPIN_CLIENT_WRAP(date, timeValue, PIN2, rng, ID[:], X[:], TOKEN[:], TP[:], MESSAGE[:]) + + got, _, _, _, _, _ := MPIN_SERVER_WRAP(date, timeValue, SS[:], U[:], UT[:], V[:], ID[:], MESSAGE[:]) + assert.Equal(t, want, got, "Should be equal") +} + +func TestCryptoBadPIN(t *testing.T) { + want := -19 + // Assign the End-User an ID + IDstr := "[email protected]" + ID := []byte(IDstr) + + // Epoch time in days + date := 16660 + + // Epoch time in seconds + timeValue := 1439465203 + + // PIN variable to create token + PIN1 := 1234 + // PIN variable to authenticate + PIN2 := 1235 + + // Seed value for Random Number Generator (RNG) + seedHex := "9e8b4178790cd57a5761c4a6f164ba72" + seed, err := hex.DecodeString(seedHex) + if err != nil { + fmt.Println("Error decoding seed value") + return + } + rng := NewRAND() + rng.Seed(len(seed), seed) + + // Message to sign + var MESSAGE []byte + + // Generate Master Secret Share 1 + _, MS1 := MPIN_RANDOM_GENERATE_WRAP(rng) + + // Generate Master Secret Share 2 + _, MS2 := MPIN_RANDOM_GENERATE_WRAP(rng) + + // Either Client or TA calculates Hash(ID) + HCID := MPIN_HASH_ID(ID) + + // Generate server secret share 1 + _, SS1 := MPIN_GET_SERVER_SECRET_WRAP(MS1[:]) + + // Generate server secret share 2 + _, SS2 := MPIN_GET_SERVER_SECRET_WRAP(MS2[:]) + + // Combine server secret shares + _, SS := MPIN_RECOMBINE_G2_WRAP(SS1[:], SS2[:]) + + // Generate client secret share 1 + _, CS1 := MPIN_GET_CLIENT_SECRET_WRAP(MS1[:], HCID) + + // Generate client secret share 2 + _, CS2 := MPIN_GET_CLIENT_SECRET_WRAP(MS2[:], HCID) + + // Combine client secret shares + CS := make([]byte, G1S) + _, CS = MPIN_RECOMBINE_G1_WRAP(CS1[:], CS2[:]) + + // Generate time permit share 1 + _, TP1 := MPIN_GET_CLIENT_PERMIT_WRAP(date, MS1[:], HCID) + + // Generate time permit share 2 + _, TP2 := MPIN_GET_CLIENT_PERMIT_WRAP(date, MS2[:], HCID) + + // Combine time permit shares + _, TP := MPIN_RECOMBINE_G1_WRAP(TP1[:], TP2[:]) + + // Create token + _, TOKEN := MPIN_EXTRACT_PIN_WRAP(ID[:], PIN1, CS[:]) + + ////// Client ////// + + // Send U, UT, V, timeValue and Message to server + var X [EGS]byte + _, _, _, V, U, UT := MPIN_CLIENT_WRAP(date, timeValue, PIN2, rng, ID[:], X[:], TOKEN[:], TP[:], MESSAGE[:]) + + ////// Server ////// + got, _, _, _, _, _ := MPIN_SERVER_WRAP(date, timeValue, SS[:], U[:], UT[:], V[:], ID[:], MESSAGE[:]) + assert.Equal(t, want, got, "Should be equal") +} + +func TestCryptoBadToken(t *testing.T) { + want := -19 + // Assign the End-User an ID + IDstr := "[email protected]" + ID := []byte(IDstr) + + // Epoch time in days + date := 16660 + + // Epoch time in seconds + timeValue := 1439465203 + + // PIN variable to create token + PIN1 := 1234 + // PIN variable to authenticate + PIN2 := 1234 + + // Seed value for Random Number Generator (RNG) + seedHex := "9e8b4178790cd57a5761c4a6f164ba72" + seed, err := hex.DecodeString(seedHex) + if err != nil { + fmt.Println("Error decoding seed value") + return + } + rng := NewRAND() + rng.Seed(len(seed), seed) + + // Message to sign + var MESSAGE []byte + + // Generate Master Secret Share 1 + _, MS1 := MPIN_RANDOM_GENERATE_WRAP(rng) + + // Generate Master Secret Share 2 + _, MS2 := MPIN_RANDOM_GENERATE_WRAP(rng) + + // Either Client or TA calculates Hash(ID) + HCID := MPIN_HASH_ID(ID) + + // Generate server secret share 1 + _, SS1 := MPIN_GET_SERVER_SECRET_WRAP(MS1[:]) + + // Generate server secret share 2 + _, SS2 := MPIN_GET_SERVER_SECRET_WRAP(MS2[:]) + + // Combine server secret shares + _, SS := MPIN_RECOMBINE_G2_WRAP(SS1[:], SS2[:]) + + // Generate client secret share 1 + _, CS1 := MPIN_GET_CLIENT_SECRET_WRAP(MS1[:], HCID) + + // Generate client secret share 2 + _, CS2 := MPIN_GET_CLIENT_SECRET_WRAP(MS2[:], HCID) + + // Combine client secret shares + CS := make([]byte, G1S) + _, CS = MPIN_RECOMBINE_G1_WRAP(CS1[:], CS2[:]) + + // Generate time permit share 1 + _, TP1 := MPIN_GET_CLIENT_PERMIT_WRAP(date, MS1[:], HCID) + + // Generate time permit share 2 + _, TP2 := MPIN_GET_CLIENT_PERMIT_WRAP(date, MS2[:], HCID) + + // Combine time permit shares + _, TP := MPIN_RECOMBINE_G1_WRAP(TP1[:], TP2[:]) + + // Create token + _, TOKEN := MPIN_EXTRACT_PIN_WRAP(ID[:], PIN1, CS[:]) + + // Send U, UT, V, timeValue and Message to server + var X [EGS]byte + _, _, _, _, U, UT := MPIN_CLIENT_WRAP(date, timeValue, PIN2, rng, ID[:], X[:], TOKEN[:], TP[:], MESSAGE[:]) + + // Send UT as V to model bad token + got, _, _, _, _, _ := MPIN_SERVER_WRAP(date, timeValue, SS[:], U[:], UT[:], UT[:], ID[:], MESSAGE[:]) + assert.Equal(t, want, got, "Should be equal") +} + +func TestCryptoRandom(t *testing.T) { + want := 0 + + for i := 0; i < nIter; i++ { + + // Seed value for Random Number Generator (RNG) + seed := make([]byte, 16) + rand.Read(seed) + rng := NewRAND() + rng.Seed(len(seed), seed) + + // Epoch time in days + date := MPIN_today() + + // Epoch time in seconds + timeValue := MPIN_GET_TIME() + + // PIN variable to create token + PIN1 := mathrand.Intn(10000) + // PIN variable to authenticate + PIN2 := PIN1 + + // Assign the End-User a random ID + ID := make([]byte, 16) + rand.Read(ID) + + // Message to sign + var MESSAGE []byte + + // Generate Master Secret Share 1 + _, MS1 := MPIN_RANDOM_GENERATE_WRAP(rng) + + // Generate Master Secret Share 2 + _, MS2 := MPIN_RANDOM_GENERATE_WRAP(rng) + + // Either Client or TA calculates Hash(ID) + HCID := MPIN_HASH_ID(ID) + + // Generate server secret share 1 + _, SS1 := MPIN_GET_SERVER_SECRET_WRAP(MS1[:]) + + // Generate server secret share 2 + _, SS2 := MPIN_GET_SERVER_SECRET_WRAP(MS2[:]) + + // Combine server secret shares + _, SS := MPIN_RECOMBINE_G2_WRAP(SS1[:], SS2[:]) + + // Generate client secret share 1 + _, CS1 := MPIN_GET_CLIENT_SECRET_WRAP(MS1[:], HCID) + + // Generate client secret share 2 + _, CS2 := MPIN_GET_CLIENT_SECRET_WRAP(MS2[:], HCID) + + // Combine client secret shares + CS := make([]byte, G1S) + _, CS = MPIN_RECOMBINE_G1_WRAP(CS1[:], CS2[:]) + + // Generate time permit share 1 + _, TP1 := MPIN_GET_CLIENT_PERMIT_WRAP(date, MS1[:], HCID) + + // Generate time permit share 2 + _, TP2 := MPIN_GET_CLIENT_PERMIT_WRAP(date, MS2[:], HCID) + + // Combine time permit shares + _, TP := MPIN_RECOMBINE_G1_WRAP(TP1[:], TP2[:]) + + // Create token + _, TOKEN := MPIN_EXTRACT_PIN_WRAP(ID[:], PIN1, CS[:]) + + // Send U, UT, V, timeValue and Message to server + var X [EGS]byte + _, _, _, V, U, UT := MPIN_CLIENT_WRAP(date, timeValue, PIN2, rng, ID[:], X[:], TOKEN[:], TP[:], MESSAGE[:]) + + got, _, _, _, _, _ := MPIN_SERVER_WRAP(date, timeValue, SS[:], U[:], UT[:], V[:], ID[:], MESSAGE[:]) + assert.Equal(t, want, got, "Should be equal") + } +} + +func TestCryptoGoodSignature(t *testing.T) { + want := 0 + // Assign the End-User an ID + IDstr := "[email protected]" + ID := []byte(IDstr) + + // Message to sign + MESSAGE := []byte("test message to sign") + + // Epoch time in days + date := 16660 + + // Epoch time in seconds + timeValue := 1439465203 + + // PIN variable to create token + PIN1 := 1234 + // PIN variable to authenticate + PIN2 := 1234 + + // Seed value for Random Number Generator (RNG) + seedHex := "9e8b4178790cd57a5761c4a6f164ba72" + seed, err := hex.DecodeString(seedHex) + if err != nil { + fmt.Println("Error decoding seed value") + return + } + rng := NewRAND() + rng.Seed(len(seed), seed) + + // Generate Master Secret Share 1 + _, MS1 := MPIN_RANDOM_GENERATE_WRAP(rng) + + // Generate Master Secret Share 2 + _, MS2 := MPIN_RANDOM_GENERATE_WRAP(rng) + + // Either Client or TA calculates Hash(ID) + HCID := MPIN_HASH_ID(ID) + + // Generate server secret share 1 + _, SS1 := MPIN_GET_SERVER_SECRET_WRAP(MS1[:]) + + // Generate server secret share 2 + _, SS2 := MPIN_GET_SERVER_SECRET_WRAP(MS2[:]) + + // Combine server secret shares + _, SS := MPIN_RECOMBINE_G2_WRAP(SS1[:], SS2[:]) + + // Generate client secret share 1 + _, CS1 := MPIN_GET_CLIENT_SECRET_WRAP(MS1[:], HCID) + + // Generate client secret share 2 + _, CS2 := MPIN_GET_CLIENT_SECRET_WRAP(MS2[:], HCID) + + // Combine client secret shares + CS := make([]byte, G1S) + _, CS = MPIN_RECOMBINE_G1_WRAP(CS1[:], CS2[:]) + + // Generate time permit share 1 + _, TP1 := MPIN_GET_CLIENT_PERMIT_WRAP(date, MS1[:], HCID) + + // Generate time permit share 2 + _, TP2 := MPIN_GET_CLIENT_PERMIT_WRAP(date, MS2[:], HCID) + + // Combine time permit shares + _, TP := MPIN_RECOMBINE_G1_WRAP(TP1[:], TP2[:]) + + // Create token + _, TOKEN := MPIN_EXTRACT_PIN_WRAP(ID[:], PIN1, CS[:]) + + // Send U, UT, V, timeValue and Message to server + var X [EGS]byte + _, _, _, V, U, UT := MPIN_CLIENT_WRAP(date, timeValue, PIN2, rng, ID[:], X[:], TOKEN[:], TP[:], MESSAGE[:]) + + // Authenticate + got, _, _, _, _, _ := MPIN_SERVER_WRAP(date, timeValue, SS[:], U[:], UT[:], V[:], ID[:], MESSAGE[:]) + assert.Equal(t, want, got, "Should be equal") +} + +func TestCryptoSignatureExpired(t *testing.T) { + want := -19 + // Assign the End-User an ID + IDstr := "[email protected]" + ID := []byte(IDstr) + + // Message to sign + MESSAGE := []byte("test message to sign") + + // Epoch time in days + date := 16660 + + // Epoch time in seconds + timeValue := 1439465203 + + // PIN variable to create token + PIN1 := 1234 + // PIN variable to authenticate + PIN2 := 1234 + + // Seed value for Random Number Generator (RNG) + seedHex := "9e8b4178790cd57a5761c4a6f164ba72" + seed, err := hex.DecodeString(seedHex) + if err != nil { + fmt.Println("Error decoding seed value") + return + } + rng := NewRAND() + rng.Seed(len(seed), seed) + + // Generate Master Secret Share 1 + _, MS1 := MPIN_RANDOM_GENERATE_WRAP(rng) + + // Generate Master Secret Share 2 + _, MS2 := MPIN_RANDOM_GENERATE_WRAP(rng) + + // Either Client or TA calculates Hash(ID) + HCID := MPIN_HASH_ID(ID) + + // Generate server secret share 1 + _, SS1 := MPIN_GET_SERVER_SECRET_WRAP(MS1[:]) + + // Generate server secret share 2 + _, SS2 := MPIN_GET_SERVER_SECRET_WRAP(MS2[:]) + + // Combine server secret shares + _, SS := MPIN_RECOMBINE_G2_WRAP(SS1[:], SS2[:]) + + // Generate client secret share 1 + _, CS1 := MPIN_GET_CLIENT_SECRET_WRAP(MS1[:], HCID) + + // Generate client secret share 2 + _, CS2 := MPIN_GET_CLIENT_SECRET_WRAP(MS2[:], HCID) + + // Combine client secret shares + CS := make([]byte, G1S) + _, CS = MPIN_RECOMBINE_G1_WRAP(CS1[:], CS2[:]) + + // Generate time permit share 1 + _, TP1 := MPIN_GET_CLIENT_PERMIT_WRAP(date, MS1[:], HCID) + + // Generate time permit share 2 + _, TP2 := MPIN_GET_CLIENT_PERMIT_WRAP(date, MS2[:], HCID) + + // Combine time permit shares + _, TP := MPIN_RECOMBINE_G1_WRAP(TP1[:], TP2[:]) + + // Create token + _, TOKEN := MPIN_EXTRACT_PIN_WRAP(ID[:], PIN1, CS[:]) + + // Send U, UT, V, timeValue and Message to server + var X [EGS]byte + _, _, _, V, U, UT := MPIN_CLIENT_WRAP(date, timeValue, PIN2, rng, ID[:], X[:], TOKEN[:], TP[:], MESSAGE[:]) + + timeValue += 10 + // Authenticate + got, _, _, _, _, _ := MPIN_SERVER_WRAP(date, timeValue, SS[:], U[:], UT[:], V[:], ID[:], MESSAGE[:]) + assert.Equal(t, want, got, "Should be equal") +} + +func TestCryptoBadSignature(t *testing.T) { + want := -19 + // Assign the End-User an ID + IDstr := "[email protected]" + ID := []byte(IDstr) + + // Message to sign + MESSAGE := []byte("test message to sign") + + // Epoch time in days + date := 16660 + + // Epoch time in seconds + timeValue := 1439465203 + + // PIN variable to create token + PIN1 := 1234 + // PIN variable to authenticate + PIN2 := 1234 + + // Seed value for Random Number Generator (RNG) + seedHex := "9e8b4178790cd57a5761c4a6f164ba72" + seed, err := hex.DecodeString(seedHex) + if err != nil { + fmt.Println("Error decoding seed value") + return + } + rng := NewRAND() + rng.Seed(len(seed), seed) + + // Generate Master Secret Share 1 + _, MS1 := MPIN_RANDOM_GENERATE_WRAP(rng) + + // Generate Master Secret Share 2 + _, MS2 := MPIN_RANDOM_GENERATE_WRAP(rng) + + // Either Client or TA calculates Hash(ID) + HCID := MPIN_HASH_ID(ID) + + // Generate server secret share 1 + _, SS1 := MPIN_GET_SERVER_SECRET_WRAP(MS1[:]) + + // Generate server secret share 2 + _, SS2 := MPIN_GET_SERVER_SECRET_WRAP(MS2[:]) + + // Combine server secret shares + _, SS := MPIN_RECOMBINE_G2_WRAP(SS1[:], SS2[:]) + + // Generate client secret share 1 + _, CS1 := MPIN_GET_CLIENT_SECRET_WRAP(MS1[:], HCID) + + // Generate client secret share 2 + _, CS2 := MPIN_GET_CLIENT_SECRET_WRAP(MS2[:], HCID) + + // Combine client secret shares + CS := make([]byte, G1S) + _, CS = MPIN_RECOMBINE_G1_WRAP(CS1[:], CS2[:]) + + // Generate time permit share 1 + _, TP1 := MPIN_GET_CLIENT_PERMIT_WRAP(date, MS1[:], HCID) + + // Generate time permit share 2 + _, TP2 := MPIN_GET_CLIENT_PERMIT_WRAP(date, MS2[:], HCID) + + // Combine time permit shares + _, TP := MPIN_RECOMBINE_G1_WRAP(TP1[:], TP2[:]) + + // Create token + _, TOKEN := MPIN_EXTRACT_PIN_WRAP(ID[:], PIN1, CS[:]) + + // Send U, UT, V, timeValue and Message to server + var X [EGS]byte + _, _, _, V, U, UT := MPIN_CLIENT_WRAP(date, timeValue, PIN2, rng, ID[:], X[:], TOKEN[:], TP[:], MESSAGE[:]) + + // Authenticate + MESSAGE[0] = 00 + got, _, _, _, _, _ := MPIN_SERVER_WRAP(date, timeValue, SS[:], U[:], UT[:], V[:], ID[:], MESSAGE[:]) + assert.Equal(t, want, got, "Should be equal") +} + +func TestCryptoPINError(t *testing.T) { + want := 1 + // Assign the End-User an ID + IDstr := "[email protected]" + ID := []byte(IDstr) + + // Epoch time in days + date := 16660 + + // Epoch time in seconds + timeValue := 1439465203 + + // PIN variable to create token + PIN1 := 1234 + // PIN variable to authenticate + PIN2 := 1235 + + // Seed value for Random Number Generator (RNG) + seedHex := "9e8b4178790cd57a5761c4a6f164ba72" + seed, err := hex.DecodeString(seedHex) + if err != nil { + fmt.Println("Error decoding seed value") + return + } + rng := NewRAND() + rng.Seed(len(seed), seed) + + // Message to sign + var MESSAGE []byte + + // Generate Master Secret Share 1 + _, MS1 := MPIN_RANDOM_GENERATE_WRAP(rng) + + // Generate Master Secret Share 2 + _, MS2 := MPIN_RANDOM_GENERATE_WRAP(rng) + + // Either Client or TA calculates Hash(ID) + HCID := MPIN_HASH_ID(ID) + + // Generate server secret share 1 + _, SS1 := MPIN_GET_SERVER_SECRET_WRAP(MS1[:]) + + // Generate server secret share 2 + _, SS2 := MPIN_GET_SERVER_SECRET_WRAP(MS2[:]) + + // Combine server secret shares + _, SS := MPIN_RECOMBINE_G2_WRAP(SS1[:], SS2[:]) + + // Generate client secret share 1 + _, CS1 := MPIN_GET_CLIENT_SECRET_WRAP(MS1[:], HCID) + + // Generate client secret share 2 + _, CS2 := MPIN_GET_CLIENT_SECRET_WRAP(MS2[:], HCID) + + // Combine client secret shares + CS := make([]byte, G1S) + _, CS = MPIN_RECOMBINE_G1_WRAP(CS1[:], CS2[:]) + + // Generate time permit share 1 + _, TP1 := MPIN_GET_CLIENT_PERMIT_WRAP(date, MS1[:], HCID) + + // Generate time permit share 2 + _, TP2 := MPIN_GET_CLIENT_PERMIT_WRAP(date, MS2[:], HCID) + + // Combine time permit shares + _, TP := MPIN_RECOMBINE_G1_WRAP(TP1[:], TP2[:]) + + // Create token + _, TOKEN := MPIN_EXTRACT_PIN_WRAP(ID[:], PIN1, CS[:]) + + // Send U, UT, V, timeValue and Message to server + var X [EGS]byte + _, _, _, V, U, UT := MPIN_CLIENT_WRAP(date, timeValue, PIN2, rng, ID[:], X[:], TOKEN[:], TP[:], MESSAGE[:]) + + _, _, _, _, E, F := MPIN_SERVER_WRAP(date, timeValue, SS[:], U[:], UT[:], V[:], ID[:], MESSAGE[:]) + + got := MPIN_KANGAROO(E[:], F[:]) + assert.Equal(t, want, got, "Should be equal") +} + +func TestCryptoMPINFull(t *testing.T) { + want := "0afc948b03b2733a0663571f86411a07" + // Assign the End-User an ID + IDstr := "[email protected]" + ID := []byte(IDstr) + + // Epoch time in days + date := 16660 + + // Epoch time in seconds + timeValue := 1439465203 + + // PIN variable to create token + PIN1 := 1234 + // PIN variable to authenticate + PIN2 := 1234 + + // Seed value for Random Number Generator (RNG) + seedHex := "9e8b4178790cd57a5761c4a6f164ba72" + seed, err := hex.DecodeString(seedHex) + if err != nil { + fmt.Println("Error decoding seed value") + return + } + rng := NewRAND() + rng.Seed(len(seed), seed) + + // Message to sign + var MESSAGE []byte + + // Generate Master Secret Share 1 + _, MS1 := MPIN_RANDOM_GENERATE_WRAP(rng) + + // Generate Master Secret Share 2 + _, MS2 := MPIN_RANDOM_GENERATE_WRAP(rng) + + // Either Client or TA calculates Hash(ID) + HCID := MPIN_HASH_ID(ID) + + // Generate server secret share 1 + _, SS1 := MPIN_GET_SERVER_SECRET_WRAP(MS1[:]) + + // Generate server secret share 2 + _, SS2 := MPIN_GET_SERVER_SECRET_WRAP(MS2[:]) + + // Combine server secret shares + _, SS := MPIN_RECOMBINE_G2_WRAP(SS1[:], SS2[:]) + + // Generate client secret share 1 + _, CS1 := MPIN_GET_CLIENT_SECRET_WRAP(MS1[:], HCID) + + // Generate client secret share 2 + _, CS2 := MPIN_GET_CLIENT_SECRET_WRAP(MS2[:], HCID) + + // Combine client secret shares + CS := make([]byte, G1S) + _, CS = MPIN_RECOMBINE_G1_WRAP(CS1[:], CS2[:]) + + // Generate time permit share 1 + _, TP1 := MPIN_GET_CLIENT_PERMIT_WRAP(date, MS1[:], HCID) + + // Generate time permit share 2 + _, TP2 := MPIN_GET_CLIENT_PERMIT_WRAP(date, MS2[:], HCID) + + // Combine time permit shares + _, TP := MPIN_RECOMBINE_G1_WRAP(TP1[:], TP2[:]) + + // Create token + _, TOKEN := MPIN_EXTRACT_PIN_WRAP(ID[:], PIN1, CS[:]) + + // Precomputation + _, G1, G2 := MPIN_PRECOMPUTE_WRAP(TOKEN[:], HCID) + + // Send U, UT, V, timeValue and Message to server + var X [EGS]byte + _, XOut, _, V, U, UT := MPIN_CLIENT_WRAP(date, timeValue, PIN2, rng, ID[:], X[:], TOKEN[:], TP[:], MESSAGE[:]) + + // Send Z=r.ID to Server + var R [EGS]byte + _, ROut, Z := MPIN_GET_G1_MULTIPLE_WRAP(rng, 1, R[:], HCID[:]) + + // Authenticate + _, _, HTID, _, _, _ := MPIN_SERVER_WRAP(date, timeValue, SS[:], U[:], UT[:], V[:], ID[:], MESSAGE[:]) + + // send T=w.ID to client + var W [EGS]byte + _, WOut, T := MPIN_GET_G1_MULTIPLE_WRAP(rng, 0, W[:], HTID[:]) + + _, AES_KEY_SERVER := MPIN_SERVER_KEY_WRAP(Z[:], SS[:], WOut[:], U[:], UT[:]) + got := hex.EncodeToString(AES_KEY_SERVER[:]) + if got != want { + t.Errorf("%s != %s", want, got) + } + + _, AES_KEY_CLIENT := MPIN_CLIENT_KEY_WRAP(PIN2, G1[:], G2[:], ROut[:], XOut[:], T[:]) + got = hex.EncodeToString(AES_KEY_CLIENT[:]) + assert.Equal(t, want, got, "Should be equal") +} + +// Subtract a 256 bit PIN +func TestCrypoSubBigPIN(t *testing.T) { + want := "042182235070802ebc33633e70e6628f48fd896e86dfc40c81227caa2792367a581d461dbba6efa30896c71f427df335885142cc6fb64ba082ff9573b9276475c0" + + IDHex := "7465737455736572406365727469766f782e636f6d" + ID, err := hex.DecodeString(IDHex) + assert.Equal(t, nil, err, "Should be equal") + + TOKENHex := "0422a522b5c05d06cde3a65872656ab596e111c4ea7c0c349bac26f0bdaf7d5f0a1ea8a0cab99d06677cfbc3c8d667e7b0af33b9ed4df007b0ccc8c2b77353bbe6" + TOKEN, err := hex.DecodeString(TOKENHex) + assert.Equal(t, nil, err, "Should be equal") + + // Seed value for Random Number Generator (RNG) + seedHex := "9e8b4178790cd57a5761c4a6f164ba72" + seed, err := hex.DecodeString(seedHex) + assert.Equal(t, nil, err, "Should be equal") + rng := NewRAND() + rng.Seed(len(seed), seed) + + // Generate big PIN - 256 bits + errorCode, PIN := MPIN_RANDOM_GENERATE_WRAP(rng) + assert.Equal(t, 0, errorCode, "Should be equal") + + // Extract big PIN + errorCode, TK := MPIN_EXTRACT_BIG_PIN_WRAP(ID[:], PIN[:], TOKEN[:]) + assert.Equal(t, 0, errorCode, "Should be equal") + got := hex.EncodeToString(TK[:]) + assert.Equal(t, want, got, "Should be equal") +} + +// Add a 256 bit PIN +func TestCrypoAddBigPIN(t *testing.T) { + want := "0422a522b5c05d06cde3a65872656ab596e111c4ea7c0c349bac26f0bdaf7d5f0a1ea8a0cab99d06677cfbc3c8d667e7b0af33b9ed4df007b0ccc8c2b77353bbe6" + + IDHex := "7465737455736572406365727469766f782e636f6d" + ID, err := hex.DecodeString(IDHex) + assert.Equal(t, nil, err, "Should be equal") + + TOKENHex := "042182235070802ebc33633e70e6628f48fd896e86dfc40c81227caa2792367a581d461dbba6efa30896c71f427df335885142cc6fb64ba082ff9573b9276475c0" + TOKEN, err := hex.DecodeString(TOKENHex) + assert.Equal(t, nil, err, "Should be equal") + + PINHex := "1b18b8b882daf76a18bf2278fe4e15c62eed8131e708573375fd81a8415014b3" + PIN, err := hex.DecodeString(PINHex) + assert.Equal(t, nil, err, "Should be equal") + + // Extract big PIN + errorCode, TK := MPIN_ADD_BIG_PIN_WRAP(ID[:], PIN[:], TOKEN[:]) + assert.Equal(t, 0, errorCode, "Should be equal") + got := hex.EncodeToString(TK[:]) + assert.Equal(t, want, got, "Should be equal") +} + +// Split key +func TestCryptoSplitKey(t *testing.T) { + want := "64b36b7a0395e61350de8839adb019d5ae2134052b8533e7c4bbab3965e0af1b" + + // Seed value for Random Number Generator (RNG) + seedHex := "9e8b4178790cd57a5761c4a6f164ba72" + seed, err := hex.DecodeString(seedHex) + assert.Equal(t, nil, err, "Should be equal") + rng := NewRAND() + rng.Seed(len(seed), seed) + + // Generate big PIN - 256 bits + errorCode, PIN := MPIN_RANDOM_GENERATE_WRAP(rng) + assert.Equal(t, 0, errorCode, "Should be equal") + PINHex := hex.EncodeToString(PIN[:]) + PINGoldHex := "1b18b8b882daf76a18bf2278fe4e15c62eed8131e708573375fd81a8415014b3" + assert.Equal(t, PINGoldHex, PINHex, "Should be equal") + + n := len(PIN) + // Split key by C = PIN ^ A ^ B + A := GENERATE_RANDOM(rng, n) + + B := GENERATE_RANDOM(rng, n) + + C, errorCode := XORBytes(PIN[:], A[:], B[:]) + assert.Equal(t, 0, errorCode, "Should be equal") + got := hex.EncodeToString(C[:]) + assert.Equal(t, want, got, "Should be equal") +} + +// Combine key shares +func TestCryptoCombineKey(t *testing.T) { + want := "1b18b8b882daf76a18bf2278fe4e15c62eed8131e708573375fd81a8415014b3" + + CHex := "64b36b7a0395e61350de8839adb019d5ae2134052b8533e7c4bbab3965e0af1b" + C, err := hex.DecodeString(CHex) + assert.Equal(t, nil, err, "Should be equal") + + AHex := "c5add1327790087193ae541acd6dc3264c19a12afaf196291d0820c611d3fcd4" + A, err := hex.DecodeString(AHex) + assert.Equal(t, nil, err, "Should be equal") + + BHex := "ba0602f0f6df1908dbcffe5b9e93cf35ccd5141e367cf2fdac4e0a573563477c" + B, err := hex.DecodeString(BHex) + assert.Equal(t, nil, err, "Should be equal") + + // Combine key shares PIN = A ^ B ^ C + PIN, errorCode := XORBytes(C[:], A[:], B[:]) + assert.Equal(t, 0, errorCode, "Should be equal") + got := hex.EncodeToString(PIN[:]) + assert.Equal(t, want, got, "Should be equal") +} + +func TestCryptoTwoPassGoodPIN(t *testing.T) { + want := 0 + // Assign the End-User an ID + IDstr := "[email protected]" + ID := []byte(IDstr) + + // Epoch time in days + date := 16660 + + // PIN variable to create token + PIN1 := 1234 + // PIN variable to authenticate + PIN2 := 1234 + + // Seed value for Random Number Generator (RNG) + seedHex := "9e8b4178790cd57a5761c4a6f164ba72" + seed, err := hex.DecodeString(seedHex) + if err != nil { + fmt.Println("Error decoding seed value") + return + } + rng := NewRAND() + rng.Seed(len(seed), seed) + + // Generate Master Secret Share 1 + _, MS1 := MPIN_RANDOM_GENERATE_WRAP(rng) + + // Generate Master Secret Share 2 + _, MS2 := MPIN_RANDOM_GENERATE_WRAP(rng) + + // Either Client or TA calculates Hash(ID) + HCID := MPIN_HASH_ID(ID) + + // Generate server secret share 1 + _, SS1 := MPIN_GET_SERVER_SECRET_WRAP(MS1[:]) + + // Generate server secret share 2 + _, SS2 := MPIN_GET_SERVER_SECRET_WRAP(MS2[:]) + + // Combine server secret shares + _, SS := MPIN_RECOMBINE_G2_WRAP(SS1[:], SS2[:]) + + // Generate client secret share 1 + _, CS1 := MPIN_GET_CLIENT_SECRET_WRAP(MS1[:], HCID) + + // Generate client secret share 2 + _, CS2 := MPIN_GET_CLIENT_SECRET_WRAP(MS2[:], HCID) + + // Combine client secret shares + CS := make([]byte, G1S) + _, CS = MPIN_RECOMBINE_G1_WRAP(CS1[:], CS2[:]) + + // Generate time permit share 1 + _, TP1 := MPIN_GET_CLIENT_PERMIT_WRAP(date, MS1[:], HCID) + + // Generate time permit share 2 + _, TP2 := MPIN_GET_CLIENT_PERMIT_WRAP(date, MS2[:], HCID) + + // Combine time permit shares + _, TP := MPIN_RECOMBINE_G1_WRAP(TP1[:], TP2[:]) + + // Create token + _, TOKEN := MPIN_EXTRACT_PIN_WRAP(ID[:], PIN1, CS[:]) + + // Client Pass 1 + var X [EGS]byte + _, _, SEC, U, UT := MPIN_CLIENT_1_WRAP(date, ID, rng, X[:], PIN2, TOKEN[:], TP[:]) + + // Server Pass 1 + HID, HTID := MPIN_SERVER_1_WRAP(date, ID) + _, Y := MPIN_RANDOM_GENERATE_WRAP(rng) + + // Client Pass 2 + _, V := MPIN_CLIENT_2_WRAP(X[:], Y[:], SEC[:]) + + // Server Pass 2 + got, _, _ := MPIN_SERVER_2_WRAP(date, HID[:], HTID[:], Y[:], SS[:], U[:], UT[:], V[:]) + assert.Equal(t, want, got, "Should be equal") +} + +func TestCryptoTwoPassBadPIN(t *testing.T) { + want := -19 + // Assign the End-User an ID + IDstr := "[email protected]" + ID := []byte(IDstr) + + // Epoch time in days + date := 16660 + + // PIN variable to create token + PIN1 := 1234 + // PIN variable to authenticate + PIN2 := 1235 + + // Seed value for Random Number Generator (RNG) + seedHex := "9e8b4178790cd57a5761c4a6f164ba72" + seed, err := hex.DecodeString(seedHex) + if err != nil { + fmt.Println("Error decoding seed value") + return + } + rng := NewRAND() + rng.Seed(len(seed), seed) + + // Generate Master Secret Share 1 + _, MS1 := MPIN_RANDOM_GENERATE_WRAP(rng) + + // Generate Master Secret Share 2 + _, MS2 := MPIN_RANDOM_GENERATE_WRAP(rng) + + // Either Client or TA calculates Hash(ID) + HCID := MPIN_HASH_ID(ID) + + // Generate server secret share 1 + _, SS1 := MPIN_GET_SERVER_SECRET_WRAP(MS1[:]) + + // Generate server secret share 2 + _, SS2 := MPIN_GET_SERVER_SECRET_WRAP(MS2[:]) + + // Combine server secret shares + _, SS := MPIN_RECOMBINE_G2_WRAP(SS1[:], SS2[:]) + + // Generate client secret share 1 + _, CS1 := MPIN_GET_CLIENT_SECRET_WRAP(MS1[:], HCID) + + // Generate client secret share 2 + _, CS2 := MPIN_GET_CLIENT_SECRET_WRAP(MS2[:], HCID) + + // Combine client secret shares + CS := make([]byte, G1S) + _, CS = MPIN_RECOMBINE_G1_WRAP(CS1[:], CS2[:]) + + // Generate time permit share 1 + _, TP1 := MPIN_GET_CLIENT_PERMIT_WRAP(date, MS1[:], HCID) + + // Generate time permit share 2 + _, TP2 := MPIN_GET_CLIENT_PERMIT_WRAP(date, MS2[:], HCID) + + // Combine time permit shares + _, TP := MPIN_RECOMBINE_G1_WRAP(TP1[:], TP2[:]) + + // Create token + _, TOKEN := MPIN_EXTRACT_PIN_WRAP(ID[:], PIN1, CS[:]) + + // Client Pass 1 + var X [EGS]byte + _, _, SEC, U, UT := MPIN_CLIENT_1_WRAP(date, ID, rng, X[:], PIN2, TOKEN[:], TP[:]) + + // Server Pass 1 + HID, HTID := MPIN_SERVER_1_WRAP(date, ID) + _, Y := MPIN_RANDOM_GENERATE_WRAP(rng) + + // Client Pass 2 + _, V := MPIN_CLIENT_2_WRAP(X[:], Y[:], SEC[:]) + + // Server Pass 2 + got, _, _ := MPIN_SERVER_2_WRAP(date, HID[:], HTID[:], Y[:], SS[:], U[:], UT[:], V[:]) + assert.Equal(t, want, got, "Should be equal") +} + +func TestCryptoTwoPassBadToken(t *testing.T) { + want := -19 + // Assign the End-User an ID + IDstr := "[email protected]" + ID := []byte(IDstr) + + // Epoch time in days + date := 16660 + + // PIN variable to create token + PIN1 := 1234 + // PIN variable to authenticate + PIN2 := 1234 + + // Seed value for Random Number Generator (RNG) + seedHex := "9e8b4178790cd57a5761c4a6f164ba72" + seed, err := hex.DecodeString(seedHex) + if err != nil { + fmt.Println("Error decoding seed value") + return + } + rng := NewRAND() + rng.Seed(len(seed), seed) + + // Generate Master Secret Share 1 + _, MS1 := MPIN_RANDOM_GENERATE_WRAP(rng) + + // Generate Master Secret Share 2 + _, MS2 := MPIN_RANDOM_GENERATE_WRAP(rng) + + // Either Client or TA calculates Hash(ID) + HCID := MPIN_HASH_ID(ID) + + // Generate server secret share 1 + _, SS1 := MPIN_GET_SERVER_SECRET_WRAP(MS1[:]) + + // Generate server secret share 2 + _, SS2 := MPIN_GET_SERVER_SECRET_WRAP(MS2[:]) + + // Combine server secret shares + _, SS := MPIN_RECOMBINE_G2_WRAP(SS1[:], SS2[:]) + + // Generate client secret share 1 + _, CS1 := MPIN_GET_CLIENT_SECRET_WRAP(MS1[:], HCID) + + // Generate client secret share 2 + _, CS2 := MPIN_GET_CLIENT_SECRET_WRAP(MS2[:], HCID) + + // Combine client secret shares + CS := make([]byte, G1S) + _, CS = MPIN_RECOMBINE_G1_WRAP(CS1[:], CS2[:]) + + // Generate time permit share 1 + _, TP1 := MPIN_GET_CLIENT_PERMIT_WRAP(date, MS1[:], HCID) + + // Generate time permit share 2 + _, TP2 := MPIN_GET_CLIENT_PERMIT_WRAP(date, MS2[:], HCID) + + // Combine time permit shares + _, TP := MPIN_RECOMBINE_G1_WRAP(TP1[:], TP2[:]) + + // Create token + _, TOKEN := MPIN_EXTRACT_PIN_WRAP(ID[:], PIN1, CS[:]) + + // Client Pass 1 + var X [EGS]byte + _, _, SEC, U, UT := MPIN_CLIENT_1_WRAP(date, ID, rng, X[:], PIN2, TOKEN[:], TP[:]) + + // Server Pass 1 + HID, HTID := MPIN_SERVER_1_WRAP(date, ID) + _, Y := MPIN_RANDOM_GENERATE_WRAP(rng) + + // Client Pass 2 + _, _ = MPIN_CLIENT_2_WRAP(X[:], Y[:], SEC[:]) + + // Server Pass 2 + // Send UT as V to model bad token + got, _, _ := MPIN_SERVER_2_WRAP(date, HID[:], HTID[:], Y[:], SS[:], U[:], UT[:], UT[:]) + assert.Equal(t, want, got, "Should be equal") +} + +func TestCryptoRandomTwoPass(t *testing.T) { + want := 0 + + for i := 0; i < nIter; i++ { + + // Seed value for Random Number Generator (RNG) + seed := make([]byte, 16) + rand.Read(seed) + rng := NewRAND() + rng.Seed(len(seed), seed) + + // Epoch time in days + date := MPIN_today() + + // PIN variable to create token + PIN1 := mathrand.Intn(10000) + // PIN variable to authenticate + PIN2 := PIN1 + + // Assign the End-User a random ID + ID := make([]byte, 16) + rand.Read(ID) + + // Generate Master Secret Share 1 + _, MS1 := MPIN_RANDOM_GENERATE_WRAP(rng) + + // Generate Master Secret Share 2 + _, MS2 := MPIN_RANDOM_GENERATE_WRAP(rng) + + // Either Client or TA calculates Hash(ID) + HCID := MPIN_HASH_ID(ID) + + // Generate server secret share 1 + _, SS1 := MPIN_GET_SERVER_SECRET_WRAP(MS1[:]) + + // Generate server secret share 2 + _, SS2 := MPIN_GET_SERVER_SECRET_WRAP(MS2[:]) + + // Combine server secret shares + _, SS := MPIN_RECOMBINE_G2_WRAP(SS1[:], SS2[:]) + + // Generate client secret share 1 + _, CS1 := MPIN_GET_CLIENT_SECRET_WRAP(MS1[:], HCID) + + // Generate client secret share 2 + _, CS2 := MPIN_GET_CLIENT_SECRET_WRAP(MS2[:], HCID) + + // Combine client secret shares + CS := make([]byte, G1S) + _, CS = MPIN_RECOMBINE_G1_WRAP(CS1[:], CS2[:]) + + // Generate time permit share 1 + _, TP1 := MPIN_GET_CLIENT_PERMIT_WRAP(date, MS1[:], HCID) + + // Generate time permit share 2 + _, TP2 := MPIN_GET_CLIENT_PERMIT_WRAP(date, MS2[:], HCID) + + // Combine time permit shares + _, TP := MPIN_RECOMBINE_G1_WRAP(TP1[:], TP2[:]) + + // Create token + _, TOKEN := MPIN_EXTRACT_PIN_WRAP(ID[:], PIN1, CS[:]) + + // Client Pass 1 + var X [EGS]byte + _, _, SEC, U, UT := MPIN_CLIENT_1_WRAP(date, ID, rng, X[:], PIN2, TOKEN[:], TP[:]) + + // Server Pass 1 + HID, HTID := MPIN_SERVER_1_WRAP(date, ID) + _, Y := MPIN_RANDOM_GENERATE_WRAP(rng) + + // Client Pass 2 + _, V := MPIN_CLIENT_2_WRAP(X[:], Y[:], SEC[:]) + + // Server Pass 2 + got, _, _ := MPIN_SERVER_2_WRAP(date, HID[:], HTID[:], Y[:], SS[:], U[:], UT[:], V[:]) + assert.Equal(t, want, got, "Should be equal") + + } +}
