1 /******************************************************************************* 2 3 Miscellaneous cryptographic padding functions 4 5 Copyright: 6 Copyright (c) 2009-2016 dunnhumby Germany GmbH. 7 All rights reserved. 8 9 License: 10 Boost Software License Version 1.0. See LICENSE_BOOST.txt for details. 11 Alternatively, this file may be distributed under the terms of the Tango 12 3-Clause BSD License (see LICENSE_BSD.txt for details). 13 14 *******************************************************************************/ 15 16 module ocean.util.cipher.misc.Padding; 17 18 19 import ocean.meta.types.Qualifiers; 20 import ocean.core.Verify; 21 22 version (unittest) 23 { 24 import ocean.core.Test; 25 } 26 27 /******************************************************************************* 28 29 PKCS#7 padding. 30 31 Pads the given byte buffer to the given length. The value of the padding 32 byte is the same as the number of bytes added to the buffer, example: 33 34 A 3-byte buffer with the contents [0xAB, 0xCD, 0xEF] is padded to length 8. 35 The buffer will now contain [0xAB, 0xCD, 0xEF, 0x05, 0x05, 0x05, 0x05, 0x05] 36 37 PKCS#7 padding is only defined for cases where the number of bytes to be 38 padded is less than 256. 39 40 Params: 41 buffer = A reference to the buffer to pad 42 pad_len = The length to pad the buffer to 43 44 Returns: 45 The padded buffer 46 47 *******************************************************************************/ 48 49 ubyte[] padPKCS7 ( ref ubyte[] buffer, size_t pad_len ) 50 { 51 verify(pad_len >= buffer.length); 52 verify(pad_len - buffer.length <= ubyte.max); 53 54 assumeSafeAppend(buffer); 55 56 ubyte pad_byte = cast(ubyte)(pad_len - buffer.length); 57 58 size_t start = buffer.length; 59 buffer.length = pad_len; 60 buffer[start .. $] = pad_byte; 61 62 return buffer; 63 } 64 65 unittest 66 { 67 ubyte[] buf0; 68 test!("==")(padPKCS7(buf0, 0), cast(ubyte[])null); 69 test!("==")(padPKCS7(buf0, 1), cast(ubyte[])[1]); 70 71 auto buf = cast(ubyte[])"YELLOW SUBMARINE".dup; 72 auto padded = padPKCS7(buf, 20); 73 auto expected = cast(ubyte[])"YELLOW SUBMARINE".dup ~ cast(ubyte[])[4, 4, 4, 4]; 74 test!("==")(padded, expected); 75 } 76 77 /******************************************************************************* 78 79 PKCS#5 padding. 80 81 Similar to PKCS#7 padding, except PKCS#5 padding is only defined for ciphers 82 that use a block size of 8 bytes. Hence, the given buffer will be padded to 83 a length of 8 bytes. 84 85 Params: 86 buffer = A reference to the buffer to pad 87 88 Returns: 89 The padded buffer 90 91 *******************************************************************************/ 92 93 ubyte[] padPKCS5 ( ref ubyte[] buffer ) 94 { 95 verify(buffer.length <= 8); 96 97 static immutable PKCS5_BLOCK_SIZE = 8; 98 return padPKCS7(buffer, PKCS5_BLOCK_SIZE); 99 } 100 101 unittest 102 { 103 ubyte[] buf0; 104 test!("==")(padPKCS5(buf0), cast(ubyte[])[8, 8, 8, 8, 8, 8, 8, 8]); 105 106 auto buf = cast(ubyte[])[0xAB, 0xCD, 0xEF]; 107 auto padded = padPKCS5(buf); 108 auto expected = cast(ubyte[])[0xAB, 0xCD, 0xEF, 5, 5, 5, 5, 5]; 109 test!("==")(padded, expected); 110 }