\(e(aU,bV) = e(U,V)^{ab} = e(abU, V) = e(U, abV ) = e(bU,aV)\)
In this case we will use Bob's ID and a secret to sign a message, and use the MIRACL library.
Signatures with Pairing-based cryptography Identity Based Encryption (IBE)
[MIRACL Home][Home]
With pairing-based cryptography we have two cyclic groups (\(G_1\) and \(G_2\)), and which are of an order of a prime number (\(n\)). A pairing on \((G_1,G_2,G_T)\) defines the function \(e:G_1 \times G_2 \rightarrow G_T\), and where \(g_1\) is a generator for \(G_1\) and \(g_2\) is a generator for \(G_2\). If \(U\) is a point on \(G_1\), and \(V\) is a point on \(G_2\), we have following rules:
\(e(aU,bV) = e(U,V)^{ab} = e(abU, V) = e(U, abV ) = e(bU,aV)\) In this case we will use Bob's ID and a secret to sign a message, and use the MIRACL library. |
First we have two curves (\(G_1\) and \(G_2\)) and initially we define a large prime number (\(q\)). First a trust server selects a point on the \(G_2\) curve (\(P\)), and generates Bob secret key using a random number (\(s\)):
\(sk=s\)
Next the trust server creates Bob public key with:
\(P_{pub}=sP\)
This will be a point on the \(G_2\) curve.
Bob next takes the message (\(msg\)) and creates a hash of it:
\(h=H(msg)\)
And takes his ID and also hashes it:
\(ID=H(BobID)\)
He then creates this as a point on the \(G_1\) curve:
\(Q_{ID}=H(p(ID)\)
This then creates with digital identity (DID) using his private key (\(s\)):
\(D_{ID}=sQ_{ID}\)
And he then creates a random value for the message with \(r\). Now he creates two elements for the signature of the message:
\(U=r Q_{ID}\)
\(V=(r+h)D_{ID}\)
The signature is then:
\(\sigma = (U,V)\)
To verify the signature, Alice perform the pairing of:
\(e(P,V)=e(P_{pub},U+hQ_{ID})\)
This works as:
\(e(P,V)=e(P,(r+h)D_{ID})= e(P,rD_{ID} + hD_{ID}) = e(P,srQ_{ID} + shQ_{ID}) = e(sP,rQ_{ID} + hQ_{ID}) = e(P_{pub},U+hQ_{ID})\)
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" msg:="Hello" argCount := len(os.Args[1:]) if (argCount>0) {BobID= (os.Args[1])} if (argCount>1) {msg= os.Args[2]} q := BN254.NewBIGints(BN254.CURVE_Order) s:=BN254.Randomnum(q,randval()) r:=BN254.Randomnum(q,randval()) sh:=core.NewHASH256() for i:=0;i < len(msg);i++ { sh.Process(msg[i]) } h:=BN254.FromBytes(sh.Hash()) sh=core.NewHASH256() for i:=0;i < len(BobID);i++ { sh.Process(BobID[i]) } ID:=BN254.FromBytes(sh.Hash()) P := BN254.ECP2_generator() Ppub:=BN254.G2mul(P,s) QID := BN254.ECP_hashit(ID) DID:=BN254.G1mul(QID,s) U := BN254.G1mul(QID,r) e := BN254.Modadd(r,h,q) V := BN254.G1mul(DID,e) hQID := BN254.G1mul(QID,h) U.Add(hQID) LHS:=BN254.Ate(P,V); LHS=BN254.Fexp(LHS) RHS:=BN254.Ate(Ppub,U); RHS=BN254.Fexp(RHS) fmt.Printf("\nMessage: %s\nBob's ID: %s\n\n",msg,BobID) fmt.Printf("\nSecret: %s\nRandom: %s\n",s.ToString(),r.ToString()) fmt.Printf("\nDID: %s\nQID: %s\n",DID.ToString(),QID.ToString()) fmt.Printf("\nU: %s\nV: %s\n",U.ToString(),V.ToString()) fmt.Printf("\n\nPair 1 (e(P,V))- first 20 bytes:\t\t0x%x\n",FP12toByte(LHS)[:20]) fmt.Printf("Pair 2 (e(Ppub,U+h QID)) - first 20 bytes:\t0x%x\n",FP12toByte(RHS)[:20]) if LHS.Equals(RHS) { fmt.Printf("\nSignature match\n")} }
A sample run is:
Message: Hello Bob's ID: bob@home Secret: 1e19d6cabe19313358f3e7073e9793b6c042adb1c66131911a02d615e7e7d188 Random: 0bba85cee287c124a1a37d6551e6ca8fce8b9571307ffb5c10987d203dfab8cf DID: (13138dd3a91f9801e786ee2a6929fdd081ac5788ee0834e7d5d696e780d03c7c,1862027895fd167ecd659329a55bd4fe83dfea0fbb61200a179170694b6a5659) QID: (24fe782588f174682f5eea7c6f9656dfa7a138814694a5594d38ea50aec70ed4,10da986194a99f6ed947e0831257ae2d52e957d2b5f7bf9205573a44d2062e68) U: (1ec8c5fe6003821c3926b291ec184e678cca0f12d82e74ac188c7aa521a2118f,22185fba9e01b110d0b9f97c47d5f8cdd7e52d440a902619a58ca7ba1c549b89) V: (1e0c1ce20bb787a06087be5f856c8ae0f5ff6f2ccab3bb62877e7f14c5682997,24d017c46be49a474219c9a5ab478a219c19481983253691ed4935f7fefdcd10) Pair 1 (e(P,V))- first 20 bytes: 0x16409c316b58a9d7a9bda5c8a817318672af445f Pair 2 (e(Ppub,U+h QID)) - first 20 bytes: 0x16409c316b58a9d7a9bda5c8a817318672af445f Signatures match
MASTER’S THESIS, Pairing-Based Cryptography, Martijn Maas. [link].