From 3e36ec0984d46cd76313fa01ff7dd30e67bbd59c Mon Sep 17 00:00:00 2001 From: Eugen Wissner Date: Wed, 25 Jan 2017 07:24:19 +0100 Subject: [PATCH] Add support for dmd 2.070.2 --- .travis.yml | 1 + README.md | 25 +- source/tanya/crypto/bit.d | 510 --------------------------- source/tanya/crypto/des.d | 607 -------------------------------- source/tanya/crypto/mode.d | 279 --------------- source/tanya/crypto/package.d | 16 - source/tanya/crypto/symmetric.d | 177 ---------- 7 files changed, 12 insertions(+), 1603 deletions(-) delete mode 100644 source/tanya/crypto/bit.d delete mode 100644 source/tanya/crypto/des.d delete mode 100644 source/tanya/crypto/mode.d delete mode 100644 source/tanya/crypto/package.d delete mode 100644 source/tanya/crypto/symmetric.d diff --git a/.travis.yml b/.travis.yml index 07da794..d2c2f90 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,6 +10,7 @@ d: - dmd-2.073.0 - dmd-2.072.2 - dmd-2.071.2 + - dmd-2.070.2 env: matrix: diff --git a/README.md b/README.md index 9863a71..9ace08b 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ Tanya consists of the following packages: * `async`: Event loop (epoll, kqueue and IOCP). * `container`: Queue, Vector, Singly linked list, buffers. -* `math`: Multiple precision integer and a set of functions. +* `math`: Arbitrary precision integer and a set of functions. * `memory`: Tools for manual memory management (allocator, reference counting, helper functions). * `network`: URL-Parsing, sockets. @@ -29,24 +29,21 @@ helper functions). * dmd 2.073.0 * dmd 2.072.2 * dmd 2.071.2 +* dmd 2.070.2 ### Current status -The library is currently under development, but some parts of it can already be -used. +The library is currently under development, but the API is becoming gradually +stable. -`network` and `async` exist for quite some time and are better tested than -other components. +`container`s are being extended to support ranges. Also following modules are +coming soon: +* UTF-8 string. +* Hash table. -`container`s were newly reworked and the API won't change significantly, but -will be only extended. The same is true for the `memory` package. - -`math` package contains an arbitrary precision integer implementation that has -a stable API (that mostly consists of operator overloads), but still needs -testing and work on its performance. - -I'm currently mostly working on `crypto` that is not a complete cryptographic -suite, but contains (will contain) algorithm implementations required by TLS. +`math` package contains an arbitrary precision integer implementation that +needs more test cases, better performance and some additional features +(constructing from a string and an ubyte array, and converting it back). ### Further characteristics diff --git a/source/tanya/crypto/bit.d b/source/tanya/crypto/bit.d deleted file mode 100644 index 8610577..0000000 --- a/source/tanya/crypto/bit.d +++ /dev/null @@ -1,510 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -/** - * Copyright: Eugene Wissner 2016. - * License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/, - * Mozilla Public License, v. 2.0). - * Authors: $(LINK2 mailto:belka@caraus.de, Eugene Wissner) - */ -module tanya.crypto.bit; - -/** - * Wrapper that allows bit manipulation on $(D_KEYWORD ubyte[]) array. - */ -struct BitVector -{ - protected ubyte[] vector; - - /** - * Params: - * array = Array should be manipulated on. - */ - this(inout(ubyte[]) array) inout pure nothrow @safe @nogc - in - { - assert(array.length <= size_t.max / 8); - assert(array !is null); - } - body - { - vector = array; - } - - /// - unittest - { - ubyte[5] array1 = [234, 3, 252, 10, 18]; - ubyte[3] array2 = [65, 13, 173]; - auto bits = BitVector(array1); - - assert(bits[] is array1); - assert(bits[] !is array2); - - bits = BitVector(array2); - assert(bits[] is array2); - - } - - /** - * Returns: Number of bits in the vector. - */ - @property inout(size_t) length() inout const pure nothrow @safe @nogc - { - return vector.length * 8; - } - - /// Ditto. - inout(size_t) opDollar() inout const pure nothrow @safe @nogc - { - return vector.length * 8; - } - - /// - unittest - { - // [01000001, 00001101, 10101101] - ubyte[3] arr = [65, 13, 173]; - auto bits = BitVector(arr); - - assert(bits.length == 24); - } - - /** - * Params: - * bit = Bit position. - * - * Returns: $(D_KEYWORD true) if the bit on position $(D_PARAM bit) is set, - * $(D_KEYWORD false) if not set. - */ - inout(bool) opIndex(size_t bit) inout const pure nothrow @safe @nogc - in - { - assert(bit / 8 <= vector.length); - } - body - { - return (vector[bit / 8] & (0x80 >> (bit % 8))) != 0; - } - - /// - unittest - { - // [01000001, 00001101, 10101101] - ubyte[3] arr = [65, 13, 173]; - auto bits = BitVector(arr); - - assert(!bits[0]); - assert(bits[1]); - assert(bits[7]); - assert(!bits[8]); - assert(!bits[11]); - assert(bits[12]); - assert(bits[20]); - assert(bits[23]); - } - - /** - * Returns: Underlying array. - */ - inout(ubyte[]) opIndex() inout pure nothrow @safe @nogc - { - return vector; - } - - /// - unittest - { - // [01000001, 00001101, 10101101] - ubyte[3] arr = [65, 13, 173]; - auto bits = BitVector(arr); - - assert(bits[] is arr); - } - - /** - * Params: - * value = $(D_KEYWORD true) if the bit should be set, - * $(D_KEYWORD false) if cleared. - * bit = Bit position. - * - * Returns: $(D_PSYMBOL this). - */ - bool opIndexAssign(bool value, size_t bit) pure nothrow @safe @nogc - in - { - assert(bit / 8 <= vector.length); - } - body - { - if (value) - { - vector[bit / 8] |= (0x80 >> (bit % 8)); - } - else - { - vector[bit / 8] &= ~(0x80 >> (bit % 8)); - } - return value; - } - - /// - unittest - { - // [01000001, 00001101, 10101101] - ubyte[3] arr = [65, 13, 173]; - auto bits = BitVector(arr); - - bits[5] = bits[6] = true; - assert(bits[][0] == 71); - - bits[14] = true; - bits[15] = false; - assert(bits[][1] == 14); - - bits[16] = bits[23] = false; - assert(bits[][2] == 44); - } - - /** - * Copies bits from $(D_PARAM vector) into this $(D_PSYMBOL BitVector). - * - * The array that should be assigned, can be smaller (but not larger) than - * the underlying array of this $(D_PSYMBOL BitVector), leading zeros will - * be added in this case to the left. - * - * Params: - * vector = $(D_KEYWORD ubyte[]) array not larger than - * `$(D_PSYMBOL length) / 8`. - * - * Returns: $(D_KEYWORD this). - */ - BitVector opAssign(ubyte[] vector) pure nothrow @safe @nogc - in - { - assert(vector.length <= this.vector.length); - } - body - { - immutable delta = this.vector.length - vector.length; - if (delta > 0) - { - this.vector[0..delta] = 0; - } - this.vector[delta..$] = vector[0..$]; - return this; - } - - /// - unittest - { - ubyte[5] array1 = [234, 3, 252, 10, 18]; - ubyte[3] array2 = [65, 13, 173]; - auto bits = BitVector(array1); - - bits = array2; - assert(bits[][0] == 0); - assert(bits[][1] == 0); - assert(bits[][2] == 65); - assert(bits[][3] == 13); - assert(bits[][4] == 173); - - bits = array2[0..2]; - assert(bits[][0] == 0); - assert(bits[][1] == 0); - assert(bits[][2] == 0); - assert(bits[][3] == 65); - assert(bits[][4] == 13); - } - - /** - * Support for bitwise operations. - * - * Params: - * that = Another bit vector. - * - * Returns: $(D_KEYWORD this). - */ - BitVector opOpAssign(string op)(BitVector that) pure nothrow @safe @nogc - if ((op == "^") || (op == "|") || (op == "&")) - { - return opOpAssign(op)(that.vector); - } - - /// Ditto. - BitVector opOpAssign(string op)(ubyte[] that) pure nothrow @safe @nogc - if ((op == "^") || (op == "|") || (op == "&")) - in - { - assert(that.length <= vector.length); - } - body - { - for (int i = cast(int) vector.length - 1; i >= 0; --i) - { - mixin("vector[i] " ~ op ~ "= " ~ "that[i];"); - } - immutable delta = vector.length - that.length; - if (delta) - { - static if (op == "&") - { - vector[0..delta] = 0; - } - } - return this; - } - - /// - unittest - { - // [01000001, 00001101, 10101101] - ubyte[3] array1 = [65, 13, 173]; - ubyte[3] array2 = [0b01010010, 0b10111110, 0b10111110]; - auto bits = BitVector(array1); - - bits |= array2; - assert(bits[][0] == 0b01010011); - assert(bits[][1] == 0b10111111); - assert(bits[][2] == 0b10111111); - - bits &= array2; - assert(bits[][0] == array2[0]); - assert(bits[][1] == array2[1]); - assert(bits[][2] == array2[2]); - - bits ^= array2; - assert(bits[][0] == 0); - assert(bits[][1] == 0); - assert(bits[][2] == 0); - } - - /** - * Support for shift operations. - * - * Params: - * n = Number of bits. - * - * Returns: $(D_KEYWORD this). - */ - BitVector opOpAssign(string op)(in size_t n) pure nothrow @safe @nogc - if ((op == "<<") || (op == ">>")) - - { - if (n >= length) - { - vector[0..$] = 0; - } - else if (n != 0) - { - immutable bit = n % 8, step = n / 8; - immutable delta = 8 - bit; - size_t i, j; - - static if (op == "<<") - { - for (j = step; j < vector.length - 1; ++i) - { - vector[i] = cast(ubyte)((vector[j] << bit) - | vector[++j] >> delta); - } - vector[i] = cast(ubyte)(vector[j] << bit); - vector[$ - step ..$] = 0; - } - else static if (op == ">>") - { - for (i = vector.length - 1, j = i - step; j > 0; --i) - { - vector[i] = cast(ubyte)((vector[j] >> bit) - | vector[--j] << delta); - } - vector[i] = cast(ubyte)(vector[j] >> bit); - vector[0..step] = 0; - } - } - return this; - } - - /// - nothrow @safe @nogc unittest - { - ubyte[4] arr = [0b10111110, 0b11110010, 0b01010010, 0b01010011]; - auto bits = BitVector(arr); - - bits <<= 0; - assert(bits[][0] == 0b10111110 && bits[][1] == 0b11110010 - && bits[][2] == 0b01010010 && bits[][3] == 0b01010011); - - bits <<= 2; - assert(bits[][0] == 0b11111011 && bits[][1] == 0b11001001 - && bits[][2] == 0b01001001 && bits[][3] == 0b01001100); - - bits <<= 4; - assert(bits[][0] == 0b10111100 && bits[][1] == 0b10010100 - && bits[][2] == 0b10010100 && bits[][3] == 0b11000000); - - bits <<= 8; - assert(bits[][0] == 0b10010100 && bits[][1] == 0b10010100 - && bits[][2] == 0b11000000 && bits[][3] == 0b00000000); - - bits <<= 7; - assert(bits[][0] == 0b01001010 && bits[][1] == 0b01100000 - && bits[][2] == 0b00000000 && bits[][3] == 0b00000000); - - bits <<= 25; - assert(bits[][0] == 0b00000000 && bits[][1] == 0b00000000 - && bits[][2] == 0b00000000 && bits[][3] == 0b00000000); - - arr = [0b00110011, 0b11001100, 0b11111111, 0b01010101]; - bits <<= 24; - assert(bits[][0] == 0b01010101 && bits[][1] == 0b00000000 - && bits[][2] == 0b00000000 && bits[][3] == 0b00000000); - - arr[1] = 0b11001100; - arr[2] = 0b11111111; - arr[3] = 0b01010101; - bits <<= 12; - assert(bits[][0] == 0b11001111 && bits[][1] == 0b11110101 - && bits[][2] == 0b01010000 && bits[][3] == 0b00000000); - - bits <<= 100; - assert(bits[][0] == 0b00000000 && bits[][1] == 0b00000000 - && bits[][2] == 0b00000000 && bits[][3] == 0b00000000); - - arr = [0b10111110, 0b11110010, 0b01010010, 0b01010011]; - bits >>= 0; - assert(bits[][0] == 0b10111110 && bits[][1] == 0b11110010 - && bits[][2] == 0b01010010 && bits[][3] == 0b01010011); - - bits >>= 2; - assert(bits[][0] == 0b00101111 && bits[][1] == 0b10111100 - && bits[][2] == 0b10010100 && bits[][3] == 0b10010100); - - bits >>= 4; - assert(bits[][0] == 0b00000010 && bits[][1] == 0b11111011 - && bits[][2] == 0b11001001 && bits[][3] == 0b01001001); - - bits >>= 8; - assert(bits[][0] == 0b00000000 && bits[][1] == 0b00000010 - && bits[][2] == 0b11111011 && bits[][3] == 0b11001001); - - bits >>= 7; - assert(bits[][0] == 0b00000000 && bits[][1] == 0b00000000 - && bits[][2] == 0b00000101 && bits[][3] == 0b11110111); - - bits >>= 25; - assert(bits[][0] == 0b00000000 && bits[][1] == 0b00000000 - && bits[][2] == 0b00000000 && bits[][3] == 0b00000000); - - arr = [0b00110011, 0b11001100, 0b11111111, 0b01010101]; - bits >>= 24; - assert(bits[][0] == 0b00000000 && bits[][1] == 0b00000000 - && bits[][2] == 0b00000000 && bits[][3] == 0b00110011); - - arr[1] = 0b11001100; - arr[2] = 0b11111111; - arr[3] = 0b01010101; - bits >>= 12; - assert(bits[][0] == 0b00000000 && bits[][1] == 0b00000000 - && bits[][2] == 0b00001100 && bits[][3] == 0b11001111); - - bits >>= 100; - assert(bits[][0] == 0b00000000 && bits[][1] == 0b00000000 - && bits[][2] == 0b00000000 && bits[][3] == 0b00000000); - } - - /** - * Negates all bits. - * - * Returns: $(D_KEYWORD this). - */ - BitVector opUnary(string op)() pure nothrow @safe @nogc - if (op == "~") - { - foreach (ref b; vector) - { - b = ~b; - } - return this; - } - - /// - unittest - { - // [01000001, 00001101, 10101101] - ubyte[3] arr = [65, 13, 173]; - auto bits = BitVector(arr); - - ~bits; - assert(bits[][0] == 0b10111110); - assert(bits[][1] == 0b11110010); - assert(bits[][2] == 0b01010010); - } - - /** - * Iterates through all bits. - * - * Params: - * dg = $(D_KEYWORD foreach) delegate. - * - * Returns: By $(D_PARAM dg) returned value. - */ - int opApply(int delegate(size_t, bool) dg) - { - int result; - foreach (i, ref v; vector) - { - foreach (c; 0..8) - { - result = dg(i * 8 + c, (v & (0x80 >> c)) != 0); - if (result) - { - return result; - } - } - } - return result; - } - - /// Ditto. - int opApply(int delegate(bool) dg) - { - int result; - foreach (ref v; vector) - { - foreach (c; 0..8) - { - result = dg((v & (0x80 >> c)) != 0); - if (result) - { - return result; - } - } - } - return result; - } - - /// - unittest - { - ubyte[2] arr = [0b01000001, 0b00001101]; - auto bits = BitVector(arr); - size_t c; - - foreach (i, v; bits) - { - assert(i == c); - if (i == 1 || i == 7 || i == 15 || i == 13 || i == 12) - { - assert(v); - } - else - { - assert(!v); - } - ++c; - } - assert(c == 16); - } -} diff --git a/source/tanya/crypto/des.d b/source/tanya/crypto/des.d deleted file mode 100644 index 8154056..0000000 --- a/source/tanya/crypto/des.d +++ /dev/null @@ -1,607 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -/** - * Copyright: Eugene Wissner 2016. - * License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/, - * Mozilla Public License, v. 2.0). - * Authors: $(LINK2 mailto:belka@caraus.de, Eugene Wissner) - */ -module tanya.crypto.des; - -import tanya.crypto.bit; -import tanya.crypto.symmetric; - -/// Initial permutation table. -private immutable ubyte[64] ipTable = [58, 50, 42, 34, 26, 18, 10, 2, - 60, 52, 44, 36, 28, 20, 12, 4, - 62, 54, 46, 38, 30, 22, 14, 6, - 64, 56, 48, 40, 32, 24, 16, 8, - 57, 49, 41, 33, 25, 17, 9, 1, - 59, 51, 43, 35, 27, 19, 11, 3, - 61, 53, 45, 37, 29, 21, 13, 5, - 63, 55, 47, 39, 31, 23, 15, 7]; - -/// Final permutation table. -private immutable ubyte[64] fpTable = [40, 8, 48, 16, 56, 24, 64, 32, - 39, 7, 47, 15, 55, 23, 63, 31, - 38, 6, 46, 14, 54, 22, 62, 30, - 37, 5, 45, 13, 53, 21, 61, 29, - 36, 4, 44, 12, 52, 20, 60, 28, - 35, 3, 43, 11, 51, 19, 59, 27, - 34, 2, 42, 10, 50, 18, 58, 26, - 33, 1, 41, 9, 49, 17, 57, 25]; - -/// Key permutation table 1. -private immutable ubyte[64] pc1Table = [57, 49, 41, 33, 25, 17, 9, 1, - 58, 50, 42, 34, 26, 18, 10, 2, - 59, 51, 43, 35, 27, 19, 11, 3, - 60, 52, 44, 36, 63, 55, 47, 39, - 31, 23, 15, 7, 62, 54, 46, 38, - 30, 22, 14, 6, 61, 53, 45, 37, - 29, 21, 13, 5, 28, 20, 12, 4]; - -/// Key permutation table 2. -private immutable ubyte[48] pc2Table = [14, 17, 11, 24, 1, 5, 3, 28, - 15, 6, 21, 10, 23, 19, 12, 4, - 26, 8, 16, 7, 27, 20, 13, 2, - 41, 52, 31, 37, 47, 55, 30, 40, - 51, 45, 33, 48, 44, 49, 39, 56, - 34, 53, 46, 42, 50, 36, 29, 32]; - -/// Expansion table. -private immutable ubyte[48] expansionTable = [32, 1, 2, 3, 4, 5, 4, 5, - 6, 7, 8, 9, 8, 9, 10, 11, - 12, 13, 12, 13, 14, 15, 16, 17, - 16, 17, 18, 19, 20, 21, 20, 21, - 22, 23, 24, 25, 24, 25, 26, 27, - 28, 29, 28, 29, 30, 31, 32, 1]; - -/// Final input block permutation. -private immutable ubyte[32] pTable = [16, 7, 20, 21, 29, 12, 28, 17, - 1, 15, 23, 26, 5, 18, 31, 10, - 2, 8, 24, 14, 32, 27, 3, 9, - 19, 13, 30, 6, 22, 11, 4, 25]; - -/// The (in)famous S-boxes. -private immutable ubyte[64][8] sBox = [[ - 14, 0, 4, 15, 13, 7, 1, 4, 2, 14, 15, 2, 11, 13, 8, 1, - 3, 10, 10, 6, 6, 12, 12, 11, 5, 9, 9, 5, 0, 3, 7, 8, - 4, 15, 1, 12, 14, 8, 8, 2, 13, 4, 6, 9, 2, 1, 11, 7, - 15, 5, 12, 11, 9, 3, 7, 14, 3, 10, 10, 0, 5, 6, 0, 13, - ],[ - 15, 3, 1, 13, 8, 4, 14, 7, 6, 15, 11, 2, 3, 8, 4, 14, - 9, 12, 7, 0, 2, 1, 13, 10, 12, 6, 0, 9, 5, 11, 10, 5, - 0, 13, 14, 8, 7, 10, 11, 1, 10, 3, 4, 15, 13, 4, 1, 2, - 5, 11, 8, 6, 12, 7, 6, 12, 9, 0, 3, 5, 2, 14, 15, 9, - ],[ - 10, 13, 0, 7, 9, 0, 14, 9, 6, 3, 3, 4, 15, 6, 5, 10, - 1, 2, 13, 8, 12, 5, 7, 14, 11, 12, 4, 11, 2, 15, 8, 1, - 13, 1, 6, 10, 4, 13, 9, 0, 8, 6, 15, 9, 3, 8, 0, 7, - 11, 4, 1, 15, 2, 14, 12, 3, 5, 11, 10, 5, 14, 2, 7, 12, - ],[ - 7, 13, 13, 8, 14, 11, 3, 5, 0, 6, 6, 15, 9, 0, 10, 3, - 1, 4, 2, 7, 8, 2, 5, 12, 11, 1, 12, 10, 4, 14, 15, 9, - 10, 3, 6, 15, 9, 0, 0, 6, 12, 10, 11, 1, 7, 13, 13, 8, - 15, 9, 1, 4, 3, 5, 14, 11, 5, 12, 2, 7, 8, 2, 4, 14, - ],[ - 2, 14, 12, 11, 4, 2, 1, 12, 7, 4, 10, 7, 11, 13, 6, 1, - 8, 5, 5, 0, 3, 15, 15, 10, 13, 3, 0, 9, 14, 8, 9, 6, - 4, 11, 2, 8, 1, 12, 11, 7, 10, 1, 13, 14, 7, 2, 8, 13, - 15, 6, 9, 15, 12, 0, 5, 9, 6, 10, 3, 4, 0, 5, 14, 3, - ],[ - 12, 10, 1, 15, 10, 4, 15, 2, 9, 7, 2, 12, 6, 9, 8, 5, - 0, 6, 13, 1, 3, 13, 4, 14, 14, 0, 7, 11, 5, 3, 11, 8, - 9, 4, 14, 3, 15, 2, 5, 12, 2, 9, 8, 5, 12, 15, 3, 10, - 7, 11, 0, 14, 4, 1, 10, 7, 1, 6, 13, 0, 11, 8, 6, 13, - ],[ - 4, 13, 11, 0, 2, 11, 14, 7, 15, 4, 0, 9, 8, 1, 13, 10, - 3, 14, 12, 3, 9, 5, 7, 12, 5, 2, 10, 15, 6, 8, 1, 6, - 1, 6, 4, 11, 11, 13, 13, 8, 12, 1, 3, 4, 7, 10, 14, 7, - 10, 9, 15, 5, 6, 0, 8, 15, 0, 14, 5, 2, 9, 3, 2, 12, - ],[ - 13, 1, 2, 15, 8, 13, 4, 8, 6, 10, 15, 3, 11, 7, 1, 4, - 10, 12, 9, 5, 3, 6, 14, 11, 5, 0, 0, 14, 12, 9, 7, 2, - 7, 2, 11, 1, 4, 14, 1, 7, 9, 4, 12, 10, 14, 8, 2, 13, - 0, 15, 6, 12, 10, 9, 13, 0, 15, 3, 3, 5, 5, 6, 8, 11, - ]]; - -/** - * Data Encryption Standard. - * - * Params: - * L = Number of keys. - */ -class DES(ushort L = 1) : BlockCipher - if (L == 1) -{ - mixin FixedBlockSize!8; - mixin KeyLength!8; - - private enum expansionBlockSize = 6; - private enum pc1KeyLength = 7; - private enum subkeyLength = 6; - private ubyte[] key_; - - /** - * Params: - * key = Key. - */ - @property void key(ubyte[] key) pure nothrow @safe @nogc - in - { - assert(key.length >= minKeyLength); - assert(key.length <= maxKeyLength); - } - body - { - key_ = key; - } - - /** - * Encrypts a block. - * - * Params: - * plain = Plain text, input. - * cipher = Cipher text, output. - */ - void encrypt(in ubyte[] plain, ubyte[] cipher) - nothrow - in - { - assert(plain.length == blockSize); - assert(cipher.length == blockSize); - } - body - { - operateBlock!(Direction.encryption)(plain, cipher); - } - - /** - * Decrypts a block. - * - * Params: - * cipher = Cipher text, input. - * plain = Plain text, output. - */ - void decrypt(in ubyte[] cipher, ubyte[] plain) - nothrow - in - { - assert(plain.length == blockSize); - assert(cipher.length == blockSize); - } - body - { - operateBlock!(Direction.decryption)(cipher, plain); - } - - private void operateBlock(Direction D)(in ubyte[] source, ref ubyte[] target) - { - ubyte[blockSize_] ipBlock; - ubyte[expansionBlockSize] expansionBlock; - ubyte[4] substitutionBlock; - ubyte[4] pBoxTarget; - ubyte[pc1KeyLength] pc1Key; - ubyte[subkeyLength] subkey; - - // Initial permutation - permute(source, ipBlock, ipTable, blockSize); - - // Key schedule computation - permute(key_, pc1Key, pc1Table, pc1KeyLength); - - // Feistel function - for (ubyte round; round < 16; ++round) - { - auto bitVector = BitVector(expansionBlock); - /* Expansion. This permutation only looks at the first 4 bytes (32 - bits of ipBlock); 16 of these are repeated in expansion table.*/ - permute(BitVector(ipBlock[4..$]), bitVector, expansionTable, 6); - - // Key mixing - static if (D == Direction.encryption) - { - rotateLeft(pc1Key); - if (!(round <= 1 || round == 8 || round == 15)) - { - // Rotate twice. - rotateLeft(pc1Key); - } - } - permute(pc1Key, subkey, pc2Table, subkeyLength); - static if (D == Direction.decryption) - { - rotateRight(pc1Key); - if (!(round >= 14 || round == 7 || round == 0)) - { - // Rotate twice. - rotateRight(pc1Key); - } - } - - bitVector ^= subkey; - - // Substitution; copy from updated expansion block to ciphertext block - substitutionBlock[0] = cast(ubyte) (sBox[0][(expansionBlock[0] & 0xfc ) >> 2] << 4); - substitutionBlock[0] |= sBox[1][(expansionBlock[0] & 0x03) << 4 | (expansionBlock[1] & 0xf0) >> 4]; - substitutionBlock[1] = cast(ubyte) (sBox[2][(expansionBlock[1] & 0x0f) << 2 | (expansionBlock[2] & 0xc0) >> 6] << 4); - substitutionBlock[1] |= sBox[3][(expansionBlock[2] & 0x3f)]; - substitutionBlock[2] = cast(ubyte) (sBox[4][(expansionBlock[3] & 0xfc) >> 2 ] << 4); - substitutionBlock[2] |= sBox[5][(expansionBlock[3] & 0x03) << 4 | (expansionBlock[4] & 0xf0) >> 4]; - substitutionBlock[3] = cast(ubyte) (sBox[6][(expansionBlock[4] & 0x0F) << 2 | (expansionBlock[5] & 0xc0) >> 6] << 4); - substitutionBlock[3] |= sBox[7][(expansionBlock[5] & 0x3f)]; - - // Permutation - bitVector = BitVector(substitutionBlock); - permute(bitVector, pBoxTarget, pTable, blockSize / 2); - - // Swap the halves. - substitutionBlock = ipBlock[0..4]; - ipBlock[0..4] = ipBlock[4..$]; - - bitVector ^= pBoxTarget; - ipBlock[4..$] = substitutionBlock; - } - - substitutionBlock = ipBlock[0..4]; - ipBlock[0..4] = ipBlock[4..$]; - ipBlock[4..$] = substitutionBlock; - - // Final permutaion (undo initial permuation). - permute(ipBlock, target, fpTable, blockSize); - } - - /** - * Performs the left rotation operation on the key. - * - * Params: - * key = The key to rotate. - */ - private void rotateLeft(ref ubyte[7] key) const pure nothrow @safe @nogc - { - immutable carryLeft = (key[0] & 0x80) >> 3; - - key[0] = cast(ubyte) ((key[0] << 1) | ((key[1] & 0x80) >> 7)); - key[1] = cast(ubyte) ((key[1] << 1) | ((key[2] & 0x80) >> 7)); - key[2] = cast(ubyte) ((key[2] << 1) | ((key[3] & 0x80) >> 7)); - - immutable carryRight = (key[3] & 0x08) >> 3; - key[3] = cast(ubyte) ((((key[3] << 1) | ((key[4] & 0x80) >> 7)) & ~0x10) | carryLeft); - - key[4] = cast(ubyte) ((key[4] << 1) | ((key[5] & 0x80) >> 7)); - key[5] = cast(ubyte) ((key[5] << 1) | ((key[6] & 0x80) >> 7)); - key[6] = cast(ubyte) ((key[6] << 1) | carryRight); - } - - /** - * Performs the right rotation operation on the key. - * - * Params: - * key = The key to rotate. - */ - private void rotateRight(ref ubyte[7] key) const pure nothrow @safe @nogc - { - immutable carryRight = (key[6] & 0x01) << 3; - - key[6] = cast(ubyte) ((key[6] >> 1) | ((key[5] & 0x01) << 7)); - key[5] = cast(ubyte) ((key[5] >> 1) | ((key[4] & 0x01) << 7)); - key[4] = cast(ubyte) ((key[4] >> 1) | ((key[3] & 0x01) << 7)); - - immutable carryLeft = (key[3] & 0x10) << 3; - key[3] = cast(ubyte) ((((key[3] >> 1) | ((key[2] & 0x01) << 7)) & ~0x08) | carryRight); - - key[2] = cast(ubyte) ((key[2] >> 1) | ((key[1] & 0x01) << 7)); - key[1] = cast(ubyte) ((key[1] >> 1) | ((key[0] & 0x01) << 7)); - key[0] = cast(ubyte) ((key[0] >> 1) | carryLeft); - } - - private void permute(in ubyte[] source, ubyte[] target, immutable(ubyte[]) permuteTable, size_t length) - const pure nothrow @safe @nogc - { - const sourceVector = const BitVector(source); - auto targetVector = BitVector(target); - - permute(sourceVector, targetVector, permuteTable, length); - } - - private void permute(in BitVector source, ubyte[] target, immutable(ubyte[]) permuteTable, size_t length) - const pure nothrow @safe @nogc - { - auto targetVector = BitVector(target); - - permute(source, targetVector, permuteTable, length); - } - - private void permute(in BitVector source, ref BitVector target, immutable(ubyte[]) permuteTable, size_t length) - const pure nothrow @safe @nogc - { - for (uint i; i < length * 8; ++i) - { - target[i] = source[permuteTable[i] - 1]; - } - } -} - -version (unittest) -{ - import std.typecons; - - /* Test vectors for DES. Source: - "Validating the Correctness of Hardware - Implementations of the NBS Data Encryption Standard" - NBS Special Publication 500-20, 1980. Appendix B */ - - // Initial and reverse Permutation and Expansion tests. Encrypt. - ubyte[8][64] desTestVectors1 = [ - [0x95, 0xf8, 0xa5, 0xe5, 0xdd, 0x31, 0xd9, 0x00], - [0xdd, 0x7f, 0x12, 0x1c, 0xa5, 0x01, 0x56, 0x19], - [0x2e, 0x86, 0x53, 0x10, 0x4f, 0x38, 0x34, 0xea], - [0x4b, 0xd3, 0x88, 0xff, 0x6c, 0xd8, 0x1d, 0x4f], - [0x20, 0xb9, 0xe7, 0x67, 0xb2, 0xfb, 0x14, 0x56], - [0x55, 0x57, 0x93, 0x80, 0xd7, 0x71, 0x38, 0xef], - [0x6c, 0xc5, 0xde, 0xfa, 0xaf, 0x04, 0x51, 0x2f], - [0x0d, 0x9f, 0x27, 0x9b, 0xa5, 0xd8, 0x72, 0x60], - [0xd9, 0x03, 0x1b, 0x02, 0x71, 0xbd, 0x5a, 0x0a], - [0x42, 0x42, 0x50, 0xb3, 0x7c, 0x3d, 0xd9, 0x51], - [0xb8, 0x06, 0x1b, 0x7e, 0xcd, 0x9a, 0x21, 0xe5], - [0xf1, 0x5d, 0x0f, 0x28, 0x6b, 0x65, 0xbd, 0x28], - [0xad, 0xd0, 0xcc, 0x8d, 0x6e, 0x5d, 0xeb, 0xa1], - [0xe6, 0xd5, 0xf8, 0x27, 0x52, 0xad, 0x63, 0xd1], - [0xec, 0xbf, 0xe3, 0xbd, 0x3f, 0x59, 0x1a, 0x5e], - [0xf3, 0x56, 0x83, 0x43, 0x79, 0xd1, 0x65, 0xcd], - [0x2b, 0x9f, 0x98, 0x2f, 0x20, 0x03, 0x7f, 0xa9], - [0x88, 0x9d, 0xe0, 0x68, 0xa1, 0x6f, 0x0b, 0xe6], - [0xe1, 0x9e, 0x27, 0x5d, 0x84, 0x6a, 0x12, 0x98], - [0x32, 0x9a, 0x8e, 0xd5, 0x23, 0xd7, 0x1a, 0xec], - [0xe7, 0xfc, 0xe2, 0x25, 0x57, 0xd2, 0x3c, 0x97], - [0x12, 0xa9, 0xf5, 0x81, 0x7f, 0xf2, 0xd6, 0x5d], - [0xa4, 0x84, 0xc3, 0xad, 0x38, 0xdc, 0x9c, 0x19], - [0xfb, 0xe0, 0x0a, 0x8a, 0x1e, 0xf8, 0xad, 0x72], - [0x75, 0x0d, 0x07, 0x94, 0x07, 0x52, 0x13, 0x63], - [0x64, 0xfe, 0xed, 0x9c, 0x72, 0x4c, 0x2f, 0xaf], - [0xf0, 0x2b, 0x26, 0x3b, 0x32, 0x8e, 0x2b, 0x60], - [0x9d, 0x64, 0x55, 0x5a, 0x9a, 0x10, 0xb8, 0x52], - [0xd1, 0x06, 0xff, 0x0b, 0xed, 0x52, 0x55, 0xd7], - [0xe1, 0x65, 0x2c, 0x6b, 0x13, 0x8c, 0x64, 0xa5], - [0xe4, 0x28, 0x58, 0x11, 0x86, 0xec, 0x8f, 0x46], - [0xae, 0xb5, 0xf5, 0xed, 0xe2, 0x2d, 0x1a, 0x36], - [0xe9, 0x43, 0xd7, 0x56, 0x8a, 0xec, 0x0c, 0x5c], - [0xdf, 0x98, 0xc8, 0x27, 0x6f, 0x54, 0xb0, 0x4b], - [0xb1, 0x60, 0xe4, 0x68, 0x0f, 0x6c, 0x69, 0x6f], - [0xfa, 0x07, 0x52, 0xb0, 0x7d, 0x9c, 0x4a, 0xb8], - [0xca, 0x3a, 0x2b, 0x03, 0x6d, 0xbc, 0x85, 0x02], - [0x5e, 0x09, 0x05, 0x51, 0x7b, 0xb5, 0x9b, 0xcf], - [0x81, 0x4e, 0xeb, 0x3b, 0x91, 0xd9, 0x07, 0x26], - [0x4d, 0x49, 0xdb, 0x15, 0x32, 0x91, 0x9c, 0x9f], - [0x25, 0xeb, 0x5f, 0xc3, 0xf8, 0xcf, 0x06, 0x21], - [0xab, 0x6a, 0x20, 0xc0, 0x62, 0x0d, 0x1c, 0x6f], - [0x79, 0xe9, 0x0d, 0xbc, 0x98, 0xf9, 0x2c, 0xca], - [0x86, 0x6e, 0xce, 0xdd, 0x80, 0x72, 0xbb, 0x0e], - [0x8b, 0x54, 0x53, 0x6f, 0x2f, 0x3e, 0x64, 0xa8], - [0xea, 0x51, 0xd3, 0x97, 0x55, 0x95, 0xb8, 0x6b], - [0xca, 0xff, 0xc6, 0xac, 0x45, 0x42, 0xde, 0x31], - [0x8d, 0xd4, 0x5a, 0x2d, 0xdf, 0x90, 0x79, 0x6c], - [0x10, 0x29, 0xd5, 0x5e, 0x88, 0x0e, 0xc2, 0xd0], - [0x5d, 0x86, 0xcb, 0x23, 0x63, 0x9d, 0xbe, 0xa9], - [0x1d, 0x1c, 0xa8, 0x53, 0xae, 0x7c, 0x0c, 0x5f], - [0xce, 0x33, 0x23, 0x29, 0x24, 0x8f, 0x32, 0x28], - [0x84, 0x05, 0xd1, 0xab, 0xe2, 0x4f, 0xb9, 0x42], - [0xe6, 0x43, 0xd7, 0x80, 0x90, 0xca, 0x42, 0x07], - [0x48, 0x22, 0x1b, 0x99, 0x37, 0x74, 0x8a, 0x23], - [0xdd, 0x7c, 0x0b, 0xbd, 0x61, 0xfa, 0xfd, 0x54], - [0x2f, 0xbc, 0x29, 0x1a, 0x57, 0x0d, 0xb5, 0xc4], - [0xe0, 0x7c, 0x30, 0xd7, 0xe4, 0xe2, 0x6e, 0x12], - [0x09, 0x53, 0xe2, 0x25, 0x8e, 0x8e, 0x90, 0xa1], - [0x5b, 0x71, 0x1b, 0xc4, 0xce, 0xeb, 0xf2, 0xee], - [0xcc, 0x08, 0x3f, 0x1e, 0x6d, 0x9e, 0x85, 0xf6], - [0xd2, 0xfd, 0x88, 0x67, 0xd5, 0x0d, 0x2d, 0xfe], - [0x06, 0xe7, 0xea, 0x22, 0xce, 0x92, 0x70, 0x8f], - [0x16, 0x6b, 0x40, 0xb4, 0x4a, 0xba, 0x4b, 0xd6], - ]; - - // Key Permutation test. Encrypt. - // Test of right-shifts. Decrypt. - ubyte[8][56] desTestVectors2 = [ - [0x95, 0xa8, 0xd7, 0x28, 0x13, 0xda, 0xa9, 0x4d], - [0x0e, 0xec, 0x14, 0x87, 0xdd, 0x8c, 0x26, 0xd5], - [0x7a, 0xd1, 0x6f, 0xfb, 0x79, 0xc4, 0x59, 0x26], - [0xd3, 0x74, 0x62, 0x94, 0xca, 0x6a, 0x6c, 0xf3], - [0x80, 0x9f, 0x5f, 0x87, 0x3c, 0x1f, 0xd7, 0x61], - [0xc0, 0x2f, 0xaf, 0xfe, 0xc9, 0x89, 0xd1, 0xfc], - [0x46, 0x15, 0xaa, 0x1d, 0x33, 0xe7, 0x2f, 0x10], - [0x20, 0x55, 0x12, 0x33, 0x50, 0xc0, 0x08, 0x58], - [0xdf, 0x3b, 0x99, 0xd6, 0x57, 0x73, 0x97, 0xc8], - [0x31, 0xfe, 0x17, 0x36, 0x9b, 0x52, 0x88, 0xc9], - [0xdf, 0xdd, 0x3c, 0xc6, 0x4d, 0xae, 0x16, 0x42], - [0x17, 0x8c, 0x83, 0xce, 0x2b, 0x39, 0x9d, 0x94], - [0x50, 0xf6, 0x36, 0x32, 0x4a, 0x9b, 0x7f, 0x80], - [0xa8, 0x46, 0x8e, 0xe3, 0xbc, 0x18, 0xf0, 0x6d], - [0xa2, 0xdc, 0x9e, 0x92, 0xfd, 0x3c, 0xde, 0x92], - [0xca, 0xc0, 0x9f, 0x79, 0x7d, 0x03, 0x12, 0x87], - [0x90, 0xba, 0x68, 0x0b, 0x22, 0xae, 0xb5, 0x25], - [0xce, 0x7a, 0x24, 0xf3, 0x50, 0xe2, 0x80, 0xb6], - [0x88, 0x2b, 0xff, 0x0a, 0xa0, 0x1a, 0x0b, 0x87], - [0x25, 0x61, 0x02, 0x88, 0x92, 0x45, 0x11, 0xc2], - [0xc7, 0x15, 0x16, 0xc2, 0x9c, 0x75, 0xd1, 0x70], - [0x51, 0x99, 0xc2, 0x9a, 0x52, 0xc9, 0xf0, 0x59], - [0xc2, 0x2f, 0x0a, 0x29, 0x4a, 0x71, 0xf2, 0x9f], - [0xee, 0x37, 0x14, 0x83, 0x71, 0x4c, 0x02, 0xea], - [0xa8, 0x1f, 0xbd, 0x44, 0x8f, 0x9e, 0x52, 0x2f], - [0x4f, 0x64, 0x4c, 0x92, 0xe1, 0x92, 0xdf, 0xed], - [0x1a, 0xfa, 0x9a, 0x66, 0xa6, 0xdf, 0x92, 0xae], - [0xb3, 0xc1, 0xcc, 0x71, 0x5c, 0xb8, 0x79, 0xd8], - [0x19, 0xd0, 0x32, 0xe6, 0x4a, 0xb0, 0xbd, 0x8b], - [0x3c, 0xfa, 0xa7, 0xa7, 0xdc, 0x87, 0x20, 0xdc], - [0xb7, 0x26, 0x5f, 0x7f, 0x44, 0x7a, 0xc6, 0xf3], - [0x9d, 0xb7, 0x3b, 0x3c, 0x0d, 0x16, 0x3f, 0x54], - [0x81, 0x81, 0xb6, 0x5b, 0xab, 0xf4, 0xa9, 0x75], - [0x93, 0xc9, 0xb6, 0x40, 0x42, 0xea, 0xa2, 0x40], - [0x55, 0x70, 0x53, 0x08, 0x29, 0x70, 0x55, 0x92], - [0x86, 0x38, 0x80, 0x9e, 0x87, 0x87, 0x87, 0xa0], - [0x41, 0xb9, 0xa7, 0x9a, 0xf7, 0x9a, 0xc2, 0x08], - [0x7a, 0x9b, 0xe4, 0x2f, 0x20, 0x09, 0xa8, 0x92], - [0x29, 0x03, 0x8d, 0x56, 0xba, 0x6d, 0x27, 0x45], - [0x54, 0x95, 0xc6, 0xab, 0xf1, 0xe5, 0xdf, 0x51], - [0xae, 0x13, 0xdb, 0xd5, 0x61, 0x48, 0x89, 0x33], - [0x02, 0x4d, 0x1f, 0xfa, 0x89, 0x04, 0xe3, 0x89], - [0xd1, 0x39, 0x97, 0x12, 0xf9, 0x9b, 0xf0, 0x2e], - [0x14, 0xc1, 0xd7, 0xc1, 0xcf, 0xfe, 0xc7, 0x9e], - [0x1d, 0xe5, 0x27, 0x9d, 0xae, 0x3b, 0xed, 0x6f], - [0xe9, 0x41, 0xa3, 0x3f, 0x85, 0x50, 0x13, 0x03], - [0xda, 0x99, 0xdb, 0xbc, 0x9a, 0x03, 0xf3, 0x79], - [0xb7, 0xfc, 0x92, 0xf9, 0x1d, 0x8e, 0x92, 0xe9], - [0xae, 0x8e, 0x5c, 0xaa, 0x3c, 0xa0, 0x4e, 0x85], - [0x9c, 0xc6, 0x2d, 0xf4, 0x3b, 0x6e, 0xed, 0x74], - [0xd8, 0x63, 0xdb, 0xb5, 0xc5, 0x9a, 0x91, 0xa0], - [0xa1, 0xab, 0x21, 0x90, 0x54, 0x5b, 0x91, 0xd7], - [0x08, 0x75, 0x04, 0x1e, 0x64, 0xc5, 0x70, 0xf7], - [0x5a, 0x59, 0x45, 0x28, 0xbe, 0xbe, 0xf1, 0xcc], - [0xfc, 0xdb, 0x32, 0x91, 0xde, 0x21, 0xf0, 0xc0], - [0x86, 0x9e, 0xfd, 0x7f, 0x9f, 0x26, 0x5a, 0x09], - ]; - - // Data permutation test. Encrypt. - ubyte[8][2][32] desTestVectors3 = [ - [[0x10, 0x46, 0x91, 0x34, 0x89, 0x98, 0x01, 0x31], [0x88, 0xd5, 0x5e, 0x54, 0xf5, 0x4c, 0x97, 0xb4]], - [[0x10, 0x07, 0x10, 0x34, 0x89, 0x98, 0x80, 0x20], [0x0c, 0x0c, 0xc0, 0x0c, 0x83, 0xea, 0x48, 0xfd]], - [[0x10, 0x07, 0x10, 0x34, 0xc8, 0x98, 0x01, 0x20], [0x83, 0xbc, 0x8e, 0xf3, 0xa6, 0x57, 0x01, 0x83]], - [[0x10, 0x46, 0x10, 0x34, 0x89, 0x98, 0x80, 0x20], [0xdf, 0x72, 0x5d, 0xca, 0xd9, 0x4e, 0xa2, 0xe9]], - [[0x10, 0x86, 0x91, 0x15, 0x19, 0x19, 0x01, 0x01], [0xe6, 0x52, 0xb5, 0x3b, 0x55, 0x0b, 0xe8, 0xb0]], - [[0x10, 0x86, 0x91, 0x15, 0x19, 0x58, 0x01, 0x01], [0xaf, 0x52, 0x71, 0x20, 0xc4, 0x85, 0xcb, 0xb0]], - [[0x51, 0x07, 0xb0, 0x15, 0x19, 0x58, 0x01, 0x01], [0x0f, 0x04, 0xce, 0x39, 0x3d, 0xb9, 0x26, 0xd5]], - [[0x10, 0x07, 0xb0, 0x15, 0x19, 0x19, 0x01, 0x01], [0xc9, 0xf0, 0x0f, 0xfc, 0x74, 0x07, 0x90, 0x67]], - [[0x31, 0x07, 0x91, 0x54, 0x98, 0x08, 0x01, 0x01], [0x7c, 0xfd, 0x82, 0xa5, 0x93, 0x25, 0x2b, 0x4e]], - [[0x31, 0x07, 0x91, 0x94, 0x98, 0x08, 0x01, 0x01], [0xcb, 0x49, 0xa2, 0xf9, 0xe9, 0x13, 0x63, 0xe3]], - [[0x10, 0x07, 0x91, 0x15, 0xb9, 0x08, 0x01, 0x40], [0x00, 0xb5, 0x88, 0xbe, 0x70, 0xd2, 0x3f, 0x56]], - [[0x31, 0x07, 0x91, 0x15, 0x98, 0x08, 0x01, 0x40], [0x40, 0x6a, 0x9a, 0x6a, 0xb4, 0x33, 0x99, 0xae]], - [[0x10, 0x07, 0xd0, 0x15, 0x89, 0x98, 0x01, 0x01], [0x6c, 0xb7, 0x73, 0x61, 0x1d, 0xca, 0x9a, 0xda]], - [[0x91, 0x07, 0x91, 0x15, 0x89, 0x98, 0x01, 0x01], [0x67, 0xfd, 0x21, 0xc1, 0x7d, 0xbb, 0x5d, 0x70]], - [[0x91, 0x07, 0xd0, 0x15, 0x89, 0x19, 0x01, 0x01], [0x95, 0x92, 0xcb, 0x41, 0x10, 0x43, 0x07, 0x87]], - [[0x10, 0x07, 0xd0, 0x15, 0x98, 0x98, 0x01, 0x20], [0xa6, 0xb7, 0xff, 0x68, 0xa3, 0x18, 0xdd, 0xd3]], - [[0x10, 0x07, 0x94, 0x04, 0x98, 0x19, 0x01, 0x01], [0x4d, 0x10, 0x21, 0x96, 0xc9, 0x14, 0xca, 0x16]], - [[0x01, 0x07, 0x91, 0x04, 0x91, 0x19, 0x04, 0x01], [0x2d, 0xfa, 0x9f, 0x45, 0x73, 0x59, 0x49, 0x65]], - [[0x01, 0x07, 0x91, 0x04, 0x91, 0x19, 0x01, 0x01], [0xb4, 0x66, 0x04, 0x81, 0x6c, 0x0e, 0x07, 0x74]], - [[0x01, 0x07, 0x94, 0x04, 0x91, 0x19, 0x04, 0x01], [0x6e, 0x7e, 0x62, 0x21, 0xa4, 0xf3, 0x4e, 0x87]], - [[0x19, 0x07, 0x92, 0x10, 0x98, 0x1a, 0x01, 0x01], [0xaa, 0x85, 0xe7, 0x46, 0x43, 0x23, 0x31, 0x99]], - [[0x10, 0x07, 0x91, 0x19, 0x98, 0x19, 0x08, 0x01], [0x2e, 0x5a, 0x19, 0xdb, 0x4d, 0x19, 0x62, 0xd6]], - [[0x10, 0x07, 0x91, 0x19, 0x98, 0x1a, 0x08, 0x01], [0x23, 0xa8, 0x66, 0xa8, 0x09, 0xd3, 0x08, 0x94]], - [[0x10, 0x07, 0x92, 0x10, 0x98, 0x19, 0x01, 0x01], [0xd8, 0x12, 0xd9, 0x61, 0xf0, 0x17, 0xd3, 0x20]], - [[0x10, 0x07, 0x91, 0x15, 0x98, 0x19, 0x01, 0x0b], [0x05, 0x56, 0x05, 0x81, 0x6e, 0x58, 0x60, 0x8f]], - [[0x10, 0x04, 0x80, 0x15, 0x98, 0x19, 0x01, 0x01], [0xab, 0xd8, 0x8e, 0x8b, 0x1b, 0x77, 0x16, 0xf1]], - [[0x10, 0x04, 0x80, 0x15, 0x98, 0x19, 0x01, 0x02], [0x53, 0x7a, 0xc9, 0x5b, 0xe6, 0x9d, 0xa1, 0xe1]], - [[0x10, 0x04, 0x80, 0x15, 0x98, 0x19, 0x01, 0x08], [0xae, 0xd0, 0xf6, 0xae, 0x3c, 0x25, 0xcd, 0xd8]], - [[0x10, 0x02, 0x91, 0x14, 0x98, 0x10, 0x01, 0x04], [0xb3, 0xe3, 0x5a, 0x5e, 0xe5, 0x3e, 0x7b, 0x8d]], - [[0x10, 0x02, 0x91, 0x15, 0x98, 0x19, 0x01, 0x04], [0x61, 0xc7, 0x9c, 0x71, 0x92, 0x1a, 0x2e, 0xf8]], - [[0x10, 0x02, 0x91, 0x15, 0x98, 0x10, 0x02, 0x01], [0xe2, 0xf5, 0x72, 0x8f, 0x09, 0x95, 0x01, 0x3c]], - [[0x10, 0x02, 0x91, 0x16, 0x98, 0x10, 0x01, 0x01], [0x1a, 0xea, 0xc3, 0x9a, 0x61, 0xf0, 0xa4, 0x64]], - ]; - - // S-Box test. Encrypt. - ubyte[8][3][19] desTestVectors4 = [ - [[0x7c, 0xa1, 0x10, 0x45, 0x4a, 0x1a, 0x6e, 0x57], [0x01, 0xa1, 0xd6, 0xd0, 0x39, 0x77, 0x67, 0x42], - [0x69, 0x0f, 0x5b, 0x0d, 0x9a, 0x26, 0x93, 0x9b]], - [[0x01, 0x31, 0xd9, 0x61, 0x9d, 0xc1, 0x37, 0x6e], [0x5c, 0xd5, 0x4c, 0xa8, 0x3d, 0xef, 0x57, 0xda], - [0x7a, 0x38, 0x9d, 0x10, 0x35, 0x4b, 0xd2, 0x71]], - [[0x07, 0xa1, 0x13, 0x3e, 0x4a, 0x0b, 0x26, 0x86], [0x02, 0x48, 0xd4, 0x38, 0x06, 0xf6, 0x71, 0x72], - [0x86, 0x8e, 0xbb, 0x51, 0xca, 0xb4, 0x59, 0x9a]], - [[0x38, 0x49, 0x67, 0x4c, 0x26, 0x02, 0x31, 0x9e], [0x51, 0x45, 0x4b, 0x58, 0x2d, 0xdf, 0x44, 0x0a], - [0x71, 0x78, 0x87, 0x6e, 0x01, 0xf1, 0x9b, 0x2a]], - [[0x04, 0xb9, 0x15, 0xba, 0x43, 0xfe, 0xb5, 0xb6], [0x42, 0xfd, 0x44, 0x30, 0x59, 0x57, 0x7f, 0xa2], - [0xaf, 0x37, 0xfb, 0x42, 0x1f, 0x8c, 0x40, 0x95]], - [[0x01, 0x13, 0xb9, 0x70, 0xfd, 0x34, 0xf2, 0xce], [0x05, 0x9b, 0x5e, 0x08, 0x51, 0xcf, 0x14, 0x3a], - [0x86, 0xa5, 0x60, 0xf1, 0x0e, 0xc6, 0xd8, 0x5b]], - [[0x01, 0x70, 0xf1, 0x75, 0x46, 0x8f, 0xb5, 0xe6], [0x07, 0x56, 0xd8, 0xe0, 0x77, 0x47, 0x61, 0xd2], - [0x0c, 0xd3, 0xda, 0x02, 0x00, 0x21, 0xdc, 0x09]], - [[0x43, 0x29, 0x7f, 0xad, 0x38, 0xe3, 0x73, 0xfe], [0x76, 0x25, 0x14, 0xb8, 0x29, 0xbf, 0x48, 0x6a], - [0xea, 0x67, 0x6b, 0x2c, 0xb7, 0xdb, 0x2b, 0x7a]], - [[0x07, 0xa7, 0x13, 0x70, 0x45, 0xda, 0x2a, 0x16], [0x3b, 0xdd, 0x11, 0x90, 0x49, 0x37, 0x28, 0x02], - [0xdf, 0xd6, 0x4a, 0x81, 0x5c, 0xaf, 0x1a, 0x0f]], - [[0x04, 0x68, 0x91, 0x04, 0xc2, 0xfd, 0x3b, 0x2f], [0x26, 0x95, 0x5f, 0x68, 0x35, 0xaf, 0x60, 0x9a], - [0x5c, 0x51, 0x3c, 0x9c, 0x48, 0x86, 0xc0, 0x88]], - [[0x37, 0xd0, 0x6b, 0xb5, 0x16, 0xcb, 0x75, 0x46], [0x16, 0x4d, 0x5e, 0x40, 0x4f, 0x27, 0x52, 0x32], - [0x0a, 0x2a, 0xee, 0xae, 0x3f, 0xf4, 0xab, 0x77]], - [[0x1f, 0x08, 0x26, 0x0d, 0x1a, 0xc2, 0x46, 0x5e], [0x6b, 0x05, 0x6e, 0x18, 0x75, 0x9f, 0x5c, 0xca], - [0xef, 0x1b, 0xf0, 0x3e, 0x5d, 0xfa, 0x57, 0x5a]], - [[0x58, 0x40, 0x23, 0x64, 0x1a, 0xba, 0x61, 0x76], [0x00, 0x4b, 0xd6, 0xef, 0x09, 0x17, 0x60, 0x62], - [0x88, 0xbf, 0x0d, 0xb6, 0xd7, 0x0d, 0xee, 0x56]], - [[0x02, 0x58, 0x16, 0x16, 0x46, 0x29, 0xb0, 0x07], [0x48, 0x0d, 0x39, 0x00, 0x6e, 0xe7, 0x62, 0xf2], - [0xa1, 0xf9, 0x91, 0x55, 0x41, 0x02, 0x0b, 0x56]], - [[0x49, 0x79, 0x3e, 0xbc, 0x79, 0xb3, 0x25, 0x8f], [0x43, 0x75, 0x40, 0xc8, 0x69, 0x8f, 0x3c, 0xfa], - [0x6f, 0xbf, 0x1c, 0xaf, 0xcf, 0xfd, 0x05, 0x56]], - [[0x4f, 0xb0, 0x5e, 0x15, 0x15, 0xab, 0x73, 0xa7], [0x07, 0x2d, 0x43, 0xa0, 0x77, 0x07, 0x52, 0x92], - [0x2f, 0x22, 0xe4, 0x9b, 0xab, 0x7c, 0xa1, 0xac]], - [[0x49, 0xe9, 0x5d, 0x6d, 0x4c, 0xa2, 0x29, 0xbf], [0x02, 0xfe, 0x55, 0x77, 0x81, 0x17, 0xf1, 0x2a], - [0x5a, 0x6b, 0x61, 0x2c, 0xc2, 0x6c, 0xce, 0x4a]], - [[0x01, 0x83, 0x10, 0xdc, 0x40, 0x9b, 0x26, 0xd6], [0x1d, 0x9d, 0x5c, 0x50, 0x18, 0xf7, 0x28, 0xc2], - [0x5f, 0x4c, 0x03, 0x8e, 0xd1, 0x2b, 0x2e, 0x41]], - [[0x1c, 0x58, 0x7f, 0x1c, 0x13, 0x92, 0x4f, 0xef], [0x30, 0x55, 0x32, 0x28, 0x6d, 0x6f, 0x29, 0x5a], - [0x63, 0xfa, 0xc0, 0xd0, 0x34, 0xd9, 0xf7, 0x93]], - ]; -} - -/// -unittest -{ - auto des = scoped!(DES!1); - ubyte[8] key = [0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01]; - ubyte[8] plain = [0x80, 0, 0, 0, 0, 0, 0, 0]; - ubyte[8] cipher; - - des.key = key; - foreach (ubyte i; 0..64) - { - if (i != 0) - { - plain[i / 8] = i % 8 ? plain[i / 8] >> 1 : 0x80; - if (i % 8 == 0) - { - plain[i / 8 - 1] = 0; - } - } - // Initial Permutation and Expansion test. - des.encrypt(plain, cipher); - assert(cipher == desTestVectors1[i]); - - // Inverse Permutation and Expansion test. - des.encrypt(cipher, cipher); - assert(cipher == plain); - } - - plain[0..$] = 0; - foreach (ubyte i; 0..56) - { - key[i / 7] = i % 7 ? key[i / 7] >> 1 : 0x80; - if (i % 7 == 0 && i != 0) - { - key[i / 7 - 1] = 0x01; - } - des.key = key; - - // Initial Permutation and Expansion test. - des.encrypt(plain, cipher); - assert(cipher == desTestVectors2[i]); - - // Test of right-shifts in Decryption. - des.decrypt(desTestVectors2[i], cipher); - assert(cipher == plain); - } - - // Data permutation test. - plain[0..$] = 0; - foreach (i; desTestVectors3) - { - des.key = i[0]; - des.encrypt(plain, cipher); - assert(cipher == i[1]); - } - - // S-Box test. - foreach (i; desTestVectors4) - { - des.key = i[0]; - des.encrypt(i[1], cipher); - assert(cipher == i[2]); - } -} diff --git a/source/tanya/crypto/mode.d b/source/tanya/crypto/mode.d deleted file mode 100644 index be02d10..0000000 --- a/source/tanya/crypto/mode.d +++ /dev/null @@ -1,279 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -/** - * Block cipher modes of operation. - * - * Copyright: Eugene Wissner 2016. - * License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/, - * Mozilla Public License, v. 2.0). - * Authors: $(LINK2 mailto:belka@caraus.de, Eugene Wissner) - */ -module tanya.crypto.mode; - -import tanya.memory; -import std.algorithm.iteration; -import std.typecons; - -/** - * Supported padding mode. - * - * See_Also: - * $(D_PSYMBOL pad) - */ -enum PaddingMode -{ - zero, - pkcs7, - ansiX923, -} - -/** - * Params: - * input = Sequence that should be padded. - * mode = Padding mode. - * blockSize = Block size. - * allocator = Allocator was used to allocate $(D_PARAM input). - * - * Returns: The function modifies the initial array and returns it. - * - * See_Also: - * $(D_PSYMBOL PaddingMode) - */ -ubyte[] pad(ref ubyte[] input, - in PaddingMode mode, - in ushort blockSize, - shared Allocator allocator = defaultAllocator) -in -{ - assert(blockSize > 0 && blockSize <= 256); - assert(blockSize % 64 == 0); - assert(input.length > 0); -} -body -{ - immutable rest = cast(ubyte) input.length % blockSize; - immutable size_t lastBlock = input.length - (rest > 0 ? rest : blockSize); - immutable needed = cast(ubyte) (rest > 0 ? blockSize - rest : 0); - - final switch (mode) with (PaddingMode) - { - case zero: - allocator.resizeArray(input, input.length + needed); - break; - case pkcs7: - if (needed) - { - allocator.resizeArray(input, input.length + needed); - input[input.length - needed ..$].each!((ref e) => e = needed); - } - else - { - allocator.resizeArray(input, input.length + blockSize); - } - break; - case ansiX923: - allocator.resizeArray(input, input.length + (needed ? needed : blockSize)); - input[$ - 1] = needed; - break; - } - - return input; -} - -/// -unittest -{ - { // Zeros - auto input = defaultAllocator.makeArray!ubyte(50); - - pad(input, PaddingMode.zero, 64); - assert(input.length == 64); - - pad(input, PaddingMode.zero, 64); - assert(input.length == 64); - assert(input[63] == 0); - - defaultAllocator.dispose(input); - } - { // PKCS#7 - auto input = defaultAllocator.makeArray!ubyte(50); - for (ubyte i; i < 40; ++i) - { - input[i] = i; - } - - pad(input, PaddingMode.pkcs7, 64); - assert(input.length == 64); - for (ubyte i; i < 64; ++i) - { - if (i >= 40 && i < 50) - { - assert(input[i] == 0); - } - else if (i >= 50) - { - assert(input[i] == 14); - } - else - { - assert(input[i] == i); - } - } - - pad(input, PaddingMode.pkcs7, 64); - assert(input.length == 128); - for (ubyte i; i < 128; ++i) - { - if (i >= 64 || (i >= 40 && i < 50)) - { - assert(input[i] == 0); - } - else if (i >= 50 && i < 64) - { - assert(input[i] == 14); - } - else - { - assert(input[i] == i); - } - } - - defaultAllocator.dispose(input); - } - { // ANSI X.923 - auto input = defaultAllocator.makeArray!ubyte(50); - for (ubyte i; i < 40; ++i) - { - input[i] = i; - } - - pad(input, PaddingMode.ansiX923, 64); - assert(input.length == 64); - for (ubyte i; i < 64; ++i) - { - if (i < 40) - { - assert(input[i] == i); - } - else if (i == 63) - { - assert(input[i] == 14); - } - else - { - assert(input[i] == 0); - } - } - - pad(input, PaddingMode.pkcs7, 64); - assert(input.length == 128); - for (ubyte i = 0; i < 128; ++i) - { - if (i < 40) - { - assert(input[i] == i); - } - else if (i == 63) - { - assert(input[i] == 14); - } - else - { - assert(input[i] == 0); - } - } - - defaultAllocator.dispose(input); - } -} - -/** - * Params: - * input = Sequence that should be padded. - * mode = Padding mode. - * blockSize = Block size. - * allocator = Allocator was used to allocate $(D_PARAM input). - * - * Returns: The function modifies the initial array and returns it. - * - * See_Also: - * $(D_PSYMBOL pad) - */ -ref ubyte[] unpad(ref ubyte[] input, - in PaddingMode mode, - in ushort blockSize, - shared Allocator allocator = defaultAllocator) -in -{ - assert(input.length != 0); - assert(input.length % 64 == 0); -} -body -{ - final switch (mode) with (PaddingMode) - { - case zero: - break; - case pkcs7: - case ansiX923: - immutable last = input[$ - 1]; - - allocator.resizeArray(input, input.length - (last ? last : blockSize)); - break; - } - - return input; -} - -/// -unittest -{ - { // Zeros - auto input = defaultAllocator.makeArray!ubyte(50); - auto inputDup = defaultAllocator.makeArray!ubyte(50); - - pad(input, PaddingMode.zero, 64); - pad(inputDup, PaddingMode.zero, 64); - - unpad(input, PaddingMode.zero, 64); - assert(input == inputDup); - - defaultAllocator.dispose(input); - defaultAllocator.dispose(inputDup); - - } - { // PKCS#7 - auto input = defaultAllocator.makeArray!ubyte(50); - auto inputDup = defaultAllocator.makeArray!ubyte(50); - for (ubyte i; i < 40; ++i) - { - input[i] = i; - inputDup[i] = i; - } - - pad(input, PaddingMode.pkcs7, 64); - unpad(input, PaddingMode.pkcs7, 64); - assert(input == inputDup); - - defaultAllocator.dispose(input); - defaultAllocator.dispose(inputDup); - } - { // ANSI X.923 - auto input = defaultAllocator.makeArray!ubyte(50); - auto inputDup = defaultAllocator.makeArray!ubyte(50); - for (ubyte i; i < 40; ++i) - { - input[i] = i; - inputDup[i] = i; - } - - pad(input, PaddingMode.pkcs7, 64); - unpad(input, PaddingMode.pkcs7, 64); - assert(input == inputDup); - - defaultAllocator.dispose(input); - defaultAllocator.dispose(inputDup); - } -} diff --git a/source/tanya/crypto/package.d b/source/tanya/crypto/package.d deleted file mode 100644 index 37cb3c7..0000000 --- a/source/tanya/crypto/package.d +++ /dev/null @@ -1,16 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -/** - * Copyright: Eugene Wissner 2016. - * License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/, - * Mozilla Public License, v. 2.0). - * Authors: $(LINK2 mailto:belka@caraus.de, Eugene Wissner) - */ -module tanya.crypto; - -public import tanya.crypto.bit; -public import tanya.crypto.des; -public import tanya.crypto.mode; -public import tanya.crypto.symmetric; diff --git a/source/tanya/crypto/symmetric.d b/source/tanya/crypto/symmetric.d deleted file mode 100644 index b6c268a..0000000 --- a/source/tanya/crypto/symmetric.d +++ /dev/null @@ -1,177 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -/** - * Interfaces for implementing secret key algorithms. - * - * Copyright: Eugene Wissner 2016. - * License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/, - * Mozilla Public License, v. 2.0). - * Authors: $(LINK2 mailto:belka@caraus.de, Eugene Wissner) - */ -module tanya.crypto.symmetric; - -/** - * Implemented by secret key algorithms. - */ -interface SymmetricCipher -{ - /** - * Returns: Key length. - */ - @property inout(uint) keyLength() inout const pure nothrow @safe @nogc; - - /** - * Returns: Minimum key length. - */ - @property inout(uint) minKeyLength() inout const pure nothrow @safe @nogc; - - /** - * Returns: Maximum key length. - */ - @property inout(uint) maxKeyLength() inout const pure nothrow @safe @nogc; - - /// Cipher direction. - protected enum Direction : ushort - { - encryption, - decryption, - } - - /** - * Params: - * key = Key. - */ - @property void key(ubyte[] key) pure nothrow @safe @nogc - in - { - assert(key.length >= minKeyLength); - assert(key.length <= maxKeyLength); - } -} - -/** - * Implemented by block ciphers. - */ -interface BlockCipher : SymmetricCipher -{ - /** - * Returns: Block size. - */ - @property inout(uint) blockSize() inout const pure nothrow @safe @nogc; - - /** - * Encrypts a block. - * - * Params: - * plain = Plain text, input. - * cipher = Cipher text, output. - */ - void encrypt(in ubyte[] plain, ubyte[] cipher) - in - { - assert(plain.length == blockSize); - assert(cipher.length == blockSize); - } - - /** - * Decrypts a block. - * - * Params: - * cipher = Cipher text, input. - * plain = Plain text, output. - */ - void decrypt(in ubyte[] cipher, ubyte[] plain) - in - { - assert(plain.length == blockSize); - assert(cipher.length == blockSize); - } -} - -/** - * Mixed in by algorithms with fixed block size. - * - * Params: - * N = Block size. - */ -mixin template FixedBlockSize(uint N) - if (N != 0) -{ - private enum uint blockSize_ = N; - - /** - * Returns: Fixed block size. - */ - final @property inout(uint) blockSize() inout const pure nothrow @safe @nogc - { - return blockSize_; - } -} - -/** - * Mixed in by symmetric algorithms. - * If $(D_PARAM Min) equals $(D_PARAM Max) fixed key length is assumed. - * - * Params: - * Min = Minimum key length. - * Max = Maximum key length. - */ -mixin template KeyLength(uint Min, uint Max = Min) - if (Min != 0 && Max != 0) -{ - static if (Min == Max) - { - private enum uint keyLength_ = Min; - - /** - * Returns: Key length. - */ - final @property inout(uint) keyLength() inout const pure nothrow @safe @nogc - { - return keyLength_; - } - - /** - * Returns: Minimum key length. - */ - final @property inout(uint) minKeyLength() inout const pure nothrow @safe @nogc - { - return keyLength_; - } - - /** - * Returns: Maximum key length. - */ - final @property inout(uint) maxKeyLength() inout const pure nothrow @safe @nogc - { - return keyLength_; - } - } - else static if (Min < Max) - { - private enum uint minKeyLength_ = Min; - private enum uint maxKeyLength_ = Max; - - /** - * Returns: Minimum key length. - */ - final @property inout(uint) minKeyLength() inout const pure nothrow @safe @nogc - { - return minKeyLength_; - } - - /** - * Returns: Maximum key length. - */ - final @property inout(uint) maxKeyLength() inout const pure nothrow @safe @nogc - { - return maxKeyLength_; - } - } - else - { - static assert(false, "Max should be larger or equal to Min"); - } -}