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