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

Generated on Sun Mar 14 20:44:27 2004 for Crypto++ by doxygen 1.3.6-20040222