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

Generated on Sat Dec 23 02:07:09 2006 for Crypto++ by  doxygen 1.5.1-p1