diff --git a/src/keystore.ts b/src/keystore.ts index 3bb113e..57e6780 100644 --- a/src/keystore.ts +++ b/src/keystore.ts @@ -123,7 +123,7 @@ export class KeyStore { authTagLength, } = finalOptions - const keys = key ? [ key ] : defaultKeys + const keys = key ? [key] : defaultKeys if (keys.length === 0) { throw new Error("keys required for encrypted cookies") } @@ -148,10 +148,12 @@ export class KeyStore { authTag = Buffer.from(authTag, encoding) } - if (!iv) { - iv = dataBuff.slice(0, cipherInfo.ivLength) + if (cipherInfo.ivLength !== undefined) { + if (!iv) { + iv = dataBuff.slice(0, cipherInfo.ivLength) + } + dataBuff = dataBuff.slice(cipherInfo.ivLength, dataBuff.length) } - dataBuff = dataBuff.slice(cipherInfo.ivLength, dataBuff.length) if (AUTH_TAG_REQUIRED.test(algorithm)) { @@ -170,20 +172,21 @@ export class KeyStore { private static doDecrypt(data: Buffer, options: DecryptOptions): string | null { const {algorithm, key, iv, authTagLength, authTag} = options - const decipher = crypto.createDecipheriv(algorithm as any, key!, iv as Buffer, {authTagLength}); + const decipher = crypto.createDecipheriv(algorithm as any, key!, iv as Buffer || null, {authTagLength}); if (authTag) { decipher.setAuthTag(authTag as Buffer) } const plainText = decipher.update(data) + let final: Buffer try { - decipher.final() - } catch { + final = decipher.final() + } catch(e:any) { // authentication failed return null } - return plainText.toString('utf-8') + return Buffer.concat([plainText, final]).toString('utf-8') } //region: signing diff --git a/tests/keystore.spec.ts b/tests/keystore.spec.ts index 90ea5f7..a26289a 100644 --- a/tests/keystore.spec.ts +++ b/tests/keystore.spec.ts @@ -247,6 +247,20 @@ describe("encryption", () => { expect(decrypted).toBe(null) }); + + it("should allow using different secret key", () => { + const ks = new KeyStore({ + encryption: { + keys: ["secretsecretsecretsecret"], + algorithm: "aes-192-cbc", + encoding: "hex" + } + }) + jest.spyOn(crypto, 'randomBytes').mockImplementationOnce(() => Buffer.from("1234123412341234", "utf-8")) + const encrypted = ks.encrypt("ohmytext", {key: "necretnecretnecretnecret"}) + expect(ks.decrypt(encrypted, { key: "necretnecretnecretnecret" })).toBe("ohmytext") + }) + it("should fail if no key exists to decrypt with", () => { const ks = new KeyStore({ encryption: {keys: [genRandom(24)]} @@ -257,6 +271,19 @@ describe("encryption", () => { }).toThrow(Error) }) + + it("should work w/ algorithms without iv", () => { + const ks = new KeyStore({ + encryption: { + keys: ["32secretsecretsecretsecretsecret"], + algorithm: "aes-256-ecb", + encoding: "base64" + } + }) + const encrypted = ks.encrypt("ohmytext") + expect(ks.decrypt(encrypted)).toBe("ohmytext") + }) + it("should accept iv buffer", () => { const ks = new KeyStore({ encryption: {