mode-ofb.ts 1.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051
  1. // Output Feedback
  2. import { ModeOfOperation } from "./mode.js";
  3. export class OFB extends ModeOfOperation {
  4. #iv: Uint8Array;
  5. #lastPrecipher: Uint8Array;
  6. #lastPrecipherIndex: number;
  7. constructor(key: Uint8Array, iv?: Uint8Array) {
  8. super("OFB", key, OFB);
  9. if (iv) {
  10. if (iv.length % 16) {
  11. throw new TypeError("invalid iv size (must be 16 bytes)");
  12. }
  13. this.#iv = new Uint8Array(iv);
  14. } else {
  15. this.#iv = new Uint8Array(16);
  16. }
  17. this.#lastPrecipher = this.iv;
  18. this.#lastPrecipherIndex = 16;
  19. }
  20. get iv(): Uint8Array { return new Uint8Array(this.#iv); }
  21. encrypt(plaintext: Uint8Array): Uint8Array {
  22. if (plaintext.length % 16) {
  23. throw new TypeError("invalid plaintext size (must be multiple of 16 bytes)");
  24. }
  25. const ciphertext = new Uint8Array(plaintext);
  26. for (let i = 0; i < ciphertext.length; i++) {
  27. if (this.#lastPrecipherIndex === 16) {
  28. this.#lastPrecipher = this.aes.encrypt(this.#lastPrecipher);
  29. this.#lastPrecipherIndex = 0;
  30. }
  31. ciphertext[i] ^= this.#lastPrecipher[this.#lastPrecipherIndex++];
  32. }
  33. return ciphertext;
  34. }
  35. decrypt(ciphertext: Uint8Array): Uint8Array {
  36. if (ciphertext.length % 16) {
  37. throw new TypeError("invalid ciphertext size (must be multiple of 16 bytes)");
  38. }
  39. return this.encrypt(ciphertext);
  40. }
  41. }