github.com/hellobchain/third_party@v0.0.0-20230331131523-deb0478a2e52/hyperledger/fabric-amcl/amcl/FP256BN/MPIN.go (about)

     1  /*
     2  Licensed to the Apache Software Foundation (ASF) under one
     3  or more contributor license agreements.  See the NOTICE file
     4  distributed with this work for additional information
     5  regarding copyright ownership.  The ASF licenses this file
     6  to you under the Apache License, Version 2.0 (the
     7  "License"); you may not use this file except in compliance
     8  with the License.  You may obtain a copy of the License at
     9  
    10    http://www.apache.org/licenses/LICENSE-2.0
    11  
    12  Unless required by applicable law or agreed to in writing,
    13  software distributed under the License is distributed on an
    14  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    15  KIND, either express or implied.  See the License for the
    16  specific language governing permissions and limitations
    17  under the License.
    18  */
    19  
    20  /* MPIN API Functions */
    21  
    22  package FP256BN
    23  
    24  import "time"
    25  import "github.com/hellobchain/third_party/hyperledger/fabric-amcl/amcl"
    26  
    27  const MFS int = int(MODBYTES)
    28  const MGS int = int(MODBYTES)
    29  
    30  //const PAS int=16
    31  const BAD_PARAMS int = -11
    32  const INVALID_POINT int = -14
    33  const WRONG_ORDER int = -18
    34  const BAD_PIN int = -19
    35  
    36  /* Configure your PIN here */
    37  
    38  const MAXPIN int32 = 10000 /* PIN less than this */
    39  const PBLEN int32 = 14     /* Number of bits in PIN */
    40  const TS int = 10          /* 10 for 4 digit PIN, 14 for 6-digit PIN - 2^TS/TS approx = sqrt(MAXPIN) */
    41  const TRAP int = 200       /* 200 for 4 digit PIN, 2000 for 6-digit PIN  - approx 2*sqrt(MAXPIN) */
    42  
    43  //const MPIN_HASH_TYPE int=amcl.SHA256
    44  
    45  func mpin_hash(sha int, c *FP4, U *ECP) []byte {
    46  	var w [MFS]byte
    47  	var t [6 * MFS]byte
    48  	var h []byte
    49  
    50  	c.geta().GetA().ToBytes(w[:])
    51  	for i := 0; i < MFS; i++ {
    52  		t[i] = w[i]
    53  	}
    54  	c.geta().GetB().ToBytes(w[:])
    55  	for i := MFS; i < 2*MFS; i++ {
    56  		t[i] = w[i-MFS]
    57  	}
    58  	c.getb().GetA().ToBytes(w[:])
    59  	for i := 2 * MFS; i < 3*MFS; i++ {
    60  		t[i] = w[i-2*MFS]
    61  	}
    62  	c.getb().GetB().ToBytes(w[:])
    63  	for i := 3 * MFS; i < 4*MFS; i++ {
    64  		t[i] = w[i-3*MFS]
    65  	}
    66  
    67  	U.GetX().ToBytes(w[:])
    68  	for i := 4 * MFS; i < 5*MFS; i++ {
    69  		t[i] = w[i-4*MFS]
    70  	}
    71  	U.GetY().ToBytes(w[:])
    72  	for i := 5 * MFS; i < 6*MFS; i++ {
    73  		t[i] = w[i-5*MFS]
    74  	}
    75  
    76  	if sha == amcl.SHA256 {
    77  		H := amcl.NewHASH256()
    78  		H.Process_array(t[:])
    79  		h = H.Hash()
    80  	}
    81  	if sha == amcl.SHA384 {
    82  		H := amcl.NewHASH384()
    83  		H.Process_array(t[:])
    84  		h = H.Hash()
    85  	}
    86  	if sha == amcl.SHA512 {
    87  		H := amcl.NewHASH512()
    88  		H.Process_array(t[:])
    89  		h = H.Hash()
    90  	}
    91  	if h == nil {
    92  		return nil
    93  	}
    94  	R := make([]byte, AESKEY)
    95  	for i := 0; i < AESKEY; i++ {
    96  		R[i] = h[i]
    97  	}
    98  	return R
    99  }
   100  
   101  /* Hash number (optional) and string to coordinate on curve */
   102  
   103  func mhashit(sha int, n int32, ID []byte) []byte {
   104  	var R []byte
   105  	if sha == amcl.SHA256 {
   106  		H := amcl.NewHASH256()
   107  		if n != 0 {
   108  			H.Process_num(n)
   109  		}
   110  		H.Process_array(ID)
   111  		R = H.Hash()
   112  	}
   113  	if sha == amcl.SHA384 {
   114  		H := amcl.NewHASH384()
   115  		if n != 0 {
   116  			H.Process_num(n)
   117  		}
   118  		H.Process_array(ID)
   119  		R = H.Hash()
   120  	}
   121  	if sha == amcl.SHA512 {
   122  		H := amcl.NewHASH512()
   123  		if n != 0 {
   124  			H.Process_num(n)
   125  		}
   126  		H.Process_array(ID)
   127  		R = H.Hash()
   128  	}
   129  	if R == nil {
   130  		return nil
   131  	}
   132  	const RM int = int(MODBYTES)
   133  	var W [RM]byte
   134  	if sha >= RM {
   135  		for i := 0; i < RM; i++ {
   136  			W[i] = R[i]
   137  		}
   138  	} else {
   139  		for i := 0; i < sha; i++ {
   140  			W[i+RM-sha] = R[i]
   141  		}
   142  		for i := 0; i < RM-sha; i++ {
   143  			W[i] = 0
   144  		}
   145  
   146  		//	for i:=0;i<sha;i++ {W[i]=R[i]}
   147  		//	for i:=sha;i<RM;i++ {W[i]=0}
   148  	}
   149  
   150  	return W[:]
   151  }
   152  
   153  /* return time in slots since epoch */
   154  func Today() int {
   155  	now := time.Now()
   156  	return int(now.Unix()) / (60 * 1440)
   157  }
   158  
   159  /* these next two functions help to implement elligator squared - http://eprint.iacr.org/2014/043 */
   160  /* maps a random u to a point on the curve */
   161  func emap(u *BIG, cb int) *ECP {
   162  	var P *ECP
   163  	x := NewBIGcopy(u)
   164  	p := NewBIGints(Modulus)
   165  	x.Mod(p)
   166  	for true {
   167  		P = NewECPbigint(x, cb)
   168  		if !P.Is_infinity() {
   169  			break
   170  		}
   171  		x.inc(1)
   172  		x.norm()
   173  	}
   174  	return P
   175  }
   176  
   177  /* returns u derived from P. Random value in range 1 to return value should then be added to u */
   178  func unmap(u *BIG, P *ECP) int {
   179  	s := P.GetS()
   180  	var R *ECP
   181  	r := 0
   182  	x := P.GetX()
   183  	u.copy(x)
   184  	for true {
   185  		u.dec(1)
   186  		u.norm()
   187  		r++
   188  		R = NewECPbigint(u, s)
   189  		if !R.Is_infinity() {
   190  			break
   191  		}
   192  	}
   193  	return r
   194  }
   195  
   196  func MPIN_HASH_ID(sha int, ID []byte) []byte {
   197  	return mhashit(sha, 0, ID)
   198  }
   199  
   200  /* these next two functions implement elligator squared - http://eprint.iacr.org/2014/043 */
   201  /* Elliptic curve point E in format (0x04,x,y} is converted to form {0x0-,u,v} */
   202  /* Note that u and v are indistinguisible from random strings */
   203  func MPIN_ENCODING(rng *amcl.RAND, E []byte) int {
   204  	var T [MFS]byte
   205  
   206  	for i := 0; i < MFS; i++ {
   207  		T[i] = E[i+1]
   208  	}
   209  	u := FromBytes(T[:])
   210  	for i := 0; i < MFS; i++ {
   211  		T[i] = E[i+MFS+1]
   212  	}
   213  	v := FromBytes(T[:])
   214  
   215  	P := NewECPbigs(u, v)
   216  	if P.Is_infinity() {
   217  		return INVALID_POINT
   218  	}
   219  
   220  	p := NewBIGints(Modulus)
   221  	u = Randomnum(p, rng)
   222  
   223  	su := int(rng.GetByte()); /*if (su<0) su=-su;*/ su %= 2
   224  
   225  	W := emap(u, su)
   226  	P.Sub(W)
   227  	sv := P.GetS()
   228  	rn := unmap(v, P)
   229  	m := int(rng.GetByte()); /*if (m<0) m=-m;*/ m %= rn
   230  	v.inc(m + 1)
   231  	E[0] = byte(su + 2*sv)
   232  	u.ToBytes(T[:])
   233  	for i := 0; i < MFS; i++ {
   234  		E[i+1] = T[i]
   235  	}
   236  	v.ToBytes(T[:])
   237  	for i := 0; i < MFS; i++ {
   238  		E[i+MFS+1] = T[i]
   239  	}
   240  
   241  	return 0
   242  }
   243  
   244  func MPIN_DECODING(D []byte) int {
   245  	var T [MFS]byte
   246  
   247  	if (D[0] & 0x04) != 0 {
   248  		return INVALID_POINT
   249  	}
   250  
   251  	for i := 0; i < MFS; i++ {
   252  		T[i] = D[i+1]
   253  	}
   254  	u := FromBytes(T[:])
   255  	for i := 0; i < MFS; i++ {
   256  		T[i] = D[i+MFS+1]
   257  	}
   258  	v := FromBytes(T[:])
   259  
   260  	su := int(D[0] & 1)
   261  	sv := int((D[0] >> 1) & 1)
   262  	W := emap(u, su)
   263  	P := emap(v, sv)
   264  	P.Add(W)
   265  	u = P.GetX()
   266  	v = P.GetY()
   267  	D[0] = 0x04
   268  	u.ToBytes(T[:])
   269  	for i := 0; i < MFS; i++ {
   270  		D[i+1] = T[i]
   271  	}
   272  	v.ToBytes(T[:])
   273  	for i := 0; i < MFS; i++ {
   274  		D[i+MFS+1] = T[i]
   275  	}
   276  
   277  	return 0
   278  }
   279  
   280  /* R=R1+R2 in group G1 */
   281  func MPIN_RECOMBINE_G1(R1 []byte, R2 []byte, R []byte) int {
   282  	P := ECP_fromBytes(R1)
   283  	Q := ECP_fromBytes(R2)
   284  
   285  	if P.Is_infinity() || Q.Is_infinity() {
   286  		return INVALID_POINT
   287  	}
   288  
   289  	P.Add(Q)
   290  
   291  	P.ToBytes(R[:], false)
   292  	return 0
   293  }
   294  
   295  /* W=W1+W2 in group G2 */
   296  func MPIN_RECOMBINE_G2(W1 []byte, W2 []byte, W []byte) int {
   297  	P := ECP2_fromBytes(W1)
   298  	Q := ECP2_fromBytes(W2)
   299  
   300  	if P.Is_infinity() || Q.Is_infinity() {
   301  		return INVALID_POINT
   302  	}
   303  
   304  	P.Add(Q)
   305  
   306  	P.ToBytes(W)
   307  	return 0
   308  }
   309  
   310  /* create random secret S */
   311  func MPIN_RANDOM_GENERATE(rng *amcl.RAND, S []byte) int {
   312  	r := NewBIGints(CURVE_Order)
   313  	s := Randomnum(r, rng)
   314  	//if AES_S>0 {
   315  	//	s.mod2m(2*AES_S)
   316  	//}		
   317  	s.ToBytes(S)
   318  	return 0
   319  }
   320  
   321  func MPIN_EXTRACT_PIN(sha int, CID []byte, pin int, TOKEN []byte) int {
   322  	return MPIN_EXTRACT_FACTOR(sha, CID, int32(pin)%MAXPIN, PBLEN, TOKEN)
   323  }
   324  
   325  /* Extract factor from TOKEN for identity CID */
   326  func MPIN_EXTRACT_FACTOR(sha int, CID []byte, factor int32, facbits int32, TOKEN []byte) int {
   327  	P := ECP_fromBytes(TOKEN)
   328  	if P.Is_infinity() {
   329  		return INVALID_POINT
   330  	}
   331  	h := mhashit(sha, 0, CID)
   332  	R := ECP_mapit(h)
   333  
   334  	R = R.pinmul(factor, facbits)
   335  	P.Sub(R)
   336  
   337  	P.ToBytes(TOKEN, false)
   338  
   339  	return 0
   340  }
   341  
   342  /* Restore factor to TOKEN for identity CID */
   343  func MPIN_RESTORE_FACTOR(sha int, CID []byte, factor int32, facbits int32, TOKEN []byte) int {
   344  	P := ECP_fromBytes(TOKEN)
   345  	if P.Is_infinity() {
   346  		return INVALID_POINT
   347  	}
   348  	h := mhashit(sha, 0, CID)
   349  	R := ECP_mapit(h)
   350  
   351  	R = R.pinmul(factor, facbits)
   352  	P.Add(R)
   353  
   354  	P.ToBytes(TOKEN, false)
   355  
   356  	return 0
   357  }
   358  
   359  /* Extract PIN from TOKEN for identity CID
   360  func MPIN_EXTRACT_PIN(sha int,CID []byte,pin int,TOKEN []byte) int {
   361  	P:=ECP_fromBytes(TOKEN)
   362  	if P.Is_infinity() {return INVALID_POINT}
   363  	h:=mhashit(sha,0,CID)
   364  	R:=ECP_mapit(h)
   365  
   366  	R=R.pinmul(int32(pin)%MAXPIN,PBLEN)
   367  	P.Sub(R)
   368  
   369  	P.ToBytes(TOKEN,false)
   370  
   371  	return 0
   372  }*/
   373  
   374  /* Implement step 2 on client side of MPin protocol */
   375  func MPIN_CLIENT_2(X []byte, Y []byte, SEC []byte) int {
   376  	r := NewBIGints(CURVE_Order)
   377  	P := ECP_fromBytes(SEC)
   378  	if P.Is_infinity() {
   379  		return INVALID_POINT
   380  	}
   381  
   382  	px := FromBytes(X)
   383  	py := FromBytes(Y)
   384  	px.add(py)
   385  	px.Mod(r)
   386  	//px.rsub(r)
   387  
   388  	P = G1mul(P, px)
   389  	P.neg()
   390  	P.ToBytes(SEC, false)
   391  	//G1mul(P,px).ToBytes(SEC,false)
   392  	return 0
   393  }
   394  
   395  /* Implement step 1 on client side of MPin protocol */
   396  func MPIN_CLIENT_1(sha int, date int, CLIENT_ID []byte, rng *amcl.RAND, X []byte, pin int, TOKEN []byte, SEC []byte, xID []byte, xCID []byte, PERMIT []byte) int {
   397  	r := NewBIGints(CURVE_Order)
   398  
   399  	var x *BIG
   400  	if rng != nil {
   401  		x = Randomnum(r, rng)
   402  		//if AES_S>0 {
   403  		//	x.mod2m(2*AES_S)
   404  		//}
   405  		x.ToBytes(X)
   406  	} else {
   407  		x = FromBytes(X)
   408  	}
   409  
   410  	h := mhashit(sha, 0, CLIENT_ID)
   411  	P := ECP_mapit(h)
   412  
   413  	T := ECP_fromBytes(TOKEN)
   414  	if T.Is_infinity() {
   415  		return INVALID_POINT
   416  	}
   417  
   418  	W := P.pinmul(int32(pin)%MAXPIN, PBLEN)
   419  	T.Add(W)
   420  	if date != 0 {
   421  		W = ECP_fromBytes(PERMIT)
   422  		if W.Is_infinity() {
   423  			return INVALID_POINT
   424  		}
   425  		T.Add(W)
   426  		h = mhashit(sha, int32(date), h)
   427  		W = ECP_mapit(h)
   428  		if xID != nil {
   429  			P = G1mul(P, x)
   430  			P.ToBytes(xID, false)
   431  			W = G1mul(W, x)
   432  			P.Add(W)
   433  		} else {
   434  			P.Add(W)
   435  			P = G1mul(P, x)
   436  		}
   437  		if xCID != nil {
   438  			P.ToBytes(xCID, false)
   439  		}
   440  	} else {
   441  		if xID != nil {
   442  			P = G1mul(P, x)
   443  			P.ToBytes(xID, false)
   444  		}
   445  	}
   446  
   447  	T.ToBytes(SEC, false)
   448  	return 0
   449  }
   450  
   451  /* Extract Server Secret SST=S*Q where Q is fixed generator in G2 and S is master secret */
   452  func MPIN_GET_SERVER_SECRET(S []byte, SST []byte) int {
   453  	Q := ECP2_generator()
   454  
   455  	s := FromBytes(S)
   456  	Q = G2mul(Q, s)
   457  	Q.ToBytes(SST)
   458  	return 0
   459  }
   460  
   461  /*
   462   W=x*H(G);
   463   if RNG == NULL then X is passed in
   464   if RNG != NULL the X is passed out
   465   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
   466  */
   467  func MPIN_GET_G1_MULTIPLE(rng *amcl.RAND, typ int, X []byte, G []byte, W []byte) int {
   468  	var x *BIG
   469  	r := NewBIGints(CURVE_Order)
   470  	if rng != nil {
   471  		x = Randomnum(r, rng)
   472  		//if AES_S>0 {
   473  		//	x.mod2m(2*AES_S)
   474  		//}
   475  		x.ToBytes(X)
   476  	} else {
   477  		x = FromBytes(X)
   478  	}
   479  	var P *ECP
   480  	if typ == 0 {
   481  		P = ECP_fromBytes(G)
   482  		if P.Is_infinity() {
   483  			return INVALID_POINT
   484  		}
   485  	} else {
   486  		P = ECP_mapit(G)
   487  	}
   488  
   489  	G1mul(P, x).ToBytes(W, false)
   490  	return 0
   491  }
   492  
   493  /* Client secret CST=S*H(CID) where CID is client ID and S is master secret */
   494  /* CID is hashed externally */
   495  func MPIN_GET_CLIENT_SECRET(S []byte, CID []byte, CST []byte) int {
   496  	return MPIN_GET_G1_MULTIPLE(nil, 1, S, CID, CST)
   497  }
   498  
   499  /* Time Permit CTT=S*(date|H(CID)) where S is master secret */
   500  func MPIN_GET_CLIENT_PERMIT(sha, date int, S []byte, CID []byte, CTT []byte) int {
   501  	h := mhashit(sha, int32(date), CID)
   502  	P := ECP_mapit(h)
   503  
   504  	s := FromBytes(S)
   505  	G1mul(P, s).ToBytes(CTT, false)
   506  	return 0
   507  }
   508  
   509  /* Outputs H(CID) and H(T|H(CID)) for time permits. If no time permits set HID=HTID */
   510  func MPIN_SERVER_1(sha int, date int, CID []byte, HID []byte, HTID []byte) {
   511  	h := mhashit(sha, 0, CID)
   512  	P := ECP_mapit(h)
   513  
   514  	P.ToBytes(HID, false)
   515  	if date != 0 {
   516  		//	if HID!=nil {P.ToBytes(HID,false)}
   517  		h = mhashit(sha, int32(date), h)
   518  		R := ECP_mapit(h)
   519  		P.Add(R)
   520  		P.ToBytes(HTID, false)
   521  	} //else {P.ToBytes(HID,false)}
   522  }
   523  
   524  /* Implement step 2 of MPin protocol on server side */
   525  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 {
   526  	//	q:=NewBIGints(Modulus)
   527  	Q := ECP2_generator()
   528  
   529  	sQ := ECP2_fromBytes(SST)
   530  	if sQ.Is_infinity() {
   531  		return INVALID_POINT
   532  	}
   533  
   534  	var R *ECP
   535  	if date != 0 {
   536  		R = ECP_fromBytes(xCID)
   537  	} else {
   538  		if xID == nil {
   539  			return BAD_PARAMS
   540  		}
   541  		R = ECP_fromBytes(xID)
   542  	}
   543  	if R.Is_infinity() {
   544  		return INVALID_POINT
   545  	}
   546  
   547  	y := FromBytes(Y)
   548  	var P *ECP
   549  	if date != 0 {
   550  		P = ECP_fromBytes(HTID)
   551  	} else {
   552  		if HID == nil {
   553  			return BAD_PARAMS
   554  		}
   555  		P = ECP_fromBytes(HID)
   556  	}
   557  
   558  	if P.Is_infinity() {
   559  		return INVALID_POINT
   560  	}
   561  
   562  	P = G1mul(P, y)
   563  	P.Add(R)
   564  	//P.Affine()
   565  	R = ECP_fromBytes(mSEC)
   566  	if R.Is_infinity() {
   567  		return INVALID_POINT
   568  	}
   569  
   570  	var g *FP12
   571  	//		FP12 g1=new FP12(0);
   572  
   573  	g = Ate2(Q, R, sQ, P)
   574  	g = Fexp(g)
   575  
   576  	if !g.Isunity() {
   577  		if HID != nil && xID != nil && E != nil && F != nil {
   578  			g.ToBytes(E)
   579  			if date != 0 {
   580  				P = ECP_fromBytes(HID)
   581  				if P.Is_infinity() {
   582  					return INVALID_POINT
   583  				}
   584  				R = ECP_fromBytes(xID)
   585  				if R.Is_infinity() {
   586  					return INVALID_POINT
   587  				}
   588  
   589  				P = G1mul(P, y)
   590  				P.Add(R)
   591  				//P.Affine()
   592  			}
   593  			g = Ate(Q, P)
   594  			g = Fexp(g)
   595  			g.ToBytes(F)
   596  		}
   597  		return BAD_PIN
   598  	}
   599  
   600  	return 0
   601  }
   602  
   603  /* Pollards kangaroos used to return PIN error */
   604  func MPIN_KANGAROO(E []byte, F []byte) int {
   605  	ge := FP12_fromBytes(E)
   606  	gf := FP12_fromBytes(F)
   607  	var distance [TS]int
   608  	t := NewFP12copy(gf)
   609  
   610  	var table []*FP12
   611  	var i int
   612  	s := 1
   613  	for m := 0; m < TS; m++ {
   614  		distance[m] = s
   615  		table = append(table, NewFP12copy(t))
   616  		s *= 2
   617  		t.usqr()
   618  	}
   619  	t.one()
   620  	dn := 0
   621  	for j := 0; j < TRAP; j++ {
   622  		i = t.geta().geta().GetA().lastbits(20) % TS
   623  		t.Mul(table[i])
   624  		dn += distance[i]
   625  	}
   626  	gf.Copy(t)
   627  	gf.conj()
   628  	steps := 0
   629  	dm := 0
   630  	res := 0
   631  	for dm-dn < int(MAXPIN) {
   632  		steps++
   633  		if steps > 4*TRAP {
   634  			break
   635  		}
   636  		i = ge.geta().geta().GetA().lastbits(20) % TS
   637  		ge.Mul(table[i])
   638  		dm += distance[i]
   639  		if ge.Equals(t) {
   640  			res = dm - dn
   641  			break
   642  		}
   643  		if ge.Equals(gf) {
   644  			res = dn - dm
   645  			break
   646  		}
   647  
   648  	}
   649  	if steps > 4*TRAP || dm-dn >= int(MAXPIN) {
   650  		res = 0
   651  	} // Trap Failed  - probable invalid token
   652  	return int(res)
   653  }
   654  
   655  /* Functions to support M-Pin Full */
   656  
   657  func MPIN_PRECOMPUTE(TOKEN []byte, CID []byte, G1 []byte, G2 []byte) int {
   658  	var P, T *ECP
   659  	var g *FP12
   660  
   661  	T = ECP_fromBytes(TOKEN)
   662  	if T.Is_infinity() {
   663  		return INVALID_POINT
   664  	}
   665  
   666  	P = ECP_mapit(CID)
   667  
   668  	Q := ECP2_generator()
   669  
   670  	g = Ate(Q, T)
   671  	g = Fexp(g)
   672  	g.ToBytes(G1)
   673  
   674  	g = Ate(Q, P)
   675  	g = Fexp(g)
   676  	g.ToBytes(G2)
   677  
   678  	return 0
   679  }
   680  
   681  /* Hash the M-Pin transcript - new */
   682  
   683  func MPIN_HASH_ALL(sha int, HID []byte, xID []byte, xCID []byte, SEC []byte, Y []byte, R []byte, W []byte) []byte {
   684  	tlen := 0
   685  	var T [10*int(MODBYTES) + 4]byte
   686  
   687  	for i := 0; i < len(HID); i++ {
   688  		T[i] = HID[i]
   689  	}
   690  	tlen += len(HID)
   691  	if xCID != nil {
   692  		for i := 0; i < len(xCID); i++ {
   693  			T[i+tlen] = xCID[i]
   694  		}
   695  		tlen += len(xCID)
   696  	} else {
   697  		for i := 0; i < len(xID); i++ {
   698  			T[i+tlen] = xID[i]
   699  		}
   700  		tlen += len(xID)
   701  	}
   702  	for i := 0; i < len(SEC); i++ {
   703  		T[i+tlen] = SEC[i]
   704  	}
   705  	tlen += len(SEC)
   706  	for i := 0; i < len(Y); i++ {
   707  		T[i+tlen] = Y[i]
   708  	}
   709  	tlen += len(Y)
   710  	for i := 0; i < len(R); i++ {
   711  		T[i+tlen] = R[i]
   712  	}
   713  	tlen += len(R)
   714  	for i := 0; i < len(W); i++ {
   715  		T[i+tlen] = W[i]
   716  	}
   717  	tlen += len(W)
   718  
   719  	return mhashit(sha, 0, T[:])
   720  }
   721  
   722  /* calculate common key on client side */
   723  /* wCID = w.(A+AT) */
   724  func MPIN_CLIENT_KEY(sha int, G1 []byte, G2 []byte, pin int, R []byte, X []byte, H []byte, wCID []byte, CK []byte) int {
   725  
   726  	g1 := FP12_fromBytes(G1)
   727  	g2 := FP12_fromBytes(G2)
   728  	z := FromBytes(R)
   729  	x := FromBytes(X)
   730  	h := FromBytes(H)
   731  
   732  	W := ECP_fromBytes(wCID)
   733  	if W.Is_infinity() {
   734  		return INVALID_POINT
   735  	}
   736  
   737  	W = G1mul(W, x)
   738  
   739  	//	f:=NewFP2bigs(NewBIGints(Fra),NewBIGints(Frb))
   740  	r := NewBIGints(CURVE_Order)
   741  	//	q:=NewBIGints(Modulus)
   742  
   743  	z.add(h) //new
   744  	z.Mod(r)
   745  
   746  	g2.pinpow(pin, int(PBLEN))
   747  	g1.Mul(g2)
   748  
   749  	c := g1.Compow(z, r)
   750  	/*
   751  		m:=NewBIGcopy(q)
   752  		m.Mod(r)
   753  
   754  		a:=NewBIGcopy(z)
   755  		a.Mod(m)
   756  
   757  		b:=NewBIGcopy(z)
   758  		b.div(m)
   759  
   760  
   761  		c:=g1.trace()
   762  		g2.Copy(g1)
   763  		g2.frob(f)
   764  		cp:=g2.trace()
   765  		g1.conj()
   766  		g2.Mul(g1)
   767  		cpm1:=g2.trace()
   768  		g2.Mul(g1)
   769  		cpm2:=g2.trace()
   770  
   771  		c=c.xtr_pow2(cp,cpm1,cpm2,a,b)
   772  	*/
   773  	t := mpin_hash(sha, c, W)
   774  
   775  	for i := 0; i < AESKEY; i++ {
   776  		CK[i] = t[i]
   777  	}
   778  
   779  	return 0
   780  }
   781  
   782  /* calculate common key on server side */
   783  /* Z=r.A - no time permits involved */
   784  
   785  func MPIN_SERVER_KEY(sha int, Z []byte, SST []byte, W []byte, H []byte, HID []byte, xID []byte, xCID []byte, SK []byte) int {
   786  	sQ := ECP2_fromBytes(SST)
   787  	if sQ.Is_infinity() {
   788  		return INVALID_POINT
   789  	}
   790  	R := ECP_fromBytes(Z)
   791  	if R.Is_infinity() {
   792  		return INVALID_POINT
   793  	}
   794  	A := ECP_fromBytes(HID)
   795  	if A.Is_infinity() {
   796  		return INVALID_POINT
   797  	}
   798  
   799  	var U *ECP
   800  	if xCID != nil {
   801  		U = ECP_fromBytes(xCID)
   802  	} else {
   803  		U = ECP_fromBytes(xID)
   804  	}
   805  	if U.Is_infinity() {
   806  		return INVALID_POINT
   807  	}
   808  
   809  	w := FromBytes(W)
   810  	h := FromBytes(H)
   811  	A = G1mul(A, h) // new
   812  	R.Add(A)
   813  	//R.Affine()
   814  
   815  	U = G1mul(U, w)
   816  	g := Ate(sQ, R)
   817  	g = Fexp(g)
   818  
   819  	c := g.trace()
   820  
   821  	t := mpin_hash(sha, c, U)
   822  
   823  	for i := 0; i < AESKEY; i++ {
   824  		SK[i] = t[i]
   825  	}
   826  
   827  	return 0
   828  }
   829  
   830  /* return time since epoch */
   831  func MPIN_GET_TIME() int {
   832  	now := time.Now()
   833  	return int(now.Unix())
   834  }
   835  
   836  /* Generate Y = H(epoch, xCID/xID) */
   837  func MPIN_GET_Y(sha int, TimeValue int, xCID []byte, Y []byte) {
   838  	h := mhashit(sha, int32(TimeValue), xCID)
   839  	y := FromBytes(h)
   840  	q := NewBIGints(CURVE_Order)
   841  	y.Mod(q)
   842  	//if AES_S>0 {
   843  	//	y.mod2m(2*AES_S)
   844  	//}
   845  	y.ToBytes(Y)
   846  }
   847  
   848  /* One pass MPIN Client */
   849  func MPIN_CLIENT(sha int, date int, CLIENT_ID []byte, RNG *amcl.RAND, X []byte, pin int, TOKEN []byte, SEC []byte, xID []byte, xCID []byte, PERMIT []byte, TimeValue int, Y []byte) int {
   850  	rtn := 0
   851  
   852  	var pID []byte
   853  	if date == 0 {
   854  		pID = xID
   855  	} else {
   856  		pID = xCID
   857  	}
   858  
   859  	rtn = MPIN_CLIENT_1(sha, date, CLIENT_ID, RNG, X, pin, TOKEN, SEC, xID, xCID, PERMIT)
   860  	if rtn != 0 {
   861  		return rtn
   862  	}
   863  
   864  	MPIN_GET_Y(sha, TimeValue, pID, Y)
   865  
   866  	rtn = MPIN_CLIENT_2(X, Y, SEC)
   867  	if rtn != 0 {
   868  		return rtn
   869  	}
   870  
   871  	return 0
   872  }
   873  
   874  /* One pass MPIN Server */
   875  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 {
   876  	rtn := 0
   877  
   878  	var pID []byte
   879  	if date == 0 {
   880  		pID = xID
   881  	} else {
   882  		pID = xCID
   883  	}
   884  
   885  	MPIN_SERVER_1(sha, date, CID, HID, HTID)
   886  	MPIN_GET_Y(sha, TimeValue, pID, Y)
   887  
   888  	rtn = MPIN_SERVER_2(date, HID, HTID, Y, SST, xID, xCID, SEC, E, F)
   889  	if rtn != 0 {
   890  		return rtn
   891  	}
   892  
   893  	return 0
   894  }