// Copyright (C) 2016 Dmitry Chestnykh // MIT License. See LICENSE file for details. import { describe, expect, it } from 'vitest'; import { XChaCha20Poly1305 } from "./xchacha20poly1305.js"; import { encode, decode } from "@stablelib/hex"; const testVectors = [ /** * Test vector from draft-irtf-cfrg-xchacha * see https://tools.ietf.org/html/draft-irtf-cfrg-xchacha-01#appendix-A.3.1 * tag value is appended to the result (aka ciphertext) */ { key: "808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9F", nonce: "404142434445464748494a4b4c4d4e4f5051525354555657", aad: "50515253C0C1C2C3C4C5C6C7", plaintext: "4C616469657320616E642047656E746C656D656E206F662074686520636C617373206F66" + "202739393A204966204920636F756C64206F6666657220796F75206F6E6C79206F6E6520" + "74697020666F7220746865206675747572652C2073756E73637265656E20776F756C6420" + "62652069742E", result: "BD6D179D3E83D43B9576579493C0E939" + "572A1700252BFACCBED2902C21396CBB" + "731C7F1B0B4AA6440BF3A82F4EDA7E39" + "AE64C6708C54C216CB96B72E1213B452" + "2F8C9BA40DB5D945B11B69B982C1BB9E" + "3F3FAC2BC369488F76B2383565D3FFF9" + "21F9664C97637DA9768812F615C68B13" + "B52EC0875924C1C7987947DEAFD8780A" + "CF49", } ]; // TODO(dchest): add more various tests. describe("XChaCha20Poly1305", () => { it("should correctly seal", () => { testVectors.forEach(v => { const aead = new XChaCha20Poly1305(decode(v.key)); const sealed = aead.seal(decode(v.nonce), decode(v.plaintext), v.aad ? decode(v.aad) : undefined); expect(encode(sealed)).toBe(v.result); }); }); it("should correctly open", () => { testVectors.forEach(v => { const aead = new XChaCha20Poly1305(decode(v.key)); const plaintext = aead.open(decode(v.nonce), decode(v.result), v.aad ? decode(v.aad) : undefined); expect(plaintext).not.toBeNull(); if (plaintext) { expect(encode(plaintext)).toBe(v.plaintext); } }); }); it("should not open when ciphertext is corrupted", () => { const v = testVectors[0]; const sealed = decode(v.result); sealed[0] ^= sealed[0]; const aead = new XChaCha20Poly1305(decode(v.key)); const plaintext = aead.open(decode(v.nonce), sealed, v.aad ? decode(v.aad) : undefined); expect(plaintext).toBeNull(); }); it("should not open when tag is corrupted", () => { const v = testVectors[0]; const sealed = decode(v.result); sealed[sealed.length - 1] ^= sealed[sealed.length - 1]; const aead = new XChaCha20Poly1305(decode(v.key)); const plaintext = aead.open(decode(v.nonce), sealed, v.aad ? decode(v.aad) : undefined); expect(plaintext).toBeNull(); }); it("should seal to dst it is provided", () => { const v = testVectors[0]; const aead = new XChaCha20Poly1305(decode(v.key)); const plaintext = decode(v.plaintext); const ad = v.aad ? decode(v.aad) : undefined; const dst = new Uint8Array(plaintext.length + aead.tagLength); const sealed = aead.seal(decode(v.nonce), decode(v.plaintext), ad, dst); expect(encode(dst)).toBe(encode(sealed)); expect(encode(sealed)).toBe(v.result); }); it("should throw if seal got dst of wrong length", () => { const v = testVectors[0]; const aead = new XChaCha20Poly1305(decode(v.key)); const plaintext = decode(v.plaintext); const ad = v.aad ? decode(v.aad) : undefined; const dst = new Uint8Array(plaintext.length + aead.tagLength - 1); // wrong length expect(() => aead.seal(decode(v.nonce), decode(v.plaintext), ad, dst)).toThrowError(/length/); }); it("should open to dst it is provided", () => { const v = testVectors[0]; const aead = new XChaCha20Poly1305(decode(v.key)); const sealed = decode(v.result); const ad = v.aad ? decode(v.aad) : undefined; const dst = new Uint8Array(sealed.length - aead.tagLength); const plaintext = aead.open(decode(v.nonce), decode(v.result), ad, dst); expect(plaintext).not.toBeNull(); if (plaintext) { expect(encode(dst)).toBe(encode(plaintext)); expect(encode(plaintext)).toBe(v.plaintext); } }); it("should throw if open got dst of wrong length", () => { const v = testVectors[0]; const aead = new XChaCha20Poly1305(decode(v.key)); const sealed = decode(v.result); const ad = v.aad ? decode(v.aad) : undefined; const dst = new Uint8Array(sealed.length - aead.tagLength + 1); // wrong length expect(() => aead.open(decode(v.nonce), decode(v.result), ad, dst)).toThrowError(/length/); }); }); //# sourceMappingURL=xchacha20poly1305.test.js.map