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