2003-03-20 01:24:12 +00:00
|
|
|
// pssr.cpp - written and placed in the public domain by Wei Dai
|
|
|
|
|
|
|
|
#include "pch.h"
|
|
|
|
#include "pssr.h"
|
2015-07-26 19:51:16 +00:00
|
|
|
#include "trap.h"
|
|
|
|
|
2006-06-09 06:27:44 +00:00
|
|
|
#include <functional>
|
2003-03-20 01:24:12 +00:00
|
|
|
|
|
|
|
NAMESPACE_BEGIN(CryptoPP)
|
|
|
|
|
2004-09-03 10:57:31 +00:00
|
|
|
// more in dll.cpp
|
2003-03-20 01:24:12 +00:00
|
|
|
template<> const byte EMSA2HashId<RIPEMD160>::id = 0x31;
|
2003-08-25 21:41:09 +00:00
|
|
|
template<> const byte EMSA2HashId<RIPEMD128>::id = 0x32;
|
|
|
|
template<> const byte EMSA2HashId<Whirlpool>::id = 0x37;
|
2003-03-20 01:24:12 +00:00
|
|
|
|
2004-09-03 10:57:31 +00:00
|
|
|
#ifndef CRYPTOPP_IMPORTS
|
|
|
|
|
2005-07-12 04:23:32 +00:00
|
|
|
size_t PSSR_MEM_Base::MinRepresentativeBitLength(size_t hashIdentifierLength, size_t digestLength) const
|
2005-01-20 04:19:35 +00:00
|
|
|
{
|
2005-07-12 04:23:32 +00:00
|
|
|
size_t saltLen = SaltLen(digestLength);
|
|
|
|
size_t minPadLen = MinPadLen(digestLength);
|
2005-01-20 04:19:35 +00:00
|
|
|
return 9 + 8*(minPadLen + saltLen + digestLength + hashIdentifierLength);
|
|
|
|
}
|
|
|
|
|
2005-07-12 04:23:32 +00:00
|
|
|
size_t PSSR_MEM_Base::MaxRecoverableLength(size_t representativeBitLength, size_t hashIdentifierLength, size_t digestLength) const
|
2003-03-20 01:24:12 +00:00
|
|
|
{
|
|
|
|
if (AllowRecovery())
|
2005-01-20 04:19:35 +00:00
|
|
|
return SaturatingSubtract(representativeBitLength, MinRepresentativeBitLength(hashIdentifierLength, digestLength)) / 8;
|
2003-03-20 01:24:12 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool PSSR_MEM_Base::IsProbabilistic() const
|
|
|
|
{
|
|
|
|
return SaltLen(1) > 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool PSSR_MEM_Base::AllowNonrecoverablePart() const
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool PSSR_MEM_Base::RecoverablePartFirst() const
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void PSSR_MEM_Base::ComputeMessageRepresentative(RandomNumberGenerator &rng,
|
2005-07-12 04:23:32 +00:00
|
|
|
const byte *recoverableMessage, size_t recoverableMessageLength,
|
2003-03-20 01:24:12 +00:00
|
|
|
HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty,
|
2005-07-12 04:23:32 +00:00
|
|
|
byte *representative, size_t representativeBitLength) const
|
2003-03-20 01:24:12 +00:00
|
|
|
{
|
2015-07-26 20:03:14 +00:00
|
|
|
CRYPTOPP_ASSERT(representativeBitLength >= MinRepresentativeBitLength(hashIdentifier.second, hash.DigestSize()));
|
2005-01-20 04:19:35 +00:00
|
|
|
|
2005-07-12 04:23:32 +00:00
|
|
|
const size_t u = hashIdentifier.second + 1;
|
|
|
|
const size_t representativeByteLength = BitsToBytes(representativeBitLength);
|
|
|
|
const size_t digestSize = hash.DigestSize();
|
|
|
|
const size_t saltSize = SaltLen(digestSize);
|
2003-03-20 01:24:12 +00:00
|
|
|
byte *const h = representative + representativeByteLength - u - digestSize;
|
|
|
|
|
|
|
|
SecByteBlock digest(digestSize), salt(saltSize);
|
|
|
|
hash.Final(digest);
|
|
|
|
rng.GenerateBlock(salt, saltSize);
|
|
|
|
|
|
|
|
// compute H = hash of M'
|
|
|
|
byte c[8];
|
2007-04-16 00:20:57 +00:00
|
|
|
PutWord(false, BIG_ENDIAN_ORDER, c, (word32)SafeRightShift<29>(recoverableMessageLength));
|
|
|
|
PutWord(false, BIG_ENDIAN_ORDER, c+4, word32(recoverableMessageLength << 3));
|
2003-03-20 01:24:12 +00:00
|
|
|
hash.Update(c, 8);
|
|
|
|
hash.Update(recoverableMessage, recoverableMessageLength);
|
|
|
|
hash.Update(digest, digestSize);
|
|
|
|
hash.Update(salt, saltSize);
|
|
|
|
hash.Final(h);
|
|
|
|
|
|
|
|
// compute representative
|
|
|
|
GetMGF().GenerateAndMask(hash, representative, representativeByteLength - u - digestSize, h, digestSize, false);
|
|
|
|
byte *xorStart = representative + representativeByteLength - u - digestSize - salt.size() - recoverableMessageLength - 1;
|
|
|
|
xorStart[0] ^= 1;
|
|
|
|
xorbuf(xorStart + 1, recoverableMessage, recoverableMessageLength);
|
|
|
|
xorbuf(xorStart + 1 + recoverableMessageLength, salt, salt.size());
|
2015-07-18 01:36:13 +00:00
|
|
|
|
2015-07-30 17:07:33 +00:00
|
|
|
if (representative && hashIdentifier.first)
|
2015-07-18 01:36:13 +00:00
|
|
|
memcpy(representative + representativeByteLength - u, hashIdentifier.first, hashIdentifier.second);
|
2015-07-18 01:44:53 +00:00
|
|
|
representative[representativeByteLength - 1] = hashIdentifier.second ? 0xcc : 0xbc;
|
2015-07-18 01:36:13 +00:00
|
|
|
|
2003-03-20 01:24:12 +00:00
|
|
|
if (representativeBitLength % 8 != 0)
|
2003-03-20 20:39:59 +00:00
|
|
|
representative[0] = (byte)Crop(representative[0], representativeBitLength % 8);
|
2003-03-20 01:24:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
DecodingResult PSSR_MEM_Base::RecoverMessageFromRepresentative(
|
|
|
|
HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty,
|
2005-07-12 04:23:32 +00:00
|
|
|
byte *representative, size_t representativeBitLength,
|
2003-03-20 01:24:12 +00:00
|
|
|
byte *recoverableMessage) const
|
|
|
|
{
|
2015-07-26 20:03:14 +00:00
|
|
|
CRYPTOPP_ASSERT(representativeBitLength >= MinRepresentativeBitLength(hashIdentifier.second, hash.DigestSize()));
|
2005-01-20 04:19:35 +00:00
|
|
|
|
2005-07-12 04:23:32 +00:00
|
|
|
const size_t u = hashIdentifier.second + 1;
|
|
|
|
const size_t representativeByteLength = BitsToBytes(representativeBitLength);
|
|
|
|
const size_t digestSize = hash.DigestSize();
|
|
|
|
const size_t saltSize = SaltLen(digestSize);
|
2003-03-20 01:24:12 +00:00
|
|
|
const byte *const h = representative + representativeByteLength - u - digestSize;
|
|
|
|
|
|
|
|
SecByteBlock digest(digestSize);
|
|
|
|
hash.Final(digest);
|
|
|
|
|
|
|
|
DecodingResult result(0);
|
|
|
|
bool &valid = result.isValidCoding;
|
2005-07-12 04:23:32 +00:00
|
|
|
size_t &recoverableMessageLength = result.messageLength;
|
2003-03-20 01:24:12 +00:00
|
|
|
|
|
|
|
valid = (representative[representativeByteLength - 1] == (hashIdentifier.second ? 0xcc : 0xbc)) && valid;
|
2009-03-02 02:39:17 +00:00
|
|
|
valid = VerifyBufsEqual(representative + representativeByteLength - u, hashIdentifier.first, hashIdentifier.second) && valid;
|
2003-03-20 01:24:12 +00:00
|
|
|
|
|
|
|
GetMGF().GenerateAndMask(hash, representative, representativeByteLength - u - digestSize, h, digestSize);
|
|
|
|
if (representativeBitLength % 8 != 0)
|
2003-03-20 20:39:59 +00:00
|
|
|
representative[0] = (byte)Crop(representative[0], representativeBitLength % 8);
|
2003-03-20 01:24:12 +00:00
|
|
|
|
|
|
|
// extract salt and recoverableMessage from DB = 00 ... || 01 || M || salt
|
|
|
|
byte *salt = representative + representativeByteLength - u - digestSize - saltSize;
|
2015-07-30 17:07:33 +00:00
|
|
|
byte *M = std::find_if (representative, salt-1, std::bind2nd(std::not_equal_to<byte>(), byte(0)));
|
2005-01-20 04:19:35 +00:00
|
|
|
recoverableMessageLength = salt-M-1;
|
|
|
|
if (*M == 0x01
|
2005-07-12 04:23:32 +00:00
|
|
|
&& (size_t)(M - representative - (representativeBitLength % 8 != 0)) >= MinPadLen(digestSize)
|
2005-01-20 04:19:35 +00:00
|
|
|
&& recoverableMessageLength <= MaxRecoverableLength(representativeBitLength, hashIdentifier.second, digestSize))
|
2003-03-20 01:24:12 +00:00
|
|
|
{
|
2015-07-30 17:07:33 +00:00
|
|
|
if (recoverableMessage && M && recoverableMessageLength)
|
2015-07-18 01:36:13 +00:00
|
|
|
memcpy(recoverableMessage, M+1, recoverableMessageLength);
|
2003-03-20 01:24:12 +00:00
|
|
|
}
|
|
|
|
else
|
2005-01-20 04:19:35 +00:00
|
|
|
{
|
|
|
|
recoverableMessageLength = 0;
|
2003-03-20 01:24:12 +00:00
|
|
|
valid = false;
|
2005-01-20 04:19:35 +00:00
|
|
|
}
|
2003-03-20 01:24:12 +00:00
|
|
|
|
|
|
|
// verify H = hash of M'
|
|
|
|
byte c[8];
|
2007-04-16 00:20:57 +00:00
|
|
|
PutWord(false, BIG_ENDIAN_ORDER, c, (word32)SafeRightShift<29>(recoverableMessageLength));
|
|
|
|
PutWord(false, BIG_ENDIAN_ORDER, c+4, word32(recoverableMessageLength << 3));
|
2003-03-20 01:24:12 +00:00
|
|
|
hash.Update(c, 8);
|
|
|
|
hash.Update(recoverableMessage, recoverableMessageLength);
|
|
|
|
hash.Update(digest, digestSize);
|
|
|
|
hash.Update(salt, saltSize);
|
|
|
|
valid = hash.Verify(h) && valid;
|
|
|
|
|
|
|
|
if (!AllowRecovery() && valid && recoverableMessageLength != 0)
|
|
|
|
{throw NotImplemented("PSSR_MEM: message recovery disabled");}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2004-09-03 10:57:31 +00:00
|
|
|
#endif
|
|
|
|
|
2003-03-20 01:24:12 +00:00
|
|
|
NAMESPACE_END
|