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