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

Generated on Fri Dec 16 03:04:17 2005 for Crypto++ by  doxygen 1.4.5