Encrypted Searches Using Crypto Pairing, Rust and MIRACL

We give away too much information. Let’s say I have to search to see if a given post code is on a database, but I want to keep the search…

Photo by Ben White on Unsplash

Encrypted Searches Using Crypto Pairing, Rust and MIRACL

We give away too much information. Let’s say I have to search to see if a given post code is on a database, but I want to keep the search and search term secret. In this case we will implement the following [paper]:

With crypto pairing we have two elliptic curves: G1 and G2, and then map onto a third curve: Gt. The pairing of the points on G1 (P) and G2 (Q) is defined as a pairing function, and where we determine e (Q,P). For the points of P and Q, this has special mappings of:

e (sQ,rP)=e (rQ,sP)=e (rsQ,P)=e (Q,rsP)=e (sQ,P)r=e (Q,P)rs

and:

e (R+Q,P)=e (R,Pe (Q,P)

First we have two curves (G1 and G2) and initially we define a large prime number (q). First Alice — who wants to perform the search — selects a point on the G2 curve (P), and generates a using a random number (s):

sk=s

Alice then creates public key with:

Ps=sP

Next Bob creates a random value (r) and creates:

Pr=rP

Bob then hashes the word to search (m) to the G2 curve:

QW=H1(m)

Bob takes Alice’s public key (Ps) and his private key (r) and creates the pairing of:

e (QW,Ps)^r

If Alice wants to search for W2, she matches to:

e (Tw,Pr)

and where Tw=sH1(W2))

This works because:

e (Tw,Pr)=e (sH1(W2),rP)=e (rH1(W2),sP)=e (QW,sP)r=e (QW,Ps)^r

Coding

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

extern crate rand_core;
use mcore::bn254::big;
use mcore::bn254::ecp;
use mcore::bn254::ecp2;
use mcore::bn254::fp2;
use mcore::bn254::pair;
use mcore::bn254::rom;
use mcore::rand::{RAND,RAND_impl};
use sha2::{Sha256, Sha512,Digest};
use rand::Rng;
use std::env;
fn get_random() ->RAND_impl{
let random_bytes = rand::thread_rng().gen::<[u8; 32]>();
let mut rng = RAND_impl::new();
rng.seed(32, &random_bytes);
rng
}
fn main() {
let mut rng = get_random();
println!("Encrypted search using bn254 Pairings");
let P = ecp::ECP::generator();

let max = big::BIG::new_ints(&rom::CURVE_ORDER);
let r = big::BIG::randomnum(&max, &mut rng);
let s = big::BIG::randomnum(&max, &mut rng);
let A_public = pair::g1mul( &P, &s);
let rP= pair::g1mul(&P, &r);
let mut message="password";
let mut tofind="password";
let args: Vec<String> = env::args().collect();

if args.len() >1 { message = args[1].as_str();}
if args.len() >2 { tofind = args[2].as_str();}
println!("r={}",r.to_string());
println!("s={}",s.to_string());
println!("\nA_public (on G1)= {}",A_public);
println!("Search public (rP) (on G2)= {}",rP);
println!("\nMessasge= {}",message);
println!("\nWord to find= {}",tofind);
let mut hasher = Sha256::new(); hasher.update(message.as_bytes());
let result = hasher.finalize();
let mut Qw=ecp2::ECP2::mapit(result.as_slice());

let mut p1 = pair::ate(&Qw, &A_public);
p1 = pair::fexp(&p1);
p1=p1.pow(&r);
println!("--- Now let's search for it ---");
let mut hasher = Sha256::new(); hasher.update(tofind.as_bytes());
let result = hasher.finalize();
Qw=ecp2::ECP2::mapit(result.as_slice());
let sQw=pair::g2mul(&Qw, &s);
let mut p2 = pair::ate(&sQw, &rP);
p2 = pair::fexp(&p2);


if (p1.equals(&p2)) { println!("Found it");}
else { println!("Not Found");}
}

A sample run is [here]:

Encrypted search using bn254 Pairings
r=07B1E91F0FA4A1401F255FFEC386DD0FAB13B86955A38494A9E62C2665351182
s=1B0BE6A42EBB67FF5827B995914D344EC7A6B344BBBC61DEC0D47600B3587171
A_public (on G1)= (0FA55551E12EF58F6F12FEEDF9C2F12645CFF6B3AE4B839D3448BD83DFCB64E4,20C7DF6FCF73D00AF71CF94BD203BC6CF43A8F0B1439B7F9EA9713D8F3582E23)
Search public (rP) (on G2)= (0D5FF73D7F1713843C6649594CAD8091AA265C2CEEB1BA18E770039F4E022FF5,0E960F2ACA203ECCB2EF3E6DFF6B562D5F2DEBC9EA4FC29AA2D6C370BF7DBDD8)
Messasge= hello
Word to find= hello
--- Now let's search for it ---
Found it

and a false search:

Encrypted search using bn254 Pairings
r=1A6E5292FA89777EA9F1548930B0009944898CA4DDB177E916E3BE5BC954C3E3
s=189F4B2FC764CD0CAEB50FB625165BB121430BD1FC21ED3826C8EC39FC8C9D60
A_public (on G1)= (00D52F76FD3FDA13B0CC3AEC01F0AE534FD8523D7C268BC6285FBEB2192BC6C8,224E883078BEC41CAB8423DF1C12E6B9DA795E48A44BCD343DA00BC752FC267A)
Search public (rP) (on G2)= (1D6EFC11E7C5D1F32C9B4020EF316E9942B0A1031A2870A107B63971B8E1D09A,0D2F61EC6323EB45C0518031EF99B1554FACEBE6AC5B551C6F08C51A9FA4E546)
Messasge= hello
Word to find= hello123
--- Now let's search for it ---
Not Found

Go try it for yourself:

https://asecuritysite.com/rust/rust_miracl02

and here is the running code: