00001
00002
00003 #include "pch.h"
00004 #include "pssr.h"
00005 #include <functional>
00006
00007 NAMESPACE_BEGIN(CryptoPP)
00008
00009
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
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
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
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
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