# HG changeset patch # User Thomas Dixon # Date 1241926160 14400 # Node ID 8b5eaf3c297954befc76e8dfbf7747fdf8d483a2 # Parent 176c933827a8a9c9ea9306162bcfd2554fc7d9a9 Fixed error in hash message padding reported by Glenn Haecker. diff -r 176c933827a8 -r 8b5eaf3c2979 dcrypt/crypto/BlockCipher.d --- a/dcrypt/crypto/BlockCipher.d Sun Mar 01 13:06:48 2009 -0500 +++ b/dcrypt/crypto/BlockCipher.d Sat May 09 23:29:20 2009 -0400 @@ -12,7 +12,8 @@ public import dcrypt.crypto.params.SymmetricKey; /** Interface for a standard block cipher. */ -abstract class BlockCipher : Cipher { +abstract class BlockCipher : Cipher +{ /** Returns: The block size in bytes that this cipher will operate on. */ uint blockSize(); diff -r 176c933827a8 -r 8b5eaf3c2979 dcrypt/crypto/BlockCipherPadding.d --- a/dcrypt/crypto/BlockCipherPadding.d Sun Mar 01 13:06:48 2009 -0500 +++ b/dcrypt/crypto/BlockCipherPadding.d Sat May 09 23:29:20 2009 -0400 @@ -11,7 +11,8 @@ public import dcrypt.crypto.errors.InvalidPaddingError; /** Base padding class for implementing block padding schemes. */ - abstract class BlockCipherPadding { + abstract class BlockCipherPadding + { /** Returns: The name of the padding scheme implemented. */ char[] name(); diff -r 176c933827a8 -r 8b5eaf3c2979 dcrypt/crypto/Cipher.d --- a/dcrypt/crypto/Cipher.d Sun Mar 01 13:06:48 2009 -0500 +++ b/dcrypt/crypto/Cipher.d Sat May 09 23:29:20 2009 -0400 @@ -16,7 +16,8 @@ public import dcrypt.crypto.params.CipherParameters; /** Base symmetric cipher class */ -abstract class Cipher { +abstract class Cipher +{ static const bool ENCRYPT = true, DECRYPT = false; @@ -48,7 +49,8 @@ char[] name(); /** Returns: Whether or not the cipher has been initialized. */ - bool initialized() { + bool initialized() + { return _initialized; } diff -r 176c933827a8 -r 8b5eaf3c2979 dcrypt/crypto/Hash.d --- a/dcrypt/crypto/Hash.d Sun Mar 01 13:06:48 2009 -0500 +++ b/dcrypt/crypto/Hash.d Sat May 09 23:29:20 2009 -0400 @@ -12,20 +12,24 @@ public import dcrypt.misc.Bitwise; /** Base class for all cryptographic hash functions */ -class Hash { - private const enum { +class Hash +{ + private const enum + { MODE_MD=0, // MDx, RipeMD, etc MODE_SHA, MODE_TIGER } - protected { + protected + { ubyte[] buffer; ulong bytes; uint index; } - this (void[] input_=null) { + this (void[] input_=null) + { buffer = new ubyte[blockSize]; ubyte[] input = cast(ubyte[]) input_; if (input) @@ -52,16 +56,20 @@ * * Returns: Self */ - Hash update(void[] input_) { + Hash update(void[] input_) + { ubyte[] input = cast(ubyte[]) input_; - foreach (ubyte i; input) { + foreach (ubyte i; input) + { bytes++; buffer[index++] = i; - if (index == blockSize) { + if (index == blockSize) + { transform(buffer); index = 0; } } + return this; } @@ -75,28 +83,39 @@ * mode = Mode constant dictating in which manner * to pad the message. */ - protected void padMessage(uint mode) { + protected void padMessage(uint mode) + { ulong bits = bytes << 3; // Add the pad marker buffer[index++] = ((mode == MODE_TIGER) ? 0x01 : 0x80); - if (index == blockSize) { + if (index == blockSize) + { transform(buffer); index = 0; } // Pad with null bytes - if (index >= (blockSize-(blockSize >> 3))) - update(new ubyte[blockSize-index]); - update(new ubyte[(blockSize-ulong.sizeof)-index]); + while ((index & (blockSize - 1)) != (blockSize - long.sizeof)) + { + buffer[index++] = 0; + + if (index == blockSize) + { + transform(buffer); + index = 0; + } + } // Length padding - ubyte[] length = new ubyte[ulong.sizeof]; - for (int i = 0, j = 0; i < 64; i+=8) // little endian - length[j++] = bits >> i; + for (int i = 0; i < 64; i+=8) // little endian + buffer[index++] = bits >> i; + if (mode == MODE_SHA) - length.reverse; // big endian - update(length); + buffer[index-ulong.sizeof..index].reverse; // big endian + + transform(buffer); + index = 0; } /** @@ -112,12 +131,14 @@ * * Returns: Representation of the final hash value in hex. */ - char[] hexDigest() { + char[] hexDigest() + { return ByteConverter.hexEncode(digest()); } /** Reset hash to initial state. */ - void reset() { + void reset() + { bytes = index = 0; } } diff -r 176c933827a8 -r 8b5eaf3c2979 dcrypt/crypto/MAC.d --- a/dcrypt/crypto/MAC.d Sun Mar 01 13:06:48 2009 -0500 +++ b/dcrypt/crypto/MAC.d Sat May 09 23:29:20 2009 -0400 @@ -14,7 +14,8 @@ import dcrypt.misc.ByteConverter; /** Base MAC class */ -abstract class MAC { +abstract class MAC +{ /** * Initialize a MAC. * @@ -47,7 +48,8 @@ ubyte[] digest(); /** Returns: The computed MAC in hexadecimal. */ - char[] hexDigest() { + char[] hexDigest() + { return ByteConverter.hexEncode(digest()); } } diff -r 176c933827a8 -r 8b5eaf3c2979 dcrypt/crypto/ManagedBlockCipher.d --- a/dcrypt/crypto/ManagedBlockCipher.d Sun Mar 01 13:06:48 2009 -0500 +++ b/dcrypt/crypto/ManagedBlockCipher.d Sat May 09 23:29:20 2009 -0400 @@ -17,11 +17,13 @@ * * Based on PaddedBufferedBlockCipher from BC. */ -class ManagedBlockCipher : BlockCipher { +class ManagedBlockCipher : BlockCipher +{ BlockCipher cipher; BlockCipherPadding padding; - protected { + protected + { ubyte[] buffer; uint index; bool encrypt, @@ -37,7 +39,8 @@ * * Returns: A new ManagedBlockCipher */ - this(BlockCipher cipher, BlockCipherPadding padding=null) { + this(BlockCipher cipher, BlockCipherPadding padding=null) + { this.cipher = cipher; char[] mode = cipher.name; @@ -45,27 +48,33 @@ for (i = 0; i < mode.length; i++) if (mode[i] == '/') break; - if (i < mode.length) { + + if (i < mode.length) + { mode = mode[i+1..i+4]; - this.streamMode = (mode == "CTR" || mode == "CFB" || mode == "OFB"); + this.streamMode = (mode == "CTR" /*|| mode == "CFB" || mode == "OFB"*/); } this.padding = padding; // null signifies no padding is to be applied buffer = new ubyte[blockSize]; } - void init(bool encrypt, CipherParameters params) { + void init(bool encrypt, CipherParameters params) + { this.encrypt = encrypt; cipher.init(encrypt, params); } - char[] name() { + char[] name() + { if (padding is null) return cipher.name; + return cipher.name~"/"~padding.name; } - uint blockSize() { + uint blockSize() + { return cipher.blockSize; } @@ -75,7 +84,8 @@ * * Returns: The number of bytes placed in output_. */ - uint update(void[] input_, void[] output_) { + uint update(void[] input_, void[] output_) + { ubyte[] input = cast(ubyte[]) input_, output = cast(ubyte[]) output_; @@ -86,14 +96,16 @@ len = input.length, diff = buffer.length - index, i = 0; - if (len >= diff) { + if (len >= diff) + { buffer[index..buffer.length] = input[i..diff]; result += cipher.update(buffer, output[i..i+blockSize]); index = 0; len -= diff; i += blockSize; - while (len > blockSize) { + while (len > blockSize) + { result += cipher.update(input[i..i+blockSize], output[i..i+blockSize]); len -= blockSize; i += blockSize; @@ -113,18 +125,23 @@ * * Returns: The number of bytes placed in output_. */ - uint finish(void[] output_) { + uint finish(void[] output_) + { ubyte[] output = cast(ubyte[]) output_; uint result = 0; - if (encrypt) { - if (index == blockSize) { + if (encrypt) + { + if (index == blockSize) + { if (padding !is null && output.length < (blockSize << 1)) throw new ShortBufferError("Managed "~name()~": Output buffer too short"); + result += cipher.update(buffer, output[result..result+blockSize]); index = 0; } - if (padding !is null) { + if (padding !is null) + { uint diff = buffer.length - index; buffer[index..buffer.length] = padding.pad(diff); index += diff; @@ -132,24 +149,37 @@ if (index) result += cipher.update(buffer[0..index], output[result..result+index]); - } else { // decrypt - if (streamMode || index == blockSize) { + + } + else // decrypt + { + if (streamMode || index == blockSize) + { result += cipher.update(buffer[0..index], buffer[0..index]); index = 0; - } else { + } + else + { reset(); throw new ShortBufferError( "Managed "~name()~": Padded last block not equal to cipher's blocksize"); } - try { + + try + { if (padding !is null) result -= padding.unpad(buffer); + output[0..result] = buffer[0..result]; - } finally { + } + finally + { reset(); } } + reset(); + return result; } @@ -160,7 +190,8 @@ * Returns: The number of bytes to be output upon a call to update() * with an input length of len bytes. */ - uint updateOutputSize(uint len) { + uint updateOutputSize(uint len) + { uint result = len + index; return result - (result % blockSize); } @@ -175,7 +206,8 @@ * return 0 if your input is likely to error (i.e. len is 14 * for AES in ECB mode). */ - uint finishOutputSize(uint len) { + uint finishOutputSize(uint len) + { uint result = len + index, diff = result % blockSize; @@ -191,7 +223,8 @@ return (encrypt ? result - diff + blockSize : 0); } - void reset() { + void reset() + { cipher.reset(); index = 0; buffer[] = 0; diff -r 176c933827a8 -r 8b5eaf3c2979 dcrypt/crypto/PRNG.d --- a/dcrypt/crypto/PRNG.d Sun Mar 01 13:06:48 2009 -0500 +++ b/dcrypt/crypto/PRNG.d Sat May 09 23:29:20 2009 -0400 @@ -14,12 +14,14 @@ public import dcrypt.crypto.errors.NotSupportedError; /** Relatively simple interface for PRNGs. */ -abstract class PRNG { +abstract class PRNG +{ protected bool _initialized; /** Returns: Whether or not the PRNG has been initialized. */ - bool initialized() { + bool initialized() + { return _initialized; } diff -r 176c933827a8 -r 8b5eaf3c2979 dcrypt/crypto/StreamCipher.d --- a/dcrypt/crypto/StreamCipher.d Sun Mar 01 13:06:48 2009 -0500 +++ b/dcrypt/crypto/StreamCipher.d Sat May 09 23:29:20 2009 -0400 @@ -13,7 +13,8 @@ public import dcrypt.crypto.params.SymmetricKey; /** Interface for a standard stream cipher. */ -abstract class StreamCipher : Cipher { +abstract class StreamCipher : Cipher +{ /** * Process one byte of input. * diff -r 176c933827a8 -r 8b5eaf3c2979 dcrypt/crypto/ciphers/AES.d --- a/dcrypt/crypto/ciphers/AES.d Sun Mar 01 13:06:48 2009 -0500 +++ b/dcrypt/crypto/ciphers/AES.d Sat May 09 23:29:20 2009 -0400 @@ -19,8 +19,10 @@ * Conforms: FIPS-197 * References: http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf */ -class AES : BlockCipher { - private { +class AES : BlockCipher +{ + private + { // Round constants static const uint[10] RCON = [ 0x01000000u, 0x02000000u, 0x04000000u, 0x08000000u, 0x10000000u, @@ -644,31 +646,37 @@ } // end private - char[] name() { + char[] name() + { return "AES"; } - uint rounds() { + uint rounds() + { if (!_initialized) throw new NotInitializedError(name()~": Cipher not initialized."); return ROUNDS; } - uint blockSize() { + uint blockSize() + { return BLOCK_SIZE; } - void init(bool encrypt, CipherParameters params) { + void init(bool encrypt, CipherParameters params) + { SymmetricKey keyParams = cast(SymmetricKey)params; if (!keyParams) throw new InvalidParameterError( name()~": Invalid parameter passed to init"); + _encrypt = encrypt; uint len = keyParams.key.length; if (len != 16 && len != 24 && len != 32) throw new InvalidKeyError( - name()~": Invalid key length (requires 16, 24 or 32 bytes)"); + name()~": Invalid key length (requires 16, 24 or 32 bytes)"); + workingKey = keyParams.key; setup(workingKey); @@ -676,11 +684,14 @@ _initialized = true; } - private void encryptBlock() { + private void encryptBlock() + { uint i = 4, r = ROUNDS >> 1, t0, t1, t2, t3; - while (--r >= 0) { + + while (--r >= 0) + { t0 = w[i++] ^ TE0[s0 >> 24] ^ TE1[cast(ubyte)(s1 >> 16)] ^ TE2[cast(ubyte)(s2 >> 8)] ^ @@ -738,11 +749,14 @@ S[cast(ubyte) t2]; } - private void decryptBlock() { + private void decryptBlock() + { uint i = 4, r = ROUNDS >> 1, t0, t1, t2, t3; - while (--r >= 0) { + + while (--r >= 0) + { t0 = w[i++] ^ TD0[s0 >> 24] ^ TD1[cast(ubyte)(s3 >> 16)] ^ TD2[cast(ubyte)(s2 >> 8)] ^ @@ -799,7 +813,8 @@ RS[cast(ubyte) t0]; } - uint update(void[] input_, void[] output_) { + uint update(void[] input_, void[] output_) + { if (!_initialized) throw new NotInitializedError(name()~": Cipher not initialized."); @@ -829,14 +844,16 @@ void reset() {} - private uint subWord(uint x) { + private uint subWord(uint x) + { return ((S[x>>24] << 24) | (S[cast(ubyte)(x>>8)] << 8) | (S[cast(ubyte)(x>>16)] << 16)| (S[cast(ubyte)x])); } - private void setup(ubyte[] key) { + private void setup(ubyte[] key) + { uint nk = key.length / 4; ROUNDS = nk + 6; w = new uint[4*(ROUNDS+1)]; @@ -844,7 +861,8 @@ for (uint i = 0, j = 0; i < nk; i++, j+=4) w[i] = ByteConverter.BigEndian.to!(uint)(key[j..j+int.sizeof]); - for (uint i = nk; i < w.length; i++) { + for (uint i = nk; i < w.length; i++) + { uint t = w[i-1]; if (i % nk == 0) @@ -855,23 +873,27 @@ w[i] = w[i-nk] ^ t; } - if (!_encrypt) { + if (!_encrypt) + { for (uint i = 0; i <= 4*ROUNDS; i+=4) w[i..i+4].reverse; w.reverse; - for (uint i = 4; i < w.length-4; i++) { - w[i] = (TD0[S[w[i]>>24]] ^ + for (uint i = 4; i < w.length-4; i++) + { + w[i] = (TD0[S[w[i]>>24]] ^ TD1[S[cast(ubyte)(w[i]>>16)]] ^ - TD2[S[cast(ubyte)(w[i]>>8)]] ^ + TD2[S[cast(ubyte)(w[i]>>8)]] ^ TD3[S[cast(ubyte)w[i]]]); } } } /** Some AES test vectors from the FIPS-197 paper and BC. */ - debug (UnitTest) { - unittest { + debug (UnitTest) + { + unittest + { static const char[][] test_keys = [ "000102030405060708090a0b0c0d0e0f", "000102030405060708090a0b0c0d0e0f1011121314151617", @@ -901,7 +923,8 @@ ]; AES t = new AES(); - foreach (uint i, char[] test_key; test_keys) { + foreach (uint i, char[] test_key; test_keys) + { ubyte[] buffer = new ubyte[t.blockSize]; char[] result; SymmetricKey key = new SymmetricKey(ByteConverter.hexDecode(test_key)); diff -r 176c933827a8 -r 8b5eaf3c2979 dcrypt/crypto/ciphers/Blowfish.d --- a/dcrypt/crypto/ciphers/Blowfish.d Sun Mar 01 13:06:48 2009 -0500 +++ b/dcrypt/crypto/ciphers/Blowfish.d Sat May 09 23:29:20 2009 -0400 @@ -15,8 +15,10 @@ import dcrypt.crypto.BlockCipher; /** Implementation of the Blowfish cipher designed by Bruce Schneier. */ -class Blowfish : BlockCipher { - private { +class Blowfish : BlockCipher +{ + private + { static const uint[1024] S_INIT = [ 0xd1310ba6u, 0x98dfb5acu, 0x2ffd72dbu, 0xd01adfb7u, 0xb8e1afedu, 0x6a267e96u, 0xba7c9045u, 0xf12c7f99u, 0x24a19947u, 0xb3916cf7u, 0x0801f2e2u, 0x858efc16u, @@ -212,19 +214,23 @@ ubyte[] workingKey; } // end private - char[] name() { + char[] name() + { return "Blowfish"; } - uint blockSize() { + uint blockSize() + { return BLOCK_SIZE; } - void init(bool encrypt, CipherParameters params) { + void init(bool encrypt, CipherParameters params) + { SymmetricKey keyParams = cast(SymmetricKey)params; if (!keyParams) throw new InvalidParameterError( name()~": Invalid parameter passed to init"); + _encrypt = encrypt; uint len = keyParams.key.length; @@ -243,14 +249,16 @@ P.reverse; // Oh yes I did. } - private uint F(uint x) { + private uint F(uint x) + { return (((S0[(x >> 24)] + S1[cast(ubyte)(x >> 16)]) ^ S2[cast(ubyte)(x >> 8)]) + S3[cast(ubyte)x]); } - uint update(void[] input_, void[] output_) { + uint update(void[] input_, void[] output_) + { if (!_initialized) throw new NotInitializedError(name()~": Cipher not initialized."); @@ -268,7 +276,8 @@ i = 0; xl ^= P[i++]; - for (; i < ROUNDS;) { + for (; i < ROUNDS;) + { xr ^= F(xl) ^ P[i++]; xl ^= F(xr) ^ P[i++]; } @@ -280,11 +289,13 @@ return BLOCK_SIZE; } - void reset() { + void reset() + { setup(workingKey); } - private void setup(ubyte[] key) { + private void setup(ubyte[] key) + { S0[] = S_INIT[0..256]; S1[] = S_INIT[256..512]; S2[] = S_INIT[512..768]; @@ -293,42 +304,50 @@ uint index = 0; - for (int i = 0; i < PBOX_SIZE; i++) { + for (int i = 0; i < PBOX_SIZE; i++) + { uint x = 0; - for (int j = 0; j < 4; j++) { + for (int j = 0; j < 4; j++) + { x = (x << 8) | key[index++]; if (index == key.length) index = 0; } + P[i] ^= x; } ubyte[] t = new ubyte[BLOCK_SIZE]; // Initialized to 0's - for (int i = 0; i < PBOX_SIZE;) { + for (int i = 0; i < PBOX_SIZE;) + { update(t, t); P[i++] = ByteConverter.BigEndian.to!(uint)(t[0..4]); P[i++] = ByteConverter.BigEndian.to!(uint)(t[4..8]); } - for (int i = 0; i < SBOX_SIZE;) { + for (int i = 0; i < SBOX_SIZE;) + { update(t, t); S0[i++] = ByteConverter.BigEndian.to!(uint)(t[0..4]); S0[i++] = ByteConverter.BigEndian.to!(uint)(t[4..8]); } - for (int i = 0; i < SBOX_SIZE;) { + for (int i = 0; i < SBOX_SIZE;) + { update(t, t); S1[i++] = ByteConverter.BigEndian.to!(uint)(t[0..4]); S1[i++] = ByteConverter.BigEndian.to!(uint)(t[4..8]); } - for (int i = 0; i < SBOX_SIZE;) { + for (int i = 0; i < SBOX_SIZE;) + { update(t, t); S2[i++] = ByteConverter.BigEndian.to!(uint)(t[0..4]); S2[i++] = ByteConverter.BigEndian.to!(uint)(t[4..8]); } - for (int i = 0; i < SBOX_SIZE;) { + for (int i = 0; i < SBOX_SIZE;) + { update(t, t); S3[i++] = ByteConverter.BigEndian.to!(uint)(t[0..4]); S3[i++] = ByteConverter.BigEndian.to!(uint)(t[4..8]); @@ -336,8 +355,10 @@ } /** Some Blowfish test vectors from Schneier's site. */ - debug (UnitTest) { - unittest { + debug (UnitTest) + { + unittest + { static const char[][] test_keys = [ "0000000000000000", "ffffffffffffffff", @@ -369,7 +390,8 @@ ]; Blowfish t = new Blowfish(); - foreach (uint i, char[] test_key; test_keys) { + foreach (uint i, char[] test_key; test_keys) + { ubyte[] buffer = new ubyte[t.blockSize]; char[] result; SymmetricKey key = new SymmetricKey(ByteConverter.hexDecode(test_key)); diff -r 176c933827a8 -r 8b5eaf3c2979 dcrypt/crypto/ciphers/ChaCha.d --- a/dcrypt/crypto/ciphers/ChaCha.d Sun Mar 01 13:06:48 2009 -0500 +++ b/dcrypt/crypto/ciphers/ChaCha.d Sat May 09 23:29:20 2009 -0400 @@ -15,17 +15,21 @@ import dcrypt.misc.Bitwise; /** Implementation of ChaCha designed by Daniel J. Bernstein. */ -class ChaCha : Salsa20 { - char[] name() { +class ChaCha : Salsa20 +{ + char[] name() + { return "ChaCha"; } - this() { + this() + { i0 = 12; i1 = 13; } - protected void keySetup() { + protected void keySetup() + { uint offset; ubyte[] constants; @@ -34,7 +38,8 @@ state[6] = ByteConverter.LittleEndian.to!(uint)(workingKey[8..12]); state[7] = ByteConverter.LittleEndian.to!(uint)(workingKey[12..16]); - if (workingKey.length == 32) { + if (workingKey.length == 32) + { constants = sigma; offset = 16; } else @@ -50,18 +55,21 @@ state[ 3] = ByteConverter.LittleEndian.to!(uint)(constants[12..16]); } - protected void ivSetup() { + protected void ivSetup() + { state[12] = state[13] = 0; state[14] = ByteConverter.LittleEndian.to!(uint)(workingIV[0..4]); state[15] = ByteConverter.LittleEndian.to!(uint)(workingIV[4..8]); } - protected void salsa20WordToByte(uint[] input, ref ubyte[] output) { + protected void salsa20WordToByte(uint[] input, ref ubyte[] output) + { uint[] x = new uint[16]; x[] = input; int i; - for (i = 0; i < 4; i++) { + for (i = 0; i < 4; i++) + { x[ 0] += x[ 4]; x[12] = Bitwise.rotateLeft(x[12]^x[ 0], 16); x[ 8] += x[12]; x[ 4] = Bitwise.rotateLeft(x[ 4]^x[ 8], 12); x[ 0] += x[ 4]; x[12] = Bitwise.rotateLeft(x[12]^x[ 0], 8); @@ -105,8 +113,10 @@ } /** ChaCha test vectors */ - debug (UnitTest) { - unittest { + debug (UnitTest) + { + unittest + { static const char[][] test_keys = [ "80000000000000000000000000000000", "0053a6f94c9ff24598eb3e91e4378add", @@ -173,7 +183,8 @@ ChaCha cc = new ChaCha(); ubyte[] buffer = new ubyte[64]; char[] result; - for (int i = 0; i < test_keys.length; i++) { + for (int i = 0; i < test_keys.length; i++) + { SymmetricKey key = new SymmetricKey(ByteConverter.hexDecode(test_keys[i])); ParametersWithIV params = new ParametersWithIV(key, ByteConverter.hexDecode(test_ivs[i])); diff -r 176c933827a8 -r 8b5eaf3c2979 dcrypt/crypto/ciphers/RC4.d --- a/dcrypt/crypto/ciphers/RC4.d Sun Mar 01 13:06:48 2009 -0500 +++ b/dcrypt/crypto/ciphers/RC4.d Sat May 09 23:29:20 2009 -0400 @@ -15,18 +15,22 @@ } /** Implementation of RC4 designed by Ron Rivest of RSA Security. */ -class RC4 : StreamCipher { - private { +class RC4 : StreamCipher +{ + private + { ubyte[] state, workingKey; ubyte x, y; } - this() { + this() + { state = new ubyte[256]; } - void init(bool encrypt, CipherParameters params) { + void init(bool encrypt, CipherParameters params) + { SymmetricKey keyParams = cast(SymmetricKey)params; if (!keyParams) @@ -43,11 +47,13 @@ _encrypt = _initialized = true; } - char[] name() { + char[] name() + { return "RC4"; } - ubyte returnByte(ubyte input) { + ubyte returnByte(ubyte input) + { if (!_initialized) throw new NotInitializedError(name()~": Cipher not initialized"); @@ -59,7 +65,8 @@ return (input^state[cast(ubyte)(state[x]+state[y])]); } - uint update(void[] input_, void[] output_) { + uint update(void[] input_, void[] output_) + { if (!_initialized) throw new NotInitializedError(name()~": Cipher not initialized"); @@ -69,7 +76,8 @@ if (input.length > output.length) throw new ShortBufferError(name()~": Output buffer too short"); - for (int i = 0; i < input.length; i++) { + for (int i = 0; i < input.length; i++) + { y += state[++x]; ubyte t = state[x]; state[x] = state[y]; @@ -80,17 +88,20 @@ return input.length; } - void reset() { + void reset() + { setup(workingKey); } // Do RC4's key setup in a separate method to ease resetting - private void setup(ubyte[] key) { + private void setup(ubyte[] key) + { for (int i = 0; i < 256; i++) state[i] = cast(ubyte)i; x = 0; - for (int i = 0; i < 256; i++) { + for (int i = 0; i < 256; i++) + { x += key[i % key.length] + state[i]; ubyte t = state[i]; state[i] = state[x]; @@ -101,8 +112,10 @@ } /** Some RC4 test vectors. */ - debug (UnitTest) { - unittest { + debug (UnitTest) + { + unittest + { static const char[][] test_keys = [ "0123456789abcdef", "0123456789abcdef", @@ -190,7 +203,8 @@ ]; RC4 r = new RC4(); - foreach (uint i, char[] test_key; test_keys) { + foreach (uint i, char[] test_key; test_keys) + { ubyte[] buffer = new ubyte[test_plaintexts[i].length>>1]; char[] result; diff -r 176c933827a8 -r 8b5eaf3c2979 dcrypt/crypto/ciphers/RC6.d --- a/dcrypt/crypto/ciphers/RC6.d Sun Mar 01 13:06:48 2009 -0500 +++ b/dcrypt/crypto/ciphers/RC6.d Sat May 09 23:29:20 2009 -0400 @@ -25,8 +25,10 @@ * * References: http://people.csail.mit.edu/rivest/Rc6.pdf */ -class RC6 : BlockCipher { - private { +class RC6 : BlockCipher +{ + private + { const uint ROUNDS = 20, BLOCK_SIZE = 16, // Magic constants for a 32 bit word size @@ -36,19 +38,23 @@ ubyte[] workingKey; } - char[] name() { + char[] name() + { return "RC6"; } - uint blockSize() { + uint blockSize() + { return BLOCK_SIZE; } - void init(bool encrypt, CipherParameters params) { + void init(bool encrypt, CipherParameters params) + { SymmetricKey keyParams = cast(SymmetricKey)params; if (!keyParams) throw new InvalidParameterError( name()~": Invalid parameter passed to init"); + _encrypt = encrypt; uint len = keyParams.key.length; @@ -84,10 +90,13 @@ t, u; - if (_encrypt) { + if (_encrypt) + { B += S[0]; D += S[1]; - for (int i = 1; i <= ROUNDS; i++) { + + for (int i = 1; i <= ROUNDS; i++) + { t = Bitwise.rotateLeft(B*((B<<1)+1), 5); u = Bitwise.rotateLeft(D*((D<<1)+1), 5); A = Bitwise.rotateLeft(A^t, u) + S[i<<1]; @@ -98,12 +107,17 @@ C = D; D = t; } + A += S[2*ROUNDS+2]; C += S[2*ROUNDS+3]; - } else { + } + else + { C -= S[2*ROUNDS+3]; A -= S[2*ROUNDS+2]; - for (int i = ROUNDS; i >= 1; i--) { + + for (int i = ROUNDS; i >= 1; i--) + { t = D; D = C; C = B; @@ -114,6 +128,7 @@ C = Bitwise.rotateRight(C-S[(i<<1)+1], t) ^ u; A = Bitwise.rotateRight(A-S[i<<1], u) ^ t; } + D -= S[1]; B -= S[0]; } @@ -126,11 +141,13 @@ return BLOCK_SIZE; } - void reset() { + void reset() + { setup(workingKey); } - void setup(ubyte[] key) { + void setup(ubyte[] key) + { uint c = key.length/4; uint[] L = new uint[c]; for (int i = 0, j = 0; i < c; i++, j+=4) @@ -141,7 +158,8 @@ S[i] = S[i-1] + Q; uint A, B, i, j, v = 3*(2*ROUNDS+4); // Relying on ints initializing to 0 - for (int s = 1; s <= v; s++) { + for (int s = 1; s <= v; s++) + { A = S[i] = Bitwise.rotateLeft(S[i]+A+B, 3); B = L[j] = Bitwise.rotateLeft(L[j]+A+B, A+B); i = (i + 1) % (2*ROUNDS+4); @@ -150,8 +168,10 @@ } /** Some RC6 test vectors from the spec. */ - debug (UnitTest) { - unittest { + debug (UnitTest) + { + unittest + { static const char[][] test_keys = [ "00000000000000000000000000000000", "0123456789abcdef0112233445566778", @@ -184,7 +204,8 @@ ]; RC6 t = new RC6(); - foreach (uint i, char[] test_key; test_keys) { + foreach (uint i, char[] test_key; test_keys) + { ubyte[] buffer = new ubyte[t.blockSize]; char[] result; SymmetricKey key = new SymmetricKey(ByteConverter.hexDecode(test_key)); diff -r 176c933827a8 -r 8b5eaf3c2979 dcrypt/crypto/ciphers/Salsa20.d --- a/dcrypt/crypto/ciphers/Salsa20.d Sun Mar 01 13:06:48 2009 -0500 +++ b/dcrypt/crypto/ciphers/Salsa20.d Sat May 09 23:29:20 2009 -0400 @@ -14,8 +14,10 @@ import dcrypt.misc.Bitwise; /** Implementation of Salsa20 designed by Daniel J. Bernstein. */ -class Salsa20 : StreamCipher { - protected { +class Salsa20 : StreamCipher +{ + protected + { // Constants const ubyte[] sigma = cast(ubyte[])"expand 32-byte k", tau = cast(ubyte[])"expand 16-byte k"; @@ -35,7 +37,8 @@ workingIV; } - this() { + this() + { state = new uint[16]; // State expanded into bytes @@ -45,7 +48,8 @@ i1 = 9; } - void init(bool encrypt, CipherParameters params) { + void init(bool encrypt, CipherParameters params) + { ParametersWithIV ivParams = cast(ParametersWithIV)params; if (!ivParams) @@ -57,7 +61,8 @@ ubyte[] iv = ivParams.iv, key = keyParams.key; - if (key) { + if (key) + { if (key.length != 16 && key.length != 32) throw new InvalidKeyError( name()~": Invalid key length. (requires 16 or 32 bytes)"); @@ -80,11 +85,13 @@ _encrypt = _initialized = true; } - char[] name() { + char[] name() + { return "Salsa20"; } - ubyte returnByte(ubyte input) { + ubyte returnByte(ubyte input) + { if (!_initialized) throw new NotInitializedError(name()~": Cipher not initialized"); @@ -103,7 +110,8 @@ return result; } - uint update(void[] input_, void[] output_) { + uint update(void[] input_, void[] output_) + { if (!_initialized) throw new NotInitializedError(name()~": Cipher not initialized"); @@ -113,8 +121,10 @@ if (input.length > output.length) throw new ShortBufferError(name()~": Output buffer too short"); - for (int i = 0; i < input.length; i++) { - if (index == 0) { + for (int i = 0; i < input.length; i++) + { + if (index == 0) + { salsa20WordToByte(state, keyStream); state[i0]++; if (!state[i0]) @@ -129,13 +139,15 @@ return input.length; } - void reset() { + void reset() + { keySetup(); ivSetup(); index = 0; } - protected void keySetup() { + protected void keySetup() + { uint offset; ubyte[] constants; @@ -144,7 +156,8 @@ state[3] = ByteConverter.LittleEndian.to!(uint)(workingKey[8..12]); state[4] = ByteConverter.LittleEndian.to!(uint)(workingKey[12..16]); - if (workingKey.length == 32) { + if (workingKey.length == 32) + { constants = sigma; offset = 16; } else @@ -160,18 +173,21 @@ state[15] = ByteConverter.LittleEndian.to!(uint)(constants[12..16]); } - protected void ivSetup() { + protected void ivSetup() + { state[6] = ByteConverter.LittleEndian.to!(uint)(workingIV[0..4]); state[7] = ByteConverter.LittleEndian.to!(uint)(workingIV[4..8]); state[8] = state[9] = 0; } - protected void salsa20WordToByte(uint[] input, ref ubyte[] output) { + protected void salsa20WordToByte(uint[] input, ref ubyte[] output) + { uint[] x = new uint[16]; x[] = input; int i; - for (i = 0; i < 10; i++) { + for (i = 0; i < 10; i++) + { x[ 4] ^= Bitwise.rotateLeft(x[ 0]+x[12], 7); x[ 8] ^= Bitwise.rotateLeft(x[ 4]+x[ 0], 9); x[12] ^= Bitwise.rotateLeft(x[ 8]+x[ 4], 13); @@ -215,8 +231,10 @@ } /** Salsa20 test vectors */ - debug (UnitTest) { - unittest { + debug (UnitTest) + { + unittest + { static const char[][] test_keys = [ "80000000000000000000000000000000", "0053a6f94c9ff24598eb3e91e4378add", @@ -283,7 +301,8 @@ Salsa20 s20 = new Salsa20(); ubyte[] buffer = new ubyte[64]; char[] result; - for (int i = 0; i < test_keys.length; i++) { + for (int i = 0; i < test_keys.length; i++) + { SymmetricKey key = new SymmetricKey(ByteConverter.hexDecode(test_keys[i])); ParametersWithIV params = new ParametersWithIV(key, ByteConverter.hexDecode(test_ivs[i])); diff -r 176c933827a8 -r 8b5eaf3c2979 dcrypt/crypto/ciphers/TEA.d --- a/dcrypt/crypto/ciphers/TEA.d Sun Mar 01 13:06:48 2009 -0500 +++ b/dcrypt/crypto/ciphers/TEA.d Sat May 09 23:29:20 2009 -0400 @@ -13,31 +13,37 @@ /** Implementation of the TEA cipher designed by David Wheeler and Roger Needham. */ -class TEA : BlockCipher { - private { +class TEA : BlockCipher +{ + private + { const uint ROUNDS = 32, KEY_SIZE = 16, BLOCK_SIZE = 8, - DELTA = 0x9e3779b9, - DECRYPT_SUM = 0xc6ef3720; + DELTA = 0x9e3779b9u, + DECRYPT_SUM = 0xc6ef3720u; uint sk0, sk1, sk2, sk3, sum; } void reset(){} - char[] name() { + char[] name() + { return "TEA"; } - uint blockSize() { + uint blockSize() + { return BLOCK_SIZE; } - void init(bool encrypt, CipherParameters params) { + void init(bool encrypt, CipherParameters params) + { SymmetricKey keyParams = cast(SymmetricKey)params; if (!keyParams) throw new InvalidParameterError( name()~": Invalid parameter passed to init"); + _encrypt = encrypt; if (keyParams.key.length != KEY_SIZE) @@ -52,7 +58,8 @@ _initialized = true; } - uint update(void[] input_, void[] output_) { + uint update(void[] input_, void[] output_) + { if (!_initialized) throw new NotInitializedError(name()~": Cipher not initialized"); @@ -69,12 +76,16 @@ v1 = ByteConverter.BigEndian.to!(uint)(input[4..8]); sum = _encrypt ? 0 : DECRYPT_SUM; - for (int i = 0; i < ROUNDS; i++) { - if (_encrypt) { + for (int i = 0; i < ROUNDS; i++) + { + if (_encrypt) + { sum += DELTA; v0 += ((v1 << 4) + sk0) ^ (v1 + sum) ^ ((v1 >> 5) + sk1); v1 += ((v0 << 4) + sk2) ^ (v0 + sum) ^ ((v0 >> 5) + sk3); - } else { + } + else + { v1 -= ((v0 << 4) + sk2) ^ (v0 + sum) ^ ((v0 >> 5) + sk3); v0 -= ((v1 << 4) + sk0) ^ (v1 + sum) ^ ((v1 >> 5) + sk1); sum -= DELTA; @@ -88,48 +99,53 @@ } /** Some TEA test vectors. */ - unittest { - static const char[][] test_keys = [ - "00000000000000000000000000000000", - "00000000000000000000000000000000", - "0123456712345678234567893456789a", - "0123456712345678234567893456789a" - ]; - - static const char[][] test_plaintexts = [ - "0000000000000000", - "0102030405060708", - "0000000000000000", - "0102030405060708" - ]; + debug (UnitTest) + { + unittest + { + static const char[][] test_keys = [ + "00000000000000000000000000000000", + "00000000000000000000000000000000", + "0123456712345678234567893456789a", + "0123456712345678234567893456789a" + ]; + + static const char[][] test_plaintexts = [ + "0000000000000000", + "0102030405060708", + "0000000000000000", + "0102030405060708" + ]; + + static const char[][] test_ciphertexts = [ + "41ea3a0a94baa940", + "6a2f9cf3fccf3c55", + "34e943b0900f5dcb", + "773dc179878a81c0" + ]; + - static const char[][] test_ciphertexts = [ - "41ea3a0a94baa940", - "6a2f9cf3fccf3c55", - "34e943b0900f5dcb", - "773dc179878a81c0" - ]; - - - TEA t = new TEA(); - foreach (uint i, char[] test_key; test_keys) { - ubyte[] buffer = new ubyte[t.blockSize]; - char[] result; - SymmetricKey key = new SymmetricKey(ByteConverter.hexDecode(test_key)); - - // Encryption - t.init(true, key); - t.update(ByteConverter.hexDecode(test_plaintexts[i]), buffer); - result = ByteConverter.hexEncode(buffer); - assert(result == test_ciphertexts[i], - t.name~": ("~result~") != ("~test_ciphertexts[i]~")"); + TEA t = new TEA(); + foreach (uint i, char[] test_key; test_keys) + { + ubyte[] buffer = new ubyte[t.blockSize]; + char[] result; + SymmetricKey key = new SymmetricKey(ByteConverter.hexDecode(test_key)); + + // Encryption + t.init(true, key); + t.update(ByteConverter.hexDecode(test_plaintexts[i]), buffer); + result = ByteConverter.hexEncode(buffer); + assert(result == test_ciphertexts[i], + t.name~": ("~result~") != ("~test_ciphertexts[i]~")"); - // Decryption - t.init(false, key); - t.update(ByteConverter.hexDecode(test_ciphertexts[i]), buffer); - result = ByteConverter.hexEncode(buffer); - assert(result == test_plaintexts[i], - t.name~": ("~result~") != ("~test_plaintexts[i]~")"); + // Decryption + t.init(false, key); + t.update(ByteConverter.hexDecode(test_ciphertexts[i]), buffer); + result = ByteConverter.hexEncode(buffer); + assert(result == test_plaintexts[i], + t.name~": ("~result~") != ("~test_plaintexts[i]~")"); + } } } } diff -r 176c933827a8 -r 8b5eaf3c2979 dcrypt/crypto/ciphers/XTEA.d --- a/dcrypt/crypto/ciphers/XTEA.d Sun Mar 01 13:06:48 2009 -0500 +++ b/dcrypt/crypto/ciphers/XTEA.d Sat May 09 23:29:20 2009 -0400 @@ -13,12 +13,14 @@ /** Implementation of the XTEA cipher designed by David Wheeler and Roger Needham. */ -class XTEA : BlockCipher { - private { +class XTEA : BlockCipher +{ + private + { const uint ROUNDS = 32, KEY_SIZE = 16, BLOCK_SIZE = 8, - DELTA = 0x9e3779b9; + DELTA = 0x9e3779b9u; uint[] subkeys, sum0, sum1; @@ -26,19 +28,23 @@ void reset(){} - char[] name() { + char[] name() + { return "XTEA"; } - uint blockSize() { + uint blockSize() + { return BLOCK_SIZE; } - void init(bool encrypt, CipherParameters params) { + void init(bool encrypt, CipherParameters params) + { SymmetricKey keyParams = cast(SymmetricKey)params; if (!keyParams) throw new InvalidParameterError( name()~": Invalid parameter passed to init"); + _encrypt = encrypt; if (keyParams.key.length != KEY_SIZE) @@ -54,15 +60,18 @@ subkeys[i] = ByteConverter.BigEndian.to!(uint)(keyParams.key[j..j+int.sizeof]); // Precompute the values of sum + k[] to speed up encryption - for (i = j = 0; i < ROUNDS; i++) { + for (i = j = 0; i < ROUNDS; i++) + { sum0[i] = (j + subkeys[j & 3]); j += DELTA; sum1[i] = (j + subkeys[j >> 11 & 3]); } + _initialized = true; } - uint update(void[] input_, void[] output_) { + uint update(void[] input_, void[] output_) + { if (!_initialized) throw new NotInitializedError(name()~": Cipher not initialized"); @@ -78,13 +87,18 @@ uint v0 = ByteConverter.BigEndian.to!(uint)(input[0..4]), v1 = ByteConverter.BigEndian.to!(uint)(input[4..8]); - if (_encrypt) { - for (int i = 0; i < ROUNDS; i++) { + if (_encrypt) + { + for (int i = 0; i < ROUNDS; i++) + { v0 += ((v1 << 4 ^ v1 >> 5) + v1) ^ sum0[i]; v1 += ((v0 << 4 ^ v0 >> 5) + v0) ^ sum1[i]; } - } else { - for (int i = ROUNDS-1; i >= 0; i--) { + } + else + { + for (int i = ROUNDS-1; i >= 0; i--) + { v1 -= (((v0 << 4) ^ (v0 >> 5)) + v0) ^ sum1[i]; v0 -= (((v1 << 4) ^ (v1 >> 5)) + v1) ^ sum0[i]; } @@ -97,8 +111,10 @@ } /** Some XTEA test vectors. */ - debug (UnitTest) { - unittest { + debug (UnitTest) + { + unittest + { static const char[][] test_keys = [ "00000000000000000000000000000000", "00000000000000000000000000000000", @@ -139,7 +155,8 @@ ]; XTEA t = new XTEA(); - foreach (uint i, char[] test_key; test_keys) { + foreach (uint i, char[] test_key; test_keys) + { ubyte[] buffer = new ubyte[t.blockSize]; char[] result; SymmetricKey key = new SymmetricKey(ByteConverter.hexDecode(test_key)); diff -r 176c933827a8 -r 8b5eaf3c2979 dcrypt/crypto/hashes/MD4.d --- a/dcrypt/crypto/hashes/MD4.d Sun Mar 01 13:06:48 2009 -0500 +++ b/dcrypt/crypto/hashes/MD4.d Sat May 09 23:29:20 2009 -0400 @@ -17,11 +17,13 @@ * References: http://www.faqs.org/rfcs/rfc1320.html * Bugs: MD4 is not cryptographically secure. */ -class MD4 : Hash { +class MD4 : Hash +{ private uint h0, h1, h2, h3; // Shift amounts - private enum { + private enum + { S11 = 3, S12 = 7, S13 = 11, @@ -38,24 +40,29 @@ S34 = 15 }; - this (void[] input_=null) { + this (void[] input_=null) + { reset(); super(input_); } - uint blockSize() { + uint blockSize() + { return 64; } - uint digestSize() { + uint digestSize() + { return 16; } - char[] name() { + char[] name() + { return "MD4"; } - void transform(ubyte[] input) { + void transform(ubyte[] input) + { uint[] w = new uint[16]; for (int i = 0, j = 0; i < 16; i++,j+=int.sizeof) @@ -126,34 +133,41 @@ h3 += d; } - private uint f(uint x, uint y, uint z) { + private uint f(uint x, uint y, uint z) + { return (x&y)|(~x&z); } - private uint h(uint x, uint y, uint z) { + private uint h(uint x, uint y, uint z) + { return x^y^z; } - private uint g(uint x, uint y, uint z) { + private uint g(uint x, uint y, uint z) + { return (x&y)|(x&z)|(y&z); } - private void ff(ref uint a, uint b, uint c, uint d, uint x, uint s) { + private void ff(ref uint a, uint b, uint c, uint d, uint x, uint s) + { a += f(b, c, d) + x; a = Bitwise.rotateLeft(a, s); } - private void gg(ref uint a, uint b, uint c, uint d, uint x, uint s) { + private void gg(ref uint a, uint b, uint c, uint d, uint x, uint s) + { a += g(b, c, d) + x + 0x5a827999u; a = Bitwise.rotateLeft(a, s); } - private void hh(ref uint a, uint b, uint c, uint d, uint x, uint s) { + private void hh(ref uint a, uint b, uint c, uint d, uint x, uint s) + { a += h(b, c, d) + x + 0x6ed9eba1u; a = Bitwise.rotateLeft(a, s); } - ubyte[] digest() { + ubyte[] digest() + { padMessage(MODE_MD); ubyte[] result = new ubyte[digestSize]; @@ -166,7 +180,8 @@ return result; } - void reset() { + void reset() + { super.reset(); h0 = 0x67452301u; h1 = 0xefcdab89u; @@ -174,7 +189,8 @@ h3 = 0x10325476u; } - MD4 copy() { + MD4 copy() + { MD4 h = new MD4(buffer[0..index]); h.bytes = bytes; h.h0 = h0; @@ -184,9 +200,11 @@ return h; } - debug (UnitTest) { + debug (UnitTest) + { // Found in Tango <3 - unittest { + unittest + { static const char[][] test_inputs = [ "", "a", @@ -208,7 +226,8 @@ ]; MD4 h = new MD4(); - foreach (uint i, char[] input; test_inputs) { + foreach (uint i, char[] input; test_inputs) + { h.update(input); char[] digest = h.hexDigest(); assert(digest == test_results[i], diff -r 176c933827a8 -r 8b5eaf3c2979 dcrypt/crypto/hashes/MD5.d --- a/dcrypt/crypto/hashes/MD5.d Sun Mar 01 13:06:48 2009 -0500 +++ b/dcrypt/crypto/hashes/MD5.d Sat May 09 23:29:20 2009 -0400 @@ -17,11 +17,13 @@ * References: http://www.faqs.org/rfcs/rfc1321.html * Bugs: MD5 is not cryptographically secure. */ -class MD5 : Hash { +class MD5 : Hash +{ private uint h0, h1, h2, h3; // Shift amounts - private enum { + private enum + { S11 = 7, S12 = 12, S13 = 17, @@ -43,24 +45,29 @@ S44 = 21 }; - this (void[] input_=null) { + this (void[] input_=null) + { reset(); super(input_); } - uint blockSize() { + uint blockSize() + { return 64; } - uint digestSize() { + uint digestSize() + { return 16; } - char[] name() { + char[] name() + { return "MD5"; } - void transform(ubyte[] input) { + void transform(ubyte[] input) + { uint[] w = new uint[16]; for (int i = 0, j = 0; i < 16; i++,j+=int.sizeof) @@ -151,51 +158,56 @@ // FATALITY! \o/ } - private uint f(uint x, uint y, uint z) { + private uint f(uint x, uint y, uint z) + { return (x&y)|(~x&z); } - private uint h(uint x, uint y, uint z) { + private uint h(uint x, uint y, uint z) + { return x^y^z; } - private uint g(uint x, uint y, uint z) { + private uint g(uint x, uint y, uint z) + { return (x&z)|(y&~z); } - private uint i(uint x, uint y, uint z) { + private uint i(uint x, uint y, uint z) + { return y^(x|~z); } - private void ff(ref uint a, uint b, uint c, - uint d, uint x, uint s, uint ac) { + private void ff(ref uint a, uint b, uint c, uint d, uint x, uint s, uint ac) + { a += f(b, c, d) + x + ac; a = Bitwise.rotateLeft(a, s); a += b; } - private void gg(ref uint a, uint b, uint c, - uint d, uint x, uint s, uint ac) { + private void gg(ref uint a, uint b, uint c, uint d, uint x, uint s, uint ac) + { a += g(b, c, d) + x + ac; a = Bitwise.rotateLeft(a, s); a += b; } - private void hh(ref uint a, uint b, uint c, - uint d, uint x, uint s, uint ac) { + private void hh(ref uint a, uint b, uint c, uint d, uint x, uint s, uint ac) + { a += h(b, c, d) + x + ac; a = Bitwise.rotateLeft(a, s); a += b; } - private void ii(ref uint a, uint b, uint c, - uint d, uint x, uint s, uint ac) { + private void ii(ref uint a, uint b, uint c, uint d, uint x, uint s, uint ac) + { a += i(b, c, d) + x + ac; a = Bitwise.rotateLeft(a, s); a += b; } - ubyte[] digest() { + ubyte[] digest() + { padMessage(MODE_MD); ubyte[] result = new ubyte[digestSize]; @@ -208,7 +220,8 @@ return result; } - void reset() { + void reset() + { super.reset(); h0 = 0x67452301u; h1 = 0xefcdab89u; @@ -216,7 +229,8 @@ h3 = 0x10325476u; } - MD5 copy() { + MD5 copy() + { MD5 h = new MD5(buffer[0..index]); h.bytes = bytes; h.h0 = h0; @@ -226,9 +240,11 @@ return h; } - debug (UnitTest) { + debug (UnitTest) + { // Found in Tango <3 - unittest { + unittest + { static const char[][] test_inputs = [ "", "a", @@ -250,7 +266,8 @@ ]; MD5 h = new MD5(); - foreach (uint i, char[] input; test_inputs) { + foreach (uint i, char[] input; test_inputs) + { h.update(input); char[] digest = h.hexDigest(); assert(digest == test_results[i], diff -r 176c933827a8 -r 8b5eaf3c2979 dcrypt/crypto/hashes/SHA1.d --- a/dcrypt/crypto/hashes/SHA1.d Sun Mar 01 13:06:48 2009 -0500 +++ b/dcrypt/crypto/hashes/SHA1.d Sat May 09 23:29:20 2009 -0400 @@ -17,27 +17,33 @@ * References: http://www.itl.nist.gov/fipspubs/fip180-1.htm * Bugs: SHA-1 is not cryptographically secure. */ -class SHA1 : Hash { +class SHA1 : Hash +{ protected uint h0, h1, h2, h3, h4; - this (void[] input_=null) { + this (void[] input_=null) + { reset(); super(input_); } - uint blockSize() { + uint blockSize() + { return 64; } - uint digestSize() { + uint digestSize() + { return 20; } - char[] name() { + char[] name() + { return "SHA1"; } - void transform(ubyte[] input) { + void transform(ubyte[] input) + { uint[] w = new uint[80]; for (int i = 0, j = 0; i < 16; i++,j+=int.sizeof) @@ -53,7 +59,8 @@ e = h4; int i = 0; - for (; i < 20;) { + for (; i < 20;) + { e += Bitwise.rotateLeft(a, 5) + f0(b, c, d) + w[i++]; b = Bitwise.rotateLeft(b, 30); @@ -70,7 +77,8 @@ c = Bitwise.rotateLeft(c, 30); } - for (; i < 40;) { + for (; i < 40;) + { e += Bitwise.rotateLeft(a, 5) + f1(b, c, d) + w[i++]; b = Bitwise.rotateLeft(b, 30); @@ -87,7 +95,8 @@ c = Bitwise.rotateLeft(c, 30); } - for (; i < 60;) { + for (; i < 60;) + { e += Bitwise.rotateLeft(a, 5) + f2(b, c, d) + w[i++]; b = Bitwise.rotateLeft(b, 30); @@ -104,7 +113,8 @@ c = Bitwise.rotateLeft(c, 30); } - for (; i < 80;) { + for (; i < 80;) + { e += Bitwise.rotateLeft(a, 5) + f3(b, c, d) + w[i++]; b = Bitwise.rotateLeft(b, 30); @@ -128,23 +138,28 @@ h4 += e; } - private uint f0(uint x, uint y, uint z) { + private uint f0(uint x, uint y, uint z) + { return (z^(x&(y^z))) + 0x5a827999; } - private uint f1(uint x, uint y, uint z) { + private uint f1(uint x, uint y, uint z) + { return (x^y^z) + 0x6ed9eba1; } - private uint f2(uint x, uint y, uint z) { + private uint f2(uint x, uint y, uint z) + { return ((x&y)|(z&(x|y))) + 0x8f1bbcdc; } - private uint f3(uint x, uint y, uint z) { + private uint f3(uint x, uint y, uint z) + { return (x^y^z) + 0xca62c1d6; } - ubyte[] digest() { + ubyte[] digest() + { padMessage(MODE_SHA); ubyte[] result = new ubyte[digestSize]; @@ -158,7 +173,8 @@ return result; } - void reset() { + void reset() + { super.reset(); h0 = 0x67452301u; h1 = 0xefcdab89u; @@ -167,7 +183,8 @@ h4 = 0xc3d2e1f0u; } - SHA1 copy() { + SHA1 copy() + { SHA1 h = new SHA1(buffer[0..index]); h.bytes = bytes; h.h0 = h0; @@ -178,8 +195,10 @@ return h; } - debug (UnitTest) { - unittest { + debug (UnitTest) + { + unittest + { static const char[][] test_inputs = [ "", "abc", @@ -201,7 +220,8 @@ ]; SHA1 h = new SHA1(); - foreach (uint i, char[] input; test_inputs) { + foreach (uint i, char[] input; test_inputs) + { for (int j = 0; j < test_repeat[i]; j++) h.update(input); char[] digest = h.hexDigest(); diff -r 176c933827a8 -r 8b5eaf3c2979 dcrypt/crypto/hashes/SHA224.d --- a/dcrypt/crypto/hashes/SHA224.d Sun Mar 01 13:06:48 2009 -0500 +++ b/dcrypt/crypto/hashes/SHA224.d Sat May 09 23:29:20 2009 -0400 @@ -16,21 +16,26 @@ * Conforms: FIPS-180-2 * References: http://csrc.nist.gov/publications/fips/fips180-2/FIPS180-2_changenotice.pdf */ -class SHA224 : SHA256 { - this (void[] input_=null) { +class SHA224 : SHA256 +{ + this (void[] input_=null) + { reset(); super(input_); } - uint digestSize() { + uint digestSize() + { return 28; } - char[] name() { + char[] name() + { return "SHA224"; } - ubyte[] digest() { + ubyte[] digest() + { padMessage(MODE_SHA); ubyte[] result = new ubyte[digestSize]; @@ -47,7 +52,8 @@ return result; } - void reset() { + void reset() + { super.reset(); h0 = 0xc1059ed8u; h1 = 0x367cd507u; @@ -59,7 +65,8 @@ h7 = 0xbefa4fa4u; } - SHA224 copy() { + SHA224 copy() + { SHA224 h = new SHA224(buffer[0..index]); h.bytes = bytes; h.h0 = h0; @@ -73,8 +80,10 @@ return h; } - debug (UnitTest) { - unittest { + debug (UnitTest) + { + unittest + { static const char[][] test_inputs = [ "", "abc", @@ -94,7 +103,8 @@ ]; SHA224 h = new SHA224(); - foreach (uint i, char[] input; test_inputs) { + foreach (uint i, char[] input; test_inputs) + { for (int j = 0; j < test_repeat[i]; j++) h.update(input); char[] digest = h.hexDigest(); diff -r 176c933827a8 -r 8b5eaf3c2979 dcrypt/crypto/hashes/SHA256.d --- a/dcrypt/crypto/hashes/SHA256.d Sun Mar 01 13:06:48 2009 -0500 +++ b/dcrypt/crypto/hashes/SHA256.d Sat May 09 23:29:20 2009 -0400 @@ -16,7 +16,8 @@ * Conforms: FIPS-180-2 * References: http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf */ -class SHA256 : Hash { +class SHA256 : Hash +{ private const uint[] K = [ 0x428a2f98u, 0x71374491u, 0xb5c0fbcfu, 0xe9b5dba5u, 0x3956c25bu, 0x59f111f1u, 0x923f82a4u, 0xab1c5ed5u, @@ -35,26 +36,32 @@ 0x748f82eeu, 0x78a5636fu, 0x84c87814u, 0x8cc70208u, 0x90befffau, 0xa4506cebu, 0xbef9a3f7u, 0xc67178f2u ]; + protected uint h0, h1, h2, h3, h4, h5, h6, h7; - this (void[] input_=null) { + this (void[] input_=null) + { reset(); super(input_); } - uint blockSize() { + uint blockSize() + { return 64; } - uint digestSize() { + uint digestSize() + { return 32; } - char[] name() { + char[] name() + { return "SHA256"; } - void transform(ubyte[] input) { + void transform(ubyte[] input) + { uint[] w = new uint[64]; for (int i = 0, j = 0; i < 16; i++,j+=int.sizeof) @@ -72,7 +79,8 @@ g = h6, h = h7; - for (int i = 0; i < 64; i++) { + for (int i = 0; i < 64; i++) + { uint t1 = h + sum1(e) + ch(e,f,g) + K[i] + w[i], t2 = sum0(a) + maj(a,b,c); h = g; @@ -95,31 +103,38 @@ h7 += h; } - private uint ch(uint x, uint y, uint z) { - return (x&y)^(~x&z); + private uint ch(uint x, uint y, uint z) + { + return (z ^ (x & (y ^ z))); } - private uint maj(uint x, uint y, uint z) { - return (x&y)^(x&z)^(y&z); + private uint maj(uint x, uint y, uint z) + { + return ((x & y) | (z & (x ^ y))); } - private uint sum0(uint x) { + private uint sum0(uint x) + { return Bitwise.rotateRight(x,2)^Bitwise.rotateRight(x,13)^Bitwise.rotateRight(x,22); } - private uint sum1(uint x) { + private uint sum1(uint x) + { return Bitwise.rotateRight(x,6)^Bitwise.rotateRight(x,11)^Bitwise.rotateRight(x,25); } - private uint theta0(uint x) { + private uint theta0(uint x) + { return Bitwise.rotateRight(x,7)^Bitwise.rotateRight(x,18)^(x >> 3); } - private uint theta1(uint x) { + private uint theta1(uint x) + { return Bitwise.rotateRight(x,17)^Bitwise.rotateRight(x,19)^(x >> 10); } - ubyte[] digest() { + ubyte[] digest() + { padMessage(MODE_SHA); ubyte[] result = new ubyte[digestSize]; @@ -136,7 +151,8 @@ return result; } - void reset() { + void reset() + { super.reset(); h0 = 0x6a09e667u; h1 = 0xbb67ae85u; @@ -148,7 +164,8 @@ h7 = 0x5be0cd19u; } - SHA256 copy() { + SHA256 copy() + { SHA256 h = new SHA256(buffer[0..index]); h.bytes = bytes; h.h0 = h0; @@ -162,8 +179,10 @@ return h; } - debug (UnitTest) { - unittest { + debug (UnitTest) + { + unittest + { static const char[][] test_inputs = [ "", "abc", @@ -183,7 +202,8 @@ ]; SHA256 h = new SHA256(); - foreach (uint i, char[] input; test_inputs) { + foreach (uint i, char[] input; test_inputs) + { for (int j = 0; j < test_repeat[i]; j++) h.update(input); char[] digest = h.hexDigest(); diff -r 176c933827a8 -r 8b5eaf3c2979 dcrypt/crypto/hashes/SHA384.d --- a/dcrypt/crypto/hashes/SHA384.d Sun Mar 01 13:06:48 2009 -0500 +++ b/dcrypt/crypto/hashes/SHA384.d Sat May 09 23:29:20 2009 -0400 @@ -16,21 +16,26 @@ * Conforms: FIPS-180-2 * References: http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf */ -class SHA384 : SHA512 { - this (void[] input_=null) { +class SHA384 : SHA512 +{ + this (void[] input_=null) + { reset(); super(input_); } - uint digestSize() { + uint digestSize() + { return 48; } - char[] name() { + char[] name() + { return "SHA384"; } - ubyte[] digest() { + ubyte[] digest() + { padMessage(MODE_SHA); ubyte[] result = new ubyte[digestSize]; @@ -45,7 +50,8 @@ return result; } - void reset() { + void reset() + { super.reset(); h0 = 0xcbbb9d5dc1059ed8u, h1 = 0x629a292a367cd507u, @@ -57,7 +63,8 @@ h7 = 0x47b5481dbefa4fa4u; } - SHA384 copy() { + SHA384 copy() + { SHA384 h = new SHA384(buffer[0..index]); h.bytes = bytes; h.h0 = h0; @@ -71,8 +78,10 @@ return h; } - debug (UnitTest) { - unittest { + debug (UnitTest) + { + unittest + { static const char[][] test_inputs = [ "", "abc", @@ -100,7 +109,8 @@ ]; SHA384 h = new SHA384(); - foreach (uint i, char[] input; test_inputs) { + foreach (uint i, char[] input; test_inputs) + { for (int j = 0; j < test_repeat[i]; j++) h.update(input); char[] digest = h.hexDigest(); diff -r 176c933827a8 -r 8b5eaf3c2979 dcrypt/crypto/hashes/SHA512.d --- a/dcrypt/crypto/hashes/SHA512.d Sun Mar 01 13:06:48 2009 -0500 +++ b/dcrypt/crypto/hashes/SHA512.d Sat May 09 23:29:20 2009 -0400 @@ -16,7 +16,8 @@ * Conforms: FIPS-180-2 * References: http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf */ -class SHA512 : Hash { +class SHA512 : Hash +{ private const ulong[] K = [ 0x428a2f98d728ae22u, 0x7137449123ef65cdu, 0xb5c0fbcfec4d3b2fu, 0xe9b5dba58189dbbcu, 0x3956c25bf348b538u, 0x59f111f1b605d019u, 0x923f82a4af194f9bu, 0xab1c5ed5da6d8118u, @@ -39,26 +40,32 @@ 0x28db77f523047d84u, 0x32caab7b40c72493u, 0x3c9ebe0a15c9bebcu, 0x431d67c49c100d4cu, 0x4cc5d4becb3e42b6u, 0x597f299cfc657e2au, 0x5fcb6fab3ad6faecu, 0x6c44198c4a475817u ]; + protected ulong h0, h1, h2, h3, h4, h5, h6, h7; - this (void[] input_=null) { + this (void[] input_=null) + { reset(); super(input_); } - uint blockSize() { + uint blockSize() + { return 128; } - uint digestSize() { + uint digestSize() + { return 64; } - char[] name() { + char[] name() + { return "SHA512"; } - void transform(ubyte[] input) { + void transform(ubyte[] input) + { ulong[] w = new ulong[80]; for (int i = 0, j = 0; i < 16; i++,j+=long.sizeof) @@ -76,7 +83,8 @@ g = h6, h = h7; - for (int i = 0; i < 80; i++) { + for (int i = 0; i < 80; i++) + { ulong t1 = h + sum1(e) + ch(e,f,g) + K[i] + w[i], t2 = sum0(a) + maj(a,b,c); h = g; @@ -99,35 +107,42 @@ h7 += h; } - private ulong ch(ulong x, ulong y, ulong z) { + private ulong ch(ulong x, ulong y, ulong z) + { return (x&y)^(~x&z); } - private ulong maj(ulong x, ulong y, ulong z) { + private ulong maj(ulong x, ulong y, ulong z) + { return (x&y)^(x&z)^(y&z); } - private ulong sum0(ulong x) { + private ulong sum0(ulong x) + { return (Bitwise.rotateRight(x,28)^ Bitwise.rotateRight(x,34)^ Bitwise.rotateRight(x,39)); } - private ulong sum1(ulong x) { + private ulong sum1(ulong x) + { return (Bitwise.rotateRight(x,14)^ Bitwise.rotateRight(x,18)^ Bitwise.rotateRight(x,41)); } - private ulong theta0(ulong x) { + private ulong theta0(ulong x) + { return Bitwise.rotateRight(x,1)^Bitwise.rotateRight(x,8)^(x >> 7); } - private ulong theta1(ulong x) { + private ulong theta1(ulong x) + { return Bitwise.rotateRight(x,19)^Bitwise.rotateRight(x,61)^(x >> 6); } - ubyte[] digest() { + ubyte[] digest() + { padMessage(MODE_SHA); ubyte[] result = new ubyte[digestSize]; @@ -144,7 +159,8 @@ return result; } - void reset() { + void reset() + { super.reset(); h0 = 0x6a09e667f3bcc908u; h1 = 0xbb67ae8584caa73bu; @@ -156,7 +172,8 @@ h7 = 0x5be0cd19137e2179u; } - SHA512 copy() { + SHA512 copy() + { SHA512 h = new SHA512(buffer[0..index]); h.bytes = bytes; h.h0 = h0; @@ -170,8 +187,10 @@ return h; } - debug (UnitTest) { - unittest { + debug (UnitTest) + { + unittest + { static const char[][] test_inputs = [ "", "abc", @@ -199,7 +218,8 @@ ]; SHA512 h = new SHA512(); - foreach (uint i, char[] input; test_inputs) { + foreach (uint i, char[] input; test_inputs) + { for (int j = 0; j < test_repeat[i]; j++) h.update(input); char[] digest = h.hexDigest(); diff -r 176c933827a8 -r 8b5eaf3c2979 dcrypt/crypto/macs/HMAC.d --- a/dcrypt/crypto/macs/HMAC.d Sun Mar 01 13:06:48 2009 -0500 +++ b/dcrypt/crypto/macs/HMAC.d Sat May 09 23:29:20 2009 -0400 @@ -13,7 +13,8 @@ import dcrypt.crypto.params.SymmetricKey; import dcrypt.crypto.errors.NotInitializedError; -debug (UnitTest) { +debug (UnitTest) +{ import dcrypt.crypto.hashes.SHA1; } @@ -23,14 +24,17 @@ * Conforms: RFC 2104 * References: http://www.faqs.org/rfcs/rfc2104.html */ -class HMAC : MAC { - private { +class HMAC : MAC +{ + private + { ubyte[] ipad, opad, key; Hash hash; bool initialized; } - this (Hash hash, void[] key=null) { + this (Hash hash, void[] key=null) + { this.hash = hash.copy(); this.hash.reset(); @@ -41,7 +45,8 @@ init(new SymmetricKey(key)); // I'm lazy. } - void init(CipherParameters params) { + void init(CipherParameters params) + { SymmetricKey keyParams = cast(SymmetricKey)params; if (!keyParams) throw new InvalidParameterError( @@ -49,7 +54,8 @@ hash.reset(); - if (keyParams.key.length > blockSize) { + if (keyParams.key.length > blockSize) + { hash.update(keyParams.key); key = hash.digest(); } else @@ -58,7 +64,8 @@ ipad[] = 0x36; opad[] = 0x5c; - foreach (uint i, ubyte j; key) { + foreach (uint i, ubyte j; key) + { ipad[i] ^= j; opad[i] ^= j; } @@ -68,44 +75,54 @@ initialized = true; } - void update(void[] input_) { + void update(void[] input_) + { if (!initialized) - throw new NotInitializedError( - name()~": MAC not initialized."); + throw new NotInitializedError(name()~": MAC not initialized."); + hash.update(input_); } - char[] name() { + char[] name() + { return "HMAC-"~hash.name; } - void reset() { + void reset() + { hash.reset(); hash.update(ipad); } - uint blockSize() { + uint blockSize() + { return hash.blockSize; } - uint macSize() { + uint macSize() + { return hash.digestSize; } - ubyte[] digest() { + ubyte[] digest() + { ubyte[] t = hash.digest(); hash.update(opad); hash.update(t); ubyte[] r = hash.digest(); + reset(); + return r; } - char[] hexDigest() { + char[] hexDigest() + { return ByteConverter.hexEncode(digest()); } - HMAC copy() { + HMAC copy() + { // Ghetto... oh so ghetto :\ HMAC h = new HMAC(hash.copy()); h.hash = hash.copy(); @@ -113,8 +130,10 @@ return h; } - debug (UnitTest) { - unittest { + debug (UnitTest) + { + unittest + { static char[][] test_keys = [ "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b", "4a656665", // Jefe? @@ -145,7 +164,8 @@ ]; HMAC h = new HMAC(new SHA1()); - foreach (uint i, char[] k; test_keys) { + foreach (uint i, char[] k; test_keys) + { h.init(new SymmetricKey(ByteConverter.hexDecode(k))); for (int j = 0; j < test_repeat[i]; j++) h.update(ByteConverter.hexDecode(test_inputs[i])); diff -r 176c933827a8 -r 8b5eaf3c2979 dcrypt/crypto/modes/CBC.d --- a/dcrypt/crypto/modes/CBC.d Sun Mar 01 13:06:48 2009 -0500 +++ b/dcrypt/crypto/modes/CBC.d Sat May 09 23:29:20 2009 -0400 @@ -11,34 +11,41 @@ import dcrypt.crypto.BlockCipher; public import dcrypt.crypto.params.ParametersWithIV; -debug (UnitTest) { +debug (UnitTest) +{ import dcrypt.crypto.ciphers.XTEA; import dcrypt.misc.ByteConverter; } /** This class implements the cipher block chaining (CBC) block mode. */ -class CBC : BlockCipher { - private BlockCipher wrappedCipher; - private ubyte[] iv, - previousCiphertext, - cbcOutput; - private bool encrypt, - initialized; +class CBC : BlockCipher +{ + private + { + BlockCipher wrappedCipher; + + ubyte[] iv, + previousBlock, + currentBlock; + } /** * Params: * cipher = Block cipher to wrap. */ - this (BlockCipher cipher) { + this (BlockCipher cipher) + { wrappedCipher = cipher; } /** Returns: The underlying cipher we are wrapping. */ - BlockCipher cipher() { + BlockCipher cipher() + { return wrappedCipher; } - char[] name() { + char[] name() + { return wrappedCipher.name~"/CBC"; } @@ -46,7 +53,8 @@ * Throws: dcrypt.crypto.errors.InvalidParameterError if params aren't * an instance of dcrypt.crypto.params.ParametersWithIV. */ - void init(bool encrypt, CipherParameters params) { + void init(bool encrypt, CipherParameters params) + { ParametersWithIV ivParams = cast(ParametersWithIV)params; if (!ivParams) @@ -56,21 +64,23 @@ throw new InvalidParameterError( name()~": IV must be same length as cipher block size"); - this.encrypt = encrypt; - wrappedCipher.init(encrypt, ivParams.parameters); + _encrypt = encrypt; + + wrappedCipher.init(_encrypt, ivParams.parameters); iv = ivParams.iv[0..blockSize]; - previousCiphertext = new ubyte[blockSize]; - previousCiphertext[] = iv; // C_0 = IV - cbcOutput = new ubyte[blockSize]; // Output buffer for E_k/D_k(...) - initialized = true; + currentBlock = new ubyte[blockSize]; + previousBlock = new ubyte[blockSize]; + previousBlock[] = iv; // C_0 = IV + + _initialized = true; } - uint update(void[] input_, void[] output_) { - if (!initialized) - throw new NotInitializedError( - name()~": Block mode not initialized"); + uint update(void[] input_, void[] output_) + { + if (!_initialized) + throw new NotInitializedError(name()~": Block mode not initialized"); ubyte[] input = cast(ubyte[]) input_, output = cast(ubyte[]) output_; @@ -81,49 +91,53 @@ if (output.length < blockSize) throw new ShortBufferError(name()~": Output buffer too short"); - if (encrypt) { + if (_encrypt) + { // P_i XOR C_i-1 for (int i = 0; i < blockSize; i++) - previousCiphertext[i] ^= input[i]; + previousBlock[i] ^= input[i]; - // E_k(P_i XOR C_i-1) - wrappedCipher.update(previousCiphertext, cbcOutput); - - // Store C_i for next block - previousCiphertext[] = cbcOutput; + // E_k(P_i XOR C_i-1) and store C_i for the next block + wrappedCipher.update(previousBlock, previousBlock); // C_i = E_k(P_i XOR C_i-1) - output[0..blockSize] = cbcOutput; - } else { - // Temporarily store C_i - ubyte[] t = input[0..blockSize]; + output[0..blockSize] = previousBlock; + } + else + { + // Local reference to C_i + ubyte[] temp = input[0..blockSize]; // D_k(C_i) - wrappedCipher.update(t, cbcOutput); + wrappedCipher.update(temp, currentBlock); // P_i = D_k(C_i) XOR C_i-1 for (int i = 0; i < blockSize; i++) - output[i] = (cbcOutput[i] ^ previousCiphertext[i]); + output[i] = (currentBlock[i] ^ previousBlock[i]); // Store C_i for next block - previousCiphertext[] = t; + previousBlock[] = temp; } return blockSize; } - uint blockSize() { + uint blockSize() + { return wrappedCipher.blockSize; } - void reset() { - previousCiphertext[] = iv; + void reset() + { + previousBlock[] = iv; wrappedCipher.reset(); } /** Test vectors for CBC mode. Assumes XTEA passes test vectors. */ - debug (UnitTest) { - unittest { + debug (UnitTest) + { + unittest + { static const char[][] test_keys = [ "00000000000000000000000000000000", "00000000000000000000000000000000", @@ -152,27 +166,27 @@ "f26fa5a0b6b63ba0f7ebf2f8735f85e3" ]; - XTEA x = new XTEA(); - CBC c = new CBC(x); - ubyte[] iv = new ubyte[x.blockSize], // Initialized to 0 + CBC c = new CBC(new XTEA); + ubyte[] iv = new ubyte[c.blockSize], // Initialized to 0 buffer = new ubyte[32]; char[] result; - for (int i = 0; i < test_keys.length; i++) { + for (int i = 0; i < test_keys.length; i++) + { SymmetricKey key = new SymmetricKey(ByteConverter.hexDecode(test_keys[i])); ParametersWithIV params = new ParametersWithIV(key, iv); // Encryption c.init(true, params); - for (int j = 0; j < 32; j+=x.blockSize) - c.update(ByteConverter.hexDecode(test_plaintexts[i])[j..j+x.blockSize], buffer[j..j+x.blockSize]); + for (int j = 0; j < 32; j+=c.blockSize) + c.update(ByteConverter.hexDecode(test_plaintexts[i])[j..j+c.blockSize], buffer[j..j+c.blockSize]); result = ByteConverter.hexEncode(buffer); assert(result == test_ciphertexts[i], c.name()~": ("~result~") != ("~test_ciphertexts[i]~")"); // Decryption c.init(false, params); - for (int j = 0; j < 32; j+=x.blockSize) - c.update(ByteConverter.hexDecode(test_ciphertexts[i])[j..j+x.blockSize], buffer[j..j+x.blockSize]); + for (int j = 0; j < 32; j+=c.blockSize) + c.update(ByteConverter.hexDecode(test_ciphertexts[i])[j..j+c.blockSize], buffer[j..j+c.blockSize]); result = ByteConverter.hexEncode(buffer); assert(result == test_plaintexts[i], c.name()~": ("~result~") != ("~test_plaintexts[i]~")"); diff -r 176c933827a8 -r 8b5eaf3c2979 dcrypt/crypto/modes/CTR.d --- a/dcrypt/crypto/modes/CTR.d Sun Mar 01 13:06:48 2009 -0500 +++ b/dcrypt/crypto/modes/CTR.d Sat May 09 23:29:20 2009 -0400 @@ -14,27 +14,34 @@ /** This class implements the counter (CTR/SIC/ICM) block mode, treating the counter as a big endian integer. */ -class CTR : BlockCipher { - private BlockCipher wrappedCipher; - private ubyte[] iv, - counter, - counterOutput; - private bool initialized = false; +class CTR : BlockCipher +{ + private + { + BlockCipher wrappedCipher; + + ubyte[] iv, + counter, + counterOutput; + } /** * Params: * cipher = Block cipher to wrap. */ - this (BlockCipher cipher) { + this (BlockCipher cipher) + { wrappedCipher = cipher; } /** Returns: The underlying cipher we are wrapping. */ - BlockCipher cipher() { + BlockCipher cipher() + { return wrappedCipher; } - char[] name() { + char[] name() + { return wrappedCipher.name~"/CTR"; } @@ -42,7 +49,8 @@ * Throws: dcrypt.crypto.errors.InvalidParameterError if params aren't * an instance of dcrypt.crypto.params.ParametersWithIV. */ - void init(bool encrypt, CipherParameters params) { + void init(bool encrypt, CipherParameters params) + { ParametersWithIV ivParams = cast(ParametersWithIV)params; if (!ivParams) @@ -59,13 +67,13 @@ counter[] = iv; counterOutput = new ubyte[blockSize]; - initialized = true; + _initialized = _encrypt = true; } - uint update(void[] input_, void[] output_) { - if (!initialized) - throw new NotInitializedError( - name()~": Block mode not initialized"); + uint update(void[] input_, void[] output_) + { + if (!_initialized) + throw new NotInitializedError(name()~": Block mode not initialized"); ubyte[] input = cast(ubyte[]) input_, output = cast(ubyte[]) output_; @@ -91,11 +99,13 @@ return len; } - uint blockSize() { + uint blockSize() + { return wrappedCipher.blockSize; } - void reset() { + void reset() + { counter[] = iv; wrappedCipher.reset(); } diff -r 176c933827a8 -r 8b5eaf3c2979 dcrypt/crypto/padding/NullByte.d --- a/dcrypt/crypto/padding/NullByte.d Sun Mar 01 13:06:48 2009 -0500 +++ b/dcrypt/crypto/padding/NullByte.d Sat May 09 23:29:20 2009 -0400 @@ -15,11 +15,13 @@ * Ex. [... 0x00, 0x00 ... 0x00] */ class NullByte : BlockCipherPadding { - char[] name() { + char[] name() + { return "NullByte"; } - ubyte[] pad(uint len) { + ubyte[] pad(uint len) + { ubyte[] output = new ubyte[len]; output[0..output.length] = 0; @@ -27,7 +29,8 @@ return output; } - uint unpad(void[] input_) { + uint unpad(void[] input_) + { ubyte[] input = cast(ubyte[]) input_; uint len = input.length; diff -r 176c933827a8 -r 8b5eaf3c2979 dcrypt/crypto/padding/PKCS7.d --- a/dcrypt/crypto/padding/PKCS7.d Sun Mar 01 13:06:48 2009 -0500 +++ b/dcrypt/crypto/padding/PKCS7.d Sat May 09 23:29:20 2009 -0400 @@ -14,12 +14,15 @@ * This class implements the padding scheme described in PKCS7 * from RSA Security. Ex. [... 0x03, 0x03, 0x03] */ -class PKCS7 : BlockCipherPadding { - char[] name() { +class PKCS7 : BlockCipherPadding +{ + char[] name() + { return "PKCS7"; } - ubyte[] pad(uint len) { + ubyte[] pad(uint len) + { ubyte[] output = new ubyte[len]; output[0..output.length] = cast(byte)len; @@ -27,7 +30,8 @@ return output; } - uint unpad(void[] input_) { + uint unpad(void[] input_) + { ubyte[] input = cast(ubyte[]) input_; ubyte len = input[input.length-1]; @@ -38,8 +42,8 @@ uint limit = input.length; for (int i = 0; i < len; i++) if (input[--limit] != len) - throw new InvalidPaddingError( - name()~": Pad value does not match pad length."); + throw new InvalidPaddingError(name()~": Pad value does not match pad length."); + return len; } } diff -r 176c933827a8 -r 8b5eaf3c2979 dcrypt/crypto/padding/RFC1321.d --- a/dcrypt/crypto/padding/RFC1321.d Sun Mar 01 13:06:48 2009 -0500 +++ b/dcrypt/crypto/padding/RFC1321.d Sat May 09 23:29:20 2009 -0400 @@ -14,12 +14,15 @@ * This class implements the padding described in RFC1321 (MD5 spec). * Ex. [... 0x80, 0x00 ... 0x00] */ -class RFC1321 : BlockCipherPadding { - char[] name() { +class RFC1321 : BlockCipherPadding +{ + char[] name() + { return "RFC1321"; } - ubyte[] pad(uint len) { + ubyte[] pad(uint len) + { ubyte[] output = new ubyte[len]; output[0] = 0x80; @@ -28,7 +31,8 @@ return output; } - uint unpad(void[] input_) { + uint unpad(void[] input_) + { ubyte[] input = cast(ubyte[]) input_; uint len = input.length; @@ -37,8 +41,7 @@ if (input[len] != 0) break; if (input[len] != 0x80) - throw new InvalidPaddingError( - name()~": Incorrect padding."); + throw new InvalidPaddingError(name()~": Incorrect padding."); return (input.length - len); } diff -r 176c933827a8 -r 8b5eaf3c2979 dcrypt/crypto/padding/X923.d --- a/dcrypt/crypto/padding/X923.d Sun Mar 01 13:06:48 2009 -0500 +++ b/dcrypt/crypto/padding/X923.d Sat May 09 23:29:20 2009 -0400 @@ -14,15 +14,18 @@ * This class implements the Null/Zero byte padding described in ANSI X.923. * Ex. [... 0x00, 0x00, 0x03] */ -class X923 : BlockCipherPadding { - char[] name() { +class X923 : BlockCipherPadding +{ + char[] name() + { return "X923"; } /* Assumes input_ is a multiple of the underlying * block cipher's block size. */ - ubyte[] pad(uint len) { + ubyte[] pad(uint len) + { ubyte[] output = new ubyte[len]; output[0..len-1] = 0; @@ -31,7 +34,8 @@ return output; } - uint unpad(void[] input_) { + uint unpad(void[] input_) + { ubyte[] input = cast(ubyte[]) input_; ubyte len = input[input.length-1]; diff -r 176c933827a8 -r 8b5eaf3c2979 dcrypt/crypto/params/ParametersWithIV.d --- a/dcrypt/crypto/params/ParametersWithIV.d Sun Mar 01 13:06:48 2009 -0500 +++ b/dcrypt/crypto/params/ParametersWithIV.d Sat May 09 23:29:20 2009 -0400 @@ -11,7 +11,8 @@ public import dcrypt.crypto.params.CipherParameters; /** Wrap cipher parameters and IV. */ -class ParametersWithIV : CipherParameters { +class ParametersWithIV : CipherParameters +{ private ubyte[] _iv; private CipherParameters _params; @@ -20,13 +21,15 @@ * params = Parameters to wrap. * iv = IV to be held. */ - this (CipherParameters params=null, ubyte[] iv=null) { + this (CipherParameters params=null, ubyte[] iv=null) + { _params = params; _iv = cast(ubyte[]) iv; } /** Returns: The IV. */ - ubyte[] iv() { + ubyte[] iv() + { return _iv; } @@ -37,12 +40,14 @@ * newIV = The new IV for this parameter object. * Returns: The new IV. */ - ubyte[] iv(void[] newIV) {; + ubyte[] iv(void[] newIV) + { return _iv = cast(ubyte[]) newIV; } /** Returns: The parameters for this object. */ - CipherParameters parameters() { + CipherParameters parameters() + { return _params; } @@ -53,7 +58,8 @@ * newParams = The new parameters to be held. * Returns: The new parameters. */ - CipherParameters parameters(CipherParameters newParams) { + CipherParameters parameters(CipherParameters newParams) + { return _params = newParams; } } diff -r 176c933827a8 -r 8b5eaf3c2979 dcrypt/crypto/params/SymmetricKey.d --- a/dcrypt/crypto/params/SymmetricKey.d Sun Mar 01 13:06:48 2009 -0500 +++ b/dcrypt/crypto/params/SymmetricKey.d Sat May 09 23:29:20 2009 -0400 @@ -12,19 +12,22 @@ import dcrypt.crypto.errors.InvalidParameterError; /** Object representing and wrapping a symmetric key in bytes. */ -class SymmetricKey : CipherParameters { +class SymmetricKey : CipherParameters +{ private ubyte[] _key; /** * Params: * key = Key to be held. */ - this(void[] key=null) { + this(void[] key=null) + { _key = cast(ubyte[]) key; } /** Returns: Key in ubytes held by this object. */ - ubyte[] key() { + ubyte[] key() + { return _key; } @@ -35,7 +38,8 @@ * newKey = New key to be held. * Returns: The new key. */ - ubyte[] key(void[] newKey) { + ubyte[] key(void[] newKey) + { return _key = cast(ubyte[]) newKey; } } diff -r 176c933827a8 -r 8b5eaf3c2979 dcrypt/crypto/prngs/PBKDF2.d --- a/dcrypt/crypto/prngs/PBKDF2.d Sun Mar 01 13:06:48 2009 -0500 +++ b/dcrypt/crypto/prngs/PBKDF2.d Sat May 09 23:29:20 2009 -0400 @@ -21,8 +21,10 @@ * Conforms: PKCS #5 v2.0 / RFC 2898 * References: http://www.truecrypt.org/docs/pkcs5v2-0.pdf */ -class PBKDF2 : PRNG { - private { +class PBKDF2 : PRNG +{ + private + { ubyte[] salt, buffer; @@ -42,8 +44,8 @@ * iterations = The number of total iterations * prf = The pseudo-random function */ - this(char[] password, void[] salt_, - uint iterations=1000, MAC prf=new HMAC(new SHA1)) { + this(char[] password, void[] salt_, uint iterations=1000, MAC prf=new HMAC(new SHA1)) + { salt = cast(ubyte[])salt_; if (salt == null) @@ -63,19 +65,24 @@ blockCount = 0; buffer = new ubyte[this.prf.macSize]; index = this.prf.macSize; + _initialized = true; } - void addEntropy(ubyte[] input) { + void addEntropy(ubyte[] input) + { throw new NotSupportedError(name()~": Not supported."); } /** * Throws: LimitReachedError after 2^32 blocks. */ - uint read(ubyte[] output) { - for (uint i = 0; i < output.length; i++) { - if (index == buffer.length) { + uint read(ubyte[] output) + { + for (uint i = 0; i < output.length; i++) + { + if (index == buffer.length) + { if (++blockCount == 0) // Catch rollover throw new LimitReachedError(name()~": Output limit reached."); @@ -85,7 +92,8 @@ t[0..salt.length] = salt; t[salt.length..salt.length+int.sizeof] = ByteConverter.BigEndian.from!(uint)(blockCount); - for (uint j = 0; j < iterations; j++) { + for (uint j = 0; j < iterations; j++) + { prf.reset(); prf.update(t); t = prf.digest(); @@ -93,20 +101,25 @@ for (uint k = 0; k < buffer.length; k++) buffer[k] ^= t[k]; } + index = 0; } + output[i] = buffer[index++]; } return output.length; } - char[] name() { + char[] name() + { return "PBKDF2-"~prf.name; } - debug (UnitTest) { - unittest { + debug (UnitTest) + { + unittest + { static char[][] test_passwords = [ "password", "password", @@ -138,7 +151,8 @@ ]; PBKDF2 pbkdf2; - foreach (uint i, char[] p; test_passwords) { + foreach (uint i, char[] p; test_passwords) + { pbkdf2 = new PBKDF2(p, test_salts[i], test_iterations[i]); ubyte[] result = new ubyte[test_results[i].length >> 1]; pbkdf2.read(result); diff -r 176c933827a8 -r 8b5eaf3c2979 dcrypt/crypto/prngs/PRNGFromHash.d --- a/dcrypt/crypto/prngs/PRNGFromHash.d Sun Mar 01 13:06:48 2009 -0500 +++ b/dcrypt/crypto/prngs/PRNGFromHash.d Sat May 09 23:29:20 2009 -0400 @@ -12,8 +12,10 @@ import dcrypt.crypto.Hash; /** Creates a PRNG from a hash function. */ -class PRNGFromHash : PRNG { - private { +class PRNGFromHash : PRNG +{ + private + { const uint COUNTER_SIZE = 32; Hash hash; @@ -23,17 +25,20 @@ uint index; } - char[] name() { + char[] name() + { if (hash is null) throw new NotInitializedError(name()~": PRNG not initialized"); return hash.name~"PRNG"; } - this(Hash hash) { + this(Hash hash) + { if (hash is null) throw new InvalidParameterError( name()~": Invalid parameter passed to constructor."); + this.hash = hash; this.hash.reset(); @@ -44,8 +49,10 @@ index = this.hash.digestSize; // to force updating of the state } - void addEntropy(ubyte[] input) { - if (!_initialized) { + void addEntropy(ubyte[] input) + { + if (!_initialized) + { hash.update(input); seed = hash.digest(); _initialized = true; @@ -53,12 +60,15 @@ throw new NotSupportedError(name()~": state is immutable once initialized"); } - uint read(ubyte[] output) { + uint read(ubyte[] output) + { if (!_initialized) throw new NotInitializedError(name()~": PRNG not initialized"); - for (uint i = 0; i < output.length; i++) { - if (index == state.length) { + for (uint i = 0; i < output.length; i++) + { + if (index == state.length) + { hash.update(seed); hash.update(counter); state = hash.digest(); @@ -71,6 +81,7 @@ } output[i] = state[index++]; } + return output.length; } -} \ No newline at end of file +}