Nigel’s Vision: Authenticated Key Exchange With Identity Based Encryption

One of the great visionaries in cryptography is Nigel Smart, and who moved from the University of Bristol to KU Leuven in 2018. Nigel has…

Nigel’s Vision: Authenticated Key Exchange With Identity Based Encryption

One of the great visionaries in cryptography is Nigel Smart, and who moved from the University of Bristol to KU Leuven in 2018. Nigel has been a real visionary within many areas including Identity Based Encryption (IBE), homomorphic encryption, multi-party computation (MPC), and crypto pairing.

With IBE, we use a KGC (Key Generation Centre) in order to share a secret between Bob and Alice (s) and publish a public key of sP (and where P is a generator point on an elliptic curve).

Bob then uses something about Alice’s ID to generate her public key, and Alice does the same for Bob. If Alice creates a secret (a), and Bob creates a secret (b), they can then end up with the same shared key in a matter similar to the Diffie-Hellman method, but which uses crypto pairs. One of his classic papers for this is [here]:

The paper looks rather unusual these days, as it only had one author, and does not contain pages and pages of proofs. The references, too, are fairly simple in their scope, and that abstract is just a couple of lines lone. But it is a wonderful paper, and focuses on the key contributions, rather than try to conflate things.

The method we will implement is defined in Section 3.2:

First we have two curves (G1 and G2) and initially we define a large prime number (q). Their public key will then become the hash of these values mapped to a curve:

QA=H(IDA)

QB=H(IDB)

Initially the KGC (Key Generation Centre) creates a secret random value (s) and shares a private key with Bob (sQB — where QB is a point on the elliptic curve, and s is the scalar value applied to the point) and with Alice (sQA). We then have a known ID for Bob (IDbob) and for Alice (IDalice).

For the key sharing instance, Alice generates a secret value for the secret sharing (a) and Bob generates his own secret (b). Next Alice sends aP as her public key Bob and Bob sends bP as his public key to Alice.

The key for Alice is then:

kA=e(aQB,sP)e(sQA,bP)

The key for Bob is then:

kB=e(sQB,aP)e(bQA,sP)

and where sP is the public key generated from the KGC. These keys will be the same, and no other party without the secrets (a and b) can calculate this. The shared key works because:

kA=e(aQB,sP)e(sQA,bP)

=e(sQB,aP)e(bQA,sP)

=e(sQB,aP)e(bQA,sP)=kB

We can also determine the key with:

K=e(aQB+bQA,sP)

The key is thus related to a,b,QA,QB, sP.

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)
bQA:=BN254.G1mul(QA,b)
sA:=BN254.G1mul(QA,s)
QB := BN254.ECP_mapit(Q_B)
aQB:=BN254.G1mul(QB,a)
sB:=BN254.G1mul(QB,s)
P := BN254.ECP2_generator()
bP := BN254.G2mul(P,b)
aP := BN254.G2mul(P,a)
Ppub:=BN254.G2mul(P,s)
// Alice uses a and sends aP to Bob
// Bob uses b and sends bP to Alice
// (aQb,sP)(sA,bP)
// (aQb,sP)(sQA,bP)
// (sQb,aP)(bQA,sP)
// (sB,aP)(bQA,sP)
LHS:=BN254.Ate(Ppub,aQB);  LHS=BN254.Fexp(LHS)
RHS2:=BN254.Ate(aP,sB); RHS2=BN254.Fexp(RHS2)
LHS2:=BN254.Ate(bP,sA);  LHS2=BN254.Fexp(LHS2)
RHS:=BN254.Ate(Ppub,bQA); RHS=BN254.Fexp(RHS)
RHS.Mul(RHS2)
LHS.Mul(LHS2)
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())
fmt.Printf("\n\nPair 1 e(aQb,sP)e(sA,bP) - first 20 bytes:\t0x%x\n",FP12toByte(LHS)[:20])
fmt.Printf("Pair 2 e(sB,aP)e(bQA,sP) - first 20 bytes:\t0x%x\n",FP12toByte(RHS)[:20])
if LHS.Equals(RHS) { fmt.Printf("\nSecret match\n\n")}
// e(aQB + bQA),sP)
aQB.Add(bQA)
key:=BN254.Ate(Ppub,aQB);  key=BN254.Fexp(key)
fmt.Printf("Key = e(aQB + bQA),sP) - 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): 139136eaa21c4ba8fa261c6d17f6f272395ae41dd2c1f8c85d48bccf33c2460b
Bob secret (b):  004f23ed49705f71ba2662275f20e6aa583b8d8150b46472303ad303ec655562
s: 0bd0bbdd2f79665802f7148e3b309bffb6288663e49cee22621d20759e4edaf6
QB: (24fe782588f174682f5eea7c6f9656dfa7a138814694a5594d38ea50aec70ed4,10da986194a99f6ed947e0831257ae2d52e957d2b5f7bf9205573a44d2062e68)
QA: (12274944c48d83c874fe2fd6f5bac76cb2a9062b0edbcd2d6a7eda4cdc75ccc4,074dc393de05a5d44a979a7645932ebf9c4c6bfc27f6de6e2227163011985426)
Pair 1 e(aQb,sP)e(sA,bP) - first 20 bytes: 0x08002b550a6ff942b2134afc03b97a78118a0390
Pair 2 e(sB,aP)e(bQA,sP) - first 20 bytes: 0x08002b550a6ff942b2134afc03b97a78118a0390
Secret match
Key = e(aQB + bQA),sP) - first 20 bytes: 0x08002b550a6ff942b2134afc03b97a78118a0390

Conclusions

An infrastructure based on a trust centre allows us to control sessions, and using IBE gives us the way to simply determine the public key of a device or a user. Nigel’s paper is beautifully crafted, and written in a time before we conflated our research papers. As some who spends a good amount of time reading highly verbose research papers, I love the “straight-to-the-point” conclusions:

With the complexity of using PKI with large-scale IoT infrastructures, we may see the rise in the usage of IBE, and in authenicated key exchange methods. The usage of a trust server is certainly an excellent way to manage a trust infrastructure, in a scaleable way.