diff options
author | weidai <weidai@57ff6487-cd31-0410-9ec3-f628ee90f5f0> | 2003-03-20 01:24:12 +0000 |
---|---|---|
committer | weidai <weidai@57ff6487-cd31-0410-9ec3-f628ee90f5f0> | 2003-03-20 01:24:12 +0000 |
commit | d23a489940499bd6c634a1cb0a9875f094f8a850 (patch) | |
tree | f85b3bed971083e90e5f3dbb84539ea4ba0359e9 /pssr.cpp | |
parent | b3517523a738277cfe22428bd757833e69abb66e (diff) | |
download | cryptopp-d23a489940499bd6c634a1cb0a9875f094f8a850.tar.gz |
various changes for 5.1
git-svn-id: svn://svn.code.sf.net/p/cryptopp/code/trunk/c5@38 57ff6487-cd31-0410-9ec3-f628ee90f5f0
Diffstat (limited to 'pssr.cpp')
-rw-r--r-- | pssr.cpp | 126 |
1 files changed, 126 insertions, 0 deletions
diff --git a/pssr.cpp b/pssr.cpp new file mode 100644 index 0000000..020cb98 --- /dev/null +++ b/pssr.cpp @@ -0,0 +1,126 @@ +// pssr.cpp - written and placed in the public domain by Wei Dai + +#include "pch.h" +#include "pssr.h" + +NAMESPACE_BEGIN(CryptoPP) + +template<> const byte EMSA2HashId<SHA>::id = 0x33; +template<> const byte EMSA2HashId<RIPEMD160>::id = 0x31; + +unsigned int PSSR_MEM_Base::MaxRecoverableLength(unsigned int representativeBitLength, unsigned int hashIdentifierLength, unsigned int digestLength) const +{ + if (AllowRecovery()) + { + unsigned int saltLen = SaltLen(digestLength); + unsigned int minPadLen = MinPadLen(digestLength); + return SaturatingSubtract(representativeBitLength, 8*(minPadLen + saltLen + digestLength + hashIdentifierLength) + 9) / 8; + } + 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, + const byte *recoverableMessage, unsigned int recoverableMessageLength, + HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty, + byte *representative, unsigned int representativeBitLength) const +{ + const unsigned int u = hashIdentifier.second + 1; + const unsigned int representativeByteLength = BitsToBytes(representativeBitLength); + const unsigned int digestSize = hash.DigestSize(); + const unsigned int saltSize = SaltLen(digestSize); + 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]; + UnalignedPutWord(BIG_ENDIAN_ORDER, c, (word32)SafeRightShift<29>(recoverableMessageLength)); + UnalignedPutWord(BIG_ENDIAN_ORDER, c+4, word32(recoverableMessageLength << 3)); + 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()); + memcpy(representative + representativeByteLength - u, hashIdentifier.first, hashIdentifier.second); + representative[representativeByteLength - 1] = hashIdentifier.second ? 0xcc : 0xbc; + if (representativeBitLength % 8 != 0) + representative[0] = Crop(representative[0], representativeBitLength % 8); +} + +DecodingResult PSSR_MEM_Base::RecoverMessageFromRepresentative( + HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty, + byte *representative, unsigned int representativeBitLength, + byte *recoverableMessage) const +{ + const unsigned int u = hashIdentifier.second + 1; + const unsigned int representativeByteLength = BitsToBytes(representativeBitLength); + const unsigned int digestSize = hash.DigestSize(); + const unsigned int saltSize = SaltLen(digestSize); + const byte *const h = representative + representativeByteLength - u - digestSize; + + SecByteBlock digest(digestSize); + hash.Final(digest); + + DecodingResult result(0); + bool &valid = result.isValidCoding; + unsigned int &recoverableMessageLength = result.messageLength; + + valid = (representative[representativeByteLength - 1] == (hashIdentifier.second ? 0xcc : 0xbc)) && valid; + valid = (memcmp(representative + representativeByteLength - u, hashIdentifier.first, hashIdentifier.second) == 0) && valid; + + GetMGF().GenerateAndMask(hash, representative, representativeByteLength - u - digestSize, h, digestSize); + if (representativeBitLength % 8 != 0) + representative[0] = Crop(representative[0], representativeBitLength % 8); + + // extract salt and recoverableMessage from DB = 00 ... || 01 || M || salt + byte *salt = representative + representativeByteLength - u - digestSize - saltSize; + byte *M = std::find_if(representative, salt-1, std::bind2nd(std::not_equal_to<byte>(), 0)); + if (*M == 0x01 && M - representative - (representativeBitLength % 8 != 0) >= MinPadLen(digestSize)) + { + recoverableMessageLength = salt-M-1; + memcpy(recoverableMessage, M+1, recoverableMessageLength); + } + else + valid = false; + + // verify H = hash of M' + byte c[8]; + UnalignedPutWord(BIG_ENDIAN_ORDER, c, (word32)SafeRightShift<29>(recoverableMessageLength)); + UnalignedPutWord(BIG_ENDIAN_ORDER, c+4, word32(recoverableMessageLength << 3)); + 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; +} + +NAMESPACE_END |