Crypto++  5.6.4
Free C++ class library of cryptographic schemes
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 #include "misc.h"
6 
7 #include <functional>
8 
9 NAMESPACE_BEGIN(CryptoPP)
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 
32 bool PSSR_MEM_Base::IsProbabilistic() const
33 {
34  return SaltLen(1) > 0;
35 }
36 
37 bool PSSR_MEM_Base::AllowNonrecoverablePart() const
38 {
39  return true;
40 }
41 
42 bool PSSR_MEM_Base::RecoverablePartFirst() const
43 {
44  return false;
45 }
46 
47 void PSSR_MEM_Base::ComputeMessageRepresentative(RandomNumberGenerator &rng,
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 
96 DecodingResult PSSR_MEM_Base::RecoverMessageFromRepresentative(
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 
161 NAMESPACE_END
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:740
RIPEMD-160
Definition: ripemd.h:15
Interface for random number generators.
Definition: cryptlib.h:1193
SecBlock typedef.
Definition: secblock.h:731
Returns a decoding results.
Definition: cryptlib.h:241
A method was called which was not implemented.
Definition: cryptlib.h:208
Whirlpool
Definition: whrlpool.h:10
T Crop(T value, size_t bits)
Truncates the value to the specified number of bits.
Definition: misc.h:728
T1 SaturatingSubtract(const T1 &a, const T2 &b)
Performs a saturating subtract clamped at 0.
Definition: misc.h:970
byte order is big-endian
Definition: cryptlib.h:132
virtual bool Verify(const byte *digest)
Verifies the hash of the current message.
Definition: cryptlib.h:1018
Safely right shift values when undefined behavior could occur.
#define CRYPTOPP_ASSERT(exp)
Debugging and diagnostic assertion.
Definition: trap.h:62
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.
virtual unsigned int DigestSize() const =0
Provides the digest size of the hash.
void xorbuf(byte *buf, const byte *mask, size_t count)
Performs an XOR of a buffer with a mask.
Definition: misc.cpp:28
Interface for hash functions and data processing part of MACs.
Definition: cryptlib.h:931
bool VerifyBufsEqual(const byte *buf1, const byte *buf2, size_t count)
Performs a near constant-time comparison of two equally sized buffers.
Definition: misc.cpp:96
Crypto++ library namespace.
virtual void Final(byte *digest)
Computes the hash of the current message.
Definition: cryptlib.h:963
Classes for probablistic signature schemes.
virtual void Update(const byte *input, size_t length)=0
Updates a hash with additional input.