- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

# pssr.cpp

    00001 // pssr.cpp - written and placed in the public domain by Wei Dai
    00002
    00003 #include "pch.h"
    00004 #include "pssr.h"
    00005 #include <functional>
    00006
    00007 NAMESPACE_BEGIN(CryptoPP)
    00008
    00009 // more in dll.cpp
    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         // compute H = hash of M'
    00063         byte c[8];
    00064         UnalignedPutWord(BIG_ENDIAN_ORDER, c, (word32)SafeRightShift<29>(recoverableMessageLength));
    00065         UnalignedPutWord(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         // compute representative
    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 = (memcmp(representative + representativeByteLength - u, hashIdentifier.first, hashIdentifier.second) == 0) && 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         // extract salt and recoverableMessage from DB = 00 ... || 01 || M || salt
    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         // verify H = hash of M'
    00128         byte c[8];
    00129         UnalignedPutWord(BIG_ENDIAN_ORDER, c, (word32)SafeRightShift<29>(recoverableMessageLength));
    00130         UnalignedPutWord(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