added MPIN Two go/cgo wrapper code
diff --git a/go/src/github.com/miracl/amcl-cgo/crypto.go b/go/src/github.com/miracl/amcl-cgo/crypto.go
index 37e9801..38ac3ad 100644
--- a/go/src/github.com/miracl/amcl-cgo/crypto.go
+++ b/go/src/github.com/miracl/amcl-cgo/crypto.go
@@ -647,3 +647,131 @@
}
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
+}
diff --git a/go/src/github.com/miracl/amcl-cgo/crypto_test.go b/go/src/github.com/miracl/amcl-cgo/crypto_test.go
index ebbacbb..454e943 100644
--- a/go/src/github.com/miracl/amcl-cgo/crypto_test.go
+++ b/go/src/github.com/miracl/amcl-cgo/crypto_test.go
@@ -766,3 +766,325 @@
got = hex.EncodeToString(AES_KEY_CLIENT[:])
assert.Equal(t, want, got, "Should be equal")
}
+
+func TestTwoPassGoodPIN(t *testing.T) {
+ want := 0
+ // Assign the End-User an ID
+ IDstr := "testUser@miracl.com"
+ 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 := amclgo.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 TestTwoPassBadPIN(t *testing.T) {
+ want := -19
+ // Assign the End-User an ID
+ IDstr := "testUser@miracl.com"
+ 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 := amclgo.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 TestTwoPassBadToken(t *testing.T) {
+ want := -19
+ // Assign the End-User an ID
+ IDstr := "testUser@miracl.com"
+ 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 := amclgo.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 TestRandomTwoPass(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 := amclgo.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")
+
+ }
+}
diff --git a/go/src/github.com/miracl/amcl-go/crypto.go b/go/src/github.com/miracl/amcl-go/crypto.go
index 8e34f9c..e2b8bbb 100644
--- a/go/src/github.com/miracl/amcl-go/crypto.go
+++ b/go/src/github.com/miracl/amcl-go/crypto.go
@@ -189,3 +189,34 @@
}
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[:]
+}
diff --git a/go/src/github.com/miracl/amcl-go/crypto_test.go b/go/src/github.com/miracl/amcl-go/crypto_test.go
index 7fc169a..710204e 100644
--- a/go/src/github.com/miracl/amcl-go/crypto_test.go
+++ b/go/src/github.com/miracl/amcl-go/crypto_test.go
@@ -29,7 +29,7 @@
"github.com/stretchr/testify/assert"
)
-const nIter int = 100
+const nIter int = 1000
func TestCryptoGoodPIN(t *testing.T) {
want := 0
@@ -870,3 +870,325 @@
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 := "testUser@miracl.com"
+ 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 := "testUser@miracl.com"
+ 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 := "testUser@miracl.com"
+ 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")
+
+ }
+}
diff --git a/go/src/github.com/miracl/examples-cgo/mpinTwoPass.go b/go/src/github.com/miracl/examples-cgo/mpinTwoPass.go
new file mode 100644
index 0000000..63b541b
--- /dev/null
+++ b/go/src/github.com/miracl/examples-cgo/mpinTwoPass.go
@@ -0,0 +1,227 @@
+/*
+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 main
+
+import (
+ "encoding/hex"
+ "fmt"
+
+ amclcgo "github.com/miracl/amcl-cgo"
+ amclgo "github.com/miracl/amcl-go"
+)
+
+func main() {
+ // Assign the End-User an ID
+ IDstr := "testUser@miracl.com"
+ ID := []byte(IDstr)
+ fmt.Printf("ID: ")
+ amclcgo.MPIN_printBinary(ID)
+ fmt.Printf("\n")
+
+ // Epoch time in days
+ date := amclcgo.MPIN_today()
+
+ // PIN variable to create token
+ PIN1 := -1
+ // PIN variable to authenticate
+ PIN2 := -1
+
+ // 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 := amclgo.NewRAND()
+ rng.Seed(len(seed), seed)
+
+ // Generate Master Secret Share 1
+ rtn, MS1 := amclcgo.MPIN_RANDOM_GENERATE_WRAP(rng)
+ if rtn != 0 {
+ fmt.Println("MPIN_RANDOM_GENERATE Error:", rtn)
+ return
+ }
+ fmt.Printf("MS1: 0x")
+ amclcgo.MPIN_printBinary(MS1[:])
+
+ // Generate Master Secret Share 2
+ rtn, MS2 := amclcgo.MPIN_RANDOM_GENERATE_WRAP(rng)
+ if rtn != 0 {
+ fmt.Println("MPIN_RANDOM_GENERATE Error:", rtn)
+ return
+ }
+ fmt.Printf("MS2: 0x")
+ amclcgo.MPIN_printBinary(MS2[:])
+
+ // Either Client or TA calculates Hash(ID)
+ HCID := amclcgo.MPIN_HASH_ID(ID)
+
+ // Generate server secret share 1
+ rtn, SS1 := amclcgo.MPIN_GET_SERVER_SECRET_WRAP(MS1[:])
+ if rtn != 0 {
+ fmt.Println("MPIN_GET_SERVER_SECRET Error:", rtn)
+ return
+ }
+ fmt.Printf("SS1: 0x")
+ amclcgo.MPIN_printBinary(SS1[:])
+
+ // Generate server secret share 2
+ rtn, SS2 := amclcgo.MPIN_GET_SERVER_SECRET_WRAP(MS2[:])
+ if rtn != 0 {
+ fmt.Println("MPIN_GET_SERVER_SECRET Error:", rtn)
+ return
+ }
+ fmt.Printf("SS2: 0x")
+ amclcgo.MPIN_printBinary(SS2[:])
+
+ // Combine server secret shares
+ rtn, SS := amclcgo.MPIN_RECOMBINE_G2_WRAP(SS1[:], SS2[:])
+ if rtn != 0 {
+ fmt.Println("MPIN_RECOMBINE_G2(SS1, SS2) Error:", rtn)
+ return
+ }
+ fmt.Printf("SS: 0x")
+ amclcgo.MPIN_printBinary(SS[:])
+
+ // Generate client secret share 1
+ rtn, CS1 := amclcgo.MPIN_GET_CLIENT_SECRET_WRAP(MS1[:], HCID)
+ if rtn != 0 {
+ fmt.Println("MPIN_GET_CLIENT_SECRET Error:", rtn)
+ return
+ }
+ fmt.Printf("Client Secret Share CS1: 0x")
+ amclcgo.MPIN_printBinary(CS1[:])
+
+ // Generate client secret share 2
+ rtn, CS2 := amclcgo.MPIN_GET_CLIENT_SECRET_WRAP(MS2[:], HCID)
+ if rtn != 0 {
+ fmt.Println("MPIN_GET_CLIENT_SECRET Error:", rtn)
+ return
+ }
+ fmt.Printf("Client Secret Share CS2: 0x")
+ amclcgo.MPIN_printBinary(CS2[:])
+
+ // Combine client secret shares
+ CS := make([]byte, amclcgo.G1S)
+ rtn, CS = amclcgo.MPIN_RECOMBINE_G1_WRAP(CS1[:], CS2[:])
+ if rtn != 0 {
+ fmt.Println("MPIN_RECOMBINE_G1 Error:", rtn)
+ return
+ }
+ fmt.Printf("Client Secret CS: 0x")
+ amclcgo.MPIN_printBinary(CS[:])
+
+ // Generate time permit share 1
+ rtn, TP1 := amclcgo.MPIN_GET_CLIENT_PERMIT_WRAP(date, MS1[:], HCID)
+ if rtn != 0 {
+ fmt.Println("MPIN_GET_CLIENT_PERMIT Error:", rtn)
+ return
+ }
+ fmt.Printf("TP1: 0x")
+ amclcgo.MPIN_printBinary(TP1[:])
+
+ // Generate time permit share 2
+ rtn, TP2 := amclcgo.MPIN_GET_CLIENT_PERMIT_WRAP(date, MS2[:], HCID)
+ if rtn != 0 {
+ fmt.Println("MPIN_GET_CLIENT_PERMIT Error:", rtn)
+ return
+ }
+ fmt.Printf("TP2: 0x")
+ amclcgo.MPIN_printBinary(TP2[:])
+
+ // Combine time permit shares
+ rtn, TP := amclcgo.MPIN_RECOMBINE_G1_WRAP(TP1[:], TP2[:])
+ if rtn != 0 {
+ fmt.Println("MPIN_RECOMBINE_G1(TP1, TP2) Error:", rtn)
+ return
+ }
+
+ // Client extracts PIN1 from secret to create Token
+ for PIN1 < 0 {
+ fmt.Printf("Please enter PIN to create token: ")
+ fmt.Scan(&PIN1)
+ }
+
+ rtn, TOKEN := amclcgo.MPIN_EXTRACT_PIN_WRAP(ID[:], PIN1, CS[:])
+ if rtn != 0 {
+ fmt.Printf("FAILURE: EXTRACT_PIN rtn: %d\n", rtn)
+ return
+ }
+ fmt.Printf("Client Token TK: 0x")
+ amclcgo.MPIN_printBinary(TOKEN[:])
+
+ ////// Client //////
+
+ for PIN2 < 0 {
+ fmt.Printf("Please enter PIN to authenticate: ")
+ fmt.Scan(&PIN2)
+ }
+
+ ////// Client Pass 1 //////
+ // Send U and UT to server
+ var X [amclcgo.EGS]byte
+ fmt.Printf("X: 0x")
+ amclcgo.MPIN_printBinary(X[:])
+ rtn, XOut, SEC, U, UT := amclcgo.MPIN_CLIENT_1_WRAP(date, ID, rng, X[:], PIN2, TOKEN[:], TP[:])
+ if rtn != 0 {
+ fmt.Printf("FAILURE: CLIENT rtn: %d\n", rtn)
+ return
+ }
+ fmt.Printf("XOut: 0x")
+ amclcgo.MPIN_printBinary(XOut[:])
+
+ ////// Server Pass 1 //////
+ /* Calculate H(ID) and H(T|H(ID)) (if time permits enabled), and maps them to points on the curve HID and HTID resp. */
+ HID, HTID := amclcgo.MPIN_SERVER_1_WRAP(date, ID)
+
+ /* Send Y to Client */
+ rtn, Y := amclcgo.MPIN_RANDOM_GENERATE_WRAP(rng)
+ if rtn != 0 {
+ fmt.Println("MPIN_RANDOM_GENERATE Error:", rtn)
+ return
+ }
+ fmt.Printf("Y: 0x")
+ amclcgo.MPIN_printBinary(Y[:])
+
+ /* Client Second Pass: Inputs Client secret SEC, x and y. Outputs -(x+y)*SEC */
+ rtn, V := amclcgo.MPIN_CLIENT_2_WRAP(X[:], Y[:], SEC[:])
+ if rtn != 0 {
+ fmt.Printf("FAILURE: CLIENT_2 rtn: %d\n", rtn)
+ }
+
+ /* Server Second pass. Inputs hashed client id, random Y, -(x+y)*SEC, xID and xCID and Server secret SST. E and F help kangaroos to find error. */
+ /* If PIN error not required, set E and F = null */
+ rtn, _, _ = amclcgo.MPIN_SERVER_2_WRAP(date, HID[:], HTID[:], Y[:], SS[:], U[:], UT[:], V[:])
+ if rtn != 0 {
+ fmt.Printf("FAILURE: MPIN_SERVER_2 rtn: %d\n", rtn)
+ }
+ fmt.Printf("HID: 0x")
+ amclcgo.MPIN_printBinary(HID[:])
+ fmt.Printf("HTID: 0x")
+ amclcgo.MPIN_printBinary(HTID[:])
+
+ if rtn != 0 {
+ fmt.Printf("Authentication failed Error Code %d\n", rtn)
+ return
+ } else {
+ fmt.Printf("Authenticated ID: %s \n", IDstr)
+ }
+}
diff --git a/go/src/github.com/miracl/examples-go/mpinTwoPass.go b/go/src/github.com/miracl/examples-go/mpinTwoPass.go
index f86968e..f2c3d33 100644
--- a/go/src/github.com/miracl/examples-go/mpinTwoPass.go
+++ b/go/src/github.com/miracl/examples-go/mpinTwoPass.go
@@ -164,7 +164,7 @@
fmt.Scan(&PIN2)
}
- /* Cleints first pass. Calculate U and UT */
+ /* Clients first pass. Calculate U and UT */
rtn = amcl.MPIN_CLIENT_1(date, ID, rng, X[:], PIN2, TOKEN[:], SEC[:], U[:], UT[:], TP[:])
if rtn != 0 {
fmt.Printf("FAILURE: CLIENT rtn: %d\n", rtn)
diff --git a/go/src/github.com/miracl/examples-go/mpinTwoPassWrap.go b/go/src/github.com/miracl/examples-go/mpinTwoPassWrap.go
new file mode 100644
index 0000000..6ef787d
--- /dev/null
+++ b/go/src/github.com/miracl/examples-go/mpinTwoPassWrap.go
@@ -0,0 +1,228 @@
+/*
+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 main
+
+import (
+ "encoding/hex"
+ "fmt"
+
+ amcl "github.com/miracl/amcl-go"
+)
+
+func main() {
+ // Assign the End-User an ID
+ IDstr := "testUser@miracl.com"
+ ID := []byte(IDstr)
+ fmt.Printf("ID: ")
+ amcl.MPIN_printBinary(ID)
+ fmt.Printf("\n")
+
+ // Epoch time in days
+ date := amcl.MPIN_today()
+
+ // PIN variable to create token
+ PIN1 := -1
+ // PIN variable to authenticate
+ PIN2 := -1
+
+ // 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 := amcl.NewRAND()
+ rng.Seed(len(seed), seed)
+
+ const EGS = amcl.MPIN_EGS
+ const EFS = amcl.MPIN_EFS
+ const G1S = 2*EFS + 1 /* Group 1 Size */
+ const G2S = 4 * EFS /* Group 2 Size */
+ const EAS = amcl.MPIN_PAS
+
+ var X [EGS]byte
+
+ // Generate Master Secret Share 1
+ rtn, MS1 := amcl.MPIN_RANDOM_GENERATE_WRAP(rng)
+ if rtn != 0 {
+ fmt.Println("MPIN_RANDOM_GENERATE Error:", rtn)
+ return
+ }
+ fmt.Printf("MS1: 0x")
+ amcl.MPIN_printBinary(MS1[:])
+
+ // Generate Master Secret Share 2
+ rtn, MS2 := amcl.MPIN_RANDOM_GENERATE_WRAP(rng)
+ if rtn != 0 {
+ fmt.Println("MPIN_RANDOM_GENERATE Error:", rtn)
+ return
+ }
+ fmt.Printf("MS2: 0x")
+ amcl.MPIN_printBinary(MS2[:])
+
+ // Either Client or TA calculates Hash(ID)
+ HCID := amcl.MPIN_HASH_ID(ID)
+
+ // Generate server secret share 1
+ rtn, SS1 := amcl.MPIN_GET_SERVER_SECRET_WRAP(MS1[:])
+ if rtn != 0 {
+ fmt.Println("MPIN_GET_SERVER_SECRET Error:", rtn)
+ return
+ }
+ fmt.Printf("SS1: 0x")
+ amcl.MPIN_printBinary(SS1[:])
+
+ // Generate server secret share 2
+ rtn, SS2 := amcl.MPIN_GET_SERVER_SECRET_WRAP(MS2[:])
+ if rtn != 0 {
+ fmt.Println("MPIN_GET_SERVER_SECRET Error:", rtn)
+ return
+ }
+ fmt.Printf("SS2: 0x")
+ amcl.MPIN_printBinary(SS2[:])
+
+ // Combine server secret shares
+ rtn, SS := amcl.MPIN_RECOMBINE_G2_WRAP(SS1[:], SS2[:])
+ if rtn != 0 {
+ fmt.Println("MPIN_RECOMBINE_G2(SS1, SS2) Error:", rtn)
+ return
+ }
+ fmt.Printf("SS: 0x")
+ amcl.MPIN_printBinary(SS[:])
+
+ // Generate client secret share 1
+ rtn, CS1 := amcl.MPIN_GET_CLIENT_SECRET_WRAP(MS1[:], HCID)
+ if rtn != 0 {
+ fmt.Println("MPIN_GET_CLIENT_SECRET Error:", rtn)
+ return
+ }
+ fmt.Printf("Client Secret CS: 0x")
+ amcl.MPIN_printBinary(CS1[:])
+
+ // Generate client secret share 2
+ rtn, CS2 := amcl.MPIN_GET_CLIENT_SECRET_WRAP(MS2[:], HCID)
+ if rtn != 0 {
+ fmt.Println("MPIN_GET_CLIENT_SECRET Error:", rtn)
+ return
+ }
+ fmt.Printf("Client Secret CS: 0x")
+ amcl.MPIN_printBinary(CS2[:])
+
+ // Combine client secret shares
+ rtn, CS := amcl.MPIN_RECOMBINE_G1_WRAP(CS1[:], CS2[:])
+ if rtn != 0 {
+ fmt.Println("MPIN_RECOMBINE_G1 Error:", rtn)
+ return
+ }
+ fmt.Printf("Client Secret CS: 0x")
+ amcl.MPIN_printBinary(CS[:])
+
+ // Generate time permit share 1
+ rtn, TP1 := amcl.MPIN_GET_CLIENT_PERMIT_WRAP(date, MS1[:], HCID)
+ if rtn != 0 {
+ fmt.Println("MPIN_GET_CLIENT_PERMIT Error:", rtn)
+ return
+ }
+ fmt.Printf("TP1: 0x")
+ amcl.MPIN_printBinary(TP1[:])
+
+ // Generate time permit share 2
+ rtn, TP2 := amcl.MPIN_GET_CLIENT_PERMIT_WRAP(date, MS2[:], HCID)
+ if rtn != 0 {
+ fmt.Println("MPIN_GET_CLIENT_PERMIT Error:", rtn)
+ return
+ }
+ fmt.Printf("TP2: 0x")
+ amcl.MPIN_printBinary(TP2[:])
+
+ // Combine time permit shares
+ rtn, TP := amcl.MPIN_RECOMBINE_G1_WRAP(TP1[:], TP2[:])
+ if rtn != 0 {
+ fmt.Println("MPIN_RECOMBINE_G1(TP1, TP2) Error:", rtn)
+ return
+ }
+
+ // Client extracts PIN1 from secret to create Token
+ for PIN1 < 0 {
+ fmt.Printf("Please enter PIN to create token: ")
+ fmt.Scan(&PIN1)
+ }
+
+ rtn, TOKEN := amcl.MPIN_EXTRACT_PIN_WRAP(ID[:], PIN1, CS[:])
+ if rtn != 0 {
+ fmt.Printf("FAILURE: EXTRACT_PIN rtn: %d\n", rtn)
+ return
+ }
+ fmt.Printf("Client Token TK: 0x")
+ amcl.MPIN_printBinary(TOKEN[:])
+
+ for PIN2 < 0 {
+ fmt.Printf("Please enter PIN to authenticate: ")
+ fmt.Scan(&PIN2)
+ }
+
+ /* Clients first pass. Calculate U and UT */
+ fmt.Printf("X: 0x")
+ amcl.MPIN_printBinary(X[:])
+ rtn, Xout, SEC, U, UT := amcl.MPIN_CLIENT_1_WRAP(date, ID, rng, X[:], PIN2, TOKEN[:], TP[:])
+ if rtn != 0 {
+ fmt.Printf("FAILURE: CLIENT rtn: %d\n", rtn)
+ return
+ }
+ fmt.Printf("Xout: 0x")
+ amcl.MPIN_printBinary(Xout[:])
+
+ /* Server first pass. Calculate H(ID) and H(T|H(ID)) (if time permits enabled), and maps them to points on the curve HID and HTID resp. */
+ HID, HTID := amcl.MPIN_SERVER_1_WRAP(date, ID)
+
+ /* Server generates Random number Y and sends it to Client */
+ rtn, Y := amcl.MPIN_RANDOM_GENERATE_WRAP(rng)
+ if rtn != 0 {
+ fmt.Println("MPIN_RANDOM_GENERATE Error:", rtn)
+ return
+ }
+ fmt.Printf("Y: 0x")
+ amcl.MPIN_printBinary(Y[:])
+
+ /* Client Second Pass: Inputs Client secret SEC, x and y. Outputs -(x+y)*SEC */
+ rtn, V := amcl.MPIN_CLIENT_2_WRAP(X[:], Y[:], SEC[:])
+ if rtn != 0 {
+ fmt.Printf("FAILURE: CLIENT_2 rtn: %d\n", rtn)
+ }
+
+ /* Server Second pass. Inputs hashed client id, random Y, -(x+y)*SEC, xID and xCID and Server secret SST. E and F help kangaroos to find error. */
+ /* If PIN error not required, set E and F = null */
+ rtn, _, _ = amcl.MPIN_SERVER_2_WRAP(date, HID[:], HTID[:], Y[:], SS[:], U[:], UT[:], V[:])
+ if rtn != 0 {
+ fmt.Printf("FAILURE: MPIN_SERVER_2 rtn: %d\n", rtn)
+ }
+ fmt.Printf("HID: 0x")
+ amcl.MPIN_printBinary(HID[:])
+ fmt.Printf("HTID: 0x")
+ amcl.MPIN_printBinary(HTID[:])
+
+ if rtn == amcl.MPIN_BAD_PIN {
+ fmt.Printf("Authentication failed Error Code %d\n", rtn)
+ return
+ } else {
+ fmt.Printf("Authenticated ID: %s \n", IDstr)
+ }
+}