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 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 Aug 27 22:02:11 2004 for Crypto++ by doxygen 1.3.8