Crypto++
pubkey.cpp
1 // pubkey.cpp - written and placed in the public domain by Wei Dai
2 
3 #include "pch.h"
4 
5 #ifndef CRYPTOPP_IMPORTS
6 
7 #include "pubkey.h"
8 
9 NAMESPACE_BEGIN(CryptoPP)
10 
11 void P1363_MGF1KDF2_Common(HashTransformation &hash, byte *output, size_t outputLength, const byte *input, size_t inputLength, const byte *derivationParams, size_t derivationParamsLength, bool mask, unsigned int counterStart)
12 {
13  ArraySink *sink;
14  HashFilter filter(hash, sink = mask ? new ArrayXorSink(output, outputLength) : new ArraySink(output, outputLength));
15  word32 counter = counterStart;
16  while (sink->AvailableSize() > 0)
17  {
18  filter.Put(input, inputLength);
19  filter.PutWord32(counter++);
20  filter.Put(derivationParams, derivationParamsLength);
21  filter.MessageEnd();
22  }
23 }
24 
25 bool PK_DeterministicSignatureMessageEncodingMethod::VerifyMessageRepresentative(
26  HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty,
27  byte *representative, size_t representativeBitLength) const
28 {
29  SecByteBlock computedRepresentative(BitsToBytes(representativeBitLength));
30  ComputeMessageRepresentative(NullRNG(), NULL, 0, hash, hashIdentifier, messageEmpty, computedRepresentative, representativeBitLength);
31  return VerifyBufsEqual(representative, computedRepresentative, computedRepresentative.size());
32 }
33 
34 bool PK_RecoverableSignatureMessageEncodingMethod::VerifyMessageRepresentative(
35  HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty,
36  byte *representative, size_t representativeBitLength) const
37 {
38  SecByteBlock recoveredMessage(MaxRecoverableLength(representativeBitLength, hashIdentifier.second, hash.DigestSize()));
39  DecodingResult result = RecoverMessageFromRepresentative(
40  hash, hashIdentifier, messageEmpty, representative, representativeBitLength, recoveredMessage);
41  return result.isValidCoding && result.messageLength == 0;
42 }
43 
44 void TF_SignerBase::InputRecoverableMessage(PK_MessageAccumulator &messageAccumulator, const byte *recoverableMessage, size_t recoverableMessageLength) const
45 {
46  PK_MessageAccumulatorBase &ma = static_cast<PK_MessageAccumulatorBase &>(messageAccumulator);
47  HashIdentifier id = GetHashIdentifier();
48  const MessageEncodingInterface &encoding = GetMessageEncodingInterface();
49 
50  if (MessageRepresentativeBitLength() < encoding.MinRepresentativeBitLength(id.second, ma.AccessHash().DigestSize()))
52 
53  size_t maxRecoverableLength = encoding.MaxRecoverableLength(MessageRepresentativeBitLength(), GetHashIdentifier().second, ma.AccessHash().DigestSize());
54 
55  if (maxRecoverableLength == 0)
56  {throw NotImplemented("TF_SignerBase: this algorithm does not support messsage recovery or the key is too short");}
57  if (recoverableMessageLength > maxRecoverableLength)
58  throw InvalidArgument("TF_SignerBase: the recoverable message part is too long for the given key and algorithm");
59 
60  ma.m_recoverableMessage.Assign(recoverableMessage, recoverableMessageLength);
61  encoding.ProcessRecoverableMessage(
62  ma.AccessHash(),
63  recoverableMessage, recoverableMessageLength,
64  NULL, 0, ma.m_semisignature);
65 }
66 
67 size_t TF_SignerBase::SignAndRestart(RandomNumberGenerator &rng, PK_MessageAccumulator &messageAccumulator, byte *signature, bool restart) const
68 {
69  PK_MessageAccumulatorBase &ma = static_cast<PK_MessageAccumulatorBase &>(messageAccumulator);
70  HashIdentifier id = GetHashIdentifier();
71  const MessageEncodingInterface &encoding = GetMessageEncodingInterface();
72 
73  if (MessageRepresentativeBitLength() < encoding.MinRepresentativeBitLength(id.second, ma.AccessHash().DigestSize()))
75 
76  SecByteBlock representative(MessageRepresentativeLength());
77  encoding.ComputeMessageRepresentative(rng,
78  ma.m_recoverableMessage, ma.m_recoverableMessage.size(),
79  ma.AccessHash(), id, ma.m_empty,
80  representative, MessageRepresentativeBitLength());
81  ma.m_empty = true;
82 
83  Integer r(representative, representative.size());
84  size_t signatureLength = SignatureLength();
85  GetTrapdoorFunctionInterface().CalculateRandomizedInverse(rng, r).Encode(signature, signatureLength);
86  return signatureLength;
87 }
88 
89 void TF_VerifierBase::InputSignature(PK_MessageAccumulator &messageAccumulator, const byte *signature, size_t signatureLength) const
90 {
91  PK_MessageAccumulatorBase &ma = static_cast<PK_MessageAccumulatorBase &>(messageAccumulator);
92  HashIdentifier id = GetHashIdentifier();
93  const MessageEncodingInterface &encoding = GetMessageEncodingInterface();
94 
95  if (MessageRepresentativeBitLength() < encoding.MinRepresentativeBitLength(id.second, ma.AccessHash().DigestSize()))
97 
98  ma.m_representative.New(MessageRepresentativeLength());
99  Integer x = GetTrapdoorFunctionInterface().ApplyFunction(Integer(signature, signatureLength));
100  if (x.BitCount() > MessageRepresentativeBitLength())
101  x = Integer::Zero(); // don't return false here to prevent timing attack
102  x.Encode(ma.m_representative, ma.m_representative.size());
103 }
104 
106 {
107  PK_MessageAccumulatorBase &ma = static_cast<PK_MessageAccumulatorBase &>(messageAccumulator);
108  HashIdentifier id = GetHashIdentifier();
109  const MessageEncodingInterface &encoding = GetMessageEncodingInterface();
110 
111  if (MessageRepresentativeBitLength() < encoding.MinRepresentativeBitLength(id.second, ma.AccessHash().DigestSize()))
113 
114  bool result = encoding.VerifyMessageRepresentative(
115  ma.AccessHash(), id, ma.m_empty, ma.m_representative, MessageRepresentativeBitLength());
116  ma.m_empty = true;
117  return result;
118 }
119 
120 DecodingResult TF_VerifierBase::RecoverAndRestart(byte *recoveredMessage, PK_MessageAccumulator &messageAccumulator) const
121 {
122  PK_MessageAccumulatorBase &ma = static_cast<PK_MessageAccumulatorBase &>(messageAccumulator);
123  HashIdentifier id = GetHashIdentifier();
124  const MessageEncodingInterface &encoding = GetMessageEncodingInterface();
125 
126  if (MessageRepresentativeBitLength() < encoding.MinRepresentativeBitLength(id.second, ma.AccessHash().DigestSize()))
128 
129  DecodingResult result = encoding.RecoverMessageFromRepresentative(
130  ma.AccessHash(), id, ma.m_empty, ma.m_representative, MessageRepresentativeBitLength(), recoveredMessage);
131  ma.m_empty = true;
132  return result;
133 }
134 
135 DecodingResult TF_DecryptorBase::Decrypt(RandomNumberGenerator &rng, const byte *ciphertext, size_t ciphertextLength, byte *plaintext, const NameValuePairs &parameters) const
136 {
137  if (ciphertextLength != FixedCiphertextLength())
138  throw InvalidArgument(AlgorithmName() + ": ciphertext length of " + IntToString(ciphertextLength) + " doesn't match the required length of " + IntToString(FixedCiphertextLength()) + " for this key");
139 
140  SecByteBlock paddedBlock(PaddedBlockByteLength());
141  Integer x = GetTrapdoorFunctionInterface().CalculateInverse(rng, Integer(ciphertext, ciphertextLength));
142  if (x.ByteCount() > paddedBlock.size())
143  x = Integer::Zero(); // don't return false here to prevent timing attack
144  x.Encode(paddedBlock, paddedBlock.size());
145  return GetMessageEncodingInterface().Unpad(paddedBlock, PaddedBlockBitLength(), plaintext, parameters);
146 }
147 
148 void TF_EncryptorBase::Encrypt(RandomNumberGenerator &rng, const byte *plaintext, size_t plaintextLength, byte *ciphertext, const NameValuePairs &parameters) const
149 {
150  if (plaintextLength > FixedMaxPlaintextLength())
151  {
152  if (FixedMaxPlaintextLength() < 1)
153  throw InvalidArgument(AlgorithmName() + ": this key is too short to encrypt any messages");
154  else
155  throw InvalidArgument(AlgorithmName() + ": message length of " + IntToString(plaintextLength) + " exceeds the maximum of " + IntToString(FixedMaxPlaintextLength()) + " for this public key");
156  }
157 
158  SecByteBlock paddedBlock(PaddedBlockByteLength());
159  GetMessageEncodingInterface().Pad(rng, plaintext, plaintextLength, paddedBlock, PaddedBlockBitLength(), parameters);
160  GetTrapdoorFunctionInterface().ApplyRandomizedFunction(rng, Integer(paddedBlock, paddedBlock.size())).Encode(ciphertext, FixedCiphertextLength());
161 }
162 
163 NAMESPACE_END
164 
165 #endif
exception thrown when an invalid argument is detected
Definition: cryptlib.h:145
bool VerifyAndRestart(PK_MessageAccumulator &messageAccumulator) const
check whether messageAccumulator contains a valid signature and message, and restart messageAccumulat...
Definition: pubkey.cpp:105
This file contains helper classes/functions for implementing public key algorithms.
DecodingResult RecoverAndRestart(byte *recoveredMessage, PK_MessageAccumulator &recoveryAccumulator) const
recover a message from its signature
Definition: pubkey.cpp:120
interface for message encoding method for public key signature schemes
Definition: pubkey.h:184
a block of memory allocated using A
Definition: secblock.h:238
interface for random number generators
Definition: cryptlib.h:669
void New(size_type newSize)
change size, without preserving contents
Definition: secblock.h:361
void Encrypt(RandomNumberGenerator &rng, const byte *plaintext, size_t plaintextLength, byte *ciphertext, const NameValuePairs &parameters=g_nullNameValuePairs) const
encrypt a byte string
Definition: pubkey.cpp:148
unsigned int BitCount() const
number of significant bits = floor(log2(abs(*this))) + 1
Definition: integer.cpp:3054
Copy input to a memory buffer.
Definition: filters.h:635
used to return decoding results
Definition: cryptlib.h:198
Xor input to a memory buffer.
Definition: filters.h:655
exception thrown by a class if a non-implemented method is called
Definition: cryptlib.h:166
Filter Wrapper for HashTransformation.
Definition: filters.h:291
key too short exception, may be thrown by any function in this class if the private or public key is ...
Definition: cryptlib.h:1296
size_t SignAndRestart(RandomNumberGenerator &rng, PK_MessageAccumulator &messageAccumulator, byte *signature, bool restart=true) const
sign and restart messageAccumulator
Definition: pubkey.cpp:67
multiple precision integer and basic arithmetics
Definition: integer.h:26
void Assign(const T *t, size_type len)
set contents and size
Definition: secblock.h:310
virtual std::string AlgorithmName() const
returns name of this algorithm, not universally implemented yet
Definition: cryptlib.h:343
RandomNumberGenerator & NullRNG()
returns a reference that can be passed to functions that ask for a RNG but doesn't actually use it ...
Definition: cryptlib.cpp:295
void Encode(byte *output, size_t outputLen, Signedness=UNSIGNED) const
encode in big-endian format
Definition: integer.cpp:3112
interface for accumulating messages to be signed or verified
Definition: cryptlib.h:1334
virtual unsigned int DigestSize() const =0
size of the hash/digest/MAC returned by Final()
interface for hash functions and data processing part of MACs
Definition: cryptlib.h:531
static const Integer & Zero()
avoid calling constructors for these frequently used integers
Definition: integer.cpp:2862
void InputSignature(PK_MessageAccumulator &messageAccumulator, const byte *signature, size_t signatureLength) const
input signature into a message accumulator
Definition: pubkey.cpp:89
unsigned int ByteCount() const
number of significant bytes = ceiling(BitCount()/8)
Definition: integer.cpp:3045
interface for retrieving values given their names
Definition: cryptlib.h:225
DecodingResult Decrypt(RandomNumberGenerator &rng, const byte *ciphertext, size_t ciphertextLength, byte *plaintext, const NameValuePairs &parameters=g_nullNameValuePairs) const
decrypt a byte string, and return the length of plaintext
Definition: pubkey.cpp:135