1 // pubkey.cpp - originally written and placed in the public domain by Wei Dai
2 
3 #include "pch.h"
4 #include "config.h"
5 
6 #ifndef CRYPTOPP_IMPORTS
7 
8 #include "pubkey.h"
9 #include "integer.h"
10 #include "filters.h"
11 
NAMESPACE_BEGIN(CryptoPP)12 NAMESPACE_BEGIN(CryptoPP)
13 
14 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)
15 {
16 	ArraySink *sink;
17 	HashFilter filter(hash, sink = mask ? new ArrayXorSink(output, outputLength) : new ArraySink(output, outputLength));
18 	word32 counter = counterStart;
19 	while (sink->AvailableSize() > 0)
20 	{
21 		filter.Put(input, inputLength);
22 		filter.PutWord32(counter++);
23 		filter.Put(derivationParams, derivationParamsLength);
24 		filter.MessageEnd();
25 	}
26 }
27 
VerifyMessageRepresentative(HashTransformation & hash,HashIdentifier hashIdentifier,bool messageEmpty,byte * representative,size_t representativeBitLength) const28 bool PK_DeterministicSignatureMessageEncodingMethod::VerifyMessageRepresentative(
29 	HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty,
30 	byte *representative, size_t representativeBitLength) const
31 {
32 	SecByteBlock computedRepresentative(BitsToBytes(representativeBitLength));
33 	ComputeMessageRepresentative(NullRNG(), NULLPTR, 0, hash, hashIdentifier, messageEmpty, computedRepresentative, representativeBitLength);
34 	return VerifyBufsEqual(representative, computedRepresentative, computedRepresentative.size());
35 }
36 
VerifyMessageRepresentative(HashTransformation & hash,HashIdentifier hashIdentifier,bool messageEmpty,byte * representative,size_t representativeBitLength) const37 bool PK_RecoverableSignatureMessageEncodingMethod::VerifyMessageRepresentative(
38 	HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty,
39 	byte *representative, size_t representativeBitLength) const
40 {
41 	SecByteBlock recoveredMessage(MaxRecoverableLength(representativeBitLength, hashIdentifier.second, hash.DigestSize()));
42 	DecodingResult result = RecoverMessageFromRepresentative(
43 		hash, hashIdentifier, messageEmpty, representative, representativeBitLength, recoveredMessage);
44 	return result.isValidCoding && result.messageLength == 0;
45 }
46 
InputRecoverableMessage(PK_MessageAccumulator & messageAccumulator,const byte * recoverableMessage,size_t recoverableMessageLength) const47 void TF_SignerBase::InputRecoverableMessage(PK_MessageAccumulator &messageAccumulator, const byte *recoverableMessage, size_t recoverableMessageLength) const
48 {
49 	PK_MessageAccumulatorBase &ma = static_cast<PK_MessageAccumulatorBase &>(messageAccumulator);
50 	HashIdentifier id = GetHashIdentifier();
51 	const MessageEncodingInterface &encoding = GetMessageEncodingInterface();
52 
53 	if (MessageRepresentativeBitLength() < encoding.MinRepresentativeBitLength(id.second, ma.AccessHash().DigestSize()))
54 		throw PK_SignatureScheme::KeyTooShort();
55 
56 	size_t maxRecoverableLength = encoding.MaxRecoverableLength(MessageRepresentativeBitLength(), GetHashIdentifier().second, ma.AccessHash().DigestSize());
57 
58 	if (maxRecoverableLength == 0)
59 		{throw NotImplemented("TF_SignerBase: this algorithm does not support message recovery or the key is too short");}
60 	if (recoverableMessageLength > maxRecoverableLength)
61 		throw InvalidArgument("TF_SignerBase: the recoverable message part is too long for the given key and algorithm");
62 
63 	ma.m_recoverableMessage.Assign(recoverableMessage, recoverableMessageLength);
64 	encoding.ProcessRecoverableMessage(
65 		ma.AccessHash(),
66 		recoverableMessage, recoverableMessageLength,
67 		NULLPTR, 0, ma.m_semisignature);
68 }
69 
SignAndRestart(RandomNumberGenerator & rng,PK_MessageAccumulator & messageAccumulator,byte * signature,bool restart) const70 size_t TF_SignerBase::SignAndRestart(RandomNumberGenerator &rng, PK_MessageAccumulator &messageAccumulator, byte *signature, bool restart) const
71 {
72 	CRYPTOPP_UNUSED(restart);
73 
74 	PK_MessageAccumulatorBase &ma = static_cast<PK_MessageAccumulatorBase &>(messageAccumulator);
75 	HashIdentifier id = GetHashIdentifier();
76 	const MessageEncodingInterface &encoding = GetMessageEncodingInterface();
77 
78 	if (MessageRepresentativeBitLength() < encoding.MinRepresentativeBitLength(id.second, ma.AccessHash().DigestSize()))
79 		throw PK_SignatureScheme::KeyTooShort();
80 
81 	SecByteBlock representative(MessageRepresentativeLength());
82 	encoding.ComputeMessageRepresentative(rng,
83 		ma.m_recoverableMessage, ma.m_recoverableMessage.size(),
84 		ma.AccessHash(), id, ma.m_empty,
85 		representative, MessageRepresentativeBitLength());
86 	ma.m_empty = true;
87 
88 	Integer r(representative, representative.size());
89 	size_t signatureLength = SignatureLength();
90 	GetTrapdoorFunctionInterface().CalculateRandomizedInverse(rng, r).Encode(signature, signatureLength);
91 	return signatureLength;
92 }
93 
InputSignature(PK_MessageAccumulator & messageAccumulator,const byte * signature,size_t signatureLength) const94 void TF_VerifierBase::InputSignature(PK_MessageAccumulator &messageAccumulator, const byte *signature, size_t signatureLength) const
95 {
96 	PK_MessageAccumulatorBase &ma = static_cast<PK_MessageAccumulatorBase &>(messageAccumulator);
97 	HashIdentifier id = GetHashIdentifier();
98 	const MessageEncodingInterface &encoding = GetMessageEncodingInterface();
99 
100 	if (MessageRepresentativeBitLength() < encoding.MinRepresentativeBitLength(id.second, ma.AccessHash().DigestSize()))
101 		throw PK_SignatureScheme::KeyTooShort();
102 
103 	ma.m_representative.New(MessageRepresentativeLength());
104 	Integer x = GetTrapdoorFunctionInterface().ApplyFunction(Integer(signature, signatureLength));
105 	if (x.BitCount() > MessageRepresentativeBitLength())
106 		x = Integer::Zero();	// don't return false here to prevent timing attack
107 	x.Encode(ma.m_representative, ma.m_representative.size());
108 }
109 
VerifyAndRestart(PK_MessageAccumulator & messageAccumulator) const110 bool TF_VerifierBase::VerifyAndRestart(PK_MessageAccumulator &messageAccumulator) const
111 {
112 	PK_MessageAccumulatorBase &ma = static_cast<PK_MessageAccumulatorBase &>(messageAccumulator);
113 	HashIdentifier id = GetHashIdentifier();
114 	const MessageEncodingInterface &encoding = GetMessageEncodingInterface();
115 
116 	if (MessageRepresentativeBitLength() < encoding.MinRepresentativeBitLength(id.second, ma.AccessHash().DigestSize()))
117 		throw PK_SignatureScheme::KeyTooShort();
118 
119 	bool result = encoding.VerifyMessageRepresentative(
120 		ma.AccessHash(), id, ma.m_empty, ma.m_representative, MessageRepresentativeBitLength());
121 	ma.m_empty = true;
122 	return result;
123 }
124 
RecoverAndRestart(byte * recoveredMessage,PK_MessageAccumulator & messageAccumulator) const125 DecodingResult TF_VerifierBase::RecoverAndRestart(byte *recoveredMessage, PK_MessageAccumulator &messageAccumulator) const
126 {
127 	PK_MessageAccumulatorBase &ma = static_cast<PK_MessageAccumulatorBase &>(messageAccumulator);
128 	HashIdentifier id = GetHashIdentifier();
129 	const MessageEncodingInterface &encoding = GetMessageEncodingInterface();
130 
131 	if (MessageRepresentativeBitLength() < encoding.MinRepresentativeBitLength(id.second, ma.AccessHash().DigestSize()))
132 		throw PK_SignatureScheme::KeyTooShort();
133 
134 	DecodingResult result = encoding.RecoverMessageFromRepresentative(
135 		ma.AccessHash(), id, ma.m_empty, ma.m_representative, MessageRepresentativeBitLength(), recoveredMessage);
136 	ma.m_empty = true;
137 	return result;
138 }
139 
Decrypt(RandomNumberGenerator & rng,const byte * ciphertext,size_t ciphertextLength,byte * plaintext,const NameValuePairs & parameters) const140 DecodingResult TF_DecryptorBase::Decrypt(RandomNumberGenerator &rng, const byte *ciphertext, size_t ciphertextLength, byte *plaintext, const NameValuePairs &parameters) const
141 {
142 	if (ciphertextLength != FixedCiphertextLength())
143 			throw InvalidArgument(AlgorithmName() + ": ciphertext length of " + IntToString(ciphertextLength) + " doesn't match the required length of " + IntToString(FixedCiphertextLength()) + " for this key");
144 
145 	SecByteBlock paddedBlock(PaddedBlockByteLength());
146 	Integer x = GetTrapdoorFunctionInterface().CalculateInverse(rng, Integer(ciphertext, ciphertextLength));
147 	if (x.ByteCount() > paddedBlock.size())
148 		x = Integer::Zero();	// don't return false here to prevent timing attack
149 	x.Encode(paddedBlock, paddedBlock.size());
150 	return GetMessageEncodingInterface().Unpad(paddedBlock, PaddedBlockBitLength(), plaintext, parameters);
151 }
152 
Encrypt(RandomNumberGenerator & rng,const byte * plaintext,size_t plaintextLength,byte * ciphertext,const NameValuePairs & parameters) const153 void TF_EncryptorBase::Encrypt(RandomNumberGenerator &rng, const byte *plaintext, size_t plaintextLength, byte *ciphertext, const NameValuePairs &parameters) const
154 {
155 	if (plaintextLength > FixedMaxPlaintextLength())
156 	{
157 		if (FixedMaxPlaintextLength() < 1)
158 			throw InvalidArgument(AlgorithmName() + ": this key is too short to encrypt any messages");
159 		else
160 			throw InvalidArgument(AlgorithmName() + ": message length of " + IntToString(plaintextLength) + " exceeds the maximum of " + IntToString(FixedMaxPlaintextLength()) + " for this public key");
161 	}
162 
163 	SecByteBlock paddedBlock(PaddedBlockByteLength());
164 	GetMessageEncodingInterface().Pad(rng, plaintext, plaintextLength, paddedBlock, PaddedBlockBitLength(), parameters);
165 	GetTrapdoorFunctionInterface().ApplyRandomizedFunction(rng, Integer(paddedBlock, paddedBlock.size())).Encode(ciphertext, FixedCiphertextLength());
166 }
167 
168 NAMESPACE_END
169 
170 #endif
171