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 158 159 160 161 162
|
// 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 VerifyBufsEqual(representative, computedRepresentative, computedRepresentative.size());
}
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 ¶meters) 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 ¶meters) const
{
if (plaintextLength > FixedMaxPlaintextLength())
{
if (FixedMaxPlaintextLength() < 1)
throw InvalidArgument(AlgorithmName() + ": this key is too short to encrypt any messages");
else
throw InvalidArgument(AlgorithmName() + ": message length of " + IntToString(plaintextLength) + " exceeds the maximum of " + IntToString(FixedMaxPlaintextLength()) + " 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
|