summaryrefslogtreecommitdiffstats
path: root/CryptoPP/eccrypto.h
blob: 3530455a30bd55ed31c9ed6215d3675c78744e53 (plain) (blame)
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
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
#ifndef CRYPTOPP_ECCRYPTO_H
#define CRYPTOPP_ECCRYPTO_H

/*! \file
*/

#include "pubkey.h"
#include "integer.h"
#include "asn.h"
#include "hmac.h"
#include "sha.h"
#include "gfpcrypt.h"
#include "dh.h"
#include "mqv.h"
#include "ecp.h"
#include "ec2n.h"

NAMESPACE_BEGIN(CryptoPP)

//! Elliptic Curve Parameters
/*! This class corresponds to the ASN.1 sequence of the same name
    in ANSI X9.62 (also SEC 1).
*/
template <class EC>
class DL_GroupParameters_EC : public DL_GroupParametersImpl<EcPrecomputation<EC> >
{
	typedef DL_GroupParameters_EC<EC> ThisClass;

public:
	typedef EC EllipticCurve;
	typedef typename EllipticCurve::Point Point;
	typedef Point Element;
	typedef IncompatibleCofactorMultiplication DefaultCofactorOption;

	DL_GroupParameters_EC() : m_compress(false), m_encodeAsOID(false) {}
	DL_GroupParameters_EC(const OID &oid)
		: m_compress(false), m_encodeAsOID(false) {Initialize(oid);}
	DL_GroupParameters_EC(const EllipticCurve &ec, const Point &G, const Integer &n, const Integer &k = Integer::Zero())
		: m_compress(false), m_encodeAsOID(false) {Initialize(ec, G, n, k);}
	DL_GroupParameters_EC(BufferedTransformation &bt)
		: m_compress(false), m_encodeAsOID(false) {BERDecode(bt);}

	void Initialize(const EllipticCurve &ec, const Point &G, const Integer &n, const Integer &k = Integer::Zero())
	{
		this->m_groupPrecomputation.SetCurve(ec);
		this->SetSubgroupGenerator(G);
		m_n = n;
		m_k = k;
	}
	void Initialize(const OID &oid);

	// NameValuePairs
	bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const;
	void AssignFrom(const NameValuePairs &source);

	// GeneratibleCryptoMaterial interface
	//! this implementation doesn't actually generate a curve, it just initializes the parameters with existing values
	/*! parameters: (Curve, SubgroupGenerator, SubgroupOrder, Cofactor (optional)), or (GroupOID) */
	void GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs &alg);

	// DL_GroupParameters
	const DL_FixedBasePrecomputation<Element> & GetBasePrecomputation() const {return this->m_gpc;}
	DL_FixedBasePrecomputation<Element> & AccessBasePrecomputation() {return this->m_gpc;}
	const Integer & GetSubgroupOrder() const {return m_n;}
	Integer GetCofactor() const;
	bool ValidateGroup(RandomNumberGenerator &rng, unsigned int level) const;
	bool ValidateElement(unsigned int level, const Element &element, const DL_FixedBasePrecomputation<Element> *precomp) const;
	bool FastSubgroupCheckAvailable() const {return false;}
	void EncodeElement(bool reversible, const Element &element, byte *encoded) const
	{
		if (reversible)
			GetCurve().EncodePoint(encoded, element, m_compress);
		else
			element.x.Encode(encoded, GetEncodedElementSize(false));
	}
	unsigned int GetEncodedElementSize(bool reversible) const
	{
		if (reversible)
			return GetCurve().EncodedPointSize(m_compress);
		else
			return GetCurve().GetField().MaxElementByteLength();
	}
	Element DecodeElement(const byte *encoded, bool checkForGroupMembership) const
	{
		Point result;
		if (!GetCurve().DecodePoint(result, encoded, GetEncodedElementSize(true)))
			throw DL_BadElement();
		if (checkForGroupMembership && !ValidateElement(1, result, NULL))
			throw DL_BadElement();
		return result;
	}
	Integer ConvertElementToInteger(const Element &element) const;
	Integer GetMaxExponent() const {return GetSubgroupOrder()-1;}
	bool IsIdentity(const Element &element) const {return element.identity;}
	void SimultaneousExponentiate(Element *results, const Element &base, const Integer *exponents, unsigned int exponentsCount) const;
	static std::string CRYPTOPP_API StaticAlgorithmNamePrefix() {return "EC";}

	// ASN1Key
	OID GetAlgorithmID() const;

	// used by MQV
	Element MultiplyElements(const Element &a, const Element &b) const;
	Element CascadeExponentiate(const Element &element1, const Integer &exponent1, const Element &element2, const Integer &exponent2) const;

	// non-inherited

	// enumerate OIDs for recommended parameters, use OID() to get first one
	static OID CRYPTOPP_API GetNextRecommendedParametersOID(const OID &oid);

	void BERDecode(BufferedTransformation &bt);
	void DEREncode(BufferedTransformation &bt) const;

	void SetPointCompression(bool compress) {m_compress = compress;}
	bool GetPointCompression() const {return m_compress;}

	void SetEncodeAsOID(bool encodeAsOID) {m_encodeAsOID = encodeAsOID;}
	bool GetEncodeAsOID() const {return m_encodeAsOID;}

	const EllipticCurve& GetCurve() const {return this->m_groupPrecomputation.GetCurve();}

	bool operator==(const ThisClass &rhs) const
		{return this->m_groupPrecomputation.GetCurve() == rhs.m_groupPrecomputation.GetCurve() && this->m_gpc.GetBase(this->m_groupPrecomputation) == rhs.m_gpc.GetBase(rhs.m_groupPrecomputation);}

#ifdef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY
	const Point& GetBasePoint() const {return GetSubgroupGenerator();}
	const Integer& GetBasePointOrder() const {return GetSubgroupOrder();}
	void LoadRecommendedParameters(const OID &oid) {Initialize(oid);}
#endif

protected:
	unsigned int FieldElementLength() const {return GetCurve().GetField().MaxElementByteLength();}
	unsigned int ExponentLength() const {return m_n.ByteCount();}

	OID m_oid;			// set if parameters loaded from a recommended curve
	Integer m_n;		// order of base point
	bool m_compress, m_encodeAsOID;
	mutable Integer m_k;		// cofactor
};

//! EC public key
template <class EC>
class DL_PublicKey_EC : public DL_PublicKeyImpl<DL_GroupParameters_EC<EC> >
{
public:
	typedef typename EC::Point Element;

	void Initialize(const DL_GroupParameters_EC<EC> &params, const Element &Q)
		{this->AccessGroupParameters() = params; this->SetPublicElement(Q);}
	void Initialize(const EC &ec, const Element &G, const Integer &n, const Element &Q)
		{this->AccessGroupParameters().Initialize(ec, G, n); this->SetPublicElement(Q);}

	// X509PublicKey
	void BERDecodePublicKey(BufferedTransformation &bt, bool parametersPresent, size_t size);
	void DEREncodePublicKey(BufferedTransformation &bt) const;
};

//! EC private key
template <class EC>
class DL_PrivateKey_EC : public DL_PrivateKeyImpl<DL_GroupParameters_EC<EC> >
{
public:
	typedef typename EC::Point Element;

	void Initialize(const DL_GroupParameters_EC<EC> &params, const Integer &x)
		{this->AccessGroupParameters() = params; this->SetPrivateExponent(x);}
	void Initialize(const EC &ec, const Element &G, const Integer &n, const Integer &x)
		{this->AccessGroupParameters().Initialize(ec, G, n); this->SetPrivateExponent(x);}
	void Initialize(RandomNumberGenerator &rng, const DL_GroupParameters_EC<EC> &params)
		{this->GenerateRandom(rng, params);}
	void Initialize(RandomNumberGenerator &rng, const EC &ec, const Element &G, const Integer &n)
		{this->GenerateRandom(rng, DL_GroupParameters_EC<EC>(ec, G, n));}

	// PKCS8PrivateKey
	void BERDecodePrivateKey(BufferedTransformation &bt, bool parametersPresent, size_t size);
	void DEREncodePrivateKey(BufferedTransformation &bt) const;
};

//! Elliptic Curve Diffie-Hellman, AKA <a href="http://www.weidai.com/scan-mirror/ka.html#ECDH">ECDH</a>
template <class EC, class COFACTOR_OPTION = CPP_TYPENAME DL_GroupParameters_EC<EC>::DefaultCofactorOption>
struct ECDH
{
	typedef DH_Domain<DL_GroupParameters_EC<EC>, COFACTOR_OPTION> Domain;
};

/// Elliptic Curve Menezes-Qu-Vanstone, AKA <a href="http://www.weidai.com/scan-mirror/ka.html#ECMQV">ECMQV</a>
template <class EC, class COFACTOR_OPTION = CPP_TYPENAME DL_GroupParameters_EC<EC>::DefaultCofactorOption>
struct ECMQV
{
	typedef MQV_Domain<DL_GroupParameters_EC<EC>, COFACTOR_OPTION> Domain;
};

//! EC keys
template <class EC>
struct DL_Keys_EC
{
	typedef DL_PublicKey_EC<EC> PublicKey;
	typedef DL_PrivateKey_EC<EC> PrivateKey;
};

template <class EC, class H>
struct ECDSA;

//! ECDSA keys
template <class EC>
struct DL_Keys_ECDSA
{
	typedef DL_PublicKey_EC<EC> PublicKey;
	typedef DL_PrivateKey_WithSignaturePairwiseConsistencyTest<DL_PrivateKey_EC<EC>, ECDSA<EC, SHA256> > PrivateKey;
};

//! ECDSA algorithm
template <class EC>
class DL_Algorithm_ECDSA : public DL_Algorithm_GDSA<typename EC::Point>
{
public:
	static const char * CRYPTOPP_API StaticAlgorithmName() {return "ECDSA";}
};

//! ECNR algorithm
template <class EC>
class DL_Algorithm_ECNR : public DL_Algorithm_NR<typename EC::Point>
{
public:
	static const char * CRYPTOPP_API StaticAlgorithmName() {return "ECNR";}
};

//! <a href="http://www.weidai.com/scan-mirror/sig.html#ECDSA">ECDSA</a>
template <class EC, class H>
struct ECDSA : public DL_SS<DL_Keys_ECDSA<EC>, DL_Algorithm_ECDSA<EC>, DL_SignatureMessageEncodingMethod_DSA, H>
{
};

//! ECNR
template <class EC, class H = SHA>
struct ECNR : public DL_SS<DL_Keys_EC<EC>, DL_Algorithm_ECNR<EC>, DL_SignatureMessageEncodingMethod_NR, H>
{
};

//! Elliptic Curve Integrated Encryption Scheme, AKA <a href="http://www.weidai.com/scan-mirror/ca.html#ECIES">ECIES</a>
/*! Default to (NoCofactorMultiplication and DHAES_MODE = false) for compatibilty with SEC1 and Crypto++ 4.2.
	The combination of (IncompatibleCofactorMultiplication and DHAES_MODE = true) is recommended for best
	efficiency and security. */
template <class EC, class COFACTOR_OPTION = NoCofactorMultiplication, bool DHAES_MODE = false>
struct ECIES
	: public DL_ES<
		DL_Keys_EC<EC>,
		DL_KeyAgreementAlgorithm_DH<typename EC::Point, COFACTOR_OPTION>,
		DL_KeyDerivationAlgorithm_P1363<typename EC::Point, DHAES_MODE, P1363_KDF2<SHA1> >,
		DL_EncryptionAlgorithm_Xor<HMAC<SHA1>, DHAES_MODE>,
		ECIES<EC> >
{
	static std::string CRYPTOPP_API StaticAlgorithmName() {return "ECIES";}	// TODO: fix this after name is standardized
};

NAMESPACE_END

#ifdef CRYPTOPP_MANUALLY_INSTANTIATE_TEMPLATES
#include "eccrypto.cpp"
#endif

NAMESPACE_BEGIN(CryptoPP)

CRYPTOPP_DLL_TEMPLATE_CLASS DL_GroupParameters_EC<ECP>;
CRYPTOPP_DLL_TEMPLATE_CLASS DL_GroupParameters_EC<EC2N>;
CRYPTOPP_DLL_TEMPLATE_CLASS DL_PublicKeyImpl<DL_GroupParameters_EC<ECP> >;
CRYPTOPP_DLL_TEMPLATE_CLASS DL_PublicKeyImpl<DL_GroupParameters_EC<EC2N> >;
CRYPTOPP_DLL_TEMPLATE_CLASS DL_PublicKey_EC<ECP>;
CRYPTOPP_DLL_TEMPLATE_CLASS DL_PublicKey_EC<EC2N>;
CRYPTOPP_DLL_TEMPLATE_CLASS DL_PrivateKeyImpl<DL_GroupParameters_EC<ECP> >;
CRYPTOPP_DLL_TEMPLATE_CLASS DL_PrivateKeyImpl<DL_GroupParameters_EC<EC2N> >;
CRYPTOPP_DLL_TEMPLATE_CLASS DL_PrivateKey_EC<ECP>;
CRYPTOPP_DLL_TEMPLATE_CLASS DL_PrivateKey_EC<EC2N>;
CRYPTOPP_DLL_TEMPLATE_CLASS DL_Algorithm_GDSA<ECP::Point>;
CRYPTOPP_DLL_TEMPLATE_CLASS DL_Algorithm_GDSA<EC2N::Point>;
CRYPTOPP_DLL_TEMPLATE_CLASS DL_PrivateKey_WithSignaturePairwiseConsistencyTest<DL_PrivateKey_EC<ECP>, ECDSA<ECP, SHA256> >;
CRYPTOPP_DLL_TEMPLATE_CLASS DL_PrivateKey_WithSignaturePairwiseConsistencyTest<DL_PrivateKey_EC<EC2N>, ECDSA<EC2N, SHA256> >;

NAMESPACE_END

#endif