├── Makefile ├── README.md ├── main.c ├── peks.c └── peks.h /Makefile: -------------------------------------------------------------------------------- 1 | CC=gcc 2 | SOURCE=main.c peks.c 3 | DEPS=peks.h 4 | EXECUTABLE=peks 5 | CFLAG=-I ~/.local/include/pbc 6 | LDFLAGS=-Wl,-rpath ~/.local/lib -lpbc -lssl -lcrypto -lgmp -lm 7 | 8 | 9 | target: 10 | $(CC) $(SOURCE) -o $(EXECUTABLE) $(CFLAG) $(LDFLAGS) 11 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PEKS 2 | 3 | This is the implementation of public-key searchable encryption using bilinear maps described in 4 | Public Key Encryption with Keyword Search. It is a simple, command-line application developed in C. 5 | 6 | ## Implementation Details 7 | 8 | #### Dependencies 9 | 10 | * GMP Library: 11 | 12 | ```$ sudo apt-get install libgmp3-dev``` 13 | * OpenSSL: 14 | 15 | ```$ sudo apt-get install libssl-dev``` 16 | * [PBC Library](https://crypto.stanford.edu/pbc) 17 | 18 | ``` 19 | $ ./configure --prefix=$HOME/.local 20 | $ make 21 | $ make install 22 | ``` 23 | Makefile uses this path. In case of change in destination directory, update the Makefile accordingly. 24 | 25 | #### Build 26 | 27 | ```$ make``` 28 | 29 | #### Run 30 | 31 | ```$ ./peks ``` 32 | 33 | #### Usage 34 | 35 | ``` 36 | $ ./peks hello hello 37 | Equal 38 | $ ./peks Hello hello 39 | Not equal 40 | $ ./peks Supercalifragilisticexpialidocious Supercalifragilisticexpialidocious 41 | Equal 42 | $ ./peks Lopadotemachoselachogaleokranioleipsanodrimhypotrimmatosilphioparaomelitokatakechymenokichlepikossyphophattoperisteralektryonoptekephalliokigklopeleiolagoiosiraiobaphetraganopterygon Lopadotemachoselachogaleokranioleipsanodrimhypotrimmatosilphioparaomelitokatakechymenokichlepikossyphophattoperisteralektryonoptekephalliokigklopeleiolagoiosiraiobaphetraganopterygon 43 | Equal 44 | $ ./peks Lopadotemachoselachogaleokranioleipsanodrimhypotrimmatosilphioparaomelitokatakechymenokichlepikossyphophattoperisteralektryonoptekephalliokigklopeleiolagoiosiraiobaphetraganopterygon Lopadotemachoselachogaleokranioleipsanodrimhypotrimmatosilphioparaomelitokatakechymenokichlepikossyphophattoperisteraletryonoptekephalliokigklopeleiolagoiosiraiobaphetraganopterygon 45 | Not equal 46 | ``` 47 | 48 | *This work was a part of the master thesis from TU Dresden under the supervision of Dr. Josef Spillner and Martin Beck. 49 | 50 | ## [Public Key Encryption with Keyword Search](http://eprint.iacr.org/2003/195.pdf) 51 | 52 | by Dan Boneh, Giovanni Di Crescenzo, Rafail Ostrovsky and Giuseppe Persiano. 53 | 54 | The authors describe a way of appending information to a message that has 55 | been encrypted with a standard public key cipher, which allows a server 56 | that doesn’t have the private key necessary to decrypt the entire message 57 | to still be able to search for a certain set of keywords. For a keyword, a 58 | PEKS value can be generated which will allow the server to perform a search 59 | using a trapdoor. 60 | -------------------------------------------------------------------------------- /main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * main.c 3 | * 4 | * Created on: Jul 7, 2015 5 | * Author: mahind 6 | */ 7 | 8 | #include 9 | 10 | #include "peks.h" 11 | 12 | //#define DEBUG 1 13 | 14 | int main(int argc, char **argv) 15 | { 16 | if (argc != 3) { 17 | printf("Usage: %s \n",argv[0]); 18 | return 1; 19 | } 20 | 21 | char *W1, *W2; 22 | W1 = *(++argv); 23 | W2 = *(++argv); 24 | 25 | int match; 26 | match = peks_scheme(W1, W2); 27 | 28 | if(match) 29 | printf("Equal\n"); 30 | else 31 | printf("Not equal\n"); 32 | 33 | return 0; 34 | } 35 | -------------------------------------------------------------------------------- /peks.c: -------------------------------------------------------------------------------- 1 | /* 2 | * peks.c 3 | * 4 | * Created on: Jul 7, 2015 5 | * Author: Atul Mahind 6 | */ 7 | 8 | #include "peks.h" 9 | 10 | void sha512(const char *word, int word_size, 11 | char hashed_word[SHA512_DIGEST_LENGTH*2+1]) 12 | { 13 | int i; 14 | unsigned char digest[SHA512_DIGEST_LENGTH]; 15 | 16 | SHA512_CTX ctx; 17 | SHA512_Init(&ctx); 18 | SHA512_Update(&ctx, word, word_size); 19 | SHA512_Final(digest, &ctx); 20 | 21 | for (i = 0; i < SHA512_DIGEST_LENGTH; i++) 22 | sprintf(&hashed_word[i*2], "%02x", (unsigned int)digest[i]); 23 | } 24 | 25 | void get_n_bits(char* src, char* out, int bitswanted) 26 | { 27 | char * ptr = out; 28 | char byte; 29 | int i; 30 | 31 | while(bitswanted) 32 | { 33 | byte = *src++; 34 | for(i = 7; i >= 0 && bitswanted > 0 ; i--, bitswanted--) 35 | *ptr++ = '0' + ((byte >> i) & 0x01); 36 | if(bitswanted == 0) 37 | break; 38 | } 39 | } 40 | 41 | void key_printf(key key) 42 | { 43 | element_printf("α %B\n", key.priv); 44 | element_printf("g %B\n", key.pub.g); 45 | element_printf("h %B\n", key.pub.h); 46 | } 47 | 48 | void peks_printf(peks peks) 49 | { 50 | element_printf("A %B\n", peks.A); 51 | printf("B %s\n", peks.B); 52 | } 53 | 54 | void init_pbc_param_pairing(pbc_param_t param, pairing_t pairing) 55 | { 56 | int rbits = 160; 57 | int qbits = 512; 58 | 59 | /* Generate type A pairing parameters */ 60 | pbc_param_init_a_gen(param, rbits, qbits); 61 | 62 | /* Initialize pairing */ 63 | pairing_init_pbc_param(pairing, param); 64 | #if defined(DEBUG) 65 | printf("Symmetric %d\n", pairing_is_symmetric(pairing)); 66 | #endif 67 | } 68 | 69 | void KeyGen(key *key, pbc_param_t param, pairing_t pairing) 70 | { 71 | /* Private key - α */ 72 | element_init_Zr(key->priv, pairing); 73 | element_random(key->priv); 74 | 75 | /* Public key - Apub = [g, h=g^α] */ 76 | element_init_G1(key->pub.g, pairing); 77 | element_random(key->pub.g); 78 | element_init_G1(key->pub.h, pairing); 79 | element_pow_zn(key->pub.h, key->pub.g, key->priv); 80 | } 81 | 82 | void PEKS(peks *peks, key_pub *pub, pairing_t pairing, 83 | element_t H1_W, int bitswanted) 84 | { 85 | char *H2_t = peks->B; 86 | element_t r, hR, t; 87 | 88 | /* hR = h^r */ 89 | element_init_Zr(r ,pairing); 90 | element_random(r); 91 | element_init_G1(hR, pairing); 92 | element_pow_zn(hR, pub->h, r); 93 | 94 | /* t = hasedW1 X hR */ 95 | element_init_GT(t, pairing); 96 | pairing_apply(t, H1_W, hR, pairing); 97 | 98 | /* gR = g^r */ 99 | element_init_G1(peks->A, pairing); 100 | element_pow_zn(peks->A, pub->g, r); 101 | 102 | /* H2(t) */ 103 | char *char_t = malloc(sizeof(char)*element_length_in_bytes(t)); 104 | char *buffer = malloc(sizeof(char)*SHA512_DIGEST_LENGTH*2+1); 105 | element_snprint(char_t, element_length_in_bytes(t), t); 106 | sha512(char_t, element_length_in_bytes(t), buffer); 107 | get_n_bits(buffer, H2_t, bitswanted); 108 | 109 | free(char_t); char_t = NULL; 110 | free(buffer); buffer = NULL; 111 | } 112 | 113 | void Trapdoor(element_t Tw, pairing_t pairing, element_t alpha, 114 | element_t H1_W) 115 | { 116 | /* H1(W)^α = hashedW1^alpha */ 117 | element_init_G1(Tw, pairing); 118 | element_pow_zn(Tw, H1_W, alpha); 119 | } 120 | 121 | int Test(char *W2, int lenW2, key_pub *pub, element_t Tw, pairing_t pairing) 122 | { 123 | /* PEKS for W2S */ 124 | 125 | /* PEKS = [A, B] i.e. A=g^r and B=H2(t) */ 126 | peks peks; 127 | 128 | element_t H1_W2; 129 | element_t temp; 130 | 131 | double P = mpz_get_d(pairing->r); 132 | #if defined(DEBUG) 133 | printf("P %lf\n", P); 134 | #endif 135 | int nlogP = log2(P); 136 | #if defined(DEBUG) 137 | printf("log2(P) %d\n", nlogP); 138 | #endif 139 | /* H1(W2S) */ 140 | char *hashedW2 = malloc(sizeof(char)*SHA512_DIGEST_LENGTH*2+1); 141 | sha512(W2, lenW2, hashedW2); 142 | element_init_G1(H1_W2, pairing); 143 | element_from_hash(H1_W2, hashedW2, strlen(hashedW2)); 144 | #if defined(DEBUG) 145 | element_printf("H1_W2 %B\n", H1_W2); 146 | #endif 147 | 148 | /* PEKS(key_pub, W2) */ 149 | peks.B = malloc(sizeof(char)*(nlogP)); 150 | PEKS(&peks, pub, pairing, H1_W2, nlogP); 151 | #if defined(DEBUG) 152 | element_printf("A %B\n", peks.A); 153 | #endif 154 | element_init_GT(temp, pairing); 155 | pairing_apply(temp, Tw, peks.A, pairing); 156 | 157 | /* H2(temp) */ 158 | char *char_temp = malloc(sizeof(char)*element_length_in_bytes(temp)); 159 | char *hashed_temp = malloc(sizeof(char)*SHA512_DIGEST_LENGTH*2+1); 160 | element_snprint(char_temp, element_length_in_bytes(temp), temp); 161 | sha512(char_temp, element_length_in_bytes(temp), hashed_temp); 162 | char *H2_lhs = malloc(sizeof(char)*(nlogP)); 163 | get_n_bits(hashed_temp, H2_lhs, nlogP); 164 | 165 | /* Check for equality */ 166 | #if defined(DEBUG) 167 | int i; 168 | printf("lhs "); 169 | for(i = 0; i < nlogP; i++) 170 | printf("%c", H2_lhs[i]); 171 | printf("\nrhs "); 172 | for(i = 0; i < nlogP; i++) 173 | printf("%c", peks.B[i]); 174 | printf("\n"); 175 | #endif 176 | int match; 177 | if(!memcmp(H2_lhs, peks.B, nlogP)) 178 | match = 1; 179 | else 180 | match = 0; 181 | 182 | /* Free the memory */ 183 | free(H2_lhs); H2_lhs = NULL; 184 | free(peks.B); peks.B = NULL; 185 | free(char_temp); char_temp = NULL; 186 | free(hashed_temp); hashed_temp = NULL; 187 | free(hashedW2); hashedW2 = NULL; 188 | 189 | return match; 190 | } 191 | 192 | int peks_scheme(char* W1, char *W2) 193 | { 194 | /* Order of group G1 and G2 */ 195 | double P; 196 | 197 | /* Apriv = α and Apub = [g, h=g^α] */ 198 | key key; 199 | 200 | /* Trapdoor */ 201 | element_t Tw; 202 | 203 | /* H1(W) */ 204 | element_t H1_W1; 205 | 206 | /* PBC data types */ 207 | pbc_param_t param; 208 | pairing_t pairing; 209 | 210 | /* Initialize pairing */ 211 | init_pbc_param_pairing(param, pairing); 212 | 213 | /* Get the order of G1 */ 214 | P = mpz_get_d(pairing->r); 215 | #if defined(DEBUG) 216 | printf("P %lf\n", P); 217 | #endif 218 | //int nlogP = log2(P); 219 | 220 | /* KeyGen */ 221 | KeyGen(&key, param, pairing); 222 | #if defined(DEBUG) 223 | element_printf("α %e\n", key.priv); 224 | #endif 225 | 226 | /* H1(W) */ 227 | char *hashedW = malloc(sizeof(char)*SHA512_DIGEST_LENGTH*2+1); 228 | sha512(W1, (int)strlen(W1), hashedW); 229 | element_init_G1(H1_W1, pairing); 230 | element_from_hash(H1_W1, hashedW, (int)strlen(hashedW)); 231 | #if defined(DEBUG) 232 | element_printf("H1_W1 %B\n", H1_W1); 233 | #endif 234 | 235 | /* Trapdoor */ 236 | Trapdoor(Tw, pairing, key.priv, H1_W1); 237 | 238 | int match; 239 | match = Test(W2, (int)strlen(W2), &key.pub, Tw, pairing); 240 | 241 | free(hashedW); hashedW = NULL; 242 | //free(peks.B); peks.B = NULL; 243 | pbc_param_clear(param); 244 | 245 | return match; 246 | } 247 | -------------------------------------------------------------------------------- /peks.h: -------------------------------------------------------------------------------- 1 | /* 2 | * peks.h 3 | * 4 | * Created on: Jul 7, 2015 5 | * Author: mahind 6 | */ 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | //#define DEBUG 1 19 | 20 | /* Apriv = α and Apub = [g, h=g^α] */ 21 | typedef struct key_pub_s { 22 | element_t g; 23 | element_t h; 24 | }key_pub; 25 | typedef struct key_s { 26 | element_t priv; 27 | key_pub pub; 28 | }key; 29 | 30 | /* PEKS = [A, B] i.e. A=g^r and B=H2(t) */ 31 | typedef struct peks_s { 32 | element_t A; 33 | char* B; 34 | }peks; 35 | 36 | void sha512(const char *word, int word_size, 37 | char hashed_word[SHA512_DIGEST_LENGTH*2+1]); 38 | 39 | void get_n_bits(char* src, char* out, int bitswanted); 40 | 41 | void key_printf(key key); 42 | 43 | void peks_printf(peks peks); 44 | 45 | void init_pbc_param_pairing(pbc_param_t param, pairing_t pairing); 46 | 47 | void KeyGen(key *key, pbc_param_t param, pairing_t pairing); 48 | 49 | void PEKS(peks *peks, key_pub *pub, pairing_t pairing, 50 | element_t H1_W, int bitswanted); 51 | 52 | void Trapdoor(element_t Tw, pairing_t pairing, element_t alpha, 53 | element_t H1_W); 54 | 55 | int Test(char *W2S, int lenW2S, key_pub *pub, element_t Tw, pairing_t pairing); 56 | 57 | int peks_scheme(char* W1, char *W2); 58 | 59 | --------------------------------------------------------------------------------