Image for post
Image for post
Photo by Bradford Nicolas on Unsplash

How Does Bob Encrypt Data For Alice, Using Just Her Email Address?

Go and encrypt …

So can you send me an encrypted message by just knowing my ID? Well, IBE (Identity Based Encryption) does this, and the MIRACL library is just perfect in implementing it. Basically atrust authority creates a secret from Alice’s ID, and then passes Alice’s private key using her ID and the secret value:

First we have two curves (G1 and G2) and initially we define a large prime number (q). We then use a special pairing function e() for two points (U and V):

Image for post
Image for post

and where U is a point on the G2 curve and V is a point on the G1 curve.

A trust server selects a point on the G2 curve (P), and generates a using a random number (s): sk=s. Next the trust server creates a public key with (and where P is a base point on the G1 curve):

Image for post
Image for post

This will be a point on the G1 curve. Bob then takes Alice’s ID and hashes it:

Image for post
Image for post

He then creates this as a point on the G2 curve:

Image for post
Image for post

This is Alice’s public key. The trust server sends Alice her private key:

Image for post
Image for post

Bob takes the plaintext message (M) and creates a random number (r). Next Bob creates the ciphertext of:

Image for post
Image for post

Alice then justs uses her private key (dA) and the ciphertext elements (C1, C2) to recover the message with:

Image for post
Image for post

dA is Alice’s private key (sQA), QA is her public key, ⊕ operator is EX-OR, and e() is the pairing function. This works because:

Image for post
Image for post


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

package mainimport ("fmt"
func FP12toByte(F *BN254.FP12) []byte {const MFS int = int(BN254.MODBYTES)
var t [12 * MFS]byte
func ECPtoByte(F *BN254.ECP2) []byte {
const MFS int = int(BN254.MODBYTES)
var t [12 * MFS]byte
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 xor(a []byte, b []byte) []byte{for i := 0; i < len(a); i++ {
a[i]=(a[i]^b[i]) & 0xff
return a
func main() {AliceID:="myaddress"
argCount := len(os.Args[1:])if (argCount>1) {msg= os.Args[1]}
if (argCount>2) {AliceID= os.Args[2]}
q := BN254.NewBIGints(BN254.CURVE_Order)s:=BN254.Randomnum(q,randval())
for i:=0;i < len(AliceID);i++ {
QA := BN254.ECP2_mapit(Q_A)// Alice's secret key: dA
P := BN254.ECP_generator()
M := []byte(msg)pair:=BN254.Ate(QA,sP); pair=BN254.Fexp(pair)
C1:=BN254.G1mul(P,r)C2:=xor(M,FP12toByte(pair))pair2:=BN254.Ate(dA,C1); pair2=BN254.Fexp(pair2)fmt.Printf("Message:\t%s\n\n",msg)
fmt.Printf("Alice ID:\t%s\n\n",AliceID)
fmt.Printf("Alice QA:\t%s\n\n",QA.ToString())
fmt.Printf("Alice private:\t%s\n\n",dA.ToString())
Cres:=xor(C2,FP12toByte(pair2))fmt.Printf("Decrypt: %s\n\n",Cres)fmt.Printf("\nPairing 1 e(QA,sP)^r:\t%x\n",FP12toByte(pair)[:20])
fmt.Printf("Pairing 2 e(dA,C1):\t%x\n\n",FP12toByte(pair2)[:20])

A sample run is [here]:

Message: HelloAlice ID: myaddressAlice QA: ([22f89695210305ac8cc6f6e3b3f25564127746368f561b0a3d78838655678a04,098626898fd16868774246bd593faf156d659774febc5ff33cc3867ac07909fc],[1dd702f4a45bf6a247f6a5bb71c96d528beeb6860cc9e66baabfe25815ad2e10,130d4187e10b25ac3b6d6bc00bd433bcb02f676777e716f88cf5c3b998f1cb8d])Alice private: ([030f8ef338489ca72571bebba78fe68f02694da5f7681eddf051f90cf3b49e68,0b62b9e4f27eff39eda74bfc6cfc806e28dd8c4708771f4b474e242314d3c774],[0b195563e2f33f8fbf614054ba7075d5a017d252b5d90b48c61b57b2283343b8,0bba11988e80bfb90b6bb7b097ec1584ebab49fa9303d1f68215d8fc3f46b8de])s: 12a1dd2f951ac291b81acdc6cb9d506a3add0a8c1eb826e53f018d6b9a6673a0
r: 003a0f064288945a929324d5706c5ead13959e4995cb3df0c7ca8326942a80d4
C1: (098c71ac9f313cb903726cacb1879ff001d078deccc5fd7b0298c1d7e499a68a,0e8f3524936a078417f7dae4d6e562c3ff9bd2f89dedf8f80e0dcab168369f5f)
C2: 468f2ef773
Decrypt: HelloPairing 1 e(QA,sP)^r: 0eea429b1c0d4d505706dbd47641af6a2109dcae
Pairing 2 e(dA,C1): 0eea429b1c0d4d505706dbd47641af6a2109dcae


For IoT infrastructures, PKI is just not scalable, and so IBE may fit better.

Written by

Professor of Cryptography. Serial innovator. Believer in fairness, justice & freedom. EU Citizen. Auld Reekie native. Old World Breaker. New World Creator.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store