@ginger.io/jay-z
Advanced tools
Comparing version 0.0.5 to 0.0.6
{ | ||
"prettier.semi": false, | ||
"editor.formatOnSave": true | ||
} | ||
"prettier.semi": false, | ||
"prettier.trailingComma": "none", | ||
"editor.formatOnSave": true | ||
} |
import { DecryptParams, DecryptResult, Encryptor, EncryptParams, EncryptResult } from "./Encryptor"; | ||
import { EncryptionScheme } from "./types"; | ||
/** JSON.parse returns this object, which isn't a node Buffer */ | ||
export declare type JSONBuffer = { | ||
data: Array<number>; | ||
type: "Buffer"; | ||
}; | ||
export declare class LibsodiumEncryptor implements Encryptor { | ||
@@ -8,3 +13,5 @@ readonly scheme = EncryptionScheme.V0_LIBSODIUM; | ||
private deriveKey; | ||
private toBufferFromJSON; | ||
private isJSONBuffer; | ||
private toBuffer; | ||
} |
@@ -29,4 +29,4 @@ "use strict"; | ||
const encryptedFields = {}; | ||
fieldsToEncrypt.forEach(name => { | ||
encryptedFields[name] = libsodium_wrappers_1.crypto_secretbox_easy(this.toBuffer(item[name]), nonce, encryptionKey); | ||
fieldsToEncrypt.forEach((fieldName) => { | ||
encryptedFields[fieldName] = libsodium_wrappers_1.crypto_secretbox_easy(this.toBuffer(item[fieldName]), nonce, encryptionKey); | ||
}); | ||
@@ -44,6 +44,16 @@ libsodium_wrappers_1.memzero(encryptionKey); | ||
const decryptedItem = Object.assign({}, encryptedItem); | ||
fieldsToDecrypt.forEach(name => { | ||
const cipherText = encryptedItem[name]; | ||
fieldsToDecrypt.forEach((fieldName) => { | ||
const cipherText = encryptedItem[fieldName]; | ||
const json = libsodium_wrappers_1.crypto_secretbox_open_easy(cipherText, nonce, decryptionKey); | ||
decryptedItem[name] = JSON.parse(libsodium_wrappers_1.to_string(json)); | ||
const fieldValue = JSON.parse(libsodium_wrappers_1.to_string(json)); | ||
// If you JSON.parse an object with a binary field that was stringified, | ||
// you don't get a Buffer/Uint8Array back but rather a JSON representation of it | ||
// So we special case here to convert JSON representations of buffers back to the expected type. | ||
if (this.isJSONBuffer(fieldValue)) { | ||
const buffer = this.toBufferFromJSON(fieldValue); | ||
decryptedItem[fieldName] = buffer; | ||
} | ||
else { | ||
decryptedItem[fieldName] = fieldValue; | ||
} | ||
}); | ||
@@ -59,2 +69,8 @@ libsodium_wrappers_1.memzero(decryptionKey); | ||
} | ||
toBufferFromJSON(jsonBuffer) { | ||
return Buffer.from(jsonBuffer); | ||
} | ||
isJSONBuffer(obj) { | ||
return (obj !== undefined && obj.data instanceof Array && obj.type === "Buffer"); | ||
} | ||
toBuffer(value) { | ||
@@ -61,0 +77,0 @@ const json = fast_json_stable_stringify_1.default(value); |
{ | ||
"name": "@ginger.io/jay-z", | ||
"version": "0.0.5", | ||
"version": "0.0.6", | ||
"description": "Youve got 99 problems, but application-layer encryption aint one", | ||
@@ -5,0 +5,0 @@ "main": "dist/index.js", |
@@ -23,2 +23,8 @@ import stringify from "fast-json-stable-stringify" | ||
/** JSON.parse returns this object, which isn't a node Buffer */ | ||
export type JSONBuffer = { | ||
data: Array<number> | ||
type: "Buffer" | ||
} | ||
export class LibsodiumEncryptor implements Encryptor { | ||
@@ -38,5 +44,5 @@ public readonly scheme = EncryptionScheme.V0_LIBSODIUM | ||
fieldsToEncrypt.forEach(name => { | ||
encryptedFields[name] = crypto_secretbox_easy( | ||
this.toBuffer(item[name]), | ||
fieldsToEncrypt.forEach((fieldName) => { | ||
encryptedFields[fieldName] = crypto_secretbox_easy( | ||
this.toBuffer(item[fieldName]), | ||
nonce, | ||
@@ -65,6 +71,16 @@ encryptionKey | ||
fieldsToDecrypt.forEach(name => { | ||
const cipherText = encryptedItem[name] | ||
fieldsToDecrypt.forEach((fieldName) => { | ||
const cipherText = encryptedItem[fieldName] | ||
const json = crypto_secretbox_open_easy(cipherText, nonce, decryptionKey) | ||
decryptedItem[name] = JSON.parse(to_string(json)) | ||
const fieldValue = JSON.parse(to_string(json)) | ||
// If you JSON.parse an object with a binary field that was stringified, | ||
// you don't get a Buffer/Uint8Array back but rather a JSON representation of it | ||
// So we special case here to convert JSON representations of buffers back to the expected type. | ||
if (this.isJSONBuffer(fieldValue)) { | ||
const buffer = (this.toBufferFromJSON(fieldValue) as unknown) as T[K] | ||
decryptedItem[fieldName] = buffer | ||
} else { | ||
decryptedItem[fieldName] = fieldValue | ||
} | ||
}) | ||
@@ -88,2 +104,12 @@ | ||
private toBufferFromJSON(jsonBuffer: JSONBuffer): Uint8Array { | ||
return Buffer.from(jsonBuffer) | ||
} | ||
private isJSONBuffer(obj: any): obj is JSONBuffer { | ||
return ( | ||
obj !== undefined && obj.data instanceof Array && obj.type === "Buffer" | ||
) | ||
} | ||
private toBuffer<T extends {}>(value: T): Uint8Array { | ||
@@ -90,0 +116,0 @@ const json = stringify(value) |
@@ -43,3 +43,3 @@ import stringify from "fast-json-stable-stringify" | ||
fieldsToEncrypt.forEach(fieldName => { | ||
fieldsToEncrypt.forEach((fieldName) => { | ||
const expectedValue = crypto_secretbox_easy( | ||
@@ -74,2 +74,27 @@ from_string(stringify(account[fieldName])), | ||
}) | ||
it("should encrypt and decrypt binary fields", async () => { | ||
const dataKeyProvider = await StubDataKeyProvider.forLibsodium() | ||
const { dataKey } = await dataKeyProvider.generateDataKey() | ||
const binaryItem = { | ||
name: "hello world", | ||
binaryData: Buffer.from("hello world", "utf-8") | ||
} | ||
const { encryptedItem, nonce } = await encryptor.encrypt({ | ||
item: binaryItem, | ||
fieldsToEncrypt: ["name", "binaryData"], | ||
dataKey | ||
}) | ||
const { decryptedItem } = await encryptor.decrypt({ | ||
encryptedItem, | ||
nonce, | ||
dataKey, | ||
fieldsToDecrypt: ["name", "binaryData"] | ||
}) | ||
expect(decryptedItem).toEqual(binaryItem) | ||
}) | ||
}) |
Sorry, the diff of this file is not supported yet
113360
899
42