Crypto++
|
00001 // pssr.cpp - written and placed in the public domain by Wei Dai 00002 00003 #include "pch.h" 00004 #include "pssr.h" 00005 #include <functional> 00006 00007 NAMESPACE_BEGIN(CryptoPP) 00008 00009 // more in dll.cpp 00010 template<> const byte EMSA2HashId<RIPEMD160>::id = 0x31; 00011 template<> const byte EMSA2HashId<RIPEMD128>::id = 0x32; 00012 template<> const byte EMSA2HashId<Whirlpool>::id = 0x37; 00013 00014 #ifndef CRYPTOPP_IMPORTS 00015 00016 size_t PSSR_MEM_Base::MinRepresentativeBitLength(size_t hashIdentifierLength, size_t digestLength) const 00017 { 00018 size_t saltLen = SaltLen(digestLength); 00019 size_t minPadLen = MinPadLen(digestLength); 00020 return 9 + 8*(minPadLen + saltLen + digestLength + hashIdentifierLength); 00021 } 00022 00023 size_t PSSR_MEM_Base::MaxRecoverableLength(size_t representativeBitLength, size_t hashIdentifierLength, size_t digestLength) const 00024 { 00025 if (AllowRecovery()) 00026 return SaturatingSubtract(representativeBitLength, MinRepresentativeBitLength(hashIdentifierLength, digestLength)) / 8; 00027 return 0; 00028 } 00029 00030 bool PSSR_MEM_Base::IsProbabilistic() const 00031 { 00032 return SaltLen(1) > 0; 00033 } 00034 00035 bool PSSR_MEM_Base::AllowNonrecoverablePart() const 00036 { 00037 return true; 00038 } 00039 00040 bool PSSR_MEM_Base::RecoverablePartFirst() const 00041 { 00042 return false; 00043 } 00044 00045 void PSSR_MEM_Base::ComputeMessageRepresentative(RandomNumberGenerator &rng, 00046 const byte *recoverableMessage, size_t recoverableMessageLength, 00047 HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty, 00048 byte *representative, size_t representativeBitLength) const 00049 { 00050 assert(representativeBitLength >= MinRepresentativeBitLength(hashIdentifier.second, hash.DigestSize())); 00051 00052 const size_t u = hashIdentifier.second + 1; 00053 const size_t representativeByteLength = BitsToBytes(representativeBitLength); 00054 const size_t digestSize = hash.DigestSize(); 00055 const size_t saltSize = SaltLen(digestSize); 00056 byte *const h = representative + representativeByteLength - u - digestSize; 00057 00058 SecByteBlock digest(digestSize), salt(saltSize); 00059 hash.Final(digest); 00060 rng.GenerateBlock(salt, saltSize); 00061 00062 // compute H = hash of M' 00063 byte c[8]; 00064 PutWord(false, BIG_ENDIAN_ORDER, c, (word32)SafeRightShift<29>(recoverableMessageLength)); 00065 PutWord(false, BIG_ENDIAN_ORDER, c+4, word32(recoverableMessageLength << 3)); 00066 hash.Update(c, 8); 00067 hash.Update(recoverableMessage, recoverableMessageLength); 00068 hash.Update(digest, digestSize); 00069 hash.Update(salt, saltSize); 00070 hash.Final(h); 00071 00072 // compute representative 00073 GetMGF().GenerateAndMask(hash, representative, representativeByteLength - u - digestSize, h, digestSize, false); 00074 byte *xorStart = representative + representativeByteLength - u - digestSize - salt.size() - recoverableMessageLength - 1; 00075 xorStart[0] ^= 1; 00076 xorbuf(xorStart + 1, recoverableMessage, recoverableMessageLength); 00077 xorbuf(xorStart + 1 + recoverableMessageLength, salt, salt.size()); 00078 memcpy(representative + representativeByteLength - u, hashIdentifier.first, hashIdentifier.second); 00079 representative[representativeByteLength - 1] = hashIdentifier.second ? 0xcc : 0xbc; 00080 if (representativeBitLength % 8 != 0) 00081 representative[0] = (byte)Crop(representative[0], representativeBitLength % 8); 00082 } 00083 00084 DecodingResult PSSR_MEM_Base::RecoverMessageFromRepresentative( 00085 HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty, 00086 byte *representative, size_t representativeBitLength, 00087 byte *recoverableMessage) const 00088 { 00089 assert(representativeBitLength >= MinRepresentativeBitLength(hashIdentifier.second, hash.DigestSize())); 00090 00091 const size_t u = hashIdentifier.second + 1; 00092 const size_t representativeByteLength = BitsToBytes(representativeBitLength); 00093 const size_t digestSize = hash.DigestSize(); 00094 const size_t saltSize = SaltLen(digestSize); 00095 const byte *const h = representative + representativeByteLength - u - digestSize; 00096 00097 SecByteBlock digest(digestSize); 00098 hash.Final(digest); 00099 00100 DecodingResult result(0); 00101 bool &valid = result.isValidCoding; 00102 size_t &recoverableMessageLength = result.messageLength; 00103 00104 valid = (representative[representativeByteLength - 1] == (hashIdentifier.second ? 0xcc : 0xbc)) && valid; 00105 valid = VerifyBufsEqual(representative + representativeByteLength - u, hashIdentifier.first, hashIdentifier.second) && valid; 00106 00107 GetMGF().GenerateAndMask(hash, representative, representativeByteLength - u - digestSize, h, digestSize); 00108 if (representativeBitLength % 8 != 0) 00109 representative[0] = (byte)Crop(representative[0], representativeBitLength % 8); 00110 00111 // extract salt and recoverableMessage from DB = 00 ... || 01 || M || salt 00112 byte *salt = representative + representativeByteLength - u - digestSize - saltSize; 00113 byte *M = std::find_if(representative, salt-1, std::bind2nd(std::not_equal_to<byte>(), 0)); 00114 recoverableMessageLength = salt-M-1; 00115 if (*M == 0x01 00116 && (size_t)(M - representative - (representativeBitLength % 8 != 0)) >= MinPadLen(digestSize) 00117 && recoverableMessageLength <= MaxRecoverableLength(representativeBitLength, hashIdentifier.second, digestSize)) 00118 { 00119 memcpy(recoverableMessage, M+1, recoverableMessageLength); 00120 } 00121 else 00122 { 00123 recoverableMessageLength = 0; 00124 valid = false; 00125 } 00126 00127 // verify H = hash of M' 00128 byte c[8]; 00129 PutWord(false, BIG_ENDIAN_ORDER, c, (word32)SafeRightShift<29>(recoverableMessageLength)); 00130 PutWord(false, BIG_ENDIAN_ORDER, c+4, word32(recoverableMessageLength << 3)); 00131 hash.Update(c, 8); 00132 hash.Update(recoverableMessage, recoverableMessageLength); 00133 hash.Update(digest, digestSize); 00134 hash.Update(salt, saltSize); 00135 valid = hash.Verify(h) && valid; 00136 00137 if (!AllowRecovery() && valid && recoverableMessageLength != 0) 00138 {throw NotImplemented("PSSR_MEM: message recovery disabled");} 00139 00140 return result; 00141 } 00142 00143 #endif 00144 00145 NAMESPACE_END