summaryrefslogtreecommitdiff
path: root/plugins/CryptoPP/crypto/src/pubkey.cpp
blob: 6ebb6e111ceefc179e649e190babb1c631c0a7fb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
// pubkey.cpp - written and placed in the public domain by Wei Dai

#include "pch.h"

#ifndef CRYPTOPP_IMPORTS

#include "pubkey.h"

NAMESPACE_BEGIN(CryptoPP)

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)
{
	ArraySink *sink;
	HashFilter filter(hash, sink = mask ? new ArrayXorSink(output, outputLength) : new ArraySink(output, outputLength));
	word32 counter = counterStart;
	while (sink->AvailableSize() > 0)
	{
		filter.Put(input, inputLength);
		filter.PutWord32(counter++);
		filter.Put(derivationParams, derivationParamsLength);
		filter.MessageEnd();
	}
}

bool PK_DeterministicSignatureMessageEncodingMethod::VerifyMessageRepresentative(
	HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty,
	byte *representative, size_t representativeBitLength) const
{
	SecByteBlock computedRepresentative(BitsToBytes(representativeBitLength));
	ComputeMessageRepresentative(NullRNG(), NULL, 0, hash, hashIdentifier, messageEmpty, computedRepresentative, representativeBitLength);
	return memcmp(representative, computedRepresentative, computedRepresentative.size()) == 0;
}

bool PK_RecoverableSignatureMessageEncodingMethod::VerifyMessageRepresentative(
	HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty,
	byte *representative, size_t representativeBitLength) const
{
	SecByteBlock recoveredMessage(MaxRecoverableLength(representativeBitLength, hashIdentifier.second, hash.DigestSize()));
	DecodingResult result = RecoverMessageFromRepresentative(
		hash, hashIdentifier, messageEmpty, representative, representativeBitLength, recoveredMessage);
	return result.isValidCoding && result.messageLength == 0;
}

void TF_SignerBase::InputRecoverableMessage(PK_MessageAccumulator &messageAccumulator, const byte *recoverableMessage, size_t recoverableMessageLength) const
{
	PK_MessageAccumulatorBase &ma = static_cast<PK_MessageAccumulatorBase &>(messageAccumulator);
	HashIdentifier id = GetHashIdentifier();
	const MessageEncodingInterface &encoding = GetMessageEncodingInterface();

	if (MessageRepresentativeBitLength() < encoding.MinRepresentativeBitLength(id.second, ma.AccessHash().DigestSize()))
		throw PK_SignatureScheme::KeyTooShort();

	size_t maxRecoverableLength = encoding.MaxRecoverableLength(MessageRepresentativeBitLength(), GetHashIdentifier().second, ma.AccessHash().DigestSize());

	if (maxRecoverableLength == 0)
		{throw NotImplemented("TF_SignerBase: this algorithm does not support messsage recovery or the key is too short");}
	if (recoverableMessageLength > maxRecoverableLength)
		throw InvalidArgument("TF_SignerBase: the recoverable message part is too long for the given key and algorithm");

	ma.m_recoverableMessage.Assign(recoverableMessage, recoverableMessageLength);
	encoding.ProcessRecoverableMessage(
		ma.AccessHash(), 
		recoverableMessage, recoverableMessageLength,
		NULL, 0, ma.m_semisignature);
}

size_t TF_SignerBase::SignAndRestart(RandomNumberGenerator &rng, PK_MessageAccumulator &messageAccumulator, byte *signature, bool restart) const
{
	PK_MessageAccumulatorBase &ma = static_cast<PK_MessageAccumulatorBase &>(messageAccumulator);
	HashIdentifier id = GetHashIdentifier();
	const MessageEncodingInterface &encoding = GetMessageEncodingInterface();

	if (MessageRepresentativeBitLength() < encoding.MinRepresentativeBitLength(id.second, ma.AccessHash().DigestSize()))
		throw PK_SignatureScheme::KeyTooShort();

	SecByteBlock representative(MessageRepresentativeLength());
	encoding.ComputeMessageRepresentative(rng, 
		ma.m_recoverableMessage, ma.m_recoverableMessage.size(), 
		ma.AccessHash(), id, ma.m_empty,
		representative, MessageRepresentativeBitLength());
	ma.m_empty = true;

	Integer r(representative, representative.size());
	size_t signatureLength = SignatureLength();
	GetTrapdoorFunctionInterface().CalculateRandomizedInverse(rng, r).Encode(signature, signatureLength);
	return signatureLength;
}

void TF_VerifierBase::InputSignature(PK_MessageAccumulator &messageAccumulator, const byte *signature, size_t signatureLength) const
{
	PK_MessageAccumulatorBase &ma = static_cast<PK_MessageAccumulatorBase &>(messageAccumulator);
	HashIdentifier id = GetHashIdentifier();
	const MessageEncodingInterface &encoding = GetMessageEncodingInterface();

	if (MessageRepresentativeBitLength() < encoding.MinRepresentativeBitLength(id.second, ma.AccessHash().DigestSize()))
		throw PK_SignatureScheme::KeyTooShort();

	ma.m_representative.New(MessageRepresentativeLength());
	Integer x = GetTrapdoorFunctionInterface().ApplyFunction(Integer(signature, signatureLength));
	if (x.BitCount() > MessageRepresentativeBitLength())
		x = Integer::Zero();	// don't return false here to prevent timing attack
	x.Encode(ma.m_representative, ma.m_representative.size());
}

bool TF_VerifierBase::VerifyAndRestart(PK_MessageAccumulator &messageAccumulator) const
{
	PK_MessageAccumulatorBase &ma = static_cast<PK_MessageAccumulatorBase &>(messageAccumulator);
	HashIdentifier id = GetHashIdentifier();
	const MessageEncodingInterface &encoding = GetMessageEncodingInterface();

	if (MessageRepresentativeBitLength() < encoding.MinRepresentativeBitLength(id.second, ma.AccessHash().DigestSize()))
		throw PK_SignatureScheme::KeyTooShort();

	bool result = encoding.VerifyMessageRepresentative(
		ma.AccessHash(), id, ma.m_empty, ma.m_representative, MessageRepresentativeBitLength());
	ma.m_empty = true;
	return result;
}

DecodingResult TF_VerifierBase::RecoverAndRestart(byte *recoveredMessage, PK_MessageAccumulator &messageAccumulator) const
{
	PK_MessageAccumulatorBase &ma = static_cast<PK_MessageAccumulatorBase &>(messageAccumulator);
	HashIdentifier id = GetHashIdentifier();
	const MessageEncodingInterface &encoding = GetMessageEncodingInterface();

	if (MessageRepresentativeBitLength() < encoding.MinRepresentativeBitLength(id.second, ma.AccessHash().DigestSize()))
		throw PK_SignatureScheme::KeyTooShort();

	DecodingResult result = encoding.RecoverMessageFromRepresentative(
		ma.AccessHash(), id, ma.m_empty, ma.m_representative, MessageRepresentativeBitLength(), recoveredMessage);
	ma.m_empty = true;
	return result;
}

DecodingResult TF_DecryptorBase::Decrypt(RandomNumberGenerator &rng, const byte *ciphertext, size_t ciphertextLength, byte *plaintext, const NameValuePairs &parameters) const
{
	SecByteBlock paddedBlock(PaddedBlockByteLength());
	Integer x = GetTrapdoorFunctionInterface().CalculateInverse(rng, Integer(ciphertext, FixedCiphertextLength()));
	if (x.ByteCount() > paddedBlock.size())
		x = Integer::Zero();	// don't return false here to prevent timing attack
	x.Encode(paddedBlock, paddedBlock.size());
	return GetMessageEncodingInterface().Unpad(paddedBlock, PaddedBlockBitLength(), plaintext, parameters);
}

void TF_EncryptorBase::Encrypt(RandomNumberGenerator &rng, const byte *plaintext, size_t plaintextLength, byte *ciphertext, const NameValuePairs &parameters) const
{
	if (plaintextLength > FixedMaxPlaintextLength())
		throw InvalidArgument(AlgorithmName() + ": message too long for this public key");

	SecByteBlock paddedBlock(PaddedBlockByteLength());
	GetMessageEncodingInterface().Pad(rng, plaintext, plaintextLength, paddedBlock, PaddedBlockBitLength(), parameters);
	GetTrapdoorFunctionInterface().ApplyRandomizedFunction(rng, Integer(paddedBlock, paddedBlock.size())).Encode(ciphertext, FixedCiphertextLength());
}

NAMESPACE_END

#endif