Mercurial > projects > dcrypt
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 } |