1 | // pubkey.cpp - 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 | { |
---|
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 | |
---|
28 | 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(), NULL, 0, hash, hashIdentifier, messageEmpty, computedRepresentative, representativeBitLength); |
---|
34 | return VerifyBufsEqual(representative, computedRepresentative, computedRepresentative.size()); |
---|
35 | } |
---|
36 | |
---|
37 | 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 | |
---|
47 | 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 messsage 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 | NULL, 0, ma.m_semisignature); |
---|
68 | } |
---|
69 | |
---|
70 | 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 | |
---|
94 | 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 | |
---|
110 | 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 | |
---|
125 | 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 | |
---|
140 | DecodingResult TF_DecryptorBase::Decrypt(RandomNumberGenerator &rng, const byte *ciphertext, size_t ciphertextLength, byte *plaintext, const NameValuePairs ¶meters) 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 | |
---|
153 | void TF_EncryptorBase::Encrypt(RandomNumberGenerator &rng, const byte *plaintext, size_t plaintextLength, byte *ciphertext, const NameValuePairs ¶meters) 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 |
---|