Crypto++
|
00001 // pubkey.cpp - written and placed in the public domain by Wei Dai 00002 00003 #include "pch.h" 00004 00005 #ifndef CRYPTOPP_IMPORTS 00006 00007 #include "pubkey.h" 00008 00009 NAMESPACE_BEGIN(CryptoPP) 00010 00011 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) 00012 { 00013 ArraySink *sink; 00014 HashFilter filter(hash, sink = mask ? new ArrayXorSink(output, outputLength) : new ArraySink(output, outputLength)); 00015 word32 counter = counterStart; 00016 while (sink->AvailableSize() > 0) 00017 { 00018 filter.Put(input, inputLength); 00019 filter.PutWord32(counter++); 00020 filter.Put(derivationParams, derivationParamsLength); 00021 filter.MessageEnd(); 00022 } 00023 } 00024 00025 bool PK_DeterministicSignatureMessageEncodingMethod::VerifyMessageRepresentative( 00026 HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty, 00027 byte *representative, size_t representativeBitLength) const 00028 { 00029 SecByteBlock computedRepresentative(BitsToBytes(representativeBitLength)); 00030 ComputeMessageRepresentative(NullRNG(), NULL, 0, hash, hashIdentifier, messageEmpty, computedRepresentative, representativeBitLength); 00031 return VerifyBufsEqual(representative, computedRepresentative, computedRepresentative.size()); 00032 } 00033 00034 bool PK_RecoverableSignatureMessageEncodingMethod::VerifyMessageRepresentative( 00035 HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty, 00036 byte *representative, size_t representativeBitLength) const 00037 { 00038 SecByteBlock recoveredMessage(MaxRecoverableLength(representativeBitLength, hashIdentifier.second, hash.DigestSize())); 00039 DecodingResult result = RecoverMessageFromRepresentative( 00040 hash, hashIdentifier, messageEmpty, representative, representativeBitLength, recoveredMessage); 00041 return result.isValidCoding && result.messageLength == 0; 00042 } 00043 00044 void TF_SignerBase::InputRecoverableMessage(PK_MessageAccumulator &messageAccumulator, const byte *recoverableMessage, size_t recoverableMessageLength) const 00045 { 00046 PK_MessageAccumulatorBase &ma = static_cast<PK_MessageAccumulatorBase &>(messageAccumulator); 00047 HashIdentifier id = GetHashIdentifier(); 00048 const MessageEncodingInterface &encoding = GetMessageEncodingInterface(); 00049 00050 if (MessageRepresentativeBitLength() < encoding.MinRepresentativeBitLength(id.second, ma.AccessHash().DigestSize())) 00051 throw PK_SignatureScheme::KeyTooShort(); 00052 00053 size_t maxRecoverableLength = encoding.MaxRecoverableLength(MessageRepresentativeBitLength(), GetHashIdentifier().second, ma.AccessHash().DigestSize()); 00054 00055 if (maxRecoverableLength == 0) 00056 {throw NotImplemented("TF_SignerBase: this algorithm does not support messsage recovery or the key is too short");} 00057 if (recoverableMessageLength > maxRecoverableLength) 00058 throw InvalidArgument("TF_SignerBase: the recoverable message part is too long for the given key and algorithm"); 00059 00060 ma.m_recoverableMessage.Assign(recoverableMessage, recoverableMessageLength); 00061 encoding.ProcessRecoverableMessage( 00062 ma.AccessHash(), 00063 recoverableMessage, recoverableMessageLength, 00064 NULL, 0, ma.m_semisignature); 00065 } 00066 00067 size_t TF_SignerBase::SignAndRestart(RandomNumberGenerator &rng, PK_MessageAccumulator &messageAccumulator, byte *signature, bool restart) const 00068 { 00069 PK_MessageAccumulatorBase &ma = static_cast<PK_MessageAccumulatorBase &>(messageAccumulator); 00070 HashIdentifier id = GetHashIdentifier(); 00071 const MessageEncodingInterface &encoding = GetMessageEncodingInterface(); 00072 00073 if (MessageRepresentativeBitLength() < encoding.MinRepresentativeBitLength(id.second, ma.AccessHash().DigestSize())) 00074 throw PK_SignatureScheme::KeyTooShort(); 00075 00076 SecByteBlock representative(MessageRepresentativeLength()); 00077 encoding.ComputeMessageRepresentative(rng, 00078 ma.m_recoverableMessage, ma.m_recoverableMessage.size(), 00079 ma.AccessHash(), id, ma.m_empty, 00080 representative, MessageRepresentativeBitLength()); 00081 ma.m_empty = true; 00082 00083 Integer r(representative, representative.size()); 00084 size_t signatureLength = SignatureLength(); 00085 GetTrapdoorFunctionInterface().CalculateRandomizedInverse(rng, r).Encode(signature, signatureLength); 00086 return signatureLength; 00087 } 00088 00089 void TF_VerifierBase::InputSignature(PK_MessageAccumulator &messageAccumulator, const byte *signature, size_t signatureLength) const 00090 { 00091 PK_MessageAccumulatorBase &ma = static_cast<PK_MessageAccumulatorBase &>(messageAccumulator); 00092 HashIdentifier id = GetHashIdentifier(); 00093 const MessageEncodingInterface &encoding = GetMessageEncodingInterface(); 00094 00095 if (MessageRepresentativeBitLength() < encoding.MinRepresentativeBitLength(id.second, ma.AccessHash().DigestSize())) 00096 throw PK_SignatureScheme::KeyTooShort(); 00097 00098 ma.m_representative.New(MessageRepresentativeLength()); 00099 Integer x = GetTrapdoorFunctionInterface().ApplyFunction(Integer(signature, signatureLength)); 00100 if (x.BitCount() > MessageRepresentativeBitLength()) 00101 x = Integer::Zero(); // don't return false here to prevent timing attack 00102 x.Encode(ma.m_representative, ma.m_representative.size()); 00103 } 00104 00105 bool TF_VerifierBase::VerifyAndRestart(PK_MessageAccumulator &messageAccumulator) const 00106 { 00107 PK_MessageAccumulatorBase &ma = static_cast<PK_MessageAccumulatorBase &>(messageAccumulator); 00108 HashIdentifier id = GetHashIdentifier(); 00109 const MessageEncodingInterface &encoding = GetMessageEncodingInterface(); 00110 00111 if (MessageRepresentativeBitLength() < encoding.MinRepresentativeBitLength(id.second, ma.AccessHash().DigestSize())) 00112 throw PK_SignatureScheme::KeyTooShort(); 00113 00114 bool result = encoding.VerifyMessageRepresentative( 00115 ma.AccessHash(), id, ma.m_empty, ma.m_representative, MessageRepresentativeBitLength()); 00116 ma.m_empty = true; 00117 return result; 00118 } 00119 00120 DecodingResult TF_VerifierBase::RecoverAndRestart(byte *recoveredMessage, PK_MessageAccumulator &messageAccumulator) const 00121 { 00122 PK_MessageAccumulatorBase &ma = static_cast<PK_MessageAccumulatorBase &>(messageAccumulator); 00123 HashIdentifier id = GetHashIdentifier(); 00124 const MessageEncodingInterface &encoding = GetMessageEncodingInterface(); 00125 00126 if (MessageRepresentativeBitLength() < encoding.MinRepresentativeBitLength(id.second, ma.AccessHash().DigestSize())) 00127 throw PK_SignatureScheme::KeyTooShort(); 00128 00129 DecodingResult result = encoding.RecoverMessageFromRepresentative( 00130 ma.AccessHash(), id, ma.m_empty, ma.m_representative, MessageRepresentativeBitLength(), recoveredMessage); 00131 ma.m_empty = true; 00132 return result; 00133 } 00134 00135 DecodingResult TF_DecryptorBase::Decrypt(RandomNumberGenerator &rng, const byte *ciphertext, size_t ciphertextLength, byte *plaintext, const NameValuePairs ¶meters) const 00136 { 00137 if (ciphertextLength != FixedCiphertextLength()) 00138 throw InvalidArgument(AlgorithmName() + ": ciphertext length of " + IntToString(ciphertextLength) + " doesn't match the required length of " + IntToString(FixedCiphertextLength()) + " for this key"); 00139 00140 SecByteBlock paddedBlock(PaddedBlockByteLength()); 00141 Integer x = GetTrapdoorFunctionInterface().CalculateInverse(rng, Integer(ciphertext, ciphertextLength)); 00142 if (x.ByteCount() > paddedBlock.size()) 00143 x = Integer::Zero(); // don't return false here to prevent timing attack 00144 x.Encode(paddedBlock, paddedBlock.size()); 00145 return GetMessageEncodingInterface().Unpad(paddedBlock, PaddedBlockBitLength(), plaintext, parameters); 00146 } 00147 00148 void TF_EncryptorBase::Encrypt(RandomNumberGenerator &rng, const byte *plaintext, size_t plaintextLength, byte *ciphertext, const NameValuePairs ¶meters) const 00149 { 00150 if (plaintextLength > FixedMaxPlaintextLength()) 00151 { 00152 if (FixedMaxPlaintextLength() < 1) 00153 throw InvalidArgument(AlgorithmName() + ": this key is too short to encrypt any messages"); 00154 else 00155 throw InvalidArgument(AlgorithmName() + ": message length of " + IntToString(plaintextLength) + " exceeds the maximum of " + IntToString(FixedMaxPlaintextLength()) + " for this public key"); 00156 } 00157 00158 SecByteBlock paddedBlock(PaddedBlockByteLength()); 00159 GetMessageEncodingInterface().Pad(rng, plaintext, plaintextLength, paddedBlock, PaddedBlockBitLength(), parameters); 00160 GetTrapdoorFunctionInterface().ApplyRandomizedFunction(rng, Integer(paddedBlock, paddedBlock.size())).Encode(ciphertext, FixedCiphertextLength()); 00161 } 00162 00163 NAMESPACE_END 00164 00165 #endif