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