Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | 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 template<> const byte EMSA2HashId<SHA>::id = 0x33;
    00009 template<> const byte EMSA2HashId<RIPEMD160>::id = 0x31;
    00010 template<> const byte EMSA2HashId<RIPEMD128>::id = 0x32;
    00011 template<> const byte EMSA2HashId<SHA256>::id = 0x34;
    00012 template<> const byte EMSA2HashId<SHA384>::id = 0x36;
    00013 template<> const byte EMSA2HashId<SHA512>::id = 0x35;
    00014 template<> const byte EMSA2HashId<Whirlpool>::id = 0x37;
    00015
    00016 unsigned int PSSR_MEM_Base::MaxRecoverableLength(unsigned int representativeBitLength, unsigned int hashIdentifierLength, unsigned int digestLength) const
    00017 {
    00018         if (AllowRecovery())
    00019         {
    00020                 unsigned int saltLen = SaltLen(digestLength);
    00021                 unsigned int minPadLen = MinPadLen(digestLength);
    00022                 return SaturatingSubtract(representativeBitLength, 8*(minPadLen + saltLen + digestLength + hashIdentifierLength) + 9) / 8;
    00023         }
    00024         return 0;
    00025 }
    00026
    00027 bool PSSR_MEM_Base::IsProbabilistic() const
    00028 {
    00029         return SaltLen(1) > 0;
    00030 }
    00031
    00032 bool PSSR_MEM_Base::AllowNonrecoverablePart() const
    00033 {
    00034         return true;
    00035 }
    00036
    00037 bool PSSR_MEM_Base::RecoverablePartFirst() const
    00038 {
    00039         return false;
    00040 }
    00041
    00042 void PSSR_MEM_Base::ComputeMessageRepresentative(RandomNumberGenerator &rng,
    00043         const byte *recoverableMessage, unsigned int recoverableMessageLength,
    00044         HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty,
    00045         byte *representative, unsigned int representativeBitLength) const
    00046 {
    00047         const unsigned int u = hashIdentifier.second + 1;
    00048         const unsigned int representativeByteLength = BitsToBytes(representativeBitLength);
    00049         const unsigned int digestSize = hash.DigestSize();
    00050         const unsigned int saltSize = SaltLen(digestSize);
    00051         byte *const h = representative + representativeByteLength - u - digestSize;
    00052
    00053         SecByteBlock digest(digestSize), salt(saltSize);
    00054         hash.Final(digest);
    00055         rng.GenerateBlock(salt, saltSize);
    00056
    00057         // compute H = hash of M'
    00058         byte c[8];
    00059         UnalignedPutWord(BIG_ENDIAN_ORDER, c, (word32)SafeRightShift<29>(recoverableMessageLength));
    00060         UnalignedPutWord(BIG_ENDIAN_ORDER, c+4, word32(recoverableMessageLength << 3));
    00061         hash.Update(c, 8);
    00062         hash.Update(recoverableMessage, recoverableMessageLength);
    00063         hash.Update(digest, digestSize);
    00064         hash.Update(salt, saltSize);
    00065         hash.Final(h);
    00066
    00067         // compute representative
    00068         GetMGF().GenerateAndMask(hash, representative, representativeByteLength - u - digestSize, h, digestSize, false);
    00069         byte *xorStart = representative + representativeByteLength - u - digestSize - salt.size() - recoverableMessageLength - 1;
    00070         xorStart[0] ^= 1;
    00071         xorbuf(xorStart + 1, recoverableMessage, recoverableMessageLength);
    00072         xorbuf(xorStart + 1 + recoverableMessageLength, salt, salt.size());
    00073         memcpy(representative + representativeByteLength - u, hashIdentifier.first, hashIdentifier.second);
    00074         representative[representativeByteLength - 1] = hashIdentifier.second ? 0xcc : 0xbc;
    00075         if (representativeBitLength % 8 != 0)
    00076                 representative[0] = (byte)Crop(representative[0], representativeBitLength % 8);
    00077 }
    00078
    00079 DecodingResult PSSR_MEM_Base::RecoverMessageFromRepresentative(
    00080         HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty,
    00081         byte *representative, unsigned int representativeBitLength,
    00082         byte *recoverableMessage) const
    00083 {
    00084         const unsigned int u = hashIdentifier.second + 1;
    00085         const unsigned int representativeByteLength = BitsToBytes(representativeBitLength);
    00086         const unsigned int digestSize = hash.DigestSize();
    00087         const unsigned int saltSize = SaltLen(digestSize);
    00088         const byte *const h = representative + representativeByteLength - u - digestSize;
    00089
    00090         SecByteBlock digest(digestSize);
    00091         hash.Final(digest);
    00092
    00093         DecodingResult result(0);
    00094         bool &valid = result.isValidCoding;
    00095         unsigned int &recoverableMessageLength = result.messageLength;
    00096
    00097         valid = (representative[representativeByteLength - 1] == (hashIdentifier.second ? 0xcc : 0xbc)) && valid;
    00098         valid = (memcmp(representative + representativeByteLength - u, hashIdentifier.first, hashIdentifier.second) == 0) && valid;
    00099
    00100         GetMGF().GenerateAndMask(hash, representative, representativeByteLength - u - digestSize, h, digestSize);
    00101         if (representativeBitLength % 8 != 0)
    00102                 representative[0] = (byte)Crop(representative[0], representativeBitLength % 8);
    00103
    00104         // extract salt and recoverableMessage from DB = 00 ... || 01 || M || salt
    00105         byte *salt = representative + representativeByteLength - u - digestSize - saltSize;
    00106         byte *M = std::find_if(representative, salt-1, std::bind2nd(std::not_equal_to<byte>(), 0));
    00107         if (*M == 0x01 && (unsigned int)(M - representative - (representativeBitLength % 8 != 0)) >= MinPadLen(digestSize))
    00108         {
    00109                 recoverableMessageLength = salt-M-1;
    00110                 memcpy(recoverableMessage, M+1, recoverableMessageLength);
    00111         }
    00112         else
    00113                 valid = false;
    00114
    00115         // verify H = hash of M'
    00116         byte c[8];
    00117         UnalignedPutWord(BIG_ENDIAN_ORDER, c, (word32)SafeRightShift<29>(recoverableMessageLength));
    00118         UnalignedPutWord(BIG_ENDIAN_ORDER, c+4, word32(recoverableMessageLength << 3));
    00119         hash.Update(c, 8);
    00120         hash.Update(recoverableMessage, recoverableMessageLength);
    00121         hash.Update(digest, digestSize);
    00122         hash.Update(salt, saltSize);
    00123         valid = hash.Verify(h) && valid;
    00124
    00125         if (!AllowRecovery() && valid && recoverableMessageLength != 0)
    00126                 {throw NotImplemented("PSSR_MEM: message recovery disabled");}
    00127
    00128         return result;
    00129 }
    00130
    00131 NAMESPACE_END