summaryrefslogtreecommitdiff
path: root/ecp.h
blob: 471dc71cce3e863efbf7b9859d2b77db4a817440 (plain)
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
// ecp.h - written and placed in the public domain by Wei Dai

//! \file ecp.h
//! \brief Classes for Elliptic Curves over prime fields

#ifndef CRYPTOPP_ECP_H
#define CRYPTOPP_ECP_H

#include "cryptlib.h"
#include "integer.h"
#include "algebra.h"
#include "modarith.h"
#include "eprecomp.h"
#include "smartptr.h"
#include "pubkey.h"

NAMESPACE_BEGIN(CryptoPP)

//! \class ECPPoint
//! \brief Elliptical Curve Point over GF(p), where p is prime
struct CRYPTOPP_DLL ECPPoint
{
#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
	virtual ~ECPPoint() {}
#endif

	//! \brief Construct an ECPPoint
	//! \details identity is set to <tt>true</tt>
	ECPPoint() : identity(true) {}

	//! \brief Construct an ECPPoint from coordinates
	//! \details identity is set to <tt>false</tt>
	ECPPoint(const Integer &x, const Integer &y)
		: x(x), y(y), identity(false) {}

	bool operator==(const ECPPoint &t) const
		{return (identity && t.identity) || (!identity && !t.identity && x==t.x && y==t.y);}
	bool operator< (const ECPPoint &t) const
		{return identity ? !t.identity : (!t.identity && (x<t.x || (x==t.x && y<t.y)));}

	Integer x, y;
	bool identity;
};

CRYPTOPP_DLL_TEMPLATE_CLASS AbstractGroup<ECPPoint>;

//! \class ECP
//! \brief Elliptic Curve over GF(p), where p is prime
class CRYPTOPP_DLL ECP : public AbstractGroup<ECPPoint>
{
public:
	typedef ModularArithmetic Field;
	typedef Integer FieldElement;
	typedef ECPPoint Point;

#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
	virtual ~ECP() {}
#endif

	//! \brief Construct an ECP
	ECP() {}

	//! \brief Copy construct an ECP
	//! \param ecp the other ECP object
	//! \param convertToMontgomeryRepresentation flag indicating if the curve should be converted to a MontgomeryRepresentation
	//! \sa ModularArithmetic, MontgomeryRepresentation
	ECP(const ECP &ecp, bool convertToMontgomeryRepresentation = false);

	//! \brief Construct an ECP
	//! \param modulus the prime modulus
	//! \param a Field::Element
	//! \param b Field::Element
	ECP(const Integer &modulus, const FieldElement &a, const FieldElement &b)
		: m_fieldPtr(new Field(modulus)), m_a(a.IsNegative() ? modulus+a : a), m_b(b) {}

	//! \brief Construct an ECP from BER encoded parameters
	//! \param bt BufferedTransformation derived object
	//! \details This constructor will decode and extract the the fields fieldID and curve of the sequence ECParameters
	ECP(BufferedTransformation &bt);

	//! \brief Encode the fields fieldID and curve of the sequence ECParameters
	//! \param bt BufferedTransformation derived object
	void DEREncode(BufferedTransformation &bt) const;

	bool Equal(const Point &P, const Point &Q) const;
	const Point& Identity() const;
	const Point& Inverse(const Point &P) const;
	bool InversionIsFast() const {return true;}
	const Point& Add(const Point &P, const Point &Q) const;
	const Point& Double(const Point &P) const;
	Point ScalarMultiply(const Point &P, const Integer &k) const;
	Point CascadeScalarMultiply(const Point &P, const Integer &k1, const Point &Q, const Integer &k2) const;
	void SimultaneousMultiply(Point *results, const Point &base, const Integer *exponents, unsigned int exponentsCount) const;

	Point Multiply(const Integer &k, const Point &P) const
		{return ScalarMultiply(P, k);}
	Point CascadeMultiply(const Integer &k1, const Point &P, const Integer &k2, const Point &Q) const
		{return CascadeScalarMultiply(P, k1, Q, k2);}

	bool ValidateParameters(RandomNumberGenerator &rng, unsigned int level=3) const;
	bool VerifyPoint(const Point &P) const;

	unsigned int EncodedPointSize(bool compressed = false) const
		{return 1 + (compressed?1:2)*GetField().MaxElementByteLength();}
	// returns false if point is compressed and not valid (doesn't check if uncompressed)
	bool DecodePoint(Point &P, BufferedTransformation &bt, size_t len) const;
	bool DecodePoint(Point &P, const byte *encodedPoint, size_t len) const;
	void EncodePoint(byte *encodedPoint, const Point &P, bool compressed) const;
	void EncodePoint(BufferedTransformation &bt, const Point &P, bool compressed) const;

	Point BERDecodePoint(BufferedTransformation &bt) const;
	void DEREncodePoint(BufferedTransformation &bt, const Point &P, bool compressed) const;

	Integer FieldSize() const {return GetField().GetModulus();}
	const Field & GetField() const {return *m_fieldPtr;}
	const FieldElement & GetA() const {return m_a;}
	const FieldElement & GetB() const {return m_b;}

	bool operator==(const ECP &rhs) const
		{return GetField() == rhs.GetField() && m_a == rhs.m_a && m_b == rhs.m_b;}

private:
	clonable_ptr<Field> m_fieldPtr;
	FieldElement m_a, m_b;
	mutable Point m_R;
};

CRYPTOPP_DLL_TEMPLATE_CLASS DL_FixedBasePrecomputationImpl<ECP::Point>;
CRYPTOPP_DLL_TEMPLATE_CLASS DL_GroupPrecomputation<ECP::Point>;

//! \class EcPrecomputation
//! \brief Elliptic Curve precomputation
//! \tparam EC elliptic curve field
template <class EC> class EcPrecomputation;

//! \class EcPrecomputation<ECP>
//! \brief ECP precomputation specialization
//! \details Implementation of <tt>DL_GroupPrecomputation<ECP::Point></tt> with input and output
//!   conversions for Montgomery modular multiplication.
//! \sa DL_GroupPrecomputation, ModularArithmetic, MontgomeryRepresentation
template<> class EcPrecomputation<ECP> : public DL_GroupPrecomputation<ECP::Point>
{
public:
	typedef ECP EllipticCurve;

#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
	virtual ~EcPrecomputation() {}
#endif

	// DL_GroupPrecomputation
	bool NeedConversions() const {return true;}
	Element ConvertIn(const Element &P) const
		{return P.identity ? P : ECP::Point(m_ec->GetField().ConvertIn(P.x), m_ec->GetField().ConvertIn(P.y));};
	Element ConvertOut(const Element &P) const
		{return P.identity ? P : ECP::Point(m_ec->GetField().ConvertOut(P.x), m_ec->GetField().ConvertOut(P.y));}
	const AbstractGroup<Element> & GetGroup() const {return *m_ec;}
	Element BERDecodeElement(BufferedTransformation &bt) const {return m_ec->BERDecodePoint(bt);}
	void DEREncodeElement(BufferedTransformation &bt, const Element &v) const {m_ec->DEREncodePoint(bt, v, false);}

	// non-inherited
	void SetCurve(const ECP &ec)
	{
		m_ec.reset(new ECP(ec, true));
		m_ecOriginal = ec;
	}
	const ECP & GetCurve() const {return *m_ecOriginal;}

private:
	value_ptr<ECP> m_ec, m_ecOriginal;
};

NAMESPACE_END

#endif