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