Queries on Encrypted Data Library

Here is an example that goes through all the steps of the algorithm.

First we must include the appropriate header files

#include <stdio.h>
#include <stdlib.h>
#include "qed.h"

Here, we define a function to print error codes. NOTE: This function is not provided in our library. Users can copy this one or make their own depending on how they choose to handle errors.
#define PRINT_ERR(error, funct, label)                  \
  if( (error) ) {                                       \
    printf("%s: %s", funct, qed_return_error(error));   \
    goto label;                                         \
  }

Then we start our main program, by declaring and initializing the context.
int main() {
  /*Declarations*/
  QED_CTX c;

  /* Initialize the Context */
  int error = QED_Init(&c, TYPE1);
  PRINT_ERR(error, "QED_Init", exit);

Then we format an HVE_t, by first initailizing an HVE_FORMAT_t array, and then calling HVE_Format. We use this formatted HVE_t to run QED_Setup, generating Public and Private Keys.

In this example, we use a conjunctive query of size 3: one comparison query, one subset query, and one equality query. The HVE_t is formatted so that its first sector is COMPARISON, its second sector is SUBSET, and its last subset is EQUALITY. Subset is given a Bloomfilter Security value of EPS_PT1.* QED_Setup is run with security parameter STANDARD.*

  /*Declarations*/
  HVE_t HVE_tok;
  QEDPrivateKey_t PrivKey;
  QEDPublicKey_t PubKey;

  /* Format HVE */
  HVE_FORMAT_t format[4] = {
        {COMPARISON, 1},
        {SUBSET, EPS_PT1, 2},
        {EQUALITY},
        {END, END, END}                         };
  
  error = HVE_Format(&HVE_tok, format, 4);
  PRINT_ERR(error, "HVE_Format", exit);

  /* Run Setup */
  error = QED_Setup(&PrivKey, &PubKey, &HVE_tok, STANDARD, &c);
  PRINT_ERR(error, "QED_Setup", exit);

We populate the HVE_t and run GenToken.

In this example, the Comparison compares against the value 30000. The equality checks for the word foo. The subset query checks for its two elements, foo and bar

  /*Declarations*/
  QEDToken_t Token;

  /*Populate HVE for GenToken with raw data*/  
  error = HVE_Init(&HVE_tok);
  PRINT_ERR(error, "HVE_Init", exit);

  HVE_COMPARISON_t comp = {30000, 0};
  error = HVE_Insert_Comparison(&HVE_tok, comp);
  PRINT_ERR(error, "HVE_Insert_Comparison", exit);
  
  HVE_SUBSET_DATA_t data[3] = { {"foo",3}, {"bar",3}, {NULL,0} };
  HVE_SUBSET_t sub = { data, 3, 1 }; 
  error = HVE_Insert_Subset(&HVE_tok, sub);
  PRINT_ERR(error, "HVE_Insert_Subset", exit);
  
  HVE_EQUALITY_t eq  = {"foo", 3, 2};
  error = HVE_Insert_Equality(&HVE_tok, eq);
  PRINT_ERR(error, "HVE_Insert_Equality", exit);
        
  /* Run GenToken */
  error = QED_GenToken(&Token, &PrivKey, &HVE_tok, &c);
  PRINT_ERR(error, "QED_GenToken", exit);  

To encrypt, we format the HVE_t for encryption with QED_Encrypt_Layout, we populate the HVE_t as we did above, and then run QED_Encrypt.

  /*Declarations*/
  HVE_t HVE_enc;
  QEDEncryption_t C;
  QEDMessageKey_t M_encrypt;

  /* Format HVE for Encrypt */
  error = HVE_Encrypt_Layout(&HVE_enc, &PubKey);
  PRINT_ERR(error, "HVE_Encrypt_Layout", exit);

  /*Populate HVE for Encrypt with raw data*/  
  error = HVE_Init(&HVE_enc);
  PRINT_ERR(error, "HVE_Init", exit);
  
  HVE_COMPARISON_t comp_enc = {40000, 0};
  error = HVE_Insert_Comparison(&HVE_enc, comp_enc);   
  PRINT_ERR(error, "HVE_Insert_Comparison", exit);
  
  HVE_EQUALITY_t eq_enc  = {"foo", 3, 2};
  error = HVE_Insert_Equality(&HVE_enc, eq_enc);
  PRINT_ERR(error, "HVE_Insert_Equality", exit);

  HVE_SUBSET_t sub_enc = { data_enc, 2, 1 };
  error = HVE_Insert_Subset(&HVE_enc, sub_enc);
  PRINT_ERR(error, "HVE_Insert_Subset", exit);
  
  
  /* Run Encryption */
  error = QED_Encrypt(&C, &M_encrypt, &PubKey, &HVE_enc, &c);
  PRINT_ERR(error, "QED_Encrypt", exit);

Now we run QED_Query, which returns a QEDMessageKey_t. We have now completed all the functions, so we return.

If the return code of QED_Query is negative, the answer to the query is "NO" and the message key is null.

If the return code of QED_Query is zero, the answer to the query is "YES" and the message key can be used to generate a symmetric key.*

If the return code is greater that zero, we call PRINT_ERR.

  /*Declarations*/
  QEDMessageKey_t M_query;

  /* Run Query */
  printf("QED_Query\n");
  error = QED_Query(&M_query, &Token, &C, &c);

  if(error ==0){
      printf("YES");
  
  }else if(error < 0)
  {
      printf("NO");  
  }else if(error > 0) { 
      PRINT_ERR(error, "QED_Query", exit);
  }
 
exit:
  return 0;
}

*For more information on security parameters EPS_PT1, EPS_PT01, EPS_PT001, Bloomfilters, the security parameters for QED_Setup, and the message key, please see QED Internals.