comparison dcrypt/crypto/modes/CTR.d @ 0:0e08791a1418

Initial import.
author Thomas Dixon <reikon@reikon.us>
date Sun, 10 Aug 2008 14:20:17 -0400
parents
children 23c62e28b3a4
comparison
equal deleted inserted replaced
-1:000000000000 0:0e08791a1418
1 /**
2 * This file is part of the dcrypt project.
3 *
4 * Copyright: Copyright (C) dcrypt contributors 2008. All rights reserved.
5 * License: MIT
6 * Authors: Thomas Dixon
7 */
8
9 module dcrypt.crypto.modes.CTR;
10
11 import dcrypt.crypto.BlockCipher;
12 import dcrypt.crypto.params.ParametersWithIV;
13
14
15 /** This class implements the counter (CTR/SIC/ICM) block mode,
16 treating the counter as a big endian integer. */
17 class CTR : BlockCipher {
18 private BlockCipher m_cipher;
19 private ubyte[] iv,
20 counter,
21 counterOutput;
22 private bool initialized = false;
23
24 /**
25 * Params:
26 * cipher = Block cipher to wrap.
27 */
28 this (BlockCipher cipher) {
29 m_cipher = cipher;
30 }
31
32 /** Returns: The underlying cipher we are wrapping. */
33 BlockCipher cipher() {
34 return m_cipher;
35 }
36
37 char[] name() {
38 return m_cipher.name~"/CTR";
39 }
40
41 /**
42 * Throws: dcrypt.crypto.errors.InvalidParameterError if params aren't
43 * an instance of dcrypt.crypto.params.ParametersWithIV.
44 */
45 void init(bool encrypt, CipherParameters params) {
46 ParametersWithIV ivParams = cast(ParametersWithIV)params;
47
48 if (!ivParams)
49 throw new InvalidParameterError(
50 name()~": Block mode requires IV (use ParametersWithIV)");
51 if (ivParams.iv.length != blockSize)
52 throw new InvalidParameterError(
53 name()~": IV must be same length as cipher block size");
54
55 m_cipher.init(true, ivParams.parameters);
56
57 iv = ivParams.iv[0..blockSize];
58 counter = new ubyte[blockSize];
59 counter[] = iv;
60 counterOutput = new ubyte[blockSize];
61
62 initialized = true;
63 }
64
65 uint processBlock(void[] input_, uint inOff, void[] output_, uint outOff) {
66 if (!initialized)
67 throw new NotInitializedError(
68 name()~": Block mode not initialized");
69
70 ubyte[] input = cast(ubyte[]) input_;
71 ubyte[] output = cast(ubyte[]) output_;
72
73 // Encrypt the counter
74 m_cipher.processBlock(counter, 0, counterOutput, 0);
75
76 // XOR output with plaintext to create ciphertext
77 for (int i = 0; i < counter.length; i++)
78 output[outOff++] = (counterOutput[i] ^ input[inOff++]);
79
80 // Increment the counter
81 for (int i = counter.length-1; i >= 0; i--)
82 if (++counter[i]) break;
83
84 return counter.length;
85 }
86
87 uint blockSize() {
88 return m_cipher.blockSize;
89 }
90
91 void reset() {
92 counter[] = iv;
93 m_cipher.reset();
94 }
95 }