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 size_t PSSR_MEM_Base::MinRepresentativeBitLength(size_t hashIdentifierLength, size_t digestLength) const
00016 {
00017         size_t saltLen = SaltLen(digestLength);
00018         size_t minPadLen = MinPadLen(digestLength);
00019         return 9 + 8*(minPadLen + saltLen + digestLength + hashIdentifierLength);
00020 }
00021 
00022 size_t PSSR_MEM_Base::MaxRecoverableLength(size_t representativeBitLength, size_t hashIdentifierLength, size_t 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, size_t recoverableMessageLength,
00046         HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty,
00047         byte *representative, size_t representativeBitLength) const
00048 {
00049         assert(representativeBitLength >= MinRepresentativeBitLength(hashIdentifier.second, hash.DigestSize()));
00050 
00051         const size_t u = hashIdentifier.second + 1;
00052         const size_t representativeByteLength = BitsToBytes(representativeBitLength);
00053         const size_t digestSize = hash.DigestSize();
00054         const size_t 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, size_t representativeBitLength,
00086         byte *recoverableMessage) const
00087 {
00088         assert(representativeBitLength >= MinRepresentativeBitLength(hashIdentifier.second, hash.DigestSize()));
00089 
00090         const size_t u = hashIdentifier.second + 1;
00091         const size_t representativeByteLength = BitsToBytes(representativeBitLength);
00092         const size_t digestSize = hash.DigestSize();
00093         const size_t 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         size_t &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                 && (size_t)(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

Generated on Tue Aug 16 08:38:42 2005 for Crypto++ by  doxygen 1.3.9.1