monotone

monotone Mtn Source Tree

Root/cryptopp/pssr.cpp

1// pssr.cpp - written and placed in the public domain by Wei Dai
2
3#include "pch.h"
4#include "pssr.h"
5
6NAMESPACE_BEGIN(CryptoPP)
7
8template<> const byte EMSA2HashId<SHA>::id = 0x33;
9template<> const byte EMSA2HashId<RIPEMD160>::id = 0x31;
10
11unsigned int PSSR_MEM_Base::MaxRecoverableLength(unsigned int representativeBitLength, unsigned int hashIdentifierLength, unsigned int digestLength) const
12{
13if (AllowRecovery())
14{
15unsigned int saltLen = SaltLen(digestLength);
16unsigned int minPadLen = MinPadLen(digestLength);
17return SaturatingSubtract(representativeBitLength, 8*(minPadLen + saltLen + digestLength + hashIdentifierLength) + 9) / 8;
18}
19return 0;
20}
21
22bool PSSR_MEM_Base::IsProbabilistic() const
23{
24return SaltLen(1) > 0;
25}
26
27bool PSSR_MEM_Base::AllowNonrecoverablePart() const
28{
29return true;
30}
31
32bool PSSR_MEM_Base::RecoverablePartFirst() const
33{
34return false;
35}
36
37void PSSR_MEM_Base::ComputeMessageRepresentative(RandomNumberGenerator &rng,
38const byte *recoverableMessage, unsigned int recoverableMessageLength,
39HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty,
40byte *representative, unsigned int representativeBitLength) const
41{
42const unsigned int u = hashIdentifier.second + 1;
43const unsigned int representativeByteLength = BitsToBytes(representativeBitLength);
44const unsigned int digestSize = hash.DigestSize();
45const unsigned int saltSize = SaltLen(digestSize);
46byte *const h = representative + representativeByteLength - u - digestSize;
47
48SecByteBlock digest(digestSize), salt(saltSize);
49hash.Final(digest);
50rng.GenerateBlock(salt, saltSize);
51
52// compute H = hash of M'
53byte c[8];
54UnalignedPutWord(BIG_ENDIAN_ORDER, c, (word32)SafeRightShift<29>(recoverableMessageLength));
55UnalignedPutWord(BIG_ENDIAN_ORDER, c+4, word32(recoverableMessageLength << 3));
56hash.Update(c, 8);
57hash.Update(recoverableMessage, recoverableMessageLength);
58hash.Update(digest, digestSize);
59hash.Update(salt, saltSize);
60hash.Final(h);
61
62// compute representative
63GetMGF().GenerateAndMask(hash, representative, representativeByteLength - u - digestSize, h, digestSize, false);
64byte *xorStart = representative + representativeByteLength - u - digestSize - salt.size() - recoverableMessageLength - 1;
65xorStart[0] ^= 1;
66xorbuf(xorStart + 1, recoverableMessage, recoverableMessageLength);
67xorbuf(xorStart + 1 + recoverableMessageLength, salt, salt.size());
68memcpy(representative + representativeByteLength - u, hashIdentifier.first, hashIdentifier.second);
69representative[representativeByteLength - 1] = hashIdentifier.second ? 0xcc : 0xbc;
70if (representativeBitLength % 8 != 0)
71representative[0] = (byte)Crop(representative[0], representativeBitLength % 8);
72}
73
74DecodingResult PSSR_MEM_Base::RecoverMessageFromRepresentative(
75HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty,
76byte *representative, unsigned int representativeBitLength,
77byte *recoverableMessage) const
78{
79const unsigned int u = hashIdentifier.second + 1;
80const unsigned int representativeByteLength = BitsToBytes(representativeBitLength);
81const unsigned int digestSize = hash.DigestSize();
82const unsigned int saltSize = SaltLen(digestSize);
83const byte *const h = representative + representativeByteLength - u - digestSize;
84
85SecByteBlock digest(digestSize);
86hash.Final(digest);
87
88DecodingResult result(0);
89bool &valid = result.isValidCoding;
90unsigned int &recoverableMessageLength = result.messageLength;
91
92valid = (representative[representativeByteLength - 1] == (hashIdentifier.second ? 0xcc : 0xbc)) && valid;
93valid = (memcmp(representative + representativeByteLength - u, hashIdentifier.first, hashIdentifier.second) == 0) && valid;
94
95GetMGF().GenerateAndMask(hash, representative, representativeByteLength - u - digestSize, h, digestSize);
96if (representativeBitLength % 8 != 0)
97representative[0] = (byte)Crop(representative[0], representativeBitLength % 8);
98
99// extract salt and recoverableMessage from DB = 00 ... || 01 || M || salt
100byte *salt = representative + representativeByteLength - u - digestSize - saltSize;
101byte *M = std::find_if(representative, salt-1, std::bind2nd(std::not_equal_to<byte>(), 0));
102if (*M == 0x01 && (unsigned int)(M - representative - (representativeBitLength % 8 != 0)) >= MinPadLen(digestSize))
103{
104recoverableMessageLength = salt-M-1;
105memcpy(recoverableMessage, M+1, recoverableMessageLength);
106}
107else
108valid = false;
109
110// verify H = hash of M'
111byte c[8];
112UnalignedPutWord(BIG_ENDIAN_ORDER, c, (word32)SafeRightShift<29>(recoverableMessageLength));
113UnalignedPutWord(BIG_ENDIAN_ORDER, c+4, word32(recoverableMessageLength << 3));
114hash.Update(c, 8);
115hash.Update(recoverableMessage, recoverableMessageLength);
116hash.Update(digest, digestSize);
117hash.Update(salt, saltSize);
118valid = hash.Verify(h) && valid;
119
120if (!AllowRecovery() && valid && recoverableMessageLength != 0)
121{throw NotImplemented("PSSR_MEM: message recovery disabled");}
122
123return result;
124}
125
126NAMESPACE_END

Archive Download this file

Branches

Tags

Quick Links:     www.monotone.ca    -     Downloads    -     Documentation    -     Wiki    -     Code Forge    -     Build Status