| /* |
| 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 |
| |
| /* |
| #cgo CFLAGS: -std=c99 -O3 -I/opt/amcl/include |
| #cgo LDFLAGS: -L/opt/amcl/lib -lmpin -lamcl -lm |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include "amcl.h" |
| #include "mpin.h" |
| #include "utils.h" |
| */ |
| import "C" |
| import ( |
| "encoding/hex" |
| "fmt" |
| "unsafe" |
| |
| amcl "git.apache.org/incubator-milagro-crypto.git/go/amcl-go" |
| ) |
| |
| const EAS int = int(C.PAS) |
| const EGS int = int(C.PGS) |
| const EFS int = int(C.PFS) |
| const HASH_BYTES int = int(C.HASH_BYTES) |
| const IVS int = 12 |
| const G1S = 2*EFS + 1 |
| const G2S = 4 * EFS |
| const GTS = 12 * EFS |
| |
| var RNG C.csprng |
| |
| func OCT_free(valOctet *C.octet) { |
| C.free(unsafe.Pointer(valOctet.val)) |
| } |
| |
| func GetOctetZero(lenStr int) C.octet { |
| valBytes := make([]byte, lenStr) |
| val := string(valBytes) |
| valCS := C.CString(val) |
| lenCS := C.int(lenStr) |
| octetVal := C.octet{lenCS, lenCS, valCS} |
| return octetVal |
| } |
| |
| func GetOctet(valStr string) C.octet { |
| valCS := C.CString(valStr) |
| lenCS := C.int(len(valStr)) |
| octetVal := C.octet{lenCS, lenCS, valCS} |
| return octetVal |
| } |
| |
| func GetOctetHex(valHex string) C.octet { |
| valBytes, err := hex.DecodeString(valHex) |
| if err != nil { |
| octetVal := GetOctetZero(0) |
| return octetVal |
| } |
| valStr := string(valBytes) |
| octetVal := GetOctet(valStr) |
| return octetVal |
| } |
| |
| func OCT_len(valOctet *C.octet) int { |
| return int(valOctet.len) |
| } |
| |
| // Convert an octet to a string |
| func OCT_toStr(valOct *C.octet) string { |
| dstLen := OCT_len(valOct) |
| dstBytes := make([]byte, dstLen) |
| dstStr := string(dstBytes) |
| dst := C.CString(dstStr) |
| C.OCT_toStr(valOct, dst) |
| dstStr = C.GoStringN(dst, valOct.len) |
| C.free(unsafe.Pointer(dst)) |
| return dstStr |
| } |
| |
| // Convert an octet to bytes |
| func OCT_toBytes(valOct *C.octet) []byte { |
| dstLen := OCT_len(valOct) |
| dstBytes := make([]byte, dstLen) |
| dstStr := string(dstBytes) |
| dst := C.CString(dstStr) |
| C.OCT_toStr(valOct, dst) |
| dstStr = C.GoStringN(dst, valOct.len) |
| C.free(unsafe.Pointer(dst)) |
| dstBytes = []byte(dstStr) |
| return dstBytes |
| } |
| |
| // Convert an octet to a hex string |
| func OCT_toHex(valOctet *C.octet) string { |
| dstLen := OCT_len(valOctet) |
| dstBytes := make([]byte, hex.EncodedLen(dstLen)) |
| dstStr := string(dstBytes) |
| dst := C.CString(dstStr) |
| C.OCT_toHex(valOctet, dst) |
| dstStr = C.GoString(dst) |
| C.free(unsafe.Pointer(dst)) |
| return dstStr |
| } |
| |
| /* return time in slots since epoch */ |
| func MPIN_today() int { |
| date := C.MPIN_today() |
| return int(date) |
| } |
| |
| /* return time since epoch */ |
| func MPIN_GET_TIME() int { |
| timeValue := C.MPIN_GET_TIME() |
| return int(timeValue) |
| } |
| |
| func MPIN_CREATE_CSPRNG(RNG *C.csprng, SEED []byte) { |
| // Form Octet |
| SEEDStr := string(SEED) |
| SEEDOct := GetOctet(SEEDStr) |
| defer OCT_free(&SEEDOct) |
| C.MPIN_CREATE_CSPRNG(RNG, &SEEDOct) |
| } |
| |
| func MPIN_HASH_ID(ID []byte) (HASHID []byte) { |
| // Form Octets |
| IDStr := string(ID) |
| IDOct := GetOctet(IDStr) |
| defer OCT_free(&IDOct) |
| HASHIDOct := GetOctetZero(HASH_BYTES) |
| defer OCT_free(&HASHIDOct) |
| |
| // Hash MPIN_ID |
| C.MPIN_HASH_ID(&IDOct, &HASHIDOct) |
| |
| // Convert octet to bytes |
| HASHID = OCT_toBytes(&HASHIDOct) |
| |
| return |
| } |
| |
| /* create random secret S. Use GO RNG */ |
| func MPIN_RANDOM_GENERATE_WRAP(RNG *amcl.RAND) (int, []byte) { |
| var S [EGS]byte |
| errorCode := amcl.MPIN_RANDOM_GENERATE(RNG, S[:]) |
| return errorCode, S[:] |
| } |
| |
| /* create random secret S. Use C RNG */ |
| func MPIN_RANDOM_GENERATE_C(RNG *C.csprng) (errorCode int, S []byte) { |
| // Form Octet |
| SOct := GetOctetZero(EGS) |
| defer OCT_free(&SOct) |
| |
| rtn := C.MPIN_RANDOM_GENERATE(RNG, &SOct) |
| errorCode = int(rtn) |
| |
| // Convert octet to bytes |
| S = OCT_toBytes(&SOct) |
| |
| return |
| } |
| |
| /* 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) (errorCode int, SS []byte) { |
| // Form Octets |
| SStr := string(S) |
| SOct := GetOctet(SStr) |
| defer OCT_free(&SOct) |
| SSOct := GetOctetZero(G2S) |
| defer OCT_free(&SSOct) |
| |
| rtn := C.MPIN_GET_SERVER_SECRET(&SOct, &SSOct) |
| errorCode = int(rtn) |
| |
| // Convert octet to bytes |
| SS = OCT_toBytes(&SSOct) |
| |
| return |
| } |
| |
| /* R=R1+R2 in group G1 */ |
| func MPIN_RECOMBINE_G1_WRAP(R1 []byte, R2 []byte) (errorCode int, R []byte) { |
| // Form Octets |
| R1Str := string(R1) |
| R1Oct := GetOctet(R1Str) |
| defer OCT_free(&R1Oct) |
| R2Str := string(R2) |
| R2Oct := GetOctet(R2Str) |
| defer OCT_free(&R2Oct) |
| ROct := GetOctetZero(G1S) |
| defer OCT_free(&ROct) |
| |
| rtn := C.MPIN_RECOMBINE_G1(&R1Oct, &R2Oct, &ROct) |
| errorCode = int(rtn) |
| |
| // Convert octet to bytes |
| R = OCT_toBytes(&ROct) |
| |
| return |
| } |
| |
| /* W=W1+W2 in group G2 */ |
| func MPIN_RECOMBINE_G2_WRAP(W1 []byte, W2 []byte) (errorCode int, W []byte) { |
| // Form Octets |
| W1Str := string(W1) |
| W1Oct := GetOctet(W1Str) |
| defer OCT_free(&W1Oct) |
| W2Str := string(W2) |
| W2Oct := GetOctet(W2Str) |
| defer OCT_free(&W2Oct) |
| WOct := GetOctetZero(G2S) |
| defer OCT_free(&WOct) |
| |
| rtn := C.MPIN_RECOMBINE_G2(&W1Oct, &W2Oct, &WOct) |
| errorCode = int(rtn) |
| |
| // Convert octet to bytes |
| W = OCT_toBytes(&WOct) |
| |
| return |
| } |
| |
| /* 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) (errorCode int, CS []byte) { |
| // Form Octets |
| SStr := string(S) |
| SOct := GetOctet(SStr) |
| defer OCT_free(&SOct) |
| IDStr := string(ID) |
| IDOct := GetOctet(IDStr) |
| defer OCT_free(&IDOct) |
| CSOct := GetOctetZero(G1S) |
| defer OCT_free(&CSOct) |
| |
| rtn := C.MPIN_GET_CLIENT_SECRET(&SOct, &IDOct, &CSOct) |
| errorCode = int(rtn) |
| |
| // Convert octet to bytes |
| CS = OCT_toBytes(&CSOct) |
| |
| return |
| } |
| |
| /* Time Permit TP=S*(date|H(ID)) where S is master secret */ |
| func MPIN_GET_CLIENT_PERMIT_WRAP(date int, S, ID []byte) (errorCode int, TP []byte) { |
| // Form Octets |
| SStr := string(S) |
| SOct := GetOctet(SStr) |
| defer OCT_free(&SOct) |
| IDStr := string(ID) |
| IDOct := GetOctet(IDStr) |
| defer OCT_free(&IDOct) |
| TPOct := GetOctetZero(G1S) |
| defer OCT_free(&TPOct) |
| |
| rtn := C.MPIN_GET_CLIENT_PERMIT(C.int(date), &SOct, &IDOct, &TPOct) |
| errorCode = int(rtn) |
| |
| // Convert octet to bytes |
| TP = OCT_toBytes(&TPOct) |
| |
| return |
| } |
| |
| /* Extract PIN from CS for identity CID to form TOKEN */ |
| func MPIN_EXTRACT_PIN_WRAP(ID []byte, PIN int, CS []byte) (errorCode int, TOKEN []byte) { |
| // Form Octets |
| IDStr := string(ID) |
| IDOct := GetOctet(IDStr) |
| defer OCT_free(&IDOct) |
| CSStr := string(CS) |
| CSOct := GetOctet(CSStr) |
| defer OCT_free(&CSOct) |
| |
| rtn := C.MPIN_EXTRACT_PIN(&IDOct, C.int(PIN), &CSOct) |
| errorCode = int(rtn) |
| |
| // Convert octet to bytes |
| TOKEN = OCT_toBytes(&CSOct) |
| |
| return |
| } |
| |
| /* One pass MPIN Client. Using GO RNG */ |
| func MPIN_CLIENT_WRAP(date, TimeValue, PIN int, RNG *amcl.RAND, ID, X, TOKEN, TP, MESSAGE []byte) (errorCode int, XOut, Y, SEC, U, UT []byte) { |
| amcl.MPIN_RANDOM_GENERATE(RNG, X[:]) |
| errorCode, XOut, Y, SEC, U, UT = MPIN_CLIENT_C(date, ID[:], nil, X[:], PIN, TOKEN[:], TP[:], MESSAGE[:], TimeValue) |
| return |
| } |
| |
| /* One pass MPIN Client. Using C RNG */ |
| func MPIN_CLIENT_C(date int, ID []byte, RNG *C.csprng, X []byte, PIN int, TOKEN []byte, TP []byte, MESSAGE []byte, TimeValue int) (errorCode int, XOut, Y, SEC, U, UT []byte) { |
| // Form Octets |
| IDStr := string(ID) |
| IDOct := GetOctet(IDStr) |
| defer OCT_free(&IDOct) |
| XStr := string(X) |
| XOct := GetOctet(XStr) |
| defer OCT_free(&XOct) |
| TOKENStr := string(TOKEN) |
| TOKENOct := GetOctet(TOKENStr) |
| defer OCT_free(&TOKENOct) |
| TPStr := string(TP) |
| TPOct := GetOctet(TPStr) |
| defer OCT_free(&TPOct) |
| MESSAGEStr := string(MESSAGE) |
| MESSAGEOct := GetOctet(MESSAGEStr) |
| defer OCT_free(&MESSAGEOct) |
| |
| SECOct := GetOctetZero(G1S) |
| defer OCT_free(&SECOct) |
| UOct := GetOctetZero(G1S) |
| defer OCT_free(&UOct) |
| UTOct := GetOctetZero(G1S) |
| defer OCT_free(&UTOct) |
| YOct := GetOctetZero(EGS) |
| defer OCT_free(&YOct) |
| |
| rtn := C.MPIN_CLIENT(C.int(date), &IDOct, RNG, &XOct, C.int(PIN), &TOKENOct, &SECOct, &UOct, &UTOct, &TPOct, &MESSAGEOct, C.int(TimeValue), &YOct) |
| errorCode = int(rtn) |
| |
| // Convert octet to bytes |
| XOut = OCT_toBytes(&XOct) |
| SEC = OCT_toBytes(&SECOct) |
| U = OCT_toBytes(&UOct) |
| UT = OCT_toBytes(&UTOct) |
| Y = OCT_toBytes(&YOct) |
| |
| return |
| } |
| |
| // Precompute values for use by the client side of M-Pin Full |
| func MPIN_PRECOMPUTE_WRAP(TOKEN []byte, ID []byte) (errorCode int, GT1 []byte, GT2 []byte) { |
| // Form Octets |
| IDStr := string(ID) |
| IDOct := GetOctet(IDStr) |
| defer OCT_free(&IDOct) |
| TOKENStr := string(TOKEN) |
| TOKENOct := GetOctet(TOKENStr) |
| defer OCT_free(&TOKENOct) |
| |
| GT1Oct := GetOctetZero(GTS) |
| defer OCT_free(>1Oct) |
| GT2Oct := GetOctetZero(GTS) |
| defer OCT_free(>2Oct) |
| |
| rtn := C.MPIN_PRECOMPUTE(&TOKENOct, &IDOct, >1Oct, >2Oct) |
| errorCode = int(rtn) |
| |
| // Convert octet to bytes |
| GT1 = OCT_toBytes(>1Oct) |
| GT2 = OCT_toBytes(>2Oct) |
| |
| return |
| } |
| |
| /* |
| 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 *amcl.RAND, typ int, X, G []byte) (errorCode int, XOut, W []byte) { |
| amcl.MPIN_RANDOM_GENERATE(RNG, X[:]) |
| errorCode, XOut, W = MPIN_GET_G1_MULTIPLE_C(nil, typ, X[:], G[:]) |
| return |
| } |
| |
| /* |
| 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 C RNG |
| */ |
| func MPIN_GET_G1_MULTIPLE_C(RNG *C.csprng, typ int, X []byte, G []byte) (errorCode int, XOut, W []byte) { |
| XStr := string(X) |
| XOct := GetOctet(XStr) |
| defer OCT_free(&XOct) |
| GStr := string(G) |
| GOct := GetOctet(GStr) |
| defer OCT_free(&GOct) |
| |
| WOct := GetOctetZero(G1S) |
| defer OCT_free(&WOct) |
| |
| rtn := C.MPIN_GET_G1_MULTIPLE(RNG, C.int(typ), &XOct, &GOct, &WOct) |
| errorCode = int(rtn) |
| |
| // Convert octet to bytes |
| XOut = OCT_toBytes(&XOct) |
| W = OCT_toBytes(&WOct) |
| |
| return |
| } |
| |
| /* One pass MPIN Server */ |
| func MPIN_SERVER_WRAP(date, TimeValue int, SS, U, UT, V, ID, MESSAGE []byte) (errorCode int, HID, HTID, Y, E, F []byte) { |
| SSStr := string(SS) |
| SSOct := GetOctet(SSStr) |
| defer OCT_free(&SSOct) |
| UStr := string(U) |
| UOct := GetOctet(UStr) |
| defer OCT_free(&UOct) |
| UTStr := string(UT) |
| UTOct := GetOctet(UTStr) |
| defer OCT_free(&UTOct) |
| VStr := string(V) |
| VOct := GetOctet(VStr) |
| defer OCT_free(&VOct) |
| IDStr := string(ID) |
| IDOct := GetOctet(IDStr) |
| defer OCT_free(&IDOct) |
| MESSAGEStr := string(MESSAGE) |
| MESSAGEOct := GetOctet(MESSAGEStr) |
| defer OCT_free(&MESSAGEOct) |
| |
| HIDOct := GetOctetZero(G1S) |
| defer OCT_free(&HIDOct) |
| HTIDOct := GetOctetZero(G1S) |
| defer OCT_free(&HTIDOct) |
| YOct := GetOctetZero(EGS) |
| defer OCT_free(&YOct) |
| EOct := GetOctetZero(GTS) |
| defer OCT_free(&EOct) |
| FOct := GetOctetZero(GTS) |
| defer OCT_free(&FOct) |
| |
| rtn := C.MPIN_SERVER(C.int(date), &HIDOct, &HTIDOct, &YOct, &SSOct, &UOct, &UTOct, &VOct, &EOct, &FOct, &IDOct, &MESSAGEOct, C.int(TimeValue)) |
| errorCode = int(rtn) |
| |
| // Convert octet to bytes |
| HID = OCT_toBytes(&HIDOct) |
| HTID = OCT_toBytes(&HTIDOct) |
| Y = OCT_toBytes(&YOct) |
| E = OCT_toBytes(&EOct) |
| F = OCT_toBytes(&FOct) |
| |
| return |
| } |
| |
| /* Pollards kangaroos used to return PIN error */ |
| func MPIN_KANGAROO(E []byte, F []byte) (PINError int) { |
| EStr := string(E) |
| EOct := GetOctet(EStr) |
| defer OCT_free(&EOct) |
| FStr := string(F) |
| FOct := GetOctet(FStr) |
| defer OCT_free(&FOct) |
| |
| rtn := C.MPIN_KANGAROO(&EOct, &FOct) |
| PINError = int(rtn) |
| return |
| } |
| |
| /* calculate common key on server side */ |
| /* Z=r.A - no time permits involved */ |
| func MPIN_SERVER_KEY_WRAP(Z, SS, W, P, I, U, UT []byte) (errorCode int, SK []byte) { |
| ZStr := string(Z) |
| ZOct := GetOctet(ZStr) |
| defer OCT_free(&ZOct) |
| SSStr := string(SS) |
| SSOct := GetOctet(SSStr) |
| defer OCT_free(&SSOct) |
| WStr := string(W) |
| WOct := GetOctet(WStr) |
| defer OCT_free(&WOct) |
| PStr := string(P) |
| POct := GetOctet(PStr) |
| defer OCT_free(&POct) |
| IStr := string(I) |
| IOct := GetOctet(IStr) |
| defer OCT_free(&IOct) |
| UStr := string(U) |
| UOct := GetOctet(UStr) |
| defer OCT_free(&UOct) |
| UTStr := string(UT) |
| UTOct := GetOctet(UTStr) |
| defer OCT_free(&UTOct) |
| |
| SKOct := GetOctetZero(EAS) |
| defer OCT_free(&SKOct) |
| |
| rtn := C.MPIN_SERVER_KEY(&ZOct, &SSOct, &WOct, &POct, &IOct, &UOct, &UTOct, &SKOct) |
| errorCode = int(rtn) |
| |
| // Convert octet to bytes |
| SK = OCT_toBytes(&SKOct) |
| |
| return |
| } |
| |
| /* calculate common key on client side */ |
| /* wCID = w.(A+AT) */ |
| func MPIN_CLIENT_KEY_WRAP(PIN int, GT1, GT2, R, X, P, T []byte) (errorCode int, CK []byte) { |
| GT1Str := string(GT1) |
| GT1Oct := GetOctet(GT1Str) |
| defer OCT_free(>1Oct) |
| GT2Str := string(GT2) |
| GT2Oct := GetOctet(GT2Str) |
| defer OCT_free(>2Oct) |
| RStr := string(R) |
| ROct := GetOctet(RStr) |
| defer OCT_free(&ROct) |
| XStr := string(X) |
| XOct := GetOctet(XStr) |
| defer OCT_free(&XOct) |
| PStr := string(P) |
| POct := GetOctet(PStr) |
| defer OCT_free(&POct) |
| TStr := string(T) |
| TOct := GetOctet(TStr) |
| defer OCT_free(&TOct) |
| |
| CKOct := GetOctetZero(EAS) |
| defer OCT_free(&CKOct) |
| |
| rtn := C.MPIN_CLIENT_KEY(>1Oct, >2Oct, C.int(PIN), &ROct, &XOct, &POct, &TOct, &CKOct) |
| errorCode = int(rtn) |
| |
| // Convert octet to bytes |
| CK = OCT_toBytes(&CKOct) |
| |
| return |
| } |
| |
| // Generate a random byte array |
| func GENERATE_RANDOM_C(RNG *C.csprng, randomLen int) (random []byte) { |
| randomOct := GetOctetZero(randomLen) |
| defer OCT_free(&randomOct) |
| |
| C.generateRandom(RNG, &randomOct) |
| |
| // Convert octet to bytes |
| random = OCT_toBytes(&randomOct) |
| |
| return |
| } |
| |
| // Generate random six digit value |
| func GENERATE_OTP_C(RNG *C.csprng) int { |
| rtn := C.generateOTP(RNG) |
| return int(rtn) |
| } |
| |
| /* AES-GCM Encryption: |
| K is key, H is header, IV is initialization vector and P is plaintext. |
| Returns cipthertext and tag (MAC) */ |
| func MPIN_AES_GCM_ENCRYPT(K, IV, H, P []byte) ([]byte, []byte) { |
| KStr := string(K) |
| KOct := GetOctet(KStr) |
| defer OCT_free(&KOct) |
| IVStr := string(IV) |
| IVOct := GetOctet(IVStr) |
| defer OCT_free(&IVOct) |
| HStr := string(H) |
| HOct := GetOctet(HStr) |
| defer OCT_free(&HOct) |
| PStr := string(P) |
| POct := GetOctet(PStr) |
| defer OCT_free(&POct) |
| |
| TOct := GetOctetZero(16) |
| defer OCT_free(&TOct) |
| lenC := len(PStr) |
| COct := GetOctetZero(lenC) |
| defer OCT_free(&COct) |
| |
| C.MPIN_AES_GCM_ENCRYPT(&KOct, &IVOct, &HOct, &POct, &COct, &TOct) |
| |
| // Convert octet to bytes |
| C := OCT_toBytes(&COct) |
| T := OCT_toBytes(&TOct) |
| |
| return C, T[:] |
| } |
| |
| /* AES-GCM Deryption: |
| K is key, H is header, IV is initialization vector and P is plaintext. |
| Returns cipthertext and tag (MAC) */ |
| func MPIN_AES_GCM_DECRYPT(K, IV, H, C []byte) ([]byte, []byte) { |
| KStr := string(K) |
| KOct := GetOctet(KStr) |
| defer OCT_free(&KOct) |
| IVStr := string(IV) |
| IVOct := GetOctet(IVStr) |
| defer OCT_free(&IVOct) |
| HStr := string(H) |
| HOct := GetOctet(HStr) |
| defer OCT_free(&HOct) |
| CStr := string(C) |
| COct := GetOctet(CStr) |
| defer OCT_free(&COct) |
| |
| TOct := GetOctetZero(16) |
| defer OCT_free(&TOct) |
| lenP := len(CStr) |
| POct := GetOctetZero(lenP) |
| defer OCT_free(&POct) |
| |
| C.MPIN_AES_GCM_DECRYPT(&KOct, &IVOct, &HOct, &COct, &POct, &TOct) |
| |
| // Convert octet to bytes |
| P := OCT_toBytes(&POct) |
| T := OCT_toBytes(&TOct) |
| |
| return P, T[:] |
| } |
| |
| /* Password based Key Derivation Function */ |
| /* Input password p, salt s, and repeat count */ |
| /* Output key of length olen */ |
| func MPIN_PBKDF2(Pass, Salt []byte, rep, olen int) (Key []byte) { |
| PassStr := string(Pass) |
| PassOct := GetOctet(PassStr) |
| defer OCT_free(&PassOct) |
| SaltStr := string(Salt) |
| SaltOct := GetOctet(SaltStr) |
| defer OCT_free(&SaltOct) |
| |
| KeyOct := GetOctetZero(olen) |
| defer OCT_free(&KeyOct) |
| |
| C.MPIN_PBKDF2(&PassOct, &SaltOct, C.int(rep), C.int(olen), &KeyOct) |
| |
| // Convert octet to bytes |
| Key = OCT_toBytes(&KeyOct) |
| |
| return |
| } |
| |
| func MPIN_printBinary(array []byte) { |
| for i := 0; i < len(array); i++ { |
| fmt.Printf("%02x", array[i]) |
| } |
| fmt.Printf("\n") |
| } |
| |
| /* 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) (HID, HTID []byte) { |
| // Form Octets |
| IDStr := string(ID) |
| IDOct := GetOctet(IDStr) |
| defer OCT_free(&IDOct) |
| |
| HIDOct := GetOctetZero(G1S) |
| defer OCT_free(&HIDOct) |
| HTIDOct := GetOctetZero(G1S) |
| defer OCT_free(&HTIDOct) |
| |
| C.MPIN_SERVER_1(C.int(date), &IDOct, &HIDOct, &HTIDOct) |
| |
| // Convert octet to bytes |
| HID = OCT_toBytes(&HIDOct) |
| HTID = OCT_toBytes(&HTIDOct) |
| |
| return |
| } |
| |
| /* 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) (errorCode int, E, F []byte) { |
| // Form Octets |
| HIDStr := string(HID) |
| HIDOct := GetOctet(HIDStr) |
| defer OCT_free(&HIDOct) |
| HTIDStr := string(HTID) |
| HTIDOct := GetOctet(HTIDStr) |
| defer OCT_free(&HTIDOct) |
| YStr := string(Y) |
| YOct := GetOctet(YStr) |
| defer OCT_free(&YOct) |
| SSStr := string(SS) |
| SSOct := GetOctet(SSStr) |
| defer OCT_free(&SSOct) |
| UStr := string(U) |
| UOct := GetOctet(UStr) |
| defer OCT_free(&UOct) |
| UTStr := string(UT) |
| UTOct := GetOctet(UTStr) |
| defer OCT_free(&UTOct) |
| VStr := string(V) |
| VOct := GetOctet(VStr) |
| defer OCT_free(&VOct) |
| |
| EOct := GetOctetZero(GTS) |
| defer OCT_free(&EOct) |
| FOct := GetOctetZero(GTS) |
| defer OCT_free(&FOct) |
| rtn := C.MPIN_SERVER_2(C.int(date), &HIDOct, &HTIDOct, &YOct, &SSOct, &UOct, &UTOct, &VOct, &EOct, &FOct) |
| |
| errorCode = int(rtn) |
| E = OCT_toBytes(&EOct) |
| F = OCT_toBytes(&FOct) |
| |
| return |
| } |
| |
| /* Implement step 1 on client side of MPin protocol. Use GO code to generate random X */ |
| func MPIN_CLIENT_1_WRAP(date int, ID []byte, RNG *amcl.RAND, X []byte, PIN int, TOKEN []byte, TP []byte) (errorCode int, XOut, SEC, U, UT []byte) { |
| amcl.MPIN_RANDOM_GENERATE(RNG, X[:]) |
| errorCode, XOut, SEC, U, UT = MPIN_CLIENT_1_C(date, ID[:], nil, X[:], PIN, TOKEN[:], TP[:]) |
| return |
| } |
| |
| /* Implement step 1 on client side of MPin protocol |
| When rng=nil the X value is externally generated |
| */ |
| func MPIN_CLIENT_1_C(date int, ID []byte, rng *C.csprng, X []byte, PIN int, TOKEN []byte, TP []byte) (errorCode int, XOut, SEC, U, UT []byte) { |
| // Form Octets |
| IDStr := string(ID) |
| IDOct := GetOctet(IDStr) |
| defer OCT_free(&IDOct) |
| |
| XStr := string(X) |
| XOct := GetOctet(XStr) |
| defer OCT_free(&XOct) |
| |
| TOKENStr := string(TOKEN) |
| TOKENOct := GetOctet(TOKENStr) |
| defer OCT_free(&TOKENOct) |
| |
| TPStr := string(TP) |
| TPOct := GetOctet(TPStr) |
| defer OCT_free(&TPOct) |
| |
| SECOct := GetOctetZero(G1S) |
| defer OCT_free(&SECOct) |
| UOct := GetOctetZero(G1S) |
| defer OCT_free(&UOct) |
| UTOct := GetOctetZero(G1S) |
| defer OCT_free(&UTOct) |
| |
| rtn := C.MPIN_CLIENT_1(C.int(date), &IDOct, rng, &XOct, C.int(PIN), &TOKENOct, &SECOct, &UOct, &UTOct, &TPOct) |
| |
| errorCode = int(rtn) |
| // Convert octet to bytes |
| XOut = OCT_toBytes(&XOct) |
| SEC = OCT_toBytes(&SECOct) |
| U = OCT_toBytes(&UOct) |
| UT = OCT_toBytes(&UTOct) |
| |
| return |
| } |
| |
| /* Implement step 2 on client side of MPin protocol */ |
| func MPIN_CLIENT_2_WRAP(X []byte, Y []byte, SEC []byte) (errorCode int, V []byte) { |
| // Form Octets |
| XStr := string(X) |
| XOct := GetOctet(XStr) |
| defer OCT_free(&XOct) |
| YStr := string(Y) |
| YOct := GetOctet(YStr) |
| defer OCT_free(&YOct) |
| SECStr := string(SEC) |
| SECOct := GetOctet(SECStr) |
| defer OCT_free(&SECOct) |
| |
| rtn := C.MPIN_CLIENT_2(&XOct, &YOct, &SECOct) |
| |
| errorCode = int(rtn) |
| // Convert octet to bytes |
| V = OCT_toBytes(&SECOct) |
| |
| return |
| } |
| |
| func MPIN_HASH_ALL_WRAP(I, U, UT, Y, V, R, W []byte) (HM []byte) { |
| // Form Octets |
| IStr := string(I) |
| IOct := GetOctet(IStr) |
| defer OCT_free(&IOct) |
| |
| UStr := string(U) |
| UOct := GetOctet(UStr) |
| defer OCT_free(&UOct) |
| |
| UTStr := string(UT) |
| UTOct := GetOctet(UTStr) |
| defer OCT_free(&UTOct) |
| |
| YStr := string(Y) |
| YOct := GetOctet(YStr) |
| defer OCT_free(&YOct) |
| |
| VStr := string(V) |
| VOct := GetOctet(VStr) |
| defer OCT_free(&VOct) |
| |
| RStr := string(R) |
| ROct := GetOctet(RStr) |
| defer OCT_free(&ROct) |
| |
| WStr := string(W) |
| WOct := GetOctet(WStr) |
| defer OCT_free(&WOct) |
| |
| HMOct := GetOctetZero(HASH_BYTES) |
| defer OCT_free(&HMOct) |
| |
| // Hash values |
| C.MPIN_HASH_ALL(&IOct, &UOct, &UTOct, &YOct, &VOct, &ROct, &WOct, &HMOct) |
| |
| // Convert octet to bytes |
| HM = OCT_toBytes(&HMOct) |
| |
| return |
| } |