Fabcoin Core  0.16.2
P2P Digital Currency
pssr.cpp
Go to the documentation of this file.
1 // pssr.cpp - written and placed in the public domain by Wei Dai
2 
3 #include "pch.h"
4 #include "pssr.h"
5 #include "misc.h"
6 
7 #include <functional>
8 
10 
11 // more in dll.cpp
12 template<> const byte EMSA2HashId<RIPEMD160>::id = 0x31;
13 template<> const byte EMSA2HashId<RIPEMD128>::id = 0x32;
14 template<> const byte EMSA2HashId<Whirlpool>::id = 0x37;
15 
16 #ifndef CRYPTOPP_IMPORTS
17 
18 size_t PSSR_MEM_Base::MinRepresentativeBitLength(size_t hashIdentifierLength, size_t digestLength) const
19 {
20  size_t saltLen = SaltLen(digestLength);
21  size_t minPadLen = MinPadLen(digestLength);
22  return 9 + 8*(minPadLen + saltLen + digestLength + hashIdentifierLength);
23 }
24 
25 size_t PSSR_MEM_Base::MaxRecoverableLength(size_t representativeBitLength, size_t hashIdentifierLength, size_t digestLength) const
26 {
27  if (AllowRecovery())
28  return SaturatingSubtract(representativeBitLength, MinRepresentativeBitLength(hashIdentifierLength, digestLength)) / 8;
29  return 0;
30 }
31 
33 {
34  return SaltLen(1) > 0;
35 }
36 
38 {
39  return true;
40 }
41 
43 {
44  return false;
45 }
46 
48  const byte *recoverableMessage, size_t recoverableMessageLength,
49  HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty,
50  byte *representative, size_t representativeBitLength) const
51 {
52  CRYPTOPP_UNUSED(rng), CRYPTOPP_UNUSED(recoverableMessage), CRYPTOPP_UNUSED(recoverableMessageLength);
53  CRYPTOPP_UNUSED(messageEmpty), CRYPTOPP_UNUSED(hashIdentifier);
54  CRYPTOPP_ASSERT(representativeBitLength >= MinRepresentativeBitLength(hashIdentifier.second, hash.DigestSize()));
55 
56  const size_t u = hashIdentifier.second + 1;
57  const size_t representativeByteLength = BitsToBytes(representativeBitLength);
58  const size_t digestSize = hash.DigestSize();
59  const size_t saltSize = SaltLen(digestSize);
60  byte *const h = representative + representativeByteLength - u - digestSize;
61 
62  SecByteBlock digest(digestSize), salt(saltSize);
63  hash.Final(digest);
64  rng.GenerateBlock(salt, saltSize);
65 
66  // compute H = hash of M'
67  byte c[8];
68  PutWord(false, BIG_ENDIAN_ORDER, c, (word32)SafeRightShift<29>(recoverableMessageLength));
69  PutWord(false, BIG_ENDIAN_ORDER, c+4, word32(recoverableMessageLength << 3));
70  hash.Update(c, 8);
71  hash.Update(recoverableMessage, recoverableMessageLength);
72  hash.Update(digest, digestSize);
73  hash.Update(salt, saltSize);
74  hash.Final(h);
75 
76  // compute representative
77  GetMGF().GenerateAndMask(hash, representative, representativeByteLength - u - digestSize, h, digestSize, false);
78  byte *xorStart = representative + representativeByteLength - u - digestSize - salt.size() - recoverableMessageLength - 1;
79  xorStart[0] ^= 1;
80  if (recoverableMessage && recoverableMessageLength)
81  xorbuf(xorStart + 1, recoverableMessage, recoverableMessageLength);
82  xorbuf(xorStart + 1 + recoverableMessageLength, salt, salt.size());
83  if (hashIdentifier.first && hashIdentifier.second)
84  {
85  memcpy(representative + representativeByteLength - u, hashIdentifier.first, hashIdentifier.second);
86  representative[representativeByteLength - 1] = 0xcc;
87  }
88  else
89  {
90  representative[representativeByteLength - 1] = 0xbc;
91  }
92  if (representativeBitLength % 8 != 0)
93  representative[0] = (byte)Crop(representative[0], representativeBitLength % 8);
94 }
95 
97  HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty,
98  byte *representative, size_t representativeBitLength,
99  byte *recoverableMessage) const
100 {
101  CRYPTOPP_UNUSED(recoverableMessage), CRYPTOPP_UNUSED(messageEmpty), CRYPTOPP_UNUSED(hashIdentifier);
102  CRYPTOPP_ASSERT(representativeBitLength >= MinRepresentativeBitLength(hashIdentifier.second, hash.DigestSize()));
103 
104  const size_t u = hashIdentifier.second + 1;
105  const size_t representativeByteLength = BitsToBytes(representativeBitLength);
106  const size_t digestSize = hash.DigestSize();
107  const size_t saltSize = SaltLen(digestSize);
108  const byte *const h = representative + representativeByteLength - u - digestSize;
109 
110  SecByteBlock digest(digestSize);
111  hash.Final(digest);
112 
113  DecodingResult result(0);
114  bool &valid = result.isValidCoding;
115  size_t &recoverableMessageLength = result.messageLength;
116 
117  valid = (representative[representativeByteLength - 1] == (hashIdentifier.second ? 0xcc : 0xbc)) && valid;
118 
119  if (hashIdentifier.first && hashIdentifier.second)
120  valid = VerifyBufsEqual(representative + representativeByteLength - u, hashIdentifier.first, hashIdentifier.second) && valid;
121 
122  GetMGF().GenerateAndMask(hash, representative, representativeByteLength - u - digestSize, h, digestSize);
123  if (representativeBitLength % 8 != 0)
124  representative[0] = (byte)Crop(representative[0], representativeBitLength % 8);
125 
126  // extract salt and recoverableMessage from DB = 00 ... || 01 || M || salt
127  byte *salt = representative + representativeByteLength - u - digestSize - saltSize;
128  byte *M = std::find_if(representative, salt-1, std::bind2nd(std::not_equal_to<byte>(), byte(0)));
129  recoverableMessageLength = salt-M-1;
130  if (*M == 0x01 &&
131  (size_t)(M - representative - (representativeBitLength % 8 != 0)) >= MinPadLen(digestSize) &&
132  recoverableMessageLength <= MaxRecoverableLength(representativeBitLength, hashIdentifier.second, digestSize))
133  {
134  if (recoverableMessage)
135  memcpy(recoverableMessage, M+1, recoverableMessageLength);
136  }
137  else
138  {
139  recoverableMessageLength = 0;
140  valid = false;
141  }
142 
143  // verify H = hash of M'
144  byte c[8];
145  PutWord(false, BIG_ENDIAN_ORDER, c, (word32)SafeRightShift<29>(recoverableMessageLength));
146  PutWord(false, BIG_ENDIAN_ORDER, c+4, word32(recoverableMessageLength << 3));
147  hash.Update(c, 8);
148  hash.Update(recoverableMessage, recoverableMessageLength);
149  hash.Update(digest, digestSize);
150  hash.Update(salt, saltSize);
151  valid = hash.Verify(h) && valid;
152 
153  if (!AllowRecovery() && valid && recoverableMessageLength != 0)
154  {throw NotImplemented("PSSR_MEM: message recovery disabled");}
155 
156  return result;
157 }
158 
159 #endif
160 
uint8_t byte
Definition: Common.h:57
Utility functions for the Crypto++ library.
virtual void GenerateBlock(byte *output, size_t size)
Generate random array of bytes.
Definition: cryptlib.cpp:326
size_t BitsToBytes(size_t bitCount)
Returns the number of 8-bit bytes or octets required for the specified number of bits.
Definition: misc.h:749
void PutWord(bool assumeAligned, ByteOrder order, byte *block, T value, const byte *xorBlock=NULL)
Access a block of memory.
Definition: misc.h:2123
#define NAMESPACE_BEGIN(x)
Definition: config.h:200
#define h(i)
Definition: sha.cpp:736
RIPEMD-160 message digest.
Definition: ripemd.h:17
size_type size() const
Provides the count of elements in the SecBlock.
Definition: secblock.h:524
#define c(i)
Interface for random number generators.
Definition: cryptlib.h:1188
size_t messageLength
Recovered message length if isValidCoding is true, undefined otherwise.
Definition: cryptlib.h:261
virtual bool AllowRecovery() const =0
virtual size_t MinPadLen(size_t hashLen) const =0
bool AllowNonrecoverablePart() const
Definition: pssr.cpp:37
Returns a decoding results.
Definition: cryptlib.h:238
bool IsProbabilistic() const
Definition: pssr.cpp:32
virtual void GenerateAndMask(HashTransformation &hash, byte *output, size_t outputLength, const byte *input, size_t inputLength, bool mask=true) const =0
Generate and apply mask.
A method was called which was not implemented.
Definition: cryptlib.h:205
Whirlpool
Definition: whrlpool.h:10
T Crop(T value, size_t bits)
Truncates the value to the specified number of bits.
Definition: misc.h:737
bool RecoverablePartFirst() const
Definition: pssr.cpp:42
T1 SaturatingSubtract(const T1 &a, const T2 &b)
Performs a saturating subtract clamped at 0.
Definition: misc.h:847
size_t MinRepresentativeBitLength(size_t hashIdentifierLength, size_t digestLength) const
Definition: pssr.cpp:18
size_t MaxRecoverableLength(size_t representativeBitLength, size_t hashIdentifierLength, size_t digestLength) const
Definition: pssr.cpp:25
byte order is big-endian
Definition: cryptlib.h:128
virtual bool Verify(const byte *digest)
Verifies the hash of the current message.
Definition: cryptlib.h:1015
Safely right shift values when undefined behavior could occur.
#define CRYPTOPP_ASSERT(exp)
Definition: trap.h:92
void xorbuf(byte *buf, const byte *mask, size_t count)
Performs an XOR of a buffer with a mask.
Definition: misc.cpp:28
virtual size_t SaltLen(size_t hashLen) const =0
void ComputeMessageRepresentative(RandomNumberGenerator &rng, const byte *recoverableMessage, size_t recoverableMessageLength, HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty, byte *representative, size_t representativeBitLength) const
Definition: pssr.cpp:47
virtual unsigned int DigestSize() const =0
Provides the digest size of the hash.
void * memcpy(void *a, const void *b, size_t c)
#define CRYPTOPP_UNUSED(x)
Definition: config.h:741
Interface for hash functions and data processing part of MACs.
Definition: cryptlib.h:930
uint8_t byte
Definition: Common.h:10
#define NAMESPACE_END
Definition: config.h:201
bool isValidCoding
Flag to indicate the decoding is valid.
Definition: cryptlib.h:259
virtual const MaskGeneratingFunction & GetMGF() const =0
DecodingResult RecoverMessageFromRepresentative(HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty, byte *representative, size_t representativeBitLength, byte *recoverableMessage) const
Definition: pssr.cpp:96
std::pair< const byte *, unsigned int > HashIdentifier
Definition: pubkey.h:314
unsigned int word32
Definition: config.h:231
virtual void Final(byte *digest)
Computes the hash of the current message.
Definition: cryptlib.h:960
RIPEMD-128 message digest.
Definition: ripemd.h:42
Classes for probablistic signature schemes.
virtual void Update(const byte *input, size_t length)=0
Updates a hash with additional input.
bool VerifyBufsEqual(const byte *buf, const byte *mask, size_t count)
Performs a near constant-time comparison of two equally sized buffers.
Definition: misc.cpp:96