Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | 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
    00006 NAMESPACE_BEGIN(CryptoPP)
    00007
    00008 // more in dll.cpp
    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 unsigned int PSSR_MEM_Base::MinRepresentativeBitLength(unsigned int hashIdentifierLength, unsigned int digestLength) const
    00016 {
    00017         unsigned int saltLen = SaltLen(digestLength);
    00018         unsigned int minPadLen = MinPadLen(digestLength);
    00019         return 9 + 8*(minPadLen + saltLen + digestLength + hashIdentifierLength);
    00020 }
    00021
    00022 unsigned int PSSR_MEM_Base::MaxRecoverableLength(unsigned int representativeBitLength, unsigned int hashIdentifierLength, unsigned int 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, unsigned int recoverableMessageLength,
    00046         HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty,
    00047         byte *representative, unsigned int representativeBitLength) const
    00048 {
    00049         assert(representativeBitLength >= MinRepresentativeBitLength(hashIdentifier.second, hash.DigestSize()));
    00050
    00051         const unsigned int u = hashIdentifier.second + 1;
    00052         const unsigned int representativeByteLength = BitsToBytes(representativeBitLength);
    00053         const unsigned int digestSize = hash.DigestSize();
    00054         const unsigned int 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         // compute H = hash of M'
    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         // compute representative
    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, unsigned int representativeBitLength,
    00086         byte *recoverableMessage) const
    00087 {
    00088         assert(representativeBitLength >= MinRepresentativeBitLength(hashIdentifier.second, hash.DigestSize()));
    00089
    00090         const unsigned int u = hashIdentifier.second + 1;
    00091         const unsigned int representativeByteLength = BitsToBytes(representativeBitLength);
    00092         const unsigned int digestSize = hash.DigestSize();
    00093         const unsigned int 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         unsigned int &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         // extract salt and recoverableMessage from DB = 00 ... || 01 || M || salt
    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                 && (unsigned int)(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         // verify H = hash of M'
    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