-
Notifications
You must be signed in to change notification settings - Fork 0
Decryption
Vedad Kirlić edited this page Dec 30, 2021
·
9 revisions
In order to decrypt user file, we will need the private key associated to your contract. This should have been given to you when your contract was first created.
Once you've received user data from the query endpoint, you would have received the file content in the encrypted binary form.
In order to decrypt the data:
- It is recommended that the content size is validated. This can be done by ensuring that the number of bytes >=
352and is divisible by16; - The encrypted
DSKis sourced from the first256bytes and is asymmetrically decrypted withdecryptRsa2048using the private key. The output will always be a 32 byte array; - The Data Initialisation Vector (DIV) is sourced from the next
16bytes; the encrypted Hash & Data is sourced from the remaining bytes and is symmetrically decrypted withdecryptAes256using theDIVandDSK. The output will always be a variable length byte array, the first64bytes of which is the Data Hash, and the remaining bytes is the actual data. - The data is hashed using
hashSha512, then the resulting64byte Hash is compared to the Data Hash. If they do not match, then the file has been tampered with or corrupted in transit or storage;
| Encrypted DSK | DIV | Encrypted Hash & Data |
|---|---|---|
| 256 bytes | 16 bytes | 80+ bytes |
Decryption excerpt adapted from JS SDK (nodejs/typescript):
const BYTES = {
DSK: [0, 256],
DIV: [256, 272],
HASH_DATA: [272],
HASH: [0, 64],
DATA: [64],
};
const isValidSize = (data: Buffer): boolean => {
const bytes = data.length;
return bytes >= 352 && bytes % 16 === 0;
};
const decryptData = (key: NodeRSA, file: Buffer): Buffer => {
// Verify file data is of correct length
if (!isValidSize(file)) {
throw new FileDecryptionError("File size not valid");
}
// Extract DSK and DIV
const encryptedDSK: Buffer = file.slice(...BYTES.DSK); // initial 256 bytes - DSK encrypted with consumer Private Key
const dsk: Buffer = key.decrypt(encryptedDSK); // Decrypt DSK with consumer Private Key
const div: Buffer = file.slice(...BYTES.DIV); // next 16 bytes (256 to 272) - DIV
// Extract concatenated hash and data
const encryptedHashAndData = file.slice(...BYTES.HASH_DATA); // remaining bytes - 272 til the end
// Decrypt concatenated hash and data with DSK, DIV
const decipher = crypto.createDecipheriv("aes-256-cbc", dsk, div);
const hashAndData = Buffer.concat([decipher.update(encryptedHashAndData), decipher.final()]); // decrypt
// Extract hash and data
const hash: Buffer = hashAndData.slice(...BYTES.HASH); // initial 64 bytes
const data: Buffer = hashAndData.slice(...BYTES.DATA); // remaining bytes
// Hash plain data and compare with extracted hash to validate
const dataHash: Buffer = crypto.createHash("sha512").update(data).digest();
if (!dataHash.equals(hash)) {
throw new FileDecryptionError("Hash is not valid");
}
return data;
};