All files / src/crypter/modeOfOperation CTRMode.ts

100% Statements 5/5
100% Branches 0/0
100% Functions 0/0
100% Lines 5/5

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 761x   1x   1x   12x   12x                                                                                                                                      
import randomBytes from 'randombytes';
import type { IDecryptionModeOfOperation, IEncryptionModeOfOperation, IModeOfOperation } from './IModeOfOperation';
import { xor } from '../../utils/xor';
 
export class CTRMode implements IModeOfOperation {
 
    public readonly encryption = new CTRMode.CTREncryptionMode();
 
    public readonly decryption = new CTRMode.CTRDecryptionMode();
}
 
// istanbul ignore next
export namespace CTRMode {
 
    export function incrementCounter(counter: Uint8Array): void {
        for (let i = 15; i >= 0; i--) {
            if (counter[i] !== 255) {
                counter[i] += 1;
                break;
            } else {
                counter[i] = 0;
                if (i === 0)
                    counter[15] = 0;
            }
        }
    }
 
    export class CTREncryptionMode implements IEncryptionModeOfOperation {
 
        private counter: Uint8Array | null = null;
 
        public start(): Uint8Array {
            this.counter = randomBytes(16);
            return new Uint8Array(this.counter);
        }
 
        public combine(block: Uint8Array, encrypt: (block: Uint8Array) => Uint8Array): Uint8Array {
            if (this.counter === null)
                throw new Error('CTR encryption mode not started.');
            incrementCounter(this.counter);
            return xor(this.counter, encrypt(block));
        }
 
        public finish(): Uint8Array {
            this.counter = null;
            return new Uint8Array();
        }
    }
 
    export class CTRDecryptionMode implements IDecryptionModeOfOperation {
 
        private counter: Uint8Array | null = null;
 
        public start(): Uint8Array {
            this.counter = null;
            return new Uint8Array();
        }
 
        public combine(block: Uint8Array, decrypt: (block: Uint8Array) => Uint8Array): Uint8Array {
            if (this.counter === null) {
                this.counter = new Uint8Array(block);
                return new Uint8Array();
            }
            incrementCounter(this.counter);
            const decrypted = decrypt(xor(this.counter, block));
            return decrypted;
        }
 
        public finish(): Uint8Array {
            this.counter = null;
            return new Uint8Array();
        }
    }
 
}