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