IQrypt works best with Document Oriented Databases like MongoDB or CouchDB, but it can be used and adapted also for other database management systems.

Encryption schemes

IQrypt provides 3 encryption schemes:

  • RND - randomized encryption (not searchable)
  • DET - deterministic encryption (allows EQUAL/NOT EQUAL queries, ex: WHERE field="encrypted_value")
  • OPE - order preserving encryption (allows Equality and Range queries, ex: WHERE field>"encrypted_value")

As encryption ciphers, developers can choose between AES-128, AES-256, Camellia-128 and Camellia-256.

Using combinations of these encryption schemes, IQrypt will allow you to store data highly secure and at the same time allow server to execute queries without decrypting the data.

Let's suppose you store a Patient record in a JSON document like this:


{
  "Key": "194f0fb0-7d1e-45c5-a71c-400342ccf422",
  "SSN": "003-62-5913",
  "FirstName": "John",
  "LastName": "Doe",
  "Gender": "Male",
  "Location": "2nd Floor, Building A",
  "Building": "A",
  "Floor": 2,
  "LastVisitDate": "2015-11-18T08:10:00",
  "AgendaHourMinute": "08:10",
  "Treatment": "Treatment: Lorem ipsum",
  "Status": "Stable",
  "Doctor": "Josh Pollock",
  "PatientDetailsData": {
    "Blood_Gas": {
      "pH": "7.32",
      "pCO2": "34",
      "HCO3": "26",
      "AG": "13",
      "p02": "78"
    },
    "BloodData": {
      "Hemoglobin": "45 gb/dll",
      "Hematocrit": "23%",
      "WBC": "12 ul",
      "Platelets": "34/mcl"
    },
    "General_Chemistry": {
      "Na": "56 mEq/L",
      "K": "23 mEq/L",
      "Glucose": "26 mg/dl",
      "Creatine": "13 mg/dl",
      "BUN": "78 mg/dl"
    },
    "UrinalysisData": {
      "Protien": "(-)",
      "Sugar": "(+)",
      "OccultBlood": "(-)"
    },
    "Progress_Notes": [
      {
        "Month": "Feb",
        "Date": "14",
        "Note": "Patient admitted complaining of abdominal pain.   Administered 20 ml of Trx.  Will plan to review condition in 6 hours.   Submitted request for blood work 2/15.  Dr Pollock will be..."
      },
      {
        "Month": "Feb",
        "Date": "15",
        "Note": "Current treatment plan appears to be progressing well.  Submitted dietary change request.   Have requested that patient remain on modified diet for 4 days.  Patient family..."
      },
    ],
    "Intake_Output": [
      {
        "Date": "2/11",
        "Intake": "750ml",
        "Output": "680ml"
      },
      {
        "Date": "2/12",
        "Intake": "520ml",
        "Output": "540ml"
      },
      {
        "Date": "2/13",
        "Intake": "820ml",
        "Output": "760ml"
      },
      {
        "Date": "2/14",
        "Intake": "500ml",
        "Output": "520ml"
      }
    ],
    "Admission_Records": {
      "Doctor": "Dr. John ollock",
      "HealthcareProvider": "AETNA",
      "Address": "4122 SE 1st PL    Newcastle, WA 98056",
      "Phone": "123.456.7890",
      "DateAdmitted": "Feb. 10, 2015",
      "DateDischarged": "N/A"
    }
  },
  "Version": null,
  "IsVisited": false
}

The goal is that this entire JSON document will be encrypted with RND encryption scheme, but RND is not a searchable encryption scheme so we'll need to adjust the data model.

At the client side, before the JSON document is sent to the cloud database and before being encrypted, IQrypt extracts the keywords as {key,value} pairs that you will need to search by and those keywords( we will call further Tags) will be encrypted with different encryption schemes or even let them plain text if does not reveal sensitive information.

Supposing you want to search by Social Security Number (SSN), VisitDate and Building, so it means we should extract that info as Tags and our data model will look like this:

{
 "Key": "194f0fb0-7d1e-45c5-a71c-400342ccf422", 

 "DocContent":{
      "Key": "194f0fb0-7d1e-45c5-a71c-400342ccf422",
      "SSN": "003-62-5913",
      "FirstName": "John",
      "LastName": "Doe",
      "Gender": "Male",
      "Location": "2nd Floor, Building A",
      "Building": "A",
      "Floor": 2,
      "LastVisitDate": "2015-11-18T08:10:00",
      "AgendaHourMinute": "08:10",
      "Treatment": "Treatment: Lorem ipsum",
      "Status": "Stable",
      "Doctor": "Josh Pollock",
      "PatientDetailsData": {
        "Blood_Gas": {
          "pH": "7.32",
          "pCO2": "34",
          "HCO3": "26",
          "AG": "13",
          "p02": "78"
        },
        "BloodData": {
          "Hemoglobin": "45 gb/dll",
          "Hematocrit": "23%",
          "WBC": "12 ul",
          "Platelets": "34/mcl"
        },
        "General_Chemistry": {
          "Na": "56 mEq/L",
          "K": "23 mEq/L",
          "Glucose": "26 mg/dl",
          "Creatine": "13 mg/dl",
          "BUN": "78 mg/dl"
        },
        "UrinalysisData": {
          "Protien": "(-)",
          "Sugar": "(+)",
          "OccultBlood": "(-)"
        },
        "Progress_Notes": [
          {
            "Month": "Feb",
            "Date": "14",
            "Note": "Patient admitted complaining of abdominal pain.   Administered 20 ml of Trx.  Will plan to review condition in 6 hours.   Submitted request for blood work 2/15.  Dr Pollock will be..."
          },
          {
            "Month": "Feb",
            "Date": "15",
            "Note": "Current treatment plan appears to be progressing well.  Submitted dietary change request.   Have requested that patient remain on modified diet for 4 days.  Patient family..."
          },
        ],
        "Intake_Output": [
          {
            "Date": "2/11",
            "Intake": "750ml",
            "Output": "680ml"
          },
          {
            "Date": "2/12",
            "Intake": "520ml",
            "Output": "540ml"
          },
          {
            "Date": "2/13",
            "Intake": "820ml",
            "Output": "760ml"
          },
          {
            "Date": "2/14",
            "Intake": "500ml",
            "Output": "520ml"
          }
        ],
        "Admission_Records": {
          "Doctor": "Dr. John ollock",
          "HealthcareProvider": "AETNA",
          "Address": "4122 SE 1st PL    Newcastle, WA 98056",
          "Phone": "123.456.7890",
          "DateAdmitted": "Feb. 10, 2015",
          "DateDischarged": "N/A"
        }
      },
      "Version": null,
      "IsVisited": false
    },

   "SSN":"003-62-5913",
   "LastVisitDate":"2015-11-18T08:10:00", 
   "Building": "A" 
}

The JSON doc now has 3 main properties:

  • Key which is unique identifier within document Collection/Bucket
  • DocContent which is the initial JSON document
  • Tags: ('SSN', 'LastVisitDate' and 'Building')

Now, in fact, the data within Tags is stored redundantly (but this should not be a big overhead). Usually by SSN we will need to make Equality queries, so we will encrypt it with DET encryption scheme.For VisitDate, we would need to make range queries so we'll encrypt with OPE scheme and for Building, we'll let it plain text because it might not be considered sensitive information.

So to summarize, this is how IQrypt encrypts the record:

  • JSON Document: RND scheme
  • 'SSN' tag: DET scheme
  • 'VisitDate' tag: OPE scheme
  • 'Building' tag: Plain text

To run queries, IQrypt will encrypt the query field value , at the client side, and then sent the encrypted value to server to compare against its records.

Example of MongoDB query without IQrypt:

db.patients.find( { SSN: "003-62-5913"} )

And now using IQrypt:

db.patients.find( { SSN: "ljqEksrWV93kbQWedSNDlw9DEMFUIvZzz5uNRNwZONQ="} )

Now, MongoDB will return the record for SSN="003-62-5913" without knowing its value.

IQrypt also allows you to encrypt Tag names, so the server has no information of what might store that Tag, example of such a query would be:

db.patients.find( { "A234BCF434DDAD67": "ljqEksrWV93kbQWedSNDlw9DEMFUIvZzz5uNRNwZONQ="} )

where "A234BCF434DDAD67" is the encrypted value for "SSN".

Now let's make a range query for LastVisitDate(without IQrypt):

db.patients.find( { $and: [ { LastVisitDate: { $gt: "2015-11-15T08:10:00" } }, { LastVisitDate: { $lt: "2015-12-31T08:10:00"  } } ] } )

And now using IQrypt:

db.patients.find( { $and: [ { LastVisitDate: { $gt: "@@@2102291610482 @@@2101986497510" } }, { LastVisitDate: { $lt: "@@@2102291611547 @@@2101994746036"  } } ] } )

Now, MongoDB will return all records/documents that has LastVisitDate between 2015-11-15 and 2015-12-31 without knowing its values.

For more info about queries, take a look on our specific programming language SDK.