Chen’s Enhanced Identity-based (authenticated) key agreement

Today, I published an article on Nigel Smart’s classic paper on crypto pairing:

Chen’s Enhanced Identity-based (authenticated) key agreement

Today, I published an article on Nigel Smart’s classic paper on crypto pairing:

And I was so lucky that he replied by with this [here]:

So, here’s the paper by Chen and Kudla [here]:

Liqun [here] was also a researcher at the University of Bristol, at the time, and now is at the University of Surrey. The method is defined as:

First we have two curves (G1 and G2) and initially we define a large prime number (q). Initially the KGC (Key Generation Centre) creates a secret random value (s) and shares it with Bob and Alice. We then have a known ID for Bob (IDbob) and for Alice (IDalice). Their public key will then become the hash of these values mapped to a curve:

QA=H(IDA)

QB=H(IDB)

Alice generates a secret value for the secret sharing (a) and Bob generates his own secret (b).

The KGC generates a secret (s). Bob sends bQB as his public key to Alice, and Alice sends aQA.

The key for Alice is:

K_A=e(sA, bQ_B+aQ_B)

Bob computes:

K_B=e(aQ_A+bQ_A, sB)

This works because:

KA=e(SA,WB+aQB)=e(sQA,WB)⋅e(sA,aQB)=e(sQA,bQB)⋅e(sQa,aQB)=e(bQA,sQB)⋅e(sQa,sQB)=e(bQA+sQa,sQB)=e(sB,WA+bQA)=KB

and where WA=aQA is Alice’s public key, and WB=bQB is Bob’s public key.

Coding

The outline coding using the library from the MIRACL library [here] is:

package main
import (
	"fmt"
"github.com/miracl/core/go/core"
"github.com/miracl/core/go/core/BN254"
"math/rand"
"time"
"os"
)
func FP12toByte(F *BN254.FP12) []byte {
	const MFS int = int(BN254.MODBYTES)
var t [12 * MFS]byte
	F.ToBytes(t[:])
return(t[:])
}
func randval() *core.RAND {
    s1 := rand.NewSource(time.Now().UnixNano())
r1 := rand.New(s1)
    rng := core.NewRAND()
var raw [100]byte
for i := 0; i < 100; i++ {
raw[i] = byte(r1.Intn(255))
}
rng.Seed(100, raw[:])
return rng
}
func main() {

	BobID:="athome"
AliceID:="myaddress"
	argCount := len(os.Args[1:])
        if (argCount>0) {BobID= (os.Args[1])}
if (argCount>1) {AliceID= os.Args[2]}
    	q := BN254.NewBIGints(BN254.CURVE_Order)
	s:=BN254.Randomnum(q,randval())
a:=BN254.Randomnum(q,randval())
b:=BN254.Randomnum(q,randval())
	sh:=core.NewHASH256()
for i:=0;i < len(BobID);i++ {
sh.Process(BobID[i])
}
Q_B:=sh.Hash()

	sh=core.NewHASH256()
for i:=0;i < len(AliceID);i++ {
sh.Process(AliceID[i])
}
Q_A:=sh.Hash()
	QA := BN254.ECP_mapit(Q_A)
	Wa:=BN254.G1mul(QA,a)
bQA:=BN254.G1mul(QA,b)
sA:=BN254.G1mul(QA,s)

	QB := BN254.ECP2_mapit(Q_B)
Wb:=BN254.G2mul(QB,b)
aQB:=BN254.G2mul(QB,a)
sB:=BN254.G2mul(QB,s)
	fmt.Printf("Bob ID:\t\t%s\n",BobID)
fmt.Printf("Alice ID:\t%s\n\n",AliceID)
fmt.Printf("Alice secret (a):\t%s\n\n",a.ToString())
fmt.Printf("Bob secret (b):\t\t%s\n\n",b.ToString())
fmt.Printf("s:\t%s\n\n",s.ToString())
fmt.Printf("QB:\t%s\n\n",QB.ToString())
fmt.Printf("QA:\t%s\n\n",QA.ToString())

// e(SA, WB+aQB)
Wb.Add(aQB)
	key:=BN254.Ate(Wb,sA);  key=BN254.Fexp(key)
fmt.Printf("Key = e(SA, WB+aQB) - first 20 bytes:\t0x%x\n",FP12toByte(key)[:20])

	// e(sB,WA+bQA)
Wa.Add(bQA)
	key=BN254.Ate(sB,Wa);  key=BN254.Fexp(key)
fmt.Printf("Key = e(WA+bQA, SB)- first 20 bytes:\t0x%x\n",FP12toByte(key)[:20])
}

A sample run is [here]:

Bob ID:		bob@home
Alice ID: alice@home
Alice secret (a):	14e4a0bbac67e65154ffb1eca05c25f446f03b376343ef0ec9945fb8e11b8f86
Bob secret (b):		1b5ff8a43e3a501d674e60a4d5c346e33cf10152042419d6d80ea2869363ef8d
s:	18fe47a961118c9bb7b0a103fbce112dddbde26ba075414ac3f861c7e7b89634
QB:	([0e0c27fda99a9cebb9b647a99e3c3821ca7512ba40251577010f3d284ec5dce4,0739f52acb074f77826a1fd05e0ecb44f4e6ad38274f4d691a5ab55e97b15dd0],[0fc2a977d7e1ccfa2c070180855ea532c2c4da3538cda2bdab733c0f26e5e112,030ee76d93b45c313f43e15ddaf2fd301f9ca6ce32b37981d93283ce76ad4f2b])
QA:	(12274944c48d83c874fe2fd6f5bac76cb2a9062b0edbcd2d6a7eda4cdc75ccc4,074dc393de05a5d44a979a7645932ebf9c4c6bfc27f6de6e2227163011985426)
Key = e(SA, WB+aQB) - first 20 bytes:	0x1854fddd953cebe3c0a526435e4a15ecf6b799e8
Key = e(WA+bQA, SB)- first 20 bytes: 0x1854fddd953cebe3c0a526435e4a15ecf6b799e8

Liqun even enhanced the method further Bob and Alice using different trust authorities:

In this case, Bob connects to T1 which generates a secret (s1), and Alice connects to T2 which generates another secret (s2). Bob sends his public key values of s2QB and bP to Alice, and Alice send her public key values of s1QA and aP to Bob.

The key for Alice is:

KA=e(s1QA,bP)⋅e(QB,as2P)

and Bob computes:

KB=e(s2B,aP)⋅e(QA,bs1P)

The outline coding using the library from the MIRACL library [here] is

package main
import (
	"fmt"
"github.com/miracl/core/go/core"
"github.com/miracl/core/go/core/BN254"
"math/rand"
"time"
"os"
)
func FP12toByte(F *BN254.FP12) []byte {
	const MFS int = int(BN254.MODBYTES)
var t [12 * MFS]byte
	F.ToBytes(t[:])
return(t[:])
}
func randval() *core.RAND {
    s1 := rand.NewSource(time.Now().UnixNano())
r1 := rand.New(s1)
    rng := core.NewRAND()
var raw [100]byte
for i := 0; i < 100; i++ {
raw[i] = byte(r1.Intn(255))
}
rng.Seed(100, raw[:])
return rng
}
func main() {

	BobID:="athome"
AliceID:="myaddress"
	argCount := len(os.Args[1:])
        if (argCount>0) {BobID= (os.Args[1])}
if (argCount>1) {AliceID= os.Args[2]}
    	q := BN254.NewBIGints(BN254.CURVE_Order)
	s1:=BN254.Randomnum(q,randval())
s2:=BN254.Randomnum(q,randval())
a:=BN254.Randomnum(q,randval())
b:=BN254.Randomnum(q,randval())
	sh:=core.NewHASH256()
for i:=0;i < len(BobID);i++ {
sh.Process(BobID[i])
}
Q_B:=sh.Hash()

	sh=core.NewHASH256()
for i:=0;i < len(AliceID);i++ {
sh.Process(AliceID[i])
}
Q_A:=sh.Hash()
	QA := BN254.ECP_mapit(Q_A)
//	bQA:=BN254.G1mul(QA,b)
	sA:=BN254.G1mul(QA,s1)

	QB := BN254.ECP_mapit(Q_B)
// aQB:=BN254.G1mul(QB,a)
sB:=BN254.G1mul(QB,s2)
	P := BN254.ECP2_generator()
bP := BN254.G2mul(P,b)
	aP := BN254.G2mul(P,a)
	as2P := BN254.G2mul(aP,s2)
bs1P := BN254.G2mul(bP,s1)
	fmt.Printf("Bob ID:\t\t%s\n",BobID)
fmt.Printf("Alice ID:\t%s\n\n",AliceID)
fmt.Printf("Alice secret (a):\t%s\n\n",a.ToString())
fmt.Printf("Bob secret (b):\t\t%s\n\n",b.ToString())
fmt.Printf("s1:\t%s\n\n",s1.ToString())
fmt.Printf("s2:\t%s\n\n",s2.ToString())
fmt.Printf("QB:\t%s\n\n",QB.ToString())
fmt.Printf("QA:\t%s\n\n",QA.ToString())
// KAB = e(SA, bP)e(QB, a s2 P)
// KBA = e(SB, aP)e(QA, b s1 P)
	LHS:=BN254.Ate(bP,sA);  LHS=BN254.Fexp(LHS)
LHS2:=BN254.Ate(as2P,QB); LHS2=BN254.Fexp(LHS2)
	RHS:=BN254.Ate(aP,sB);  RHS=BN254.Fexp(RHS)
RHS2:=BN254.Ate(bs1P,QA); RHS2=BN254.Fexp(RHS2)
	RHS.Mul(RHS2)
LHS.Mul(LHS2)
	fmt.Printf("\n\nPair 1 e(SA, bP)e(QB, a s2 P) - first 20 bytes:\t0x%x\n",FP12toByte(LHS)[:20])
fmt.Printf("Pair 2 e(SB, aP)e(QA, b s1 P) - first 20 bytes:\t0x%x\n",FP12toByte(RHS)[:20])
if LHS.Equals(RHS) { fmt.Printf("\nSecret match\n\n")}

}

A sample run is [here]:

Bob ID:		athome
Alice ID: myaddress
Alice secret (a):	19832fa83a284340ff6e6738c3db9939edc8962cd53cbfd599fb012c14c5264b
Bob secret (b):		1832cb59170af2183aec15cf204850829d9756348350148186d24bd914bc82bd
s1:	1242869b574b817c9ce016d35e7b1127e46f35bd0dd9dfb8105ebb1c899c7844
s2:	1c162bdd6d1d7762c4b6e7767f096a3d94b98ea12193c8bda79b7daf5c00d19e
QB:	(1d7422d2157b29bc0235d892d2db665aebf97df7eb3da4ee99f9d6e1ca624259,00ed68263de6b05ca678db65336d326664d7c68708195c99ea8d8b94182f79a7)
QA:	(0fa34bc9cbaf3db17f5401f7ff0d10f4b8fac82a96985db493b8a1d477a6071e,1800ed5d5bd2616649bf4e20d8b7af69933f4cd1904f3ac678408672a9422a59)
Pair 1 e(SA, bP)e(QB, a s2 P) - first 20 bytes:	0x0f6e5f85bfd18897405f1f0073885599e0b3babd
Pair 2 e(SB, aP)e(QA, b s1 P) - first 20 bytes: 0x0f6e5f85bfd18897405f1f0073885599e0b3babd
Secret match

References

Smart, N. P. (2002). Identity-based authenticated key agreement protocol based on Weil pairing. Electronics letters, 38(13), 630–632. [link].

Chen, L., & Kudla, C. (2003, June). Identity based authenticated key agreement protocols from pairings. In 16th IEEE Computer Security Foundations Workshop, 2003. Proceedings. (pp. 219–233). IEEE. [link]