| /* |
| 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. |
| */ |
| |
| /* MPIN API Functions */ |
| |
| package main |
| |
| import "time" |
| |
| //import "fmt" |
| |
| /* Configure mode of operation */ |
| |
| const PERMITS bool=true |
| const PINERROR bool=true |
| const FULL bool=true |
| const SINGLE_PASS bool=false |
| |
| |
| const MPIN_EFS int=int(MODBYTES) |
| const MPIN_EGS int=int(MODBYTES) |
| const MPIN_PAS int=16 |
| const MPIN_BAD_PARAMS int=-11 |
| const MPIN_INVALID_POINT int=-14 |
| const MPIN_WRONG_ORDER int=-18 |
| const MPIN_BAD_PIN int=-19 |
| const MPIN_SHA256 int=32 |
| const MPIN_SHA384 int=48 |
| const MPIN_SHA512 int=64 |
| |
| /* Configure your PIN here */ |
| |
| const MPIN_MAXPIN int32=10000 /* PIN less than this */ |
| const MPIN_PBLEN int32=14 /* Number of bits in PIN */ |
| const MPIN_TS int=10 /* 10 for 4 digit PIN, 14 for 6-digit PIN - 2^TS/TS approx = sqrt(MAXPIN) */ |
| const MPIN_TRAP int=200 /* 200 for 4 digit PIN, 2000 for 6-digit PIN - approx 2*sqrt(MAXPIN) */ |
| |
| const MPIN_HASH_TYPE int=MPIN_SHA256 |
| |
| func mpin_hash(sha int,c *FP4,U *ECP) []byte { |
| var w [MPIN_EFS]byte |
| var t [6*MPIN_EFS]byte |
| var h []byte |
| |
| c.geta().getA().toBytes(w[:]); for i:=0;i<MPIN_EFS;i++ {t[i]=w[i]} |
| c.geta().getB().toBytes(w[:]); for i:=MPIN_EFS;i<2*MPIN_EFS;i++ {t[i]=w[i-MPIN_EFS]} |
| c.getb().getA().toBytes(w[:]); for i:=2*MPIN_EFS;i<3*MPIN_EFS;i++ {t[i]=w[i-2*MPIN_EFS]} |
| c.getb().getB().toBytes(w[:]); for i:=3*MPIN_EFS;i<4*MPIN_EFS;i++ {t[i]=w[i-3*MPIN_EFS]} |
| |
| U.getX().toBytes(w[:]); for i:=4*MPIN_EFS;i<5*MPIN_EFS;i++ {t[i]=w[i-4*MPIN_EFS]} |
| U.getY().toBytes(w[:]); for i:=5*MPIN_EFS;i<6*MPIN_EFS;i++ {t[i]=w[i-5*MPIN_EFS]} |
| |
| if sha==MPIN_SHA256 { |
| H:=NewHASH256() |
| H.Process_array(t[:]) |
| h=H.Hash() |
| } |
| if sha==MPIN_SHA384 { |
| H:=NewHASH384() |
| H.Process_array(t[:]) |
| h=H.Hash() |
| } |
| if sha==MPIN_SHA512 { |
| H:=NewHASH512() |
| H.Process_array(t[:]) |
| h=H.Hash() |
| } |
| if h==nil {return nil} |
| R:=make([]byte,MPIN_PAS) |
| for i:=0;i<MPIN_PAS;i++ {R[i]=h[i]} |
| return R |
| } |
| |
| /* Hash number (optional) and string to coordinate on curve */ |
| |
| func mhashit(sha int,n int32,ID []byte) []byte { |
| var R []byte |
| if sha==MPIN_SHA256 { |
| H:=NewHASH256() |
| if n!=0 {H.Process_num(n)} |
| H.Process_array(ID) |
| R=H.Hash() |
| } |
| if sha==MPIN_SHA384 { |
| H:=NewHASH384() |
| if n!=0 {H.Process_num(n)} |
| H.Process_array(ID) |
| R=H.Hash() |
| } |
| if sha==MPIN_SHA512 { |
| H:=NewHASH512() |
| if n!=0 {H.Process_num(n)} |
| H.Process_array(ID) |
| R=H.Hash() |
| } |
| if R==nil {return nil} |
| const RM int=int(MODBYTES) |
| var W [RM]byte |
| if sha>RM { |
| for i:=0;i<RM;i++ {W[i]=R[i]} |
| } else { |
| for i:=0;i<sha;i++ {W[i]=R[i]} |
| for i:=sha;i<RM;i++ {W[i]=0} |
| } |
| |
| return W[:] |
| } |
| |
| func mapit(h []byte) *ECP { |
| q:=NewBIGints(Modulus) |
| x:=fromBytes(h[:]) |
| x.mod(q) |
| var P *ECP |
| for true { |
| P=NewECPbigint(x,0) |
| if !P.is_infinity() {break} |
| x.inc(1); x.norm() |
| } |
| if CURVE_PAIRING_TYPE!=BN_CURVE { |
| c:=NewBIGints(CURVE_Cof) |
| P=P.mul(c) |
| } |
| return P |
| } |
| |
| /* needed for SOK */ |
| func mapit2(h []byte) *ECP2 { |
| q:=NewBIGints(Modulus) |
| x:=fromBytes(h[:]) |
| one:=NewBIGint(1) |
| var X *FP2 |
| var Q,T,K *ECP2 |
| x.mod(q) |
| for true { |
| X=NewFP2bigs(one,x) |
| Q=NewECP2fp2(X) |
| if !Q.is_infinity() {break} |
| x.inc(1); x.norm() |
| } |
| /* Fast Hashing to G2 - Fuentes-Castaneda, Knapp and Rodriguez-Henriquez */ |
| Fra:=NewBIGints(CURVE_Fra) |
| Frb:=NewBIGints(CURVE_Frb) |
| X=NewFP2bigs(Fra,Frb) |
| x=NewBIGints(CURVE_Bnx) |
| |
| T=NewECP2(); T.copy(Q) |
| T.mul(x); T.neg() |
| K=NewECP2(); K.copy(T) |
| K.dbl(); K.add(T); K.affine() |
| |
| K.frob(X) |
| Q.frob(X); Q.frob(X); Q.frob(X) |
| Q.add(T); Q.add(K) |
| T.frob(X); T.frob(X) |
| Q.add(T) |
| Q.affine() |
| return Q |
| } |
| |
| /* return time in slots since epoch */ |
| func MPIN_today() int { |
| now:=time.Now() |
| return int(now.Unix())/(60*1440) |
| } |
| |
| /* these next two functions help to implement elligator squared - http://eprint.iacr.org/2014/043 */ |
| /* maps a random u to a point on the curve */ |
| func emap(u *BIG,cb int) *ECP { |
| var P *ECP |
| x:=NewBIGcopy(u) |
| p:=NewBIGints(Modulus) |
| x.mod(p) |
| for true { |
| P=NewECPbigint(x,cb) |
| if !P.is_infinity() {break} |
| x.inc(1); x.norm() |
| } |
| return P |
| } |
| |
| /* returns u derived from P. Random value in range 1 to return value should then be added to u */ |
| func unmap(u* BIG,P *ECP) int { |
| s:=P.getS() |
| var R *ECP |
| r:=0 |
| x:=P.getX() |
| u.copy(x) |
| for true { |
| u.dec(1); u.norm() |
| r++ |
| R=NewECPbigint(u,s) |
| if !R.is_infinity() {break} |
| } |
| return r |
| } |
| |
| func MPIN_HASH_ID(sha int,ID []byte) []byte { |
| return mhashit(sha,0,ID) |
| } |
| |
| /* these next two functions implement elligator squared - http://eprint.iacr.org/2014/043 */ |
| /* Elliptic curve point E in format (0x04,x,y} is converted to form {0x0-,u,v} */ |
| /* Note that u and v are indistinguisible from random strings */ |
| func MPIN_ENCODING(rng *RAND,E []byte) int { |
| var T [MPIN_EFS]byte |
| |
| for i:=0;i<MPIN_EFS;i++ {T[i]=E[i+1]} |
| u:=fromBytes(T[:]) |
| for i:=0;i<MPIN_EFS;i++ {T[i]=E[i+MPIN_EFS+1]} |
| v:=fromBytes(T[:]) |
| |
| P:=NewECPbigs(u,v) |
| if P.is_infinity() {return MPIN_INVALID_POINT} |
| |
| p:=NewBIGints(Modulus) |
| u=randomnum(p,rng) |
| |
| su:=int(rng.GetByte()); /*if (su<0) su=-su;*/ su%=2 |
| |
| W:=emap(u,su) |
| P.sub(W) |
| sv:=P.getS() |
| rn:=unmap(v,P) |
| m:=int(rng.GetByte()); /*if (m<0) m=-m;*/ m%=rn |
| v.inc(m+1) |
| E[0]=byte(su+2*sv) |
| u.toBytes(T[:]) |
| for i:=0;i<MPIN_EFS;i++ {E[i+1]=T[i]} |
| v.toBytes(T[:]) |
| for i:=0;i<MPIN_EFS;i++ {E[i+MPIN_EFS+1]=T[i]} |
| |
| return 0 |
| } |
| |
| func MPIN_DECODING(D []byte) int { |
| var T [MPIN_EFS]byte |
| |
| if (D[0]&0x04)!=0 {return MPIN_INVALID_POINT} |
| |
| for i:=0;i<MPIN_EFS;i++ {T[i]=D[i+1]} |
| u:=fromBytes(T[:]) |
| for i:=0;i<MPIN_EFS;i++ {T[i]=D[i+MPIN_EFS+1]} |
| v:=fromBytes(T[:]) |
| |
| su:=int(D[0]&1) |
| sv:=int((D[0]>>1)&1) |
| W:=emap(u,su) |
| P:=emap(v,sv) |
| P.add(W) |
| u=P.getX() |
| v=P.getY() |
| D[0]=0x04 |
| u.toBytes(T[:]) |
| for i:=0;i<MPIN_EFS;i++ {D[i+1]=T[i]} |
| v.toBytes(T[:]) |
| for i:=0;i<MPIN_EFS;i++ {D[i+MPIN_EFS+1]=T[i]} |
| |
| return 0 |
| } |
| |
| /* R=R1+R2 in group G1 */ |
| func MPIN_RECOMBINE_G1(R1 []byte,R2 []byte,R []byte) int { |
| P:=ECP_fromBytes(R1) |
| Q:=ECP_fromBytes(R2) |
| |
| if (P.is_infinity() || Q.is_infinity()) {return MPIN_INVALID_POINT} |
| |
| P.add(Q) |
| |
| P.toBytes(R[:]) |
| return 0 |
| } |
| |
| /* W=W1+W2 in group G2 */ |
| func MPIN_RECOMBINE_G2(W1 []byte,W2 []byte,W []byte) int { |
| P:=ECP2_fromBytes(W1) |
| Q:=ECP2_fromBytes(W2) |
| |
| if (P.is_infinity() || Q.is_infinity()) {return MPIN_INVALID_POINT} |
| |
| P.add(Q) |
| |
| P.toBytes(W) |
| return 0 |
| } |
| |
| /* create random secret S */ |
| func MPIN_RANDOM_GENERATE(rng *RAND,S []byte) int { |
| r:=NewBIGints(CURVE_Order); |
| s:=randomnum(r,rng) |
| if AES_S>0 { |
| s.mod2m(2*AES_S) |
| } |
| s.toBytes(S) |
| return 0 |
| } |
| |
| /* Extract PIN from TOKEN for identity CID */ |
| func MPIN_EXTRACT_PIN(sha int,CID []byte,pin int,TOKEN []byte) int { |
| P:=ECP_fromBytes(TOKEN) |
| if P.is_infinity() {return MPIN_INVALID_POINT} |
| h:=mhashit(sha,0,CID) |
| R:=mapit(h) |
| |
| R=R.pinmul(int32(pin)%MPIN_MAXPIN,MPIN_PBLEN) |
| P.sub(R) |
| |
| P.toBytes(TOKEN) |
| |
| return 0 |
| } |
| |
| /* Implement step 2 on client side of MPin protocol */ |
| func MPIN_CLIENT_2(X []byte,Y []byte,SEC []byte) int { |
| r:=NewBIGints(CURVE_Order) |
| P:=ECP_fromBytes(SEC) |
| if P.is_infinity() {return MPIN_INVALID_POINT} |
| |
| px:=fromBytes(X) |
| py:=fromBytes(Y) |
| px.add(py) |
| px.mod(r) |
| //px.rsub(r) |
| |
| P=G1mul(P,px) |
| P.neg() |
| P.toBytes(SEC) |
| //G1mul(P,px).toBytes(SEC) |
| return 0 |
| } |
| |
| /* Implement step 1 on client side of MPin protocol */ |
| func MPIN_CLIENT_1(sha int,date int,CLIENT_ID []byte,rng *RAND,X []byte,pin int,TOKEN []byte,SEC []byte,xID []byte,xCID []byte,PERMIT []byte) int { |
| r:=NewBIGints(CURVE_Order) |
| |
| var x *BIG |
| if (rng!=nil) { |
| x=randomnum(r,rng) |
| if AES_S>0 { |
| x.mod2m(2*AES_S) |
| } |
| x.toBytes(X) |
| } else { |
| x=fromBytes(X) |
| } |
| |
| h:=mhashit(sha,0,CLIENT_ID) |
| P:=mapit(h) |
| |
| T:=ECP_fromBytes(TOKEN) |
| if T.is_infinity() {return MPIN_INVALID_POINT} |
| |
| W:=P.pinmul(int32(pin)%MPIN_MAXPIN,MPIN_PBLEN) |
| T.add(W) |
| if date!=0 { |
| W=ECP_fromBytes(PERMIT) |
| if W.is_infinity() {return MPIN_INVALID_POINT} |
| T.add(W) |
| h=mhashit(sha,int32(date),h) |
| W=mapit(h) |
| if xID!=nil { |
| P=G1mul(P,x) |
| P.toBytes(xID) |
| W=G1mul(W,x) |
| P.add(W) |
| } else { |
| P.add(W) |
| P=G1mul(P,x) |
| } |
| if xCID!=nil {P.toBytes(xCID)} |
| } else { |
| if xID!=nil { |
| P=G1mul(P,x) |
| P.toBytes(xID) |
| } |
| } |
| |
| |
| T.toBytes(SEC) |
| return 0 |
| } |
| |
| /* Extract Server Secret SST=S*Q where Q is fixed generator in G2 and S is master secret */ |
| func MPIN_GET_SERVER_SECRET(S []byte,SST []byte) int { |
| Q:=NewECP2fp2s(NewFP2bigs(NewBIGints(CURVE_Pxa),NewBIGints(CURVE_Pxb)),NewFP2bigs(NewBIGints(CURVE_Pya),NewBIGints(CURVE_Pyb))) |
| |
| s:=fromBytes(S) |
| Q=G2mul(Q,s) |
| Q.toBytes(SST) |
| return 0 |
| } |
| |
| /* |
| W=x*H(G); |
| if RNG == NULL then X is passed in |
| if RNG != NULL the X is passed out |
| if type=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 |
| */ |
| func MPIN_GET_G1_MULTIPLE(rng *RAND,typ int,X []byte,G []byte,W []byte) int { |
| var x *BIG |
| r:=NewBIGints(CURVE_Order) |
| if rng!=nil { |
| x=randomnum(r,rng) |
| if AES_S>0 { |
| x.mod2m(2*AES_S) |
| } |
| x.toBytes(X) |
| } else { |
| x=fromBytes(X) |
| } |
| var P *ECP |
| if typ==0 { |
| P=ECP_fromBytes(G) |
| if P.is_infinity() {return MPIN_INVALID_POINT} |
| } else {P=mapit(G)} |
| |
| G1mul(P,x).toBytes(W) |
| return 0 |
| } |
| |
| /* Client secret CST=S*H(CID) where CID is client ID and S is master secret */ |
| /* CID is hashed externally */ |
| func MPIN_GET_CLIENT_SECRET(S []byte,CID []byte,CST []byte) int { |
| return MPIN_GET_G1_MULTIPLE(nil,1,S,CID,CST) |
| } |
| |
| /* Time Permit CTT=S*(date|H(CID)) where S is master secret */ |
| func MPIN_GET_CLIENT_PERMIT(sha,date int,S []byte,CID []byte,CTT []byte) int { |
| h:=mhashit(sha,int32(date),CID) |
| P:=mapit(h) |
| |
| s:=fromBytes(S) |
| G1mul(P,s).toBytes(CTT) |
| return 0 |
| } |
| |
| /* Outputs H(CID) and H(T|H(CID)) for time permits. If no time permits set HID=HTID */ |
| func MPIN_SERVER_1(sha int,date int,CID []byte,HID []byte,HTID []byte) { |
| h:=mhashit(sha,0,CID) |
| P:=mapit(h) |
| |
| P.toBytes(HID); |
| if date!=0 { |
| // if HID!=nil {P.toBytes(HID)} |
| h=mhashit(sha,int32(date),h) |
| R:=mapit(h) |
| P.add(R) |
| P.toBytes(HTID) |
| } //else {P.toBytes(HID)} |
| } |
| |
| /* Implement step 2 of MPin protocol on server side */ |
| func MPIN_SERVER_2(date int,HID []byte,HTID []byte,Y []byte,SST []byte,xID []byte,xCID []byte,mSEC []byte,E []byte,F []byte) int { |
| // q:=NewBIGints(Modulus) |
| Q:=NewECP2fp2s(NewFP2bigs(NewBIGints(CURVE_Pxa),NewBIGints(CURVE_Pxb)),NewFP2bigs(NewBIGints(CURVE_Pya),NewBIGints(CURVE_Pyb))) |
| |
| sQ:=ECP2_fromBytes(SST) |
| if sQ.is_infinity() {return MPIN_INVALID_POINT} |
| |
| var R *ECP |
| if date!=0 { |
| R=ECP_fromBytes(xCID) |
| } else { |
| if xID==nil {return MPIN_BAD_PARAMS} |
| R=ECP_fromBytes(xID) |
| } |
| if R.is_infinity() {return MPIN_INVALID_POINT} |
| |
| y:=fromBytes(Y) |
| var P *ECP |
| if date!=0 { |
| P=ECP_fromBytes(HTID) |
| } else { |
| if HID==nil {return MPIN_BAD_PARAMS} |
| P=ECP_fromBytes(HID) |
| } |
| |
| if P.is_infinity() {return MPIN_INVALID_POINT} |
| |
| P=G1mul(P,y) |
| P.add(R) |
| R=ECP_fromBytes(mSEC) |
| if R.is_infinity() {return MPIN_INVALID_POINT} |
| |
| var g *FP12 |
| // FP12 g1=new FP12(0); |
| |
| g=ate2(Q,R,sQ,P) |
| g=fexp(g) |
| |
| if !g.isunity() { |
| if (HID!=nil && xID!=nil && E!=nil && F!=nil) { |
| g.toBytes(E) |
| if date!=0 { |
| P=ECP_fromBytes(HID) |
| if P.is_infinity() {return MPIN_INVALID_POINT} |
| R=ECP_fromBytes(xID) |
| if R.is_infinity() {return MPIN_INVALID_POINT} |
| |
| P=G1mul(P,y) |
| P.add(R) |
| } |
| g=ate(Q,P) |
| g=fexp(g) |
| g.toBytes(F) |
| } |
| return MPIN_BAD_PIN |
| } |
| |
| return 0 |
| } |
| |
| /* Pollards kangaroos used to return PIN error */ |
| func MPIN_KANGAROO(E []byte,F []byte) int { |
| ge:=FP12_fromBytes(E) |
| gf:=FP12_fromBytes(F) |
| var distance [MPIN_TS]int |
| t:=NewFP12copy(gf) |
| |
| var table []*FP12 |
| var i int |
| s:=1 |
| for m:=0;m<MPIN_TS;m++ { |
| distance[m]=s |
| table=append(table,NewFP12copy(t)) |
| s*=2 |
| t.usqr() |
| } |
| t.one() |
| dn:=0 |
| for j:=0;j<MPIN_TRAP;j++ { |
| i=t.geta().geta().getA().lastbits(20)%MPIN_TS |
| t.mul(table[i]) |
| dn+=distance[i] |
| } |
| gf.copy(t); gf.conj() |
| steps:=0; dm:=0 |
| res:=0 |
| for dm-dn<int(MPIN_MAXPIN) { |
| steps++ |
| if steps>4*MPIN_TRAP {break} |
| i=ge.geta().geta().getA().lastbits(20)%MPIN_TS; |
| ge.mul(table[i]) |
| dm+=distance[i] |
| if ge.equals(t) { |
| res=dm-dn |
| break; |
| } |
| if ge.equals(gf) { |
| res=dn-dm |
| break |
| } |
| |
| } |
| if (steps>4*MPIN_TRAP || dm-dn>=int(MPIN_MAXPIN)) {res=0 } // Trap Failed - probable invalid token |
| return int(res) |
| } |
| |
| /* Functions to support M-Pin Full */ |
| |
| func MPIN_PRECOMPUTE(TOKEN []byte,CID []byte,G1 []byte,G2 []byte) int { |
| var P,T *ECP |
| var g *FP12 |
| |
| T=ECP_fromBytes(TOKEN) |
| if T.is_infinity() {return MPIN_INVALID_POINT} |
| |
| P=mapit(CID) |
| |
| Q:=NewECP2fp2s(NewFP2bigs(NewBIGints(CURVE_Pxa),NewBIGints(CURVE_Pxb)),NewFP2bigs(NewBIGints(CURVE_Pya),NewBIGints(CURVE_Pyb))) |
| |
| g=ate(Q,T) |
| g=fexp(g) |
| g.toBytes(G1) |
| |
| g=ate(Q,P) |
| g=fexp(g) |
| g.toBytes(G2) |
| |
| return 0 |
| } |
| |
| /* Hash the M-Pin transcript - new */ |
| |
| func MPIN_HASH_ALL(sha int,HID []byte,xID []byte,xCID []byte,SEC []byte,Y []byte,R []byte,W []byte) []byte { |
| tlen:=0 |
| var T [10*int(MODBYTES)+4]byte |
| |
| for i:=0;i<len(HID);i++ {T[i]=HID[i]} |
| tlen+=len(HID) |
| if xCID!=nil { |
| for i:=0;i<len(xCID);i++ {T[i+tlen]=xCID[i]} |
| tlen+=len(xCID) |
| } else { |
| for i:=0;i<len(xID);i++ {T[i+tlen]=xID[i]} |
| tlen+=len(xID) |
| } |
| for i:=0;i<len(SEC);i++ {T[i+tlen]=SEC[i]} |
| tlen+=len(SEC) |
| for i:=0;i<len(Y);i++ {T[i+tlen]=Y[i]} |
| tlen+=len(Y) |
| for i:=0;i<len(R);i++ {T[i+tlen]=R[i]} |
| tlen+=len(R) |
| for i:=0;i<len(W);i++ {T[i+tlen]=W[i]} |
| tlen+=len(W) |
| |
| return mhashit(sha,0,T[:]) |
| } |
| |
| /* calculate common key on client side */ |
| /* wCID = w.(A+AT) */ |
| func MPIN_CLIENT_KEY(sha int,G1 []byte,G2 []byte,pin int,R []byte,X []byte,H []byte,wCID []byte,CK []byte) int { |
| |
| g1:=FP12_fromBytes(G1) |
| g2:=FP12_fromBytes(G2) |
| z:=fromBytes(R) |
| x:=fromBytes(X) |
| h:=fromBytes(H) |
| |
| W:=ECP_fromBytes(wCID) |
| if W.is_infinity() {return MPIN_INVALID_POINT} |
| |
| W=G1mul(W,x) |
| |
| f:=NewFP2bigs(NewBIGints(CURVE_Fra),NewBIGints(CURVE_Frb)) |
| r:=NewBIGints(CURVE_Order) |
| q:=NewBIGints(Modulus) |
| |
| z.add(h); //new |
| z.mod(r); |
| |
| m:=NewBIGcopy(q) |
| m.mod(r) |
| |
| a:=NewBIGcopy(z) |
| a.mod(m) |
| |
| b:=NewBIGcopy(z) |
| b.div(m) |
| |
| g2.pinpow(pin,int(MPIN_PBLEN)) |
| g1.mul(g2) |
| |
| c:=g1.trace() |
| g2.copy(g1) |
| g2.frob(f) |
| cp:=g2.trace() |
| g1.conj() |
| g2.mul(g1) |
| cpm1:=g2.trace() |
| g2.mul(g1) |
| cpm2:=g2.trace() |
| |
| c=c.xtr_pow2(cp,cpm1,cpm2,a,b) |
| |
| t:=mpin_hash(sha,c,W); |
| |
| for i:=0;i<MPIN_PAS;i++ {CK[i]=t[i]} |
| |
| return 0 |
| } |
| |
| /* calculate common key on server side */ |
| /* Z=r.A - no time permits involved */ |
| |
| func MPIN_SERVER_KEY(sha int,Z []byte,SST []byte,W []byte,H []byte,HID []byte,xID []byte,xCID []byte,SK []byte) int { |
| sQ:=ECP2_fromBytes(SST) |
| if sQ.is_infinity() {return MPIN_INVALID_POINT} |
| R:=ECP_fromBytes(Z) |
| if R.is_infinity() {return MPIN_INVALID_POINT} |
| A:=ECP_fromBytes(HID) |
| if A.is_infinity() {return MPIN_INVALID_POINT} |
| |
| var U *ECP |
| if xCID!=nil { |
| U=ECP_fromBytes(xCID) |
| } else {U=ECP_fromBytes(xID)} |
| if U.is_infinity() {return MPIN_INVALID_POINT} |
| |
| w:=fromBytes(W) |
| h:=fromBytes(H) |
| A=G1mul(A,h) // new |
| R.add(A) |
| |
| U=G1mul(U,w) |
| g:=ate(sQ,R) |
| g=fexp(g) |
| |
| c:=g.trace() |
| |
| t:=mpin_hash(sha,c,U) |
| |
| for i:=0;i<MPIN_PAS;i++ {SK[i]=t[i]} |
| |
| return 0 |
| } |
| |
| /* return time since epoch */ |
| func MPIN_GET_TIME() int { |
| now:=time.Now() |
| return int(now.Unix()) |
| } |
| |
| /* Generate Y = H(epoch, xCID/xID) */ |
| func MPIN_GET_Y(sha int,TimeValue int,xCID []byte,Y []byte) { |
| h:= mhashit(sha,int32(TimeValue),xCID) |
| y:= fromBytes(h) |
| q:=NewBIGints(CURVE_Order) |
| y.mod(q) |
| if AES_S>0 { |
| y.mod2m(2*AES_S) |
| } |
| y.toBytes(Y) |
| } |
| |
| /* One pass MPIN Client */ |
| func MPIN_CLIENT(sha int,date int,CLIENT_ID []byte,RNG *RAND,X []byte,pin int,TOKEN []byte,SEC []byte,xID []byte,xCID []byte,PERMIT []byte,TimeValue int,Y []byte) int { |
| rtn:=0 |
| |
| var pID []byte |
| if date == 0 { |
| pID = xID |
| } else {pID = xCID} |
| |
| rtn = MPIN_CLIENT_1(sha,date,CLIENT_ID,RNG,X,pin,TOKEN,SEC,xID,xCID,PERMIT) |
| if rtn != 0 {return rtn} |
| |
| MPIN_GET_Y(sha,TimeValue,pID,Y) |
| |
| rtn = MPIN_CLIENT_2(X,Y,SEC) |
| if rtn != 0 {return rtn} |
| |
| return 0 |
| } |
| |
| /* One pass MPIN Server */ |
| func MPIN_SERVER(sha int,date int,HID []byte,HTID []byte,Y []byte,SST []byte,xID []byte,xCID []byte,SEC []byte,E []byte,F []byte,CID []byte,TimeValue int) int { |
| rtn:=0 |
| |
| var pID []byte |
| if date == 0 { |
| pID = xID |
| } else {pID = xCID} |
| |
| MPIN_SERVER_1(sha,date,CID,HID,HTID) |
| MPIN_GET_Y(sha,TimeValue,pID,Y); |
| |
| rtn = MPIN_SERVER_2(date,HID,HTID,Y,SST,xID,xCID,SEC,E,F) |
| if rtn != 0 {return rtn} |
| |
| return 0 |
| } |
| |