1 /** 2 * EMSA1 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.pk_pad.emsa1; 12 13 import botan.constants; 14 static if (BOTAN_HAS_EMSA1): 15 16 public import botan.pk_pad.emsa; 17 import botan.hash.hash; 18 import botan.utils.types; 19 20 /** 21 * EMSA1 from IEEE 1363 22 * Essentially, sign the hash directly 23 */ 24 class EMSA1 : EMSA 25 { 26 public: 27 /** 28 * Params: 29 * hash = the hash function to use 30 */ 31 this(HashFunction hash) 32 { 33 m_hash = hash; 34 } 35 36 size_t hashOutputLength() const { return m_hash.outputLength; } 37 38 override void update(const(ubyte)* input, size_t length) 39 { 40 m_hash.update(input, length); 41 } 42 43 override SecureVector!ubyte rawData() 44 { 45 return m_hash.finished(); 46 } 47 48 override SecureVector!ubyte encodingOf(const ref SecureVector!ubyte msg, 49 size_t output_bits, 50 RandomNumberGenerator rng) 51 { 52 //logDebug("EMSA1 Encode"); 53 if (msg.length != hashOutputLength()) 54 throw new EncodingError("encodingOf: Invalid size for input"); 55 return emsa1Encoding(msg, output_bits); 56 } 57 58 override bool verify(const ref SecureVector!ubyte coded, 59 const ref SecureVector!ubyte raw, size_t key_bits) 60 { 61 try { 62 if (raw.length != m_hash.outputLength) 63 throw new EncodingError("encodingOf: Invalid size for input"); 64 65 SecureVector!ubyte our_coding = emsa1Encoding(raw, key_bits); 66 if (our_coding == coded) return true; 67 if (our_coding.empty || our_coding[0] != 0) return false; 68 if (our_coding.length <= coded.length) return false; 69 70 size_t offset = 0; 71 while (offset < our_coding.length && our_coding[offset] == 0) 72 ++offset; 73 if (our_coding.length - offset != coded.length) 74 return false; 75 76 for (size_t j = 0; j != coded.length; ++j) 77 if (coded[j] != our_coding[j+offset]) 78 return false; 79 80 return true; 81 } 82 catch(InvalidArgument) 83 { 84 return false; 85 } 86 } 87 88 Unique!HashFunction m_hash; 89 } 90 91 private: 92 93 SecureVector!ubyte emsa1Encoding(const ref SecureVector!ubyte msg_, size_t output_bits) 94 { 95 SecureVector!ubyte msg = msg_.clone; 96 97 if (8*msg.length <= output_bits) 98 return msg.move; 99 // logDebug("Generate digest"); 100 size_t shift = 8*msg.length - output_bits; 101 102 size_t byte_shift = shift / 8, bit_shift = shift % 8; 103 SecureVector!ubyte digest = SecureVector!ubyte(msg.length - byte_shift); 104 105 for (size_t j = 0; j != msg.length - byte_shift; ++j) 106 digest[j] = msg[j]; 107 108 if (bit_shift) 109 { 110 ubyte carry = 0; 111 for (size_t j = 0; j != digest.length; ++j) 112 { 113 ubyte temp = digest[j]; 114 digest[j] = (temp >> bit_shift) | carry; 115 carry = cast(ubyte)(temp << (8 - bit_shift)); 116 } 117 } 118 return digest.move(); 119 }