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 Wed Jul 28 08:07:08 2004 for Crypto++ by doxygen 1.3.7