// 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 "eprecomp.h"
#include "fips140.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);
template
struct CryptoStandardTraits
{
typedef typename STANDARD::EncryptionPaddingAlgorithm EncryptionPaddingAlgorithm;
template class SignaturePaddingAlgorithm {};
template class DecoratedHashingAlgorithm {};
};
// ********************************************************
//! .
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;
};
//! .
class TrapdoorFunction : public RandomizedTrapdoorFunction
{
public:
Integer ApplyRandomizedFunction(RandomNumberGenerator &rng, const Integer &x) const
{return ApplyFunction(x);}
virtual Integer ApplyFunction(const Integer &x) const =0;
};
//! .
class RandomizedTrapdoorFunctionInverse
{
public:
virtual ~RandomizedTrapdoorFunctionInverse() {}
virtual Integer CalculateRandomizedInverse(RandomNumberGenerator &rng, const Integer &x) const =0;
};
//! .
class TrapdoorFunctionInverse : public RandomizedTrapdoorFunctionInverse
{
public:
virtual ~TrapdoorFunctionInverse() {}
Integer CalculateRandomizedInverse(RandomNumberGenerator &rng, const Integer &x) const
{return CalculateInverse(x);}
virtual Integer CalculateInverse(const Integer &x) const =0;
};
// ********************************************************
//! .
class PK_PaddingAlgorithm
{
public:
virtual ~PK_PaddingAlgorithm() {}
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;
virtual bool IsReversible() const {return true;}
};
//! .
class PK_NonreversiblePaddingAlgorithm : public PK_PaddingAlgorithm
{
DecodingResult Unpad(const byte *padded, unsigned int paddedBitLength, byte *raw) const {assert(false); return DecodingResult();}
bool IsReversible() const {return false;}
};
// ********************************************************
//! .
template
class TF_Base
{
protected:
unsigned int PaddedBlockByteLength() const {return BitsToBytes(PaddedBlockBitLength());}
virtual const TrapdoorFunctionBounds & GetTrapdoorFunctionBounds() const =0;
virtual const PK_PaddingAlgorithm & GetPaddingAlgorithm() const =0;
virtual unsigned int PaddedBlockBitLength() const =0;
typedef TFI TrapdoorFunctionInterface;
virtual const TrapdoorFunctionInterface & GetTrapdoorFunctionInterface() const =0;
};
// ********************************************************
//! .
template
class TF_CryptoSystemBase : public INTERFACE, protected BASE
{
public:
unsigned int FixedMaxPlaintextLength() const {return GetPaddingAlgorithm().MaxUnpaddedLength(PaddedBlockBitLength());}
unsigned int FixedCiphertextLength() const {return GetTrapdoorFunctionBounds().MaxImage().ByteCount();}
protected:
unsigned int PaddedBlockBitLength() const {return GetTrapdoorFunctionBounds().PreimageBound().BitCount()-1;}
};
//! .
class TF_DecryptorBase : public TF_CryptoSystemBase >
{
public:
DecodingResult FixedLengthDecrypt(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;
};
// ********************************************************
//! .
class DigestSignatureSystem
{
public:
virtual unsigned int MaxDigestLength() const =0;
virtual unsigned int DigestSignatureLength() const =0;
};
//! .
class DigestSigner : virtual public DigestSignatureSystem, public PrivateKeyAlgorithm
{
public:
virtual void SignDigest(RandomNumberGenerator &rng, const byte *digest, unsigned int digestLen, byte *signature) const =0;
};
//! .
class DigestVerifier : virtual public DigestSignatureSystem, public PublicKeyAlgorithm
{
public:
virtual bool VerifyDigest(const byte *digest, unsigned int digestLen, const byte *sig) const =0;
};
// ********************************************************
//! .
template
class TF_DigestSignatureSystemBase : public INTERFACE, protected BASE
{
public:
unsigned int MaxDigestLength() const {return GetPaddingAlgorithm().MaxUnpaddedLength(PaddedBlockBitLength());}
unsigned int DigestSignatureLength() const {return GetTrapdoorFunctionBounds().MaxPreimage().ByteCount();}
protected:
unsigned int PaddedBlockBitLength() const {return GetTrapdoorFunctionBounds().ImageBound().BitCount()-1;}
};
//! .
class TF_DigestSignerBase : public TF_DigestSignatureSystemBase >
{
public:
void SignDigest(RandomNumberGenerator &rng, const byte *message, unsigned int messageLength, byte *signature) const;
};
//! .
class TF_DigestVerifierBase : public TF_DigestSignatureSystemBase >
{
public:
bool VerifyDigest(const byte *digest, unsigned int digestLen, const byte *sig) const;
};
// ********************************************************
//! .
template
struct TF_SchemeOptions
{
typedef T1 AlgorithmInfo;
typedef T2 Keys;
typedef typename Keys::PrivateKey PrivateKey;
typedef typename Keys::PublicKey PublicKey;
typedef T3 PaddingAlgorithm;
};
//! .
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 PK_PaddingAlgorithm & GetPaddingAlgorithm() const {static typename SCHEME_OPTIONS::PaddingAlgorithm paddingScheme; return paddingScheme;}
const TrapdoorFunctionBounds & GetTrapdoorFunctionBounds() const {return GetKey();}
const typename BASE::TrapdoorFunctionInterface & GetTrapdoorFunctionInterface() const {return GetKey();}
};
//! .
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_DigestSignerImpl : public TF_PrivateObjectImpl
{
};
//! .
template
class TF_DigestVerifierImpl : public TF_PublicObjectImpl
{
};
// ********************************************************
//! .
template
class P1363_MGF1
{
public:
static std::string StaticAlgorithmName() {return std::string("MGF1(") + H::StaticAlgorithmName() + ")";}
static void GenerateAndMask(byte *output, unsigned int outputLength, const byte *input, unsigned int inputLength);
};
template
void P1363_MGF1::GenerateAndMask(byte *output, unsigned int outputLength, const byte *input, unsigned int inputLength)
{
H h;
ArrayXorSink *sink;
HashFilter filter(h, sink = new ArrayXorSink(output, outputLength));
word32 counter = 0;
while (sink->AvailableSize() > 0)
{
filter.Put(input, inputLength);
filter.PutWord32(counter++);
filter.MessageEnd();
}
}
// ********************************************************
//! .
template
class P1363_KDF2
{
public:
static void DeriveKey(byte *output, unsigned int outputLength, const byte *input, unsigned int inputLength);
};
template
void P1363_KDF2::DeriveKey(byte *output, unsigned int outputLength, const byte *input, unsigned int inputLength)
{
H h;
ArraySink *sink;
HashFilter filter(h, sink = new ArraySink(output, outputLength));
word32 counter = 1;
while (sink->AvailableSize() > 0)
{
filter.Put(input, inputLength);
filter.PutWord32(counter++);
filter.MessageEnd();
}
}
// ********************************************************
//! .
template
class PK_SignatureSchemeBase : public INTERFACE
{
public:
unsigned int SignatureLength() const {return GetDigestSignatureSchemeInterface().DigestSignatureLength();}
HashTransformation * NewMessageAccumulator() const {return new H;}
virtual const DS_INTERFACE & GetDigestSignatureSchemeInterface() const =0;
};
//! .
template
class PK_SignerBase : public PK_SignatureSchemeBase
{
public:
void SignAndRestart(RandomNumberGenerator &rng, HashTransformation &messageAccumulator, byte *signature) const;
};
//! .
template
class PK_VerifierBase : public PK_SignatureSchemeBase
{
public:
bool VerifyAndRestart(HashTransformation &messageAccumulator, const byte *sig) const;
};
template
void PK_SignerBase::SignAndRestart(RandomNumberGenerator &rng, HashTransformation &messageAccumulator, byte *signature) const
{
if (messageAccumulator.DigestSize() > GetDigestSignatureSchemeInterface().MaxDigestLength())
throw PK_Signer::KeyTooShort();
SecByteBlock digest(messageAccumulator.DigestSize());
messageAccumulator.Final(digest);
GetDigestSignatureSchemeInterface().SignDigest(rng, digest, digest.size(), signature);
}
template
bool PK_VerifierBase::VerifyAndRestart(HashTransformation &messageAccumulator, const byte *sig) const
{
SecByteBlock digest(messageAccumulator.DigestSize());
messageAccumulator.Final(digest);
return GetDigestSignatureSchemeInterface().VerifyDigest(digest, digest.size(), sig);
}
//! .
template
class PK_SignatureSchemeImpl : public BASE
{
public:
typedef typename DS::KeyClass KeyClass;
// PublicKeyAlgorithm or PrivateKeyAlgorithm
std::string AlgorithmName() const {return m_ds.AlgorithmName();}
PrivateKey & AccessPrivateKey() {return m_ds.AccessPrivateKey();}
const PrivateKey & GetPrivateKey() const {return m_ds.GetPrivateKey();}
PublicKey & AccessPublicKey() {return m_ds.AccessPublicKey();}
const PublicKey & GetPublicKey() const {return m_ds.GetPublicKey();}
KeyClass & AccessKey() {return m_ds.AccessKey();}
const KeyClass & GetKey() const {return m_ds.GetKey();}
const KeyClass & GetTrapdoorFunction() const {return m_ds.GetTrapdoorFunction();}
DS & AccessDigestSignatureScheme() {return m_ds;}
const DS & GetDigestSignatureScheme() const {return m_ds;}
protected:
DS m_ds;
};
//! .
template
class PK_SignerImpl : public PK_SignatureSchemeImpl, DS>, public PrivateKeyCopier
{
const DigestSigner & GetDigestSignatureSchemeInterface() const {return m_ds;}
public:
// PrivateKeyCopier
void CopyKeyInto(typename DS::SchemeOptions::PublicKey &key) const
{m_ds.CopyKeyInto(key);}
void CopyKeyInto(typename DS::SchemeOptions::PrivateKey &key) const
{m_ds.CopyKeyInto(key);}
};
//! .
template
class PK_VerifierImpl : public PK_SignatureSchemeImpl, DS>, public PublicKeyCopier
{
const DigestVerifier & GetDigestSignatureSchemeInterface() const {return m_ds;}
public:
// PublicKeyCopier
void CopyKeyInto(typename DS::SchemeOptions::PublicKey &key) const
{m_ds.CopyKeyInto(key);}
};
// ********************************************************
//! .
class SignatureEncodingMethodWithRecovery : public HashTransformationWithDefaultTruncation
{
public:
void Final(byte *digest) {}
virtual void Encode(RandomNumberGenerator &rng, byte *representative) =0;
virtual bool Verify(const byte *representative) =0;
virtual DecodingResult Decode(byte *message) =0;
virtual unsigned int MaximumRecoverableLength() const =0;
};
//! .
template
class SignatureSystemWithRecoveryBaseTemplate : virtual public PK_SignatureSchemeWithRecovery
{
public:
unsigned int SignatureLength() const {return GetTrapdoorFunctionBounds().MaxPreimage().ByteCount();}
HashTransformation * NewMessageAccumulator() const {return new H(PaddedBlockBitLength());}
unsigned int MaximumRecoverableLength() const {return H::MaximumRecoverableLength(PaddedBlockBitLength());}
bool AllowLeftoverMessage() const {return H::AllowLeftoverMessage();}
protected:
unsigned int PaddedBlockByteLength() const {return BitsToBytes(PaddedBlockBitLength());}
unsigned int PaddedBlockBitLength() const {return GetTrapdoorFunctionBounds().ImageBound().BitCount()-1;}
virtual const TrapdoorFunctionBounds & GetTrapdoorFunctionBounds() const =0;
};
//! .
template
class SignerWithRecoveryTemplate : virtual public SignatureSystemWithRecoveryBaseTemplate, virtual public PK_SignerWithRecovery, public TF
{
public:
typedef TF KeyClass;
const KeyClass & GetKey() const {return *this;}
KeyClass & AccessKey() {return *this;}
PrivateKey & AccessPrivateKey() {return *this;}
SignerWithRecoveryTemplate() {}
void SignAndRestart(RandomNumberGenerator &rng, HashTransformation &messageAccumulator, byte *signature) const;
const TrapdoorFunctionBounds & GetTrapdoorFunctionBounds() const {return *this;}
};
//! .
template
class VerifierWithRecoveryTemplate : virtual public SignatureSystemWithRecoveryBaseTemplate, virtual public PK_VerifierWithRecovery, public TF
{
public:
typedef TF KeyClass;
const KeyClass & GetKey() const {return *this;}
KeyClass & AccessKey() {return *this;}
PublicKey & AccessPublicKey() {return *this;}
VerifierWithRecoveryTemplate() {}
bool VerifyAndRestart(HashTransformation &messageAccumulator, const byte *sig) const;
bool SignatureUpfrontForRecovery() const {return true;}
HashTransformation * NewRecoveryAccumulator(const byte *signature) const;
DecodingResult Recover(byte *recoveredMessage, HashTransformation *recoveryAccumulator, const byte *signature) const;
const TrapdoorFunctionBounds & GetTrapdoorFunctionBounds() const {return *this;}
};
template
void SignerWithRecoveryTemplate::SignAndRestart(RandomNumberGenerator &rng, HashTransformation &messageAccumulator, byte *signature) const
{
H &ma = static_cast(messageAccumulator);
if (ma.MaximumRecoverableLength() == 0)
throw KeyTooShort();
SecByteBlock representative(PaddedBlockByteLength());
ma.Encode(rng, representative);
CalculateInverse(Integer(representative, representative.size())).Encode(signature, SignatureLength());
}
template
bool VerifierWithRecoveryTemplate::VerifyAndRestart(HashTransformation &messageAccumulator, const byte *signature) const
{
SecByteBlock representative(PaddedBlockByteLength());
ApplyFunction(Integer(signature, SignatureLength())).Encode(representative, representative.size());
return messageAccumulator.Verify(representative);
}
template
HashTransformation * VerifierWithRecoveryTemplate::NewRecoveryAccumulator(const byte *signature) const
{
SecByteBlock representative(PaddedBlockByteLength());
ApplyFunction(Integer(signature, SignatureLength())).Encode(representative, representative.size());
return new H(representative, PaddedBlockBitLength());
}
template
DecodingResult VerifierWithRecoveryTemplate::Recover(byte *recoveredMessage, HashTransformation *recoveryAccumulator, const byte *signature) const
{
std::auto_ptr ma(static_cast(recoveryAccumulator));
return ma->Decode(recoveredMessage);
}
// ********************************************************
// to be thrown by DecodeElement and AgreeWithStaticPrivateKey
class DL_BadElement : public InvalidDataFormat
{
public:
DL_BadElement() : InvalidDataFormat("CryptoPP: invalid group element") {}
};
//! .
template
class DL_GroupParameters : public CryptoParameters
{
typedef DL_GroupParameters ThisClass;
public:
typedef T Element;
DL_GroupParameters() : m_validationLevel(0) {}
// CryptoMaterial
bool Validate(RandomNumberGenerator &rng, unsigned int level) const
{
if (!GetBasePrecomputation().IsInitialized())
return false;
if (m_validationLevel > level)
return true;
bool pass = ValidateGroup(rng, level);
pass = pass && ValidateElement(level, GetSubgroupGenerator(), &GetBasePrecomputation());
m_validationLevel = pass ? level+1 : 0;
return pass;
}
bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const
{
return GetValueHelper(this, name, valueType, pValue)
CRYPTOPP_GET_FUNCTION_ENTRY(SubgroupOrder)
CRYPTOPP_GET_FUNCTION_ENTRY(SubgroupGenerator)
;
}
bool SupportsPrecomputation() const {return true;}
void Precompute(unsigned int precomputationStorage=16)
{
AccessBasePrecomputation().Precompute(GetGroupPrecomputation(), GetSubgroupOrder().BitCount(), precomputationStorage);
}
void LoadPrecomputation(BufferedTransformation &storedPrecomputation)
{
AccessBasePrecomputation().Load(GetGroupPrecomputation(), storedPrecomputation);
m_validationLevel = 0;
}
void SavePrecomputation(BufferedTransformation &storedPrecomputation) const
{
GetBasePrecomputation().Save(GetGroupPrecomputation(), storedPrecomputation);
}
// non-inherited
virtual const Element & GetSubgroupGenerator() const {return GetBasePrecomputation().GetBase(GetGroupPrecomputation());}
virtual void SetSubgroupGenerator(const Element &base) {AccessBasePrecomputation().SetBase(GetGroupPrecomputation(), base);}
virtual Element ExponentiateBase(const Integer &exponent) const
{
return GetBasePrecomputation().Exponentiate(GetGroupPrecomputation(), exponent);
}
virtual Element ExponentiateElement(const Element &base, const Integer &exponent) const
{
Element result;
SimultaneousExponentiate(&result, base, &exponent, 1);
return result;
}
virtual const DL_GroupPrecomputation & GetGroupPrecomputation() const =0;
virtual const DL_FixedBasePrecomputation & GetBasePrecomputation() const =0;
virtual DL_FixedBasePrecomputation & AccessBasePrecomputation() =0;
virtual const Integer & GetSubgroupOrder() const =0; // order of subgroup generated by base element
virtual Integer GetMaxExponent() const =0;
virtual Integer GetGroupOrder() const {return GetSubgroupOrder()*GetCofactor();} // one of these two needs to be overriden
virtual Integer GetCofactor() const {return GetGroupOrder()/GetSubgroupOrder();}
virtual unsigned int GetEncodedElementSize(bool reversible) const =0;
virtual void EncodeElement(bool reversible, const Element &element, byte *encoded) const =0;
virtual Element DecodeElement(const byte *encoded, bool checkForGroupMembership) const =0;
virtual Integer ConvertElementToInteger(const Element &element) const =0;
virtual bool ValidateGroup(RandomNumberGenerator &rng, unsigned int level) const =0;
virtual bool ValidateElement(unsigned int level, const Element &element, const DL_FixedBasePrecomputation *precomp) const =0;
virtual bool FastSubgroupCheckAvailable() const =0;
virtual bool IsIdentity(const Element &element) const =0;
virtual void SimultaneousExponentiate(Element *results, const Element &base, const Integer *exponents, unsigned int exponentsCount) const =0;
protected:
void ParametersChanged() {m_validationLevel = 0;}
private:
mutable unsigned int m_validationLevel;
};
//! .
template , class BASE = DL_GroupParameters >
class DL_GroupParametersImpl : public BASE
{
public:
typedef GROUP_PRECOMP GroupPrecomputation;
typedef typename GROUP_PRECOMP::Element Element;
typedef BASE_PRECOMP BasePrecomputation;
const DL_GroupPrecomputation & GetGroupPrecomputation() const {return m_groupPrecomputation;}
const DL_FixedBasePrecomputation & GetBasePrecomputation() const {return m_gpc;}
DL_FixedBasePrecomputation & AccessBasePrecomputation() {return m_gpc;}
protected:
GROUP_PRECOMP m_groupPrecomputation;
BASE_PRECOMP m_gpc;
};
//! .
template
class DL_Key
{
public:
virtual const DL_GroupParameters & GetAbstractGroupParameters() const =0;
virtual DL_GroupParameters & AccessAbstractGroupParameters() =0;
};
//! .
template
class DL_PublicKey : public DL_Key
{
typedef DL_PublicKey ThisClass;
public:
typedef T Element;
bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const
{
return GetAbstractGroupParameters().GetVoidValue(name, valueType, pValue)
|| GetValueHelper(this, name, valueType, pValue)
CRYPTOPP_GET_FUNCTION_ENTRY(PublicElement);
}
void AssignFrom(const NameValuePairs &source);
// non-inherited
virtual const Element & GetPublicElement() const {return GetPublicPrecomputation().GetBase(GetAbstractGroupParameters().GetGroupPrecomputation());}
virtual void SetPublicElement(const Element &y) {AccessPublicPrecomputation().SetBase(GetAbstractGroupParameters().GetGroupPrecomputation(), y);}
virtual Element ExponentiatePublicElement(const Integer &exponent) const
{
const DL_GroupParameters ¶ms = GetAbstractGroupParameters();
return GetPublicPrecomputation().Exponentiate(params.GetGroupPrecomputation(), exponent);
}
virtual Element CascadeExponentiateBaseAndPublicElement(const Integer &baseExp, const Integer &publicExp) const
{
const DL_GroupParameters ¶ms = GetAbstractGroupParameters();
return params.GetBasePrecomputation().CascadeExponentiate(params.GetGroupPrecomputation(), baseExp, GetPublicPrecomputation(), publicExp);
}
virtual const DL_FixedBasePrecomputation & GetPublicPrecomputation() const =0;
virtual DL_FixedBasePrecomputation & AccessPublicPrecomputation() =0;
};
//! .
template
class DL_PrivateKey : public DL_Key
{
typedef DL_PrivateKey ThisClass;
public:
typedef T Element;
void MakePublicKey(DL_PublicKey &pub) const
{
pub.AccessAbstractGroupParameters().AssignFrom(GetAbstractGroupParameters());
pub.SetPublicElement(GetAbstractGroupParameters().ExponentiateBase(GetPrivateExponent()));
}
bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const
{
return GetAbstractGroupParameters().GetVoidValue(name, valueType, pValue)
|| GetValueHelper(this, name, valueType, pValue)
CRYPTOPP_GET_FUNCTION_ENTRY(PrivateExponent);
}
void AssignFrom(const NameValuePairs &source)
{
AccessAbstractGroupParameters().AssignFrom(source);
AssignFromHelper(this, source)
CRYPTOPP_SET_FUNCTION_ENTRY(PrivateExponent);
}
virtual const Integer & GetPrivateExponent() const =0;
virtual void SetPrivateExponent(const Integer &x) =0;
};
template
void DL_PublicKey::AssignFrom(const NameValuePairs &source)
{
DL_PrivateKey *pPrivateKey = NULL;
if (source.GetThisPointer(pPrivateKey))
pPrivateKey->MakePublicKey(*this);
else
{
AccessAbstractGroupParameters().AssignFrom(source);
AssignFromHelper(this, source)
CRYPTOPP_SET_FUNCTION_ENTRY(PublicElement);
}
}
class OID;
//! .
template
class DL_KeyImpl : public PK
{
public:
typedef GP GroupParameters;
OID GetAlgorithmID() const {return GetGroupParameters().GetAlgorithmID();}
// void BERDecode(BufferedTransformation &bt)
// {PK::BERDecode(bt);}
// void DEREncode(BufferedTransformation &bt) const
// {PK::DEREncode(bt);}
bool BERDecodeAlgorithmParameters(BufferedTransformation &bt)
{AccessGroupParameters().BERDecode(bt); return true;}
bool DEREncodeAlgorithmParameters(BufferedTransformation &bt) const
{GetGroupParameters().DEREncode(bt); return true;}
const GP & GetGroupParameters() const {return m_groupParameters;}
GP & AccessGroupParameters() {return m_groupParameters;}
private:
GP m_groupParameters;
};
class X509PublicKey;
class PKCS8PrivateKey;
//! .
template
class DL_PrivateKeyImpl : public DL_PrivateKey, public DL_KeyImpl
{
public:
typedef typename GP::Element Element;
// GeneratableCryptoMaterial
bool Validate(RandomNumberGenerator &rng, unsigned int level) const
{
bool pass = GetAbstractGroupParameters().Validate(rng, level);
const Integer &q = GetAbstractGroupParameters().GetSubgroupOrder();
const Integer &x = GetPrivateExponent();
pass = pass && x.IsPositive() && x < q;
if (level >= 1)
pass = pass && Integer::Gcd(x, q) == Integer::One();
return pass;
}
bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const
{
return GetValueHelper >(this, name, valueType, pValue).Assignable();
}
void AssignFrom(const NameValuePairs &source)
{
AssignFromHelper >(this, source);
}
void GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs ¶ms)
{
if (!params.GetThisObject(AccessGroupParameters()))
AccessGroupParameters().GenerateRandom(rng, params);
// std::pair seed;
Integer x(rng, Integer::One(), GetAbstractGroupParameters().GetMaxExponent());
// Integer::ANY, Integer::Zero(), Integer::One(),
// params.GetValue("DeterministicKeyGenerationSeed", seed) ? &seed : NULL);
SetPrivateExponent(x);
}
bool SupportsPrecomputation() const {return true;}
void Precompute(unsigned int precomputationStorage=16)
{AccessAbstractGroupParameters().Precompute(precomputationStorage);}
void LoadPrecomputation(BufferedTransformation &storedPrecomputation)
{AccessAbstractGroupParameters().LoadPrecomputation(storedPrecomputation);}
void SavePrecomputation(BufferedTransformation &storedPrecomputation) const
{GetAbstractGroupParameters().SavePrecomputation(storedPrecomputation);}
// DL_Key
const DL_GroupParameters & GetAbstractGroupParameters() const {return GetGroupParameters();}
DL_GroupParameters & AccessAbstractGroupParameters() {return AccessGroupParameters();}
// DL_PrivateKey
const Integer & GetPrivateExponent() const {return m_x;}
void SetPrivateExponent(const Integer &x) {m_x = x;}
// PKCS8PrivateKey
void BERDecodeKey(BufferedTransformation &bt)
{m_x.BERDecode(bt);}
void DEREncodeKey(BufferedTransformation &bt) const
{m_x.DEREncode(bt);}
private:
Integer m_x;
};
//! .
template
class DL_PrivateKey_WithSignaturePairwiseConsistencyTest : public BASE
{
public:
void GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs ¶ms)
{
BASE::GenerateRandom(rng, params);
if (FIPS_140_2_ComplianceEnabled())
{
typename SIGNATURE_SCHEME::Signer signer(*this);
typename SIGNATURE_SCHEME::Verifier verifier(signer);
SignaturePairwiseConsistencyTest(signer, verifier);
}
}
};
//! .
template
class DL_PublicKeyImpl : public DL_PublicKey, public DL_KeyImpl
{
public:
typedef typename GP::Element Element;
// CryptoMaterial
bool Validate(RandomNumberGenerator &rng, unsigned int level) const
{
bool pass = GetAbstractGroupParameters().Validate(rng, level);
pass = pass && GetAbstractGroupParameters().ValidateElement(level, GetPublicElement(), &GetPublicPrecomputation());
return pass;
}
bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const
{
return GetValueHelper >(this, name, valueType, pValue).Assignable();
}
void AssignFrom(const NameValuePairs &source)
{
AssignFromHelper >(this, source);
}
bool SupportsPrecomputation() const {return true;}
void Precompute(unsigned int precomputationStorage=16)
{
AccessAbstractGroupParameters().Precompute(precomputationStorage);
AccessPublicPrecomputation().Precompute(GetAbstractGroupParameters().GetGroupPrecomputation(), GetAbstractGroupParameters().GetSubgroupOrder().BitCount(), precomputationStorage);
}
void LoadPrecomputation(BufferedTransformation &storedPrecomputation)
{
AccessAbstractGroupParameters().LoadPrecomputation(storedPrecomputation);
AccessPublicPrecomputation().Load(GetAbstractGroupParameters().GetGroupPrecomputation(), storedPrecomputation);
}
void SavePrecomputation(BufferedTransformation &storedPrecomputation) const
{
GetAbstractGroupParameters().SavePrecomputation(storedPrecomputation);
GetPublicPrecomputation().Save(GetAbstractGroupParameters().GetGroupPrecomputation(), storedPrecomputation);
}
// DL_Key
const DL_GroupParameters & GetAbstractGroupParameters() const {return GetGroupParameters();}
DL_GroupParameters & AccessAbstractGroupParameters() {return AccessGroupParameters();}
// DL_PublicKey
const DL_FixedBasePrecomputation & GetPublicPrecomputation() const {return m_ypc;}
DL_FixedBasePrecomputation & AccessPublicPrecomputation() {return m_ypc;}
// non-inherited
bool operator==(const DL_PublicKeyImpl &rhs) const
{return GetGroupParameters() == rhs.GetGroupParameters() && GetPublicElement() == rhs.GetPublicElement();}
private:
typename GP::BasePrecomputation m_ypc;
};
//! .
template
class DL_ElgamalLikeSignatureAlgorithm
{
public:
virtual Integer EncodeDigest(unsigned int modulusBits, const byte *digest, unsigned int digestLength) const =0;
virtual bool Sign(const DL_GroupParameters ¶ms, const Integer &privateKey, const Integer &k, const Integer &e, Integer &r, Integer &s) const =0;
virtual bool Verify(const DL_GroupParameters ¶ms, const DL_PublicKey &publicKey, const Integer &e, const Integer &r, const Integer &s) const =0;
virtual unsigned int RLen(const DL_GroupParameters ¶ms) const
{return params.GetSubgroupOrder().ByteCount();}
virtual unsigned int SLen(const DL_GroupParameters ¶ms) const
{return params.GetSubgroupOrder().ByteCount();}
};
//! .
template
class DL_KeyAgreementAlgorithm
{
public:
typedef T Element;
virtual Element AgreeWithEphemeralPrivateKey(const DL_GroupParameters ¶ms, const DL_FixedBasePrecomputation &publicPrecomputation, const Integer &privateExponent) const =0;
virtual Element AgreeWithStaticPrivateKey(const DL_GroupParameters ¶ms, const Element &publicElement, bool validateOtherPublicKey, const Integer &privateExponent) const =0;
};
//! .
template
class DL_KeyDerivationAlgorithm
{
public:
virtual void Derive(const DL_GroupParameters ¶ms, byte *derivedKey, unsigned int derivedLength, const T &agreedElement, const T &ephemeralPublicKey) const =0;
};
//! .
class DL_SymmetricEncryptionAlgorithm
{
public:
virtual unsigned int GetSymmetricKeyLength(unsigned int plainTextLength) const =0;
virtual unsigned int GetSymmetricCiphertextLength(unsigned int plainTextLength) const =0;
virtual unsigned int GetMaxSymmetricPlaintextLength(unsigned int cipherTextLength) const =0;
virtual void SymmetricEncrypt(RandomNumberGenerator &rng, const byte *key, const byte *plainText, unsigned int plainTextLength, byte *cipherText) const =0;
virtual DecodingResult SymmetricDecrypt(const byte *key, const byte *cipherText, unsigned int cipherTextLength, byte *plainText) const =0;
};
//! .
template
class DL_Base
{
protected:
typedef KI KeyInterface;
typedef typename KI::Element Element;
const DL_GroupParameters & GetAbstractGroupParameters() const {return GetKeyInterface().GetAbstractGroupParameters();}
DL_GroupParameters & AccessAbstractGroupParameters() {return AccessKeyInterface().AccessAbstractGroupParameters();}
virtual KeyInterface & AccessKeyInterface() =0;
virtual const KeyInterface & GetKeyInterface() const =0;
};
//! .
template
class DL_DigestSignatureSystemBase : public INTERFACE, public DL_Base
{
public:
unsigned int MaxDigestLength() const {return UINT_MAX;}
unsigned int DigestSignatureLength() const
{
return GetSignatureAlgorithm().RLen(GetAbstractGroupParameters())
+ GetSignatureAlgorithm().SLen(GetAbstractGroupParameters());
}
protected:
virtual const DL_ElgamalLikeSignatureAlgorithm & GetSignatureAlgorithm() const =0;
};
//! .
template
class DL_DigestSignerBase : public DL_DigestSignatureSystemBase >
{
public:
// for validation testing
void RawSign(const Integer &k, const Integer &e, Integer &r, Integer &s) const
{
const DL_ElgamalLikeSignatureAlgorithm &alg = GetSignatureAlgorithm();
const DL_GroupParameters ¶ms = GetAbstractGroupParameters();
const DL_PrivateKey &key = GetKeyInterface();
alg.Sign(params, key.GetPrivateExponent(), k, e, r, s);
}
void SignDigest(RandomNumberGenerator &rng, const byte *digest, unsigned int digestLength, byte *signature) const
{
const DL_ElgamalLikeSignatureAlgorithm &alg = GetSignatureAlgorithm();
const DL_GroupParameters ¶ms = GetAbstractGroupParameters();
const DL_PrivateKey &key = GetKeyInterface();
GetMaterial().DoQuickSanityCheck();
const Integer &q = params.GetSubgroupOrder();
Integer e = alg.EncodeDigest(q.BitCount(), digest, digestLength);
Integer k, r, s;
do {k.Randomize(rng, 1, params.GetSubgroupOrder()-1);}
while (!alg.Sign(params, key.GetPrivateExponent(), k, e, r, s));
unsigned int rLen = alg.RLen(params);
r.Encode(signature, rLen);
s.Encode(signature+rLen, alg.SLen(params));
}
};
//! .
template
class DL_DigestVerifierBase : public DL_DigestSignatureSystemBase >
{
public:
bool VerifyDigest(const byte *digest, unsigned int digestLength, const byte *signature) const
{
const DL_ElgamalLikeSignatureAlgorithm &alg = GetSignatureAlgorithm();
const DL_GroupParameters ¶ms = GetAbstractGroupParameters();
const DL_PublicKey &key = GetKeyInterface();
GetMaterial().DoQuickSanityCheck();
const Integer &q = params.GetSubgroupOrder();
Integer e = alg.EncodeDigest(q.BitCount(), digest, digestLength);
unsigned int rLen = alg.RLen(params);
Integer r(signature, rLen);
Integer s(signature+rLen, alg.SLen(params));
return alg.Verify(params, key, e, r, s);
}
};
//! .
template
class DL_CryptoSystemBase : public PK, public DL_Base
{
public:
typedef typename DL_Base::Element Element;
unsigned int MaxPlaintextLength(unsigned int cipherTextLength) const
{
unsigned int minLen = GetAbstractGroupParameters().GetEncodedElementSize(true);
return cipherTextLength < minLen ? 0 : GetSymmetricEncryptionAlgorithm().GetMaxSymmetricPlaintextLength(cipherTextLength - minLen);
}
unsigned int CiphertextLength(unsigned int plainTextLength) const
{
unsigned int len = GetSymmetricEncryptionAlgorithm().GetSymmetricCiphertextLength(plainTextLength);
return len == 0 ? 0 : GetAbstractGroupParameters().GetEncodedElementSize(true) + len;
}
protected:
virtual const DL_KeyAgreementAlgorithm & GetKeyAgreementAlgorithm() const =0;
virtual const DL_KeyDerivationAlgorithm & GetKeyDerivationAlgorithm() const =0;
virtual const DL_SymmetricEncryptionAlgorithm & GetSymmetricEncryptionAlgorithm() const =0;
};
//! .
template
class DL_DecryptorBase : public DL_CryptoSystemBase >
{
public:
typedef T Element;
DecodingResult Decrypt(const byte *cipherText, unsigned int cipherTextLength, byte *plainText) const
{
try
{
const DL_KeyAgreementAlgorithm &agreeAlg = GetKeyAgreementAlgorithm();
const DL_KeyDerivationAlgorithm &derivAlg = GetKeyDerivationAlgorithm();
const DL_SymmetricEncryptionAlgorithm &encAlg = GetSymmetricEncryptionAlgorithm();
const DL_GroupParameters ¶ms = GetAbstractGroupParameters();
const DL_PrivateKey &key = GetKeyInterface();
Element q = params.DecodeElement(cipherText, true);
unsigned int elementSize = params.GetEncodedElementSize(true);
cipherText += elementSize;
cipherTextLength -= elementSize;
Element z = agreeAlg.AgreeWithStaticPrivateKey(params, q, true, key.GetPrivateExponent());
SecByteBlock derivedKey(encAlg.GetSymmetricKeyLength(encAlg.GetMaxSymmetricPlaintextLength(cipherTextLength)));
derivAlg.Derive(params, derivedKey, derivedKey.size(), z, q);
return encAlg.SymmetricDecrypt(derivedKey, cipherText, cipherTextLength, plainText);
}
catch (DL_BadElement &)
{
return DecodingResult();
}
}
};
//! .
template
class DL_EncryptorBase : public DL_CryptoSystemBase >
{
public:
typedef T Element;
void Encrypt(RandomNumberGenerator &rng, const byte *plainText, unsigned int plainTextLength, byte *cipherText) const
{
const DL_KeyAgreementAlgorithm &agreeAlg = GetKeyAgreementAlgorithm();
const DL_KeyDerivationAlgorithm &derivAlg = GetKeyDerivationAlgorithm();
const DL_SymmetricEncryptionAlgorithm &encAlg = GetSymmetricEncryptionAlgorithm();
const DL_GroupParameters ¶ms = GetAbstractGroupParameters();
const DL_PublicKey &key = GetKeyInterface();
Integer x(rng, Integer::One(), params.GetMaxExponent());
Element q = params.ExponentiateBase(x);
params.EncodeElement(true, q, cipherText);
unsigned int elementSize = params.GetEncodedElementSize(true);
cipherText += elementSize;
Element z = agreeAlg.AgreeWithEphemeralPrivateKey(params, key.GetPublicPrecomputation(), x);
SecByteBlock derivedKey(encAlg.GetSymmetricKeyLength(plainTextLength));
derivAlg.Derive(params, derivedKey, derivedKey.size(), z, q);
encAlg.SymmetricEncrypt(rng, derivedKey, plainText, plainTextLength, cipherText);
}
};
//! .
template
struct DL_SchemeOptionsBase
{
typedef T1 AlgorithmInfo;
typedef T2 GroupParameters;
typedef typename GroupParameters::Element Element;
};
//! .
template
struct DL_KeyedSchemeOptions : public DL_SchemeOptionsBase
{
typedef T2 Keys;
typedef typename Keys::PrivateKey PrivateKey;
typedef typename Keys::PublicKey PublicKey;
};
//! .
template
struct DL_SignatureSchemeOptions : public DL_KeyedSchemeOptions
{
typedef T3 SignatureAlgorithm;
};
//! .
template
struct DL_CryptoSchemeOptions : public DL_KeyedSchemeOptions
{
typedef T3 KeyAgreementAlgorithm;
typedef T4 KeyDerivationAlgorithm;
typedef T5 SymmetricEncryptionAlgorithm;
};
//! .
template
class DL_ObjectImplBase : public AlgorithmImpl
{
public:
typedef SCHEME_OPTIONS SchemeOptions;
typedef KEY KeyClass;
typedef typename KeyClass::Element Element;
PrivateKey & AccessPrivateKey() {return m_key;}
PublicKey & AccessPublicKey() {return m_key;}
// KeyAccessor
const KeyClass & GetKey() const {return m_key;}
KeyClass & AccessKey() {return m_key;}
protected:
typename BASE::KeyInterface & AccessKeyInterface() {return m_key;}
const typename BASE::KeyInterface & GetKeyInterface() const {return m_key;}
private:
KeyClass m_key;
};
//! .
template
class DL_ObjectImpl : public DL_ObjectImplBase
{
public:
typedef typename KEY::Element Element;
protected:
const DL_ElgamalLikeSignatureAlgorithm & GetSignatureAlgorithm() const
{static typename SCHEME_OPTIONS::SignatureAlgorithm a; return a;}
const DL_KeyAgreementAlgorithm & GetKeyAgreementAlgorithm() const
{static typename SCHEME_OPTIONS::KeyAgreementAlgorithm a; return a;}
const DL_KeyDerivationAlgorithm & GetKeyDerivationAlgorithm() const
{static typename SCHEME_OPTIONS::KeyDerivationAlgorithm a; return a;}
const DL_SymmetricEncryptionAlgorithm & GetSymmetricEncryptionAlgorithm() const
{static typename SCHEME_OPTIONS::SymmetricEncryptionAlgorithm a; return a;}
};
//! .
template
class DL_PublicObjectImpl : public DL_ObjectImpl, public PublicKeyCopier
{
public:
void CopyKeyInto(typename SCHEME_OPTIONS::PublicKey &key) const
{key = GetKey();}
};
//! .
template
class DL_PrivateObjectImpl : public DL_ObjectImpl, public PrivateKeyCopier
{
public:
void CopyKeyInto(typename SCHEME_OPTIONS::PublicKey &key) const
{GetKey().MakePublicKey(key);}
void CopyKeyInto(typename SCHEME_OPTIONS::PrivateKey &key) const
{key = GetKey();}
};
//! .
template
class DL_DigestSignerImpl : public DL_PrivateObjectImpl, SCHEME_OPTIONS>
{
};
//! .
template
class DL_DigestVerifierImpl : public DL_PublicObjectImpl, SCHEME_OPTIONS>
{
};
//! .
template
class DL_EncryptorImpl : public DL_PublicObjectImpl, SCHEME_OPTIONS>
{
};
//! .
template
class DL_DecryptorImpl : public DL_PrivateObjectImpl, SCHEME_OPTIONS>
{
};
// ********************************************************
//! .
template
class DL_SimpleKeyAgreementDomainBase : public SimpleKeyAgreementDomain
{
public:
typedef T Element;
CryptoParameters & AccessCryptoParameters() {return AccessAbstractGroupParameters();}
unsigned int AgreedValueLength() const {return GetAbstractGroupParameters().GetEncodedElementSize(false);}
unsigned int PrivateKeyLength() const {return GetAbstractGroupParameters().GetSubgroupOrder().ByteCount();}
unsigned int PublicKeyLength() const {return GetAbstractGroupParameters().GetEncodedElementSize(true);}
void GeneratePrivateKey(RandomNumberGenerator &rng, byte *privateKey) const
{
Integer x(rng, Integer::One(), GetAbstractGroupParameters().GetMaxExponent());
x.Encode(privateKey, PrivateKeyLength());
}
void GeneratePublicKey(RandomNumberGenerator &rng, const byte *privateKey, byte *publicKey) const
{
const DL_GroupParameters ¶ms = GetAbstractGroupParameters();
Integer x(privateKey, PrivateKeyLength());
Element y = params.ExponentiateBase(x);
params.EncodeElement(true, y, publicKey);
}
bool Agree(byte *agreedValue, const byte *privateKey, const byte *otherPublicKey, bool validateOtherPublicKey=true) const
{
try
{
const DL_GroupParameters ¶ms = GetAbstractGroupParameters();
Integer x(privateKey, PrivateKeyLength());
Element w = params.DecodeElement(otherPublicKey, validateOtherPublicKey);
Element z = GetKeyAgreementAlgorithm().AgreeWithStaticPrivateKey(
GetAbstractGroupParameters(), w, validateOtherPublicKey, x);
params.EncodeElement(false, z, agreedValue);
}
catch (DL_BadElement &)
{
return false;
}
return true;
}
const Element &GetGenerator() const {return GetAbstractGroupParameters().GetSubgroupGenerator();}
protected:
virtual const DL_KeyAgreementAlgorithm & GetKeyAgreementAlgorithm() const =0;
virtual DL_GroupParameters & AccessAbstractGroupParameters() =0;
const DL_GroupParameters & GetAbstractGroupParameters() const {return const_cast *>(this)->AccessAbstractGroupParameters();}
};
enum CofactorMultiplicationOption {NO_COFACTOR_MULTIPLICTION, COMPATIBLE_COFACTOR_MULTIPLICTION, INCOMPATIBLE_COFACTOR_MULTIPLICTION};
typedef EnumToType NoCofactorMultiplication;
typedef EnumToType CompatibleCofactorMultiplication;
typedef EnumToType IncompatibleCofactorMultiplication;
//! DH key agreement algorithm
template
class DL_KeyAgreementAlgorithm_DH : public DL_KeyAgreementAlgorithm
{
public:
typedef ELEMENT Element;
static const char *StaticAlgorithmName()
{return COFACTOR_OPTION::ToEnum() == NO_COFACTOR_MULTIPLICTION ? "DH" : "DHC";}
Element AgreeWithEphemeralPrivateKey(const DL_GroupParameters ¶ms, const DL_FixedBasePrecomputation &publicPrecomputation, const Integer &privateExponent) const
{
return publicPrecomputation.Exponentiate(params.GetGroupPrecomputation(),
COFACTOR_OPTION::ToEnum() == INCOMPATIBLE_COFACTOR_MULTIPLICTION ? privateExponent*params.GetCofactor() : privateExponent);
}
Element AgreeWithStaticPrivateKey(const DL_GroupParameters ¶ms, const Element &publicElement, bool validateOtherPublicKey, const Integer &privateExponent) const
{
if (COFACTOR_OPTION::ToEnum() == COMPATIBLE_COFACTOR_MULTIPLICTION)
{
const Integer &k = params.GetCofactor();
return params.ExponentiateElement(publicElement,
ModularArithmetic(params.GetSubgroupOrder()).Divide(privateExponent, k)*k);
}
else if (COFACTOR_OPTION::ToEnum() == INCOMPATIBLE_COFACTOR_MULTIPLICTION)
return params.ExponentiateElement(publicElement, privateExponent*params.GetCofactor());
else
{
assert(COFACTOR_OPTION::ToEnum() == NO_COFACTOR_MULTIPLICTION);
if (!validateOtherPublicKey)
return params.ExponentiateElement(publicElement, privateExponent);
if (params.FastSubgroupCheckAvailable())
{
if (!params.ValidateElement(2, publicElement, NULL))
throw DL_BadElement();
return params.ExponentiateElement(publicElement, privateExponent);
}
else
{
const Integer e[2] = {params.GetSubgroupOrder(), privateExponent};
Element r[2];
params.SimultaneousExponentiate(r, publicElement, e, 2);
if (!params.IsIdentity(r[0]))
throw DL_BadElement();
return r[1];
}
}
}
};
// ********************************************************
//! A template implementing constructors for public key algorithm classes
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::EncryptionPaddingAlgorithm PaddingAlgorithm;
public:
//! see EncryptionStandard for a list of standards
typedef STANDARD Standard;
typedef TF_SchemeOptions SchemeOptions;
static std::string StaticAlgorithmName() {return KEYS::StaticAlgorithmName() + "/" + PaddingAlgorithm::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_SSA;
//! Trapdoor Function Based Signature Scheme With Appendix
template > // VC60 workaround: doesn't work if KEYS is first parameter
class TF_SSA : public KEYS
{
#ifdef __GNUC__
// GCC3 workaround: can't do this typedef in one line
typedef typename STANDARD::SignaturePaddingAlgorithm Type1;
typedef typename Type1::type PaddingAlgorithm;
typedef typename STANDARD::DecoratedHashingAlgorithm Type2;
public:
typedef typename Type2::type DecoratedHashAlgorithm;
#else
// VC60 workaround: using STANDARD directly causes internal compiler error
typedef CryptoStandardTraits Traits;
typedef typename Traits::SignaturePaddingAlgorithm::type PaddingAlgorithm;
public:
typedef typename Traits::DecoratedHashingAlgorithm::type DecoratedHashAlgorithm;
#endif
//! see SignatureStandard for a list of standards
typedef STANDARD Standard;
typedef TF_SchemeOptions SchemeOptions;
static std::string StaticAlgorithmName() {return KEYS::StaticAlgorithmName() + "/" + PaddingAlgorithm::StaticAlgorithmName() + "(" + H::StaticAlgorithmName() + ")";}
//! implements PK_Signer interface
typedef PK_FinalTemplate, DecoratedHashAlgorithm> > Signer;
//! implements PK_Verifier interface
typedef PK_FinalTemplate, DecoratedHashAlgorithm> > Verifier;
};
template
class DL_SSA;
//! Discrete Log Based Signature Scheme With Appendix
template >
class DL_SSA : public KEYS
{
typedef DL_SignatureSchemeOptions SchemeOptions;
public:
static std::string StaticAlgorithmName() {return SA::StaticAlgorithmName() + std::string("/EMSA1(") + H::StaticAlgorithmName() + ")";}
//! implements PK_Signer interface
typedef PK_FinalTemplate, H> > Signer;
//! implements PK_Verifier interface
typedef PK_FinalTemplate, H> > Verifier;
};
//! Discrete Log Based Encryption Scheme
template
class DL_ES : public KEYS
{
typedef DL_CryptoSchemeOptions SchemeOptions;
public:
//! implements PK_Decryptor interface
typedef PK_FinalTemplate > Decryptor;
//! implements PK_Encryptor interface
typedef PK_FinalTemplate > Encryptor;
};
NAMESPACE_END
#endif