00001
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
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
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
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
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