1 /** 2 * OctetString 3 * 4 * Copyright: 5 * (C) 1999-2007 Jack Lloyd 6 * (C) 2014-2015 Etienne Cimon 7 * 8 * License: 9 * Botan is released under the Simplified BSD License (see LICENSE.md) 10 */ 11 module botan.algo_base.symkey; 12 13 import botan.utils.xor_buf; 14 import botan.rng.rng; 15 import botan.filters.pipe; 16 import botan.codec.hex; 17 import std.algorithm; 18 import memutils.vector; 19 import botan.utils.types; 20 import memutils.refcounted; 21 alias OctetString = RefCounted!OctetStringImpl; 22 23 /** 24 * Octet String 25 */ 26 struct OctetStringImpl 27 { 28 public: 29 /** 30 * Returns: size of this octet string in bytes 31 */ 32 @property size_t length() const { return m_bits.length; } 33 34 /** 35 * Returns: this object as a $(D SecureVector!ubyte) 36 */ 37 SecureVector!ubyte bitsOf() const { return m_bits.dup; } 38 39 /** 40 * Returns: Pointer to the first ubyte of this string 41 */ 42 @property ubyte* ptr() const { return m_bits.ptr; } 43 44 /** 45 * Returns: Pointer to one past the end of this string 46 */ 47 ubyte* end() const{ return ptr + m_bits.length; } 48 49 /** 50 * Returns: this encoded as hex 51 */ 52 string toString() const 53 { 54 return hexEncode(m_bits.ptr, m_bits.length); 55 } 56 57 /** 58 * XOR the contents of another octet string into this one 59 * 60 * Params: 61 * other = octet string 62 * 63 * Returns: reference to this 64 */ 65 OctetString opOpAssign(string op)(in OctetString other) 66 if (op == "^") 67 { 68 if (other.ptr is this.ptr) { zeroise(m_bits); return; } 69 xorBuf(m_bits.ptr, other.ptr, min(length(), other.length)); 70 return this; 71 } 72 73 /** 74 * Force to have odd parity 75 */ 76 void setOddParity() 77 { 78 __gshared immutable ubyte[256] ODD_PARITY = [ 79 0x01, 0x01, 0x02, 0x02, 0x04, 0x04, 0x07, 0x07, 0x08, 0x08, 0x0B, 0x0B, 80 0x0D, 0x0D, 0x0E, 0x0E, 0x10, 0x10, 0x13, 0x13, 0x15, 0x15, 0x16, 0x16, 81 0x19, 0x19, 0x1A, 0x1A, 0x1C, 0x1C, 0x1F, 0x1F, 0x20, 0x20, 0x23, 0x23, 82 0x25, 0x25, 0x26, 0x26, 0x29, 0x29, 0x2A, 0x2A, 0x2C, 0x2C, 0x2F, 0x2F, 83 0x31, 0x31, 0x32, 0x32, 0x34, 0x34, 0x37, 0x37, 0x38, 0x38, 0x3B, 0x3B, 84 0x3D, 0x3D, 0x3E, 0x3E, 0x40, 0x40, 0x43, 0x43, 0x45, 0x45, 0x46, 0x46, 85 0x49, 0x49, 0x4A, 0x4A, 0x4C, 0x4C, 0x4F, 0x4F, 0x51, 0x51, 0x52, 0x52, 86 0x54, 0x54, 0x57, 0x57, 0x58, 0x58, 0x5B, 0x5B, 0x5D, 0x5D, 0x5E, 0x5E, 87 0x61, 0x61, 0x62, 0x62, 0x64, 0x64, 0x67, 0x67, 0x68, 0x68, 0x6B, 0x6B, 88 0x6D, 0x6D, 0x6E, 0x6E, 0x70, 0x70, 0x73, 0x73, 0x75, 0x75, 0x76, 0x76, 89 0x79, 0x79, 0x7A, 0x7A, 0x7C, 0x7C, 0x7F, 0x7F, 0x80, 0x80, 0x83, 0x83, 90 0x85, 0x85, 0x86, 0x86, 0x89, 0x89, 0x8A, 0x8A, 0x8C, 0x8C, 0x8F, 0x8F, 91 0x91, 0x91, 0x92, 0x92, 0x94, 0x94, 0x97, 0x97, 0x98, 0x98, 0x9B, 0x9B, 92 0x9D, 0x9D, 0x9E, 0x9E, 0xA1, 0xA1, 0xA2, 0xA2, 0xA4, 0xA4, 0xA7, 0xA7, 93 0xA8, 0xA8, 0xAB, 0xAB, 0xAD, 0xAD, 0xAE, 0xAE, 0xB0, 0xB0, 0xB3, 0xB3, 94 0xB5, 0xB5, 0xB6, 0xB6, 0xB9, 0xB9, 0xBA, 0xBA, 0xBC, 0xBC, 0xBF, 0xBF, 95 0xC1, 0xC1, 0xC2, 0xC2, 0xC4, 0xC4, 0xC7, 0xC7, 0xC8, 0xC8, 0xCB, 0xCB, 96 0xCD, 0xCD, 0xCE, 0xCE, 0xD0, 0xD0, 0xD3, 0xD3, 0xD5, 0xD5, 0xD6, 0xD6, 97 0xD9, 0xD9, 0xDA, 0xDA, 0xDC, 0xDC, 0xDF, 0xDF, 0xE0, 0xE0, 0xE3, 0xE3, 98 0xE5, 0xE5, 0xE6, 0xE6, 0xE9, 0xE9, 0xEA, 0xEA, 0xEC, 0xEC, 0xEF, 0xEF, 99 0xF1, 0xF1, 0xF2, 0xF2, 0xF4, 0xF4, 0xF7, 0xF7, 0xF8, 0xF8, 0xFB, 0xFB, 100 0xFD, 0xFD, 0xFE, 0xFE ]; 101 102 foreach (j; 0 .. m_bits.length) 103 m_bits[j] = ODD_PARITY[m_bits[j]]; 104 } 105 106 /** 107 * Create a new OctetString 108 * 109 * Params: 110 * hex_string = A hex encoded string 111 */ 112 this(in string hex_string) // = "" 113 { 114 m_bits.resize(1 + hex_string.length / 2); 115 m_bits.resize(hexDecode(m_bits.ptr, hex_string)); 116 } 117 118 /** 119 * Create a new random OctetString 120 * 121 * Params: 122 * rng = is a random number generator 123 * len = is the desired length in bytes 124 */ 125 this(RandomNumberGenerator rng, size_t len) 126 { 127 m_bits = rng.randomVec(len); 128 } 129 130 /** 131 * Create a new OctetString 132 * 133 * Params: 134 * input = is an array 135 * len = is the length of in in bytes 136 */ 137 this(const(ubyte)* input, size_t len) 138 { 139 m_bits = SecureVector!ubyte(input[0 .. len]); 140 } 141 142 /** 143 * Create a new OctetString 144 * 145 * Params: 146 * input = a bytestring 147 */ 148 this(ALLOC)(auto const ref Vector!(ubyte, ALLOC) input) { m_bits = SecureVector!ubyte(input.ptr[0 .. input.length]); } 149 150 /// ditto 151 this(ALLOC)(auto const ref RefCounted!(Vector!(ubyte, ALLOC), ALLOC) input) { m_bits = SecureVector!ubyte(input.ptr[0 .. input.length]); } 152 153 154 /** 155 * Compare two strings 156 * 157 * Params: 158 * other = an octet string 159 * 160 * Returns: true if x is equal to y 161 */ 162 bool opEquals(const ref OctetString other) const 163 { 164 return (m_bits[] == other.m_bits[]); 165 } 166 167 /** 168 * Compare two strings 169 * Params: 170 * other = an octet string 171 * 172 * Returns: 1 if this is bigger, -1 if smaller, 0 if equal to other 173 */ 174 int opCmp(const ref OctetString other) const 175 { 176 if (this == other) return 0; 177 else if (m_bits[] < other.m_bits[]) 178 return -1; 179 else return 1; 180 } 181 182 /// Append another $(D OctetString) to this 183 void opOpAssign(string op)(auto const ref OctetString other) 184 if (op == "~") 185 { 186 m_bits ~= other.m_bits[]; 187 } 188 189 /** 190 * Concatenate two strings 191 * 192 * Params: 193 * other = an octet string 194 * 195 * Returns: this concatenated with other 196 */ 197 OctetString opBinary(string op)(auto const ref OctetString other) 198 if (op == "~") 199 { 200 SecureVector!ubyte output; 201 output = bitsOf(); 202 output ~= other.bitsOf(); 203 return OctetString(output); 204 } 205 206 /** 207 * XOR two strings 208 * 209 * Params: 210 * other = an octet string 211 * 212 * Returns: this XORed with other 213 */ 214 OctetString opBinary(string op)(auto const ref OctetString other) 215 if (op == "^") 216 { 217 SecureVector!ubyte ret = SecureVector!ubyte(max(length(), other.length)); 218 219 copyMem(ret.ptr, k1.ptr, k1.length); 220 xorBuf(ret.ptr, k2.ptr, k2.length); 221 return OctetString(ret); 222 } 223 224 /// Returns: A copy of the underlying bits in a new octet string 225 @property OctetString dup() const 226 { 227 return OctetString(m_bits.dup); 228 } 229 230 private: 231 SecureVector!ubyte m_bits; 232 } 233 234 /** 235 * Alternate name for octet string showing intent to use as a key 236 */ 237 alias SymmetricKey = OctetString; 238 239 /** 240 * Alternate name for octet string showing intent to use as an IV 241 */ 242 alias InitializationVector = OctetString;