1 module dcrypt.blockcipher.padding.x923;
2 
3 import dcrypt.blockcipher.padding.padding;
4 import dcrypt.exceptions;
5 import std.exception: enforce;
6 
7 
8 static assert(isBlockCipherPadding!X923Pad, "X923Pad violates isBlockCipherPadding.");
9 
10 /// 
11 /// A ANSI X.923 block cipher padding implementation.
12 /// This code does not support random padding anymore,
13 /// because the author thinks its more susceptible to padding oracle attacks than deterministic zero padding.
14 /// 
15 @safe
16 public struct X923Pad { 
17 
18 	public enum name = "X.923";
19 
20 	
21 	public {
22 
23 		/**
24 		 * pad with zeros or random bytes if SecureRandom is specified in constructor.
25 		 * Params: block = the block to pad
26 		 * len = the number of data bytes in this block. has to be smaller than block.length.
27 		 */
28 		void addPadding(ubyte[] block, in uint len) nothrow
29 		in{
30 			assert(len < block.length, "len has to be smaller than block size");
31 			assert(block.length < 256, "block to long. can't pad blocks with length > 255");
32 		}
33 		body {
34 
35 			if(len < block.length) {
36 				// zero pad
37 				block[len..$] = 0;
38 				// set last byte to length of padding
39 				block[$-1] = cast(ubyte)(block.length-len); 
40 			}
41 		}
42 
43 		/**
44 		 * Returns: the number of padding bytes appended to this block
45 		 * Throws: InvalidCipherTextException if the padding is corrupted
46 		 */
47 		uint padCount(in ubyte[] block) pure
48 		body {
49 			ubyte len = block[$-1];
50 
51 			enforce(len <= block.length, new InvalidCipherTextException("pad block corrupted"));
52 
53 			// check if the padding is really made out of zeros
54 			foreach(b; block[$-len..$-1]) {
55 				enforce(b == 0, new InvalidCipherTextException("pad block corrupted"));
56 			}
57 
58 			return len;
59 		}
60 	}
61 }
62 
63 /// Test X923 padding scheme.
64 unittest {
65 	X923Pad padding;
66 	ubyte[] block = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15];
67 	padding.addPadding(block, 15);
68 	assert(block == [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,1], "X923Padding failed");
69 	assert(padding.padCount(block) == 1, "X923Padding failed");
70 	padding.addPadding(block, 7);
71 	assert(block == [0,1,2,3,4,5,6,0,0,0,0,0,0,0,0,9], "X923Padding failed");
72 	assert(padding.padCount(block) == 9, "X923Padding failed");
73 	padding.addPadding(block, 0);
74 	assert(block == [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16], "X923Padding failed");
75 	assert(padding.padCount(block) == 16, "X923Padding failed");
76 }