Mercurial > projects > dcrypt
view dcrypt/crypto/ciphers/ChaCha.d @ 28:ad687db713a4
Further reworked the code for hash padding. Replaced all instances of 'char[]' with 'string' and removed a few 'const' modifiers as per Glenn Haecker's patch for D2 compatibility. Updated CONTRIBUTORS file.
author | Thomas Dixon <reikon@reikon.us> |
---|---|
date | Sun, 10 May 2009 22:38:48 -0400 |
parents | 8b5eaf3c2979 |
children |
line wrap: on
line source
/** * This file is part of the dcrypt project. * * Copyright: Copyright (C) dcrypt contributors 2009. All rights reserved. * License: MIT * Authors: Thomas Dixon */ module dcrypt.crypto.ciphers.ChaCha; import dcrypt.crypto.StreamCipher; import dcrypt.crypto.ciphers.Salsa20; import dcrypt.crypto.params.ParametersWithIV; import dcrypt.misc.ByteConverter; import dcrypt.misc.Bitwise; /** Implementation of ChaCha designed by Daniel J. Bernstein. */ class ChaCha : Salsa20 { string name() { return "ChaCha"; } this() { i0 = 12; i1 = 13; } protected void keySetup() { uint offset; ubyte[] constants; state[4] = ByteConverter.LittleEndian.to!(uint)(workingKey[0..4]); state[5] = ByteConverter.LittleEndian.to!(uint)(workingKey[4..8]); state[6] = ByteConverter.LittleEndian.to!(uint)(workingKey[8..12]); state[7] = ByteConverter.LittleEndian.to!(uint)(workingKey[12..16]); if (workingKey.length == 32) { constants = sigma; offset = 16; } else constants = tau; state[ 8] = ByteConverter.LittleEndian.to!(uint)(workingKey[offset..offset+4]); state[ 9] = ByteConverter.LittleEndian.to!(uint)(workingKey[offset+4..offset+8]); state[10] = ByteConverter.LittleEndian.to!(uint)(workingKey[offset+8..offset+12]); state[11] = ByteConverter.LittleEndian.to!(uint)(workingKey[offset+12..offset+16]); state[ 0] = ByteConverter.LittleEndian.to!(uint)(constants[0..4]); state[ 1] = ByteConverter.LittleEndian.to!(uint)(constants[4..8]); state[ 2] = ByteConverter.LittleEndian.to!(uint)(constants[8..12]); state[ 3] = ByteConverter.LittleEndian.to!(uint)(constants[12..16]); } 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) { uint[] x = new uint[16]; x[] = input; int 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); x[ 8] += x[12]; x[ 4] = Bitwise.rotateLeft(x[ 4]^x[ 8], 7); x[ 1] += x[ 5]; x[13] = Bitwise.rotateLeft(x[13]^x[ 1], 16); x[ 9] += x[13]; x[ 5] = Bitwise.rotateLeft(x[ 5]^x[ 9], 12); x[ 1] += x[ 5]; x[13] = Bitwise.rotateLeft(x[13]^x[ 1], 8); x[ 9] += x[13]; x[ 5] = Bitwise.rotateLeft(x[ 5]^x[ 9], 7); x[ 2] += x[ 6]; x[14] = Bitwise.rotateLeft(x[14]^x[ 2], 16); x[10] += x[14]; x[ 6] = Bitwise.rotateLeft(x[ 6]^x[10], 12); x[ 2] += x[ 6]; x[14] = Bitwise.rotateLeft(x[14]^x[ 2], 8); x[10] += x[14]; x[ 6] = Bitwise.rotateLeft(x[ 6]^x[10], 7); x[ 3] += x[ 7]; x[15] = Bitwise.rotateLeft(x[15]^x[ 3], 16); x[11] += x[15]; x[ 7] = Bitwise.rotateLeft(x[ 7]^x[11], 12); x[ 3] += x[ 7]; x[15] = Bitwise.rotateLeft(x[15]^x[ 3], 8); x[11] += x[15]; x[ 7] = Bitwise.rotateLeft(x[ 7]^x[11], 7); x[ 0] += x[ 5]; x[15] = Bitwise.rotateLeft(x[15]^x[ 0], 16); x[10] += x[15]; x[ 5] = Bitwise.rotateLeft(x[ 5]^x[10], 12); x[ 0] += x[ 5]; x[15] = Bitwise.rotateLeft(x[15]^x[ 0], 8); x[10] += x[15]; x[ 5] = Bitwise.rotateLeft(x[ 5]^x[10], 7); x[ 1] += x[ 6]; x[12] = Bitwise.rotateLeft(x[12]^x[ 1], 16); x[11] += x[12]; x[ 6] = Bitwise.rotateLeft(x[ 6]^x[11], 12); x[ 1] += x[ 6]; x[12] = Bitwise.rotateLeft(x[12]^x[ 1], 8); x[11] += x[12]; x[ 6] = Bitwise.rotateLeft(x[ 6]^x[11], 7); x[ 2] += x[ 7]; x[13] = Bitwise.rotateLeft(x[13]^x[ 2], 16); x[ 8] += x[13]; x[ 7] = Bitwise.rotateLeft(x[ 7]^x[ 8], 12); x[ 2] += x[ 7]; x[13] = Bitwise.rotateLeft(x[13]^x[ 2], 8); x[ 8] += x[13]; x[ 7] = Bitwise.rotateLeft(x[ 7]^x[ 8], 7); x[ 3] += x[ 4]; x[14] = Bitwise.rotateLeft(x[14]^x[ 3], 16); x[ 9] += x[14]; x[ 4] = Bitwise.rotateLeft(x[ 4]^x[ 9], 12); x[ 3] += x[ 4]; x[14] = Bitwise.rotateLeft(x[14]^x[ 3], 8); x[ 9] += x[14]; x[ 4] = Bitwise.rotateLeft(x[ 4]^x[ 9], 7); } for (i = 0; i < 16; i++) x[i] += input[i]; int j; for (i = j = 0; i < x.length; i++,j+=int.sizeof) output[j..j+int.sizeof] = ByteConverter.LittleEndian.from!(uint)(x[i]); } /** ChaCha test vectors */ debug (UnitTest) { unittest { static string[] test_keys = [ "80000000000000000000000000000000", "0053a6f94c9ff24598eb3e91e4378add", "00002000000000000000000000000000"~ "00000000000000000000000000000000", "0f62b5085bae0154a7fa4da0f34699ec"~ "3f92e5388bde3184d72a7dd02376c91c" ]; static string[] test_ivs = [ "0000000000000000", "0d74db42a91077de", "0000000000000000", "288ff65dc42b92f9" ]; static string[] test_plaintexts = [ "00000000000000000000000000000000"~ "00000000000000000000000000000000"~ "00000000000000000000000000000000"~ "00000000000000000000000000000000", "00000000000000000000000000000000"~ "00000000000000000000000000000000"~ "00000000000000000000000000000000"~ "00000000000000000000000000000000", "00000000000000000000000000000000"~ "00000000000000000000000000000000"~ "00000000000000000000000000000000"~ "00000000000000000000000000000000", "00000000000000000000000000000000"~ "00000000000000000000000000000000"~ "00000000000000000000000000000000"~ "00000000000000000000000000000000" ]; static string[] test_ciphertexts = [ "beb1e81e0f747e43ee51922b3e87fb38"~ "d0163907b4ed49336032ab78b67c2457"~ "9fe28f751bd3703e51d876c017faa435"~ "89e63593e03355a7d57b2366f30047c5", "509b267e7266355fa2dc0a25c023fce4"~ "7922d03dd9275423d7cb7118b2aedf22"~ "0568854bf47920d6fc0fd10526cfe7f9"~ "de472835afc73c916b849e91eee1f529", "653f4a18e3d27daf51f841a00b6c1a2b"~ "d2489852d4ae0711e1a4a32ad166fa6f"~ "881a2843238c7e17786ba5162bc019d5"~ "73849c167668510ada2f62b4ff31ad04", "db165814f66733b7a8e34d1ffc123427"~ "1256d3bf8d8da2166922e598acac70f4"~ "12b3fe35a94190ad0ae2e8ec62134819"~ "ab61addcccfe99d867ca3d73183fa3fd" ]; ChaCha cc = new ChaCha(); ubyte[] buffer = new ubyte[64]; string result; 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])); // Encryption cc.init(true, params); cc.update(ByteConverter.hexDecode(test_plaintexts[i]), buffer); result = ByteConverter.hexEncode(buffer); assert(result == test_ciphertexts[i], cc.name()~": ("~result~") != ("~test_ciphertexts[i]~")"); // Decryption cc.init(false, params); cc.update(ByteConverter.hexDecode(test_ciphertexts[i]), buffer); result = ByteConverter.hexEncode(buffer); assert(result == test_plaintexts[i], cc.name()~": ("~result~") != ("~test_plaintexts[i]~")"); } } } }