// pubkey.h - written and placed in the public domain by Wei Dai #ifndef CRYPTOPP_PUBKEY_H #define CRYPTOPP_PUBKEY_H /** \file This file contains helper classes/functions for implementing public key algorithms. The class hierachies in this .h file tend to look like this:
                  x1
                 / \
                y1  z1
                 |  |
            x2  x2
                 |  |
                y2  z2
                 |  |
            x3  x3
                 |  |
                y3  z3
- x1, y1, z1 are abstract interface classes defined in cryptlib.h - x2, y2, z2 are implementations of the interfaces using "abstract policies", which are pure virtual functions that should return interfaces to interchangeable algorithms. These classes have "Base" suffixes. - x3, y3, z3 hold actual algorithms and implement those virtual functions. These classes have "Impl" suffixes. The "TF_" prefix means an implementation using trapdoor functions on integers. The "DL_" prefix means an implementation using group operations (in groups where discrete log is hard). */ #include "integer.h" #include "filters.h" #include "argnames.h" #include // VC60 workaround: this macro is defined in shlobj.h and conflicts with a template parameter used in this file #undef INTERFACE NAMESPACE_BEGIN(CryptoPP) Integer NR_EncodeDigest(unsigned int modulusBits, const byte *digest, unsigned int digestLen); Integer DSA_EncodeDigest(unsigned int modulusBits, const byte *digest, unsigned int digestLen); // ******************************************************** //! . class TrapdoorFunctionBounds { public: virtual ~TrapdoorFunctionBounds() {} virtual Integer PreimageBound() const =0; virtual Integer ImageBound() const =0; virtual Integer MaxPreimage() const {return --PreimageBound();} virtual Integer MaxImage() const {return --ImageBound();} }; //! . class RandomizedTrapdoorFunction : public TrapdoorFunctionBounds { public: virtual Integer ApplyRandomizedFunction(RandomNumberGenerator &rng, const Integer &x) const =0; virtual bool IsRandomized() const {return true;} }; //! . class TrapdoorFunction : public RandomizedTrapdoorFunction { public: Integer ApplyRandomizedFunction(RandomNumberGenerator &rng, const Integer &x) const {return ApplyFunction(x);} bool IsRandomized() const {return false;} virtual Integer ApplyFunction(const Integer &x) const =0; }; //! . class RandomizedTrapdoorFunctionInverse { public: virtual ~RandomizedTrapdoorFunctionInverse() {} virtual Integer CalculateRandomizedInverse(RandomNumberGenerator &rng, const Integer &x) const =0; virtual bool IsRandomized() const {return true;} }; //! . class TrapdoorFunctionInverse : public RandomizedTrapdoorFunctionInverse { public: virtual ~TrapdoorFunctionInverse() {} Integer CalculateRandomizedInverse(RandomNumberGenerator &rng, const Integer &x) const {return CalculateInverse(rng, x);} bool IsRandomized() const {return false;} virtual Integer CalculateInverse(RandomNumberGenerator &rng, const Integer &x) const =0; }; // ******************************************************** //! . class PK_EncryptionMessageEncodingMethod { public: virtual ~PK_EncryptionMessageEncodingMethod() {} //! max size of unpadded message in bytes, given max size of padded message in bits (1 less than size of modulus) virtual unsigned int MaxUnpaddedLength(unsigned int paddedLength) const =0; virtual void Pad(RandomNumberGenerator &rng, const byte *raw, unsigned int inputLength, byte *padded, unsigned int paddedBitLength) const =0; virtual DecodingResult Unpad(const byte *padded, unsigned int paddedBitLength, byte *raw) const =0; }; // ******************************************************** //! . template class TF_Base { protected: virtual const TrapdoorFunctionBounds & GetTrapdoorFunctionBounds() const =0; typedef TFI TrapdoorFunctionInterface; virtual const TrapdoorFunctionInterface & GetTrapdoorFunctionInterface() const =0; typedef MEI MessageEncodingInterface; virtual const MessageEncodingInterface & GetMessageEncodingInterface() const =0; }; // ******************************************************** //! . template class TF_CryptoSystemBase : public INTERFACE, protected BASE { public: unsigned int FixedMaxPlaintextLength() const {return GetMessageEncodingInterface().MaxUnpaddedLength(PaddedBlockBitLength());} unsigned int FixedCiphertextLength() const {return GetTrapdoorFunctionBounds().MaxImage().ByteCount();} protected: unsigned int PaddedBlockByteLength() const {return BitsToBytes(PaddedBlockBitLength());} unsigned int PaddedBlockBitLength() const {return GetTrapdoorFunctionBounds().PreimageBound().BitCount()-1;} }; //! . class TF_DecryptorBase : public TF_CryptoSystemBase > { public: DecodingResult FixedLengthDecrypt(RandomNumberGenerator &rng, const byte *cipherText, byte *plainText) const; }; //! . class TF_EncryptorBase : public TF_CryptoSystemBase > { public: void Encrypt(RandomNumberGenerator &rng, const byte *plainText, unsigned int plainTextLength, byte *cipherText) const; }; // ******************************************************** typedef std::pair HashIdentifier; //! . class PK_SignatureMessageEncodingMethod { public: virtual ~PK_SignatureMessageEncodingMethod() {} virtual unsigned int MaxRecoverableLength(unsigned int representativeBitLength, unsigned int hashIdentifierLength, unsigned int digestLength) const {return 0;} bool IsProbabilistic() const {return true;} bool AllowNonrecoverablePart() const {throw NotImplemented("PK_MessageEncodingMethod: this signature scheme does not support message recovery");} virtual bool RecoverablePartFirst() const {throw NotImplemented("PK_MessageEncodingMethod: this signature scheme does not support message recovery");} // for verification, DL virtual void ProcessSemisignature(HashTransformation &hash, const byte *semisignature, unsigned int semisignatureLength) const {} // for signature virtual void ProcessRecoverableMessage(HashTransformation &hash, const byte *recoverableMessage, unsigned int recoverableMessageLength, const byte *presignature, unsigned int presignatureLength, SecByteBlock &semisignature) const { if (RecoverablePartFirst()) assert(!"ProcessRecoverableMessage() not implemented"); } virtual void ComputeMessageRepresentative(RandomNumberGenerator &rng, const byte *recoverableMessage, unsigned int recoverableMessageLength, HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty, byte *representative, unsigned int representativeBitLength) const =0; virtual bool VerifyMessageRepresentative( HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty, byte *representative, unsigned int representativeBitLength) const =0; virtual DecodingResult RecoverMessageFromRepresentative( // for TF HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty, byte *representative, unsigned int representativeBitLength, byte *recoveredMessage) const {throw NotImplemented("PK_MessageEncodingMethod: this signature scheme does not support message recovery");} virtual DecodingResult RecoverMessageFromSemisignature( // for DL HashTransformation &hash, HashIdentifier hashIdentifier, const byte *presignature, unsigned int presignatureLength, const byte *semisignature, unsigned int semisignatureLength, byte *recoveredMessage) const {throw NotImplemented("PK_MessageEncodingMethod: this signature scheme does not support message recovery");} // VC60 workaround struct HashIdentifierLookup { template struct HashIdentifierLookup2 { static HashIdentifier Lookup() { return HashIdentifier(NULL, 0); } }; }; }; class PK_DeterministicSignatureMessageEncodingMethod : public PK_SignatureMessageEncodingMethod { public: bool VerifyMessageRepresentative( HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty, byte *representative, unsigned int representativeBitLength) const; }; class PK_RecoverableSignatureMessageEncodingMethod : public PK_SignatureMessageEncodingMethod { public: bool VerifyMessageRepresentative( HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty, byte *representative, unsigned int representativeBitLength) const; }; class DL_SignatureMessageEncodingMethod_DSA : public PK_DeterministicSignatureMessageEncodingMethod { public: void ComputeMessageRepresentative(RandomNumberGenerator &rng, const byte *recoverableMessage, unsigned int recoverableMessageLength, HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty, byte *representative, unsigned int representativeBitLength) const; }; class DL_SignatureMessageEncodingMethod_NR : public PK_DeterministicSignatureMessageEncodingMethod { public: void ComputeMessageRepresentative(RandomNumberGenerator &rng, const byte *recoverableMessage, unsigned int recoverableMessageLength, HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty, byte *representative, unsigned int representativeBitLength) const; }; class PK_MessageAccumulatorBase : public PK_MessageAccumulator { public: PK_MessageAccumulatorBase() : m_empty(true) {} virtual HashTransformation & AccessHash() =0; void Update(const byte *input, unsigned int length) { AccessHash().Update(input, length); m_empty = m_empty && length == 0; } SecByteBlock m_recoverableMessage, m_representative, m_presignature, m_semisignature; Integer m_k, m_s; bool m_empty; }; template class PK_MessageAccumulatorImpl : public PK_MessageAccumulatorBase, protected ObjectHolder { public: HashTransformation & AccessHash() {return m_object;} }; //! . template class TF_SignatureSchemeBase : public INTERFACE, protected BASE { public: unsigned int SignatureLength() const {return GetTrapdoorFunctionBounds().MaxPreimage().ByteCount();} unsigned int MaxRecoverableLength() const {return GetMessageEncodingInterface().MaxRecoverableLength(MessageRepresentativeBitLength(), GetHashIdentifier().second, GetDigestSize());} unsigned int MaxRecoverableLengthFromSignatureLength(unsigned int signatureLength) const {return MaxRecoverableLength();} bool IsProbabilistic() const {return GetTrapdoorFunctionInterface().IsRandomized() || GetMessageEncodingInterface().IsProbabilistic();} bool AllowNonrecoverablePart() const {return GetMessageEncodingInterface().AllowNonrecoverablePart();} bool RecoverablePartFirst() const {return GetMessageEncodingInterface().RecoverablePartFirst();} protected: unsigned int MessageRepresentativeLength() const {return BitsToBytes(MessageRepresentativeBitLength());} unsigned int MessageRepresentativeBitLength() const {return GetTrapdoorFunctionBounds().ImageBound().BitCount()-1;} virtual HashIdentifier GetHashIdentifier() const =0; virtual unsigned int GetDigestSize() const =0; }; //! . class TF_SignerBase : public TF_SignatureSchemeBase > { public: void InputRecoverableMessage(PK_MessageAccumulator &messageAccumulator, const byte *recoverableMessage, unsigned int recoverableMessageLength) const; unsigned int SignAndRestart(RandomNumberGenerator &rng, PK_MessageAccumulator &messageAccumulator, byte *signature, bool restart=true) const; }; //! . class TF_VerifierBase : public TF_SignatureSchemeBase > { public: void InputSignature(PK_MessageAccumulator &messageAccumulator, const byte *signature, unsigned int signatureLength) const; bool VerifyAndRestart(PK_MessageAccumulator &messageAccumulator) const; DecodingResult RecoverAndRestart(byte *recoveredMessage, PK_MessageAccumulator &recoveryAccumulator) const; }; // ******************************************************** //! . template struct TF_CryptoSchemeOptions { typedef T1 AlgorithmInfo; typedef T2 Keys; typedef typename Keys::PrivateKey PrivateKey; typedef typename Keys::PublicKey PublicKey; typedef T3 MessageEncodingMethod; }; //! . template struct TF_SignatureSchemeOptions : public TF_CryptoSchemeOptions { typedef T4 HashFunction; }; //! . template class PublicKeyCopier { public: virtual void CopyKeyInto(typename KEYS::PublicKey &key) const =0; }; //! . template class PrivateKeyCopier { public: virtual void CopyKeyInto(typename KEYS::PublicKey &key) const =0; virtual void CopyKeyInto(typename KEYS::PrivateKey &key) const =0; }; //! . template class TF_ObjectImplBase : public AlgorithmImpl { public: typedef SCHEME_OPTIONS SchemeOptions; typedef KEY KeyClass; PublicKey & AccessPublicKey() {return AccessKey();} const PublicKey & GetPublicKey() const {return GetKey();} PrivateKey & AccessPrivateKey() {return AccessKey();} const PrivateKey & GetPrivateKey() const {return GetKey();} virtual const KeyClass & GetKey() const =0; virtual KeyClass & AccessKey() =0; const KeyClass & GetTrapdoorFunction() const {return GetKey();} protected: const typename BASE::MessageEncodingInterface & GetMessageEncodingInterface() const {static typename SCHEME_OPTIONS::MessageEncodingMethod messageEncodingMethod; return messageEncodingMethod;} const TrapdoorFunctionBounds & GetTrapdoorFunctionBounds() const {return GetKey();} const typename BASE::TrapdoorFunctionInterface & GetTrapdoorFunctionInterface() const {return GetKey();} // for signature scheme HashIdentifier GetHashIdentifier() const { typedef CPP_TYPENAME SchemeOptions::MessageEncodingMethod::HashIdentifierLookup::HashIdentifierLookup2 L; return L::Lookup(); } unsigned int GetDigestSize() const { typedef CPP_TYPENAME SchemeOptions::HashFunction H; return H::DIGESTSIZE; } }; //! . template class TF_ObjectImplExtRef : public TF_ObjectImplBase { public: TF_ObjectImplExtRef(const KEY *pKey = NULL) : m_pKey(pKey) {} void SetKeyPtr(const KEY *pKey) {m_pKey = pKey;} const KEY & GetKey() const {return *m_pKey;} KEY & AccessKey() {throw NotImplemented("TF_ObjectImplExtRef: cannot modify refererenced key");} void CopyKeyInto(typename SCHEME_OPTIONS::PrivateKey &key) const {assert(false);} void CopyKeyInto(typename SCHEME_OPTIONS::PublicKey &key) const {assert(false);} private: const KEY * m_pKey; }; //! . template class TF_ObjectImpl : public TF_ObjectImplBase { public: const KEY & GetKey() const {return m_trapdoorFunction;} KEY & AccessKey() {return m_trapdoorFunction;} private: KEY m_trapdoorFunction; }; //! . template class TF_PublicObjectImpl : public TF_ObjectImpl, public PublicKeyCopier { public: void CopyKeyInto(typename SCHEME_OPTIONS::PublicKey &key) const {key = GetKey();} }; //! . template class TF_PrivateObjectImpl : public TF_ObjectImpl, public PrivateKeyCopier { public: void CopyKeyInto(typename SCHEME_OPTIONS::PrivateKey &key) const {key = GetKey();} void CopyKeyInto(typename SCHEME_OPTIONS::PublicKey &key) const {key = GetKey();} }; //! . template class TF_DecryptorImpl : public TF_PrivateObjectImpl { }; //! . template class TF_EncryptorImpl : public TF_PublicObjectImpl { }; //! . template class TF_SignerImpl : public TF_PrivateObjectImpl { PK_MessageAccumulator * NewSignatureAccumulator(RandomNumberGenerator &rng = NullRNG()) const { return new PK_MessageAccumulatorImpl; } }; //! . template class TF_VerifierImpl : public TF_PublicObjectImpl { PK_MessageAccumulator * NewVerificationAccumulator() const { return new PK_MessageAccumulatorImpl; } }; // ******************************************************** class MaskGeneratingFunction { public: virtual ~MaskGeneratingFunction() {} virtual void GenerateAndMask(HashTransformation &hash, byte *output, unsigned int outputLength, const byte *input, unsigned int inputLength, bool mask = true) const =0; }; void P1363_MGF1KDF2_Common(HashTransformation &hash, byte *output, unsigned int outputLength, const byte *input, unsigned int inputLength, bool mask, unsigned int counterStart); //! . class P1363_MGF1 : public MaskGeneratingFunction { public: static const char * StaticAlgorithmName() {return "MGF1";} #if 0 // VC60 workaround: this function causes internal compiler error template static void GenerateAndMaskTemplate(byte *output, unsigned int outputLength, const byte *input, unsigned int inputLength, H* dummy=NULL) { H h; P1363_MGF1KDF2_Common(h, output, outputLength, input, inputLength, mask, 0); } #endif void GenerateAndMask(HashTransformation &hash, byte *output, unsigned int outputLength, const byte *input, unsigned int inputLength, bool mask = true) const { P1363_MGF1KDF2_Common(hash, output, outputLength, input, inputLength, mask, 0); } }; // ******************************************************** //! . template class P1363_KDF2 { public: static void DeriveKey(byte *output, unsigned int outputLength, const byte *input, unsigned int inputLength) { H h; P1363_MGF1KDF2_Common(h, output, outputLength, input, inputLength, false, 1); } }; // ******************************************************** template class PK_FinalTemplate : public BASE { public: PK_FinalTemplate() {} PK_FinalTemplate(const Integer &v1) {AccessKey().Initialize(v1);} PK_FinalTemplate(const typename BASE::KeyClass &key) {AccessKey().operator=(key);} template PK_FinalTemplate(const PublicKeyCopier &key) {key.CopyKeyInto(AccessKey());} template PK_FinalTemplate(const PrivateKeyCopier &key) {key.CopyKeyInto(AccessKey());} PK_FinalTemplate(BufferedTransformation &bt) {AccessKey().BERDecode(bt);} #if (defined(_MSC_VER) && _MSC_VER < 1300) template PK_FinalTemplate(T1 &v1, T2 &v2) {AccessKey().Initialize(v1, v2);} template PK_FinalTemplate(T1 &v1, T2 &v2, T3 &v3) {AccessKey().Initialize(v1, v2, v3);} template PK_FinalTemplate(T1 &v1, T2 &v2, T3 &v3, T4 &v4) {AccessKey().Initialize(v1, v2, v3, v4);} template PK_FinalTemplate(T1 &v1, T2 &v2, T3 &v3, T4 &v4, T5 &v5) {AccessKey().Initialize(v1, v2, v3, v4, v5);} template PK_FinalTemplate(T1 &v1, T2 &v2, T3 &v3, T4 &v4, T5 &v5, T6 &v6) {AccessKey().Initialize(v1, v2, v3, v4, v5, v6);} template PK_FinalTemplate(T1 &v1, T2 &v2, T3 &v3, T4 &v4, T5 &v5, T6 &v6, T7 &v7) {AccessKey().Initialize(v1, v2, v3, v4, v5, v6, v7);} template PK_FinalTemplate(T1 &v1, T2 &v2, T3 &v3, T4 &v4, T5 &v5, T6 &v6, T7 &v7, T8 &v8) {AccessKey().Initialize(v1, v2, v3, v4, v5, v6, v7, v8);} #else template PK_FinalTemplate(const T1 &v1, const T2 &v2) {AccessKey().Initialize(v1, v2);} template PK_FinalTemplate(const T1 &v1, const T2 &v2, const T3 &v3) {AccessKey().Initialize(v1, v2, v3);} template PK_FinalTemplate(const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4) {AccessKey().Initialize(v1, v2, v3, v4);} template PK_FinalTemplate(const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5) {AccessKey().Initialize(v1, v2, v3, v4, v5);} template PK_FinalTemplate(const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, const T6 &v6) {AccessKey().Initialize(v1, v2, v3, v4, v5, v6);} template PK_FinalTemplate(const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, const T6 &v6, const T7 &v7) {AccessKey().Initialize(v1, v2, v3, v4, v5, v6, v7);} template PK_FinalTemplate(const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, const T6 &v6, const T7 &v7, const T8 &v8) {AccessKey().Initialize(v1, v2, v3, v4, v5, v6, v7, v8);} template PK_FinalTemplate(T1 &v1, const T2 &v2) {AccessKey().Initialize(v1, v2);} template PK_FinalTemplate(T1 &v1, const T2 &v2, const T3 &v3) {AccessKey().Initialize(v1, v2, v3);} template PK_FinalTemplate(T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4) {AccessKey().Initialize(v1, v2, v3, v4);} template PK_FinalTemplate(T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5) {AccessKey().Initialize(v1, v2, v3, v4, v5);} template PK_FinalTemplate(T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, const T6 &v6) {AccessKey().Initialize(v1, v2, v3, v4, v5, v6);} template PK_FinalTemplate(T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, const T6 &v6, const T7 &v7) {AccessKey().Initialize(v1, v2, v3, v4, v5, v6, v7);} template PK_FinalTemplate(T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, const T6 &v6, const T7 &v7, const T8 &v8) {AccessKey().Initialize(v1, v2, v3, v4, v5, v6, v7, v8);} #endif }; //! Base class for public key encryption standard classes. These classes are used to select from variants of algorithms. Note that not all standards apply to all algorithms. struct EncryptionStandard {}; //! Base class for public key signature standard classes. These classes are used to select from variants of algorithms. Note that not all standards apply to all algorithms. struct SignatureStandard {}; template class TF_ES; //! Trapdoor Function Based Encryption Scheme template > class TF_ES : public KEYS { typedef typename STANDARD::EncryptionMessageEncodingMethod MessageEncodingMethod; public: //! see EncryptionStandard for a list of standards typedef STANDARD Standard; typedef TF_CryptoSchemeOptions SchemeOptions; static std::string StaticAlgorithmName() {return KEYS::StaticAlgorithmName() + "/" + MessageEncodingMethod::StaticAlgorithmName();} //! implements PK_Decryptor interface typedef PK_FinalTemplate > Decryptor; //! implements PK_Encryptor interface typedef PK_FinalTemplate > Encryptor; }; template // VC60 workaround: doesn't work if KEYS is first parameter class TF_SS; //! Trapdoor Function Based Signature Scheme template > // VC60 workaround: doesn't work if KEYS is first parameter class TF_SS : public KEYS { public: //! see SignatureStandard for a list of standards typedef STANDARD Standard; typedef typename Standard::SignatureMessageEncodingMethod MessageEncodingMethod; typedef TF_SignatureSchemeOptions SchemeOptions; static std::string StaticAlgorithmName() {return KEYS::StaticAlgorithmName() + "/" + MessageEncodingMethod::StaticAlgorithmName() + "(" + H::StaticAlgorithmName() + ")";} //! implements PK_Signer interface typedef PK_FinalTemplate > Signer; //! implements PK_Verifier interface typedef PK_FinalTemplate > Verifier; }; NAMESPACE_END #endif