1 module dcrypt.blockcipher.padding.pkcs7; 2 3 import dcrypt.blockcipher.padding.padding; 4 import dcrypt.random.prng; 5 import dcrypt.exceptions; 6 import std.exception: enforce; 7 8 /// test PKCS7 padding scheme on a 16 byte block 9 unittest { 10 PKCS7Pad padding; 11 ubyte[16] block = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]; 12 13 padding.addPadding(block, 15); 14 assert(block == [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,1], "PKCS7Padding failed"); 15 assert(padding.padCount(block) == 1, "PKCS7Padding failed"); 16 17 padding.addPadding(block, 7); 18 assert(block == [0,1,2,3,4,5,6,9,9,9,9,9,9,9,9,9], "PKCS7Padding failed"); 19 assert(padding.padCount(block) == 9, "PKCS7Padding failed"); 20 21 padding.addPadding(block, 0); 22 assert(block == [16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16], "PKCS7Padding failed"); 23 assert(padding.padCount(block) == 16, "PKCS7Padding failed"); 24 } 25 26 static assert(isBlockCipherPadding!PKCS7Pad, "PKCS7Pad violates isBlockCipherPadding."); 27 28 /// 29 /// PKCS7Pad is an implementation of the PKCS7 block cipher padding scheme. 30 /// A incomplete block will be padded with bytes like this: 31 /// 32 /// 01 33 /// 02 02 34 /// 03 03 03 35 /// 04 04 04 04 36 /// ... 37 /// 38 /// The block to be padded can't be full. 39 /// 40 /// Standard: rfc5652, http://tools.ietf.org/html/rfc5652#section-6.3 41 /// 42 /// Example: 43 /// PKCS7Pad pad; 44 /// ubyte[16] block; 45 /// block[0..2] = [1,2]; // block contains 2 bytes 46 /// pad.addPadding(block, 2); // fill the rest with padding bytes 47 /// assert(pad.padCount(block) == 2); 48 /// 49 /// 50 @safe 51 public struct PKCS7Pad { 52 53 enum name = "PKCS7Padding"; 54 55 public { 56 57 /** 58 * pad with zeros or random bytes if SecureRandom is specified in constructor. 59 * Params: block = the block to pad 60 * len = the number of data bytes in this block. has to be smaller than the block size. 61 */ 62 void addPadding(ubyte[] block, in uint len) pure nothrow @nogc 63 in{ 64 assert(len < block.length, "len has to be smaller than block size"); 65 assert(block.length < 256, "block to long. can't pad blocks with length > 255"); 66 } 67 body { 68 block[len..$] = cast(ubyte) (block.length-len); 69 } 70 71 /** 72 * Returns: the number of padding bytes appended to this block. 73 * Throws: InvalidCipherTextException if the padding is corrupted. 74 */ 75 uint padCount(in ubyte[] block) pure 76 body { 77 ubyte len = block[$-1]; 78 79 enforce(len <= block.length, new InvalidCipherTextException("pad block corrupted")); 80 81 foreach(b; block[$-len..$]) { 82 if(b != len) { 83 throw new InvalidCipherTextException("pad block corrupted"); 84 } 85 } 86 87 return len; 88 } 89 } 90 }