Crypto++
|
00001 #ifndef CRYPTOPP_ECCRYPTO_H 00002 #define CRYPTOPP_ECCRYPTO_H 00003 00004 /*! \file 00005 */ 00006 00007 #include "pubkey.h" 00008 #include "integer.h" 00009 #include "asn.h" 00010 #include "hmac.h" 00011 #include "sha.h" 00012 #include "gfpcrypt.h" 00013 #include "dh.h" 00014 #include "mqv.h" 00015 #include "ecp.h" 00016 #include "ec2n.h" 00017 00018 NAMESPACE_BEGIN(CryptoPP) 00019 00020 //! Elliptic Curve Parameters 00021 /*! This class corresponds to the ASN.1 sequence of the same name 00022 in ANSI X9.62 (also SEC 1). 00023 */ 00024 template <class EC> 00025 class DL_GroupParameters_EC : public DL_GroupParametersImpl<EcPrecomputation<EC> > 00026 { 00027 typedef DL_GroupParameters_EC<EC> ThisClass; 00028 00029 public: 00030 typedef EC EllipticCurve; 00031 typedef typename EllipticCurve::Point Point; 00032 typedef Point Element; 00033 typedef IncompatibleCofactorMultiplication DefaultCofactorOption; 00034 00035 DL_GroupParameters_EC() : m_compress(false), m_encodeAsOID(false) {} 00036 DL_GroupParameters_EC(const OID &oid) 00037 : m_compress(false), m_encodeAsOID(false) {Initialize(oid);} 00038 DL_GroupParameters_EC(const EllipticCurve &ec, const Point &G, const Integer &n, const Integer &k = Integer::Zero()) 00039 : m_compress(false), m_encodeAsOID(false) {Initialize(ec, G, n, k);} 00040 DL_GroupParameters_EC(BufferedTransformation &bt) 00041 : m_compress(false), m_encodeAsOID(false) {BERDecode(bt);} 00042 00043 void Initialize(const EllipticCurve &ec, const Point &G, const Integer &n, const Integer &k = Integer::Zero()) 00044 { 00045 this->m_groupPrecomputation.SetCurve(ec); 00046 this->SetSubgroupGenerator(G); 00047 m_n = n; 00048 m_k = k; 00049 } 00050 void Initialize(const OID &oid); 00051 00052 // NameValuePairs 00053 bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const; 00054 void AssignFrom(const NameValuePairs &source); 00055 00056 // GeneratibleCryptoMaterial interface 00057 //! this implementation doesn't actually generate a curve, it just initializes the parameters with existing values 00058 /*! parameters: (Curve, SubgroupGenerator, SubgroupOrder, Cofactor (optional)), or (GroupOID) */ 00059 void GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs &alg); 00060 00061 // DL_GroupParameters 00062 const DL_FixedBasePrecomputation<Element> & GetBasePrecomputation() const {return this->m_gpc;} 00063 DL_FixedBasePrecomputation<Element> & AccessBasePrecomputation() {return this->m_gpc;} 00064 const Integer & GetSubgroupOrder() const {return m_n;} 00065 Integer GetCofactor() const; 00066 bool ValidateGroup(RandomNumberGenerator &rng, unsigned int level) const; 00067 bool ValidateElement(unsigned int level, const Element &element, const DL_FixedBasePrecomputation<Element> *precomp) const; 00068 bool FastSubgroupCheckAvailable() const {return false;} 00069 void EncodeElement(bool reversible, const Element &element, byte *encoded) const 00070 { 00071 if (reversible) 00072 GetCurve().EncodePoint(encoded, element, m_compress); 00073 else 00074 element.x.Encode(encoded, GetEncodedElementSize(false)); 00075 } 00076 unsigned int GetEncodedElementSize(bool reversible) const 00077 { 00078 if (reversible) 00079 return GetCurve().EncodedPointSize(m_compress); 00080 else 00081 return GetCurve().GetField().MaxElementByteLength(); 00082 } 00083 Element DecodeElement(const byte *encoded, bool checkForGroupMembership) const 00084 { 00085 Point result; 00086 if (!GetCurve().DecodePoint(result, encoded, GetEncodedElementSize(true))) 00087 throw DL_BadElement(); 00088 if (checkForGroupMembership && !ValidateElement(1, result, NULL)) 00089 throw DL_BadElement(); 00090 return result; 00091 } 00092 Integer ConvertElementToInteger(const Element &element) const; 00093 Integer GetMaxExponent() const {return GetSubgroupOrder()-1;} 00094 bool IsIdentity(const Element &element) const {return element.identity;} 00095 void SimultaneousExponentiate(Element *results, const Element &base, const Integer *exponents, unsigned int exponentsCount) const; 00096 static std::string CRYPTOPP_API StaticAlgorithmNamePrefix() {return "EC";} 00097 00098 // ASN1Key 00099 OID GetAlgorithmID() const; 00100 00101 // used by MQV 00102 Element MultiplyElements(const Element &a, const Element &b) const; 00103 Element CascadeExponentiate(const Element &element1, const Integer &exponent1, const Element &element2, const Integer &exponent2) const; 00104 00105 // non-inherited 00106 00107 // enumerate OIDs for recommended parameters, use OID() to get first one 00108 static OID CRYPTOPP_API GetNextRecommendedParametersOID(const OID &oid); 00109 00110 void BERDecode(BufferedTransformation &bt); 00111 void DEREncode(BufferedTransformation &bt) const; 00112 00113 void SetPointCompression(bool compress) {m_compress = compress;} 00114 bool GetPointCompression() const {return m_compress;} 00115 00116 void SetEncodeAsOID(bool encodeAsOID) {m_encodeAsOID = encodeAsOID;} 00117 bool GetEncodeAsOID() const {return m_encodeAsOID;} 00118 00119 const EllipticCurve& GetCurve() const {return this->m_groupPrecomputation.GetCurve();} 00120 00121 bool operator==(const ThisClass &rhs) const 00122 {return this->m_groupPrecomputation.GetCurve() == rhs.m_groupPrecomputation.GetCurve() && this->m_gpc.GetBase(this->m_groupPrecomputation) == rhs.m_gpc.GetBase(rhs.m_groupPrecomputation);} 00123 00124 #ifdef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY 00125 const Point& GetBasePoint() const {return GetSubgroupGenerator();} 00126 const Integer& GetBasePointOrder() const {return GetSubgroupOrder();} 00127 void LoadRecommendedParameters(const OID &oid) {Initialize(oid);} 00128 #endif 00129 00130 protected: 00131 unsigned int FieldElementLength() const {return GetCurve().GetField().MaxElementByteLength();} 00132 unsigned int ExponentLength() const {return m_n.ByteCount();} 00133 00134 OID m_oid; // set if parameters loaded from a recommended curve 00135 Integer m_n; // order of base point 00136 bool m_compress, m_encodeAsOID; 00137 mutable Integer m_k; // cofactor 00138 }; 00139 00140 //! EC public key 00141 template <class EC> 00142 class DL_PublicKey_EC : public DL_PublicKeyImpl<DL_GroupParameters_EC<EC> > 00143 { 00144 public: 00145 typedef typename EC::Point Element; 00146 00147 void Initialize(const DL_GroupParameters_EC<EC> ¶ms, const Element &Q) 00148 {this->AccessGroupParameters() = params; this->SetPublicElement(Q);} 00149 void Initialize(const EC &ec, const Element &G, const Integer &n, const Element &Q) 00150 {this->AccessGroupParameters().Initialize(ec, G, n); this->SetPublicElement(Q);} 00151 00152 // X509PublicKey 00153 void BERDecodePublicKey(BufferedTransformation &bt, bool parametersPresent, size_t size); 00154 void DEREncodePublicKey(BufferedTransformation &bt) const; 00155 }; 00156 00157 //! EC private key 00158 template <class EC> 00159 class DL_PrivateKey_EC : public DL_PrivateKeyImpl<DL_GroupParameters_EC<EC> > 00160 { 00161 public: 00162 typedef typename EC::Point Element; 00163 00164 void Initialize(const DL_GroupParameters_EC<EC> ¶ms, const Integer &x) 00165 {this->AccessGroupParameters() = params; this->SetPrivateExponent(x);} 00166 void Initialize(const EC &ec, const Element &G, const Integer &n, const Integer &x) 00167 {this->AccessGroupParameters().Initialize(ec, G, n); this->SetPrivateExponent(x);} 00168 void Initialize(RandomNumberGenerator &rng, const DL_GroupParameters_EC<EC> ¶ms) 00169 {this->GenerateRandom(rng, params);} 00170 void Initialize(RandomNumberGenerator &rng, const EC &ec, const Element &G, const Integer &n) 00171 {this->GenerateRandom(rng, DL_GroupParameters_EC<EC>(ec, G, n));} 00172 00173 // PKCS8PrivateKey 00174 void BERDecodePrivateKey(BufferedTransformation &bt, bool parametersPresent, size_t size); 00175 void DEREncodePrivateKey(BufferedTransformation &bt) const; 00176 }; 00177 00178 //! Elliptic Curve Diffie-Hellman, AKA <a href="http://www.weidai.com/scan-mirror/ka.html#ECDH">ECDH</a> 00179 template <class EC, class COFACTOR_OPTION = CPP_TYPENAME DL_GroupParameters_EC<EC>::DefaultCofactorOption> 00180 struct ECDH 00181 { 00182 typedef DH_Domain<DL_GroupParameters_EC<EC>, COFACTOR_OPTION> Domain; 00183 }; 00184 00185 /// Elliptic Curve Menezes-Qu-Vanstone, AKA <a href="http://www.weidai.com/scan-mirror/ka.html#ECMQV">ECMQV</a> 00186 template <class EC, class COFACTOR_OPTION = CPP_TYPENAME DL_GroupParameters_EC<EC>::DefaultCofactorOption> 00187 struct ECMQV 00188 { 00189 typedef MQV_Domain<DL_GroupParameters_EC<EC>, COFACTOR_OPTION> Domain; 00190 }; 00191 00192 //! EC keys 00193 template <class EC> 00194 struct DL_Keys_EC 00195 { 00196 typedef DL_PublicKey_EC<EC> PublicKey; 00197 typedef DL_PrivateKey_EC<EC> PrivateKey; 00198 }; 00199 00200 template <class EC, class H> 00201 struct ECDSA; 00202 00203 //! ECDSA keys 00204 template <class EC> 00205 struct DL_Keys_ECDSA 00206 { 00207 typedef DL_PublicKey_EC<EC> PublicKey; 00208 typedef DL_PrivateKey_WithSignaturePairwiseConsistencyTest<DL_PrivateKey_EC<EC>, ECDSA<EC, SHA256> > PrivateKey; 00209 }; 00210 00211 //! ECDSA algorithm 00212 template <class EC> 00213 class DL_Algorithm_ECDSA : public DL_Algorithm_GDSA<typename EC::Point> 00214 { 00215 public: 00216 static const char * CRYPTOPP_API StaticAlgorithmName() {return "ECDSA";} 00217 }; 00218 00219 //! ECNR algorithm 00220 template <class EC> 00221 class DL_Algorithm_ECNR : public DL_Algorithm_NR<typename EC::Point> 00222 { 00223 public: 00224 static const char * CRYPTOPP_API StaticAlgorithmName() {return "ECNR";} 00225 }; 00226 00227 //! <a href="http://www.weidai.com/scan-mirror/sig.html#ECDSA">ECDSA</a> 00228 template <class EC, class H> 00229 struct ECDSA : public DL_SS<DL_Keys_ECDSA<EC>, DL_Algorithm_ECDSA<EC>, DL_SignatureMessageEncodingMethod_DSA, H> 00230 { 00231 }; 00232 00233 //! ECNR 00234 template <class EC, class H = SHA> 00235 struct ECNR : public DL_SS<DL_Keys_EC<EC>, DL_Algorithm_ECNR<EC>, DL_SignatureMessageEncodingMethod_NR, H> 00236 { 00237 }; 00238 00239 //! Elliptic Curve Integrated Encryption Scheme, AKA <a href="http://www.weidai.com/scan-mirror/ca.html#ECIES">ECIES</a> 00240 /*! Default to (NoCofactorMultiplication and DHAES_MODE = false) for compatibilty with SEC1 and Crypto++ 4.2. 00241 The combination of (IncompatibleCofactorMultiplication and DHAES_MODE = true) is recommended for best 00242 efficiency and security. */ 00243 template <class EC, class COFACTOR_OPTION = NoCofactorMultiplication, bool DHAES_MODE = false> 00244 struct ECIES 00245 : public DL_ES< 00246 DL_Keys_EC<EC>, 00247 DL_KeyAgreementAlgorithm_DH<typename EC::Point, COFACTOR_OPTION>, 00248 DL_KeyDerivationAlgorithm_P1363<typename EC::Point, DHAES_MODE, P1363_KDF2<SHA1> >, 00249 DL_EncryptionAlgorithm_Xor<HMAC<SHA1>, DHAES_MODE>, 00250 ECIES<EC> > 00251 { 00252 static std::string CRYPTOPP_API StaticAlgorithmName() {return "ECIES";} // TODO: fix this after name is standardized 00253 }; 00254 00255 NAMESPACE_END 00256 00257 #ifdef CRYPTOPP_MANUALLY_INSTANTIATE_TEMPLATES 00258 #include "eccrypto.cpp" 00259 #endif 00260 00261 NAMESPACE_BEGIN(CryptoPP) 00262 00263 CRYPTOPP_DLL_TEMPLATE_CLASS DL_GroupParameters_EC<ECP>; 00264 CRYPTOPP_DLL_TEMPLATE_CLASS DL_GroupParameters_EC<EC2N>; 00265 CRYPTOPP_DLL_TEMPLATE_CLASS DL_PublicKeyImpl<DL_GroupParameters_EC<ECP> >; 00266 CRYPTOPP_DLL_TEMPLATE_CLASS DL_PublicKeyImpl<DL_GroupParameters_EC<EC2N> >; 00267 CRYPTOPP_DLL_TEMPLATE_CLASS DL_PublicKey_EC<ECP>; 00268 CRYPTOPP_DLL_TEMPLATE_CLASS DL_PublicKey_EC<EC2N>; 00269 CRYPTOPP_DLL_TEMPLATE_CLASS DL_PrivateKeyImpl<DL_GroupParameters_EC<ECP> >; 00270 CRYPTOPP_DLL_TEMPLATE_CLASS DL_PrivateKeyImpl<DL_GroupParameters_EC<EC2N> >; 00271 CRYPTOPP_DLL_TEMPLATE_CLASS DL_PrivateKey_EC<ECP>; 00272 CRYPTOPP_DLL_TEMPLATE_CLASS DL_PrivateKey_EC<EC2N>; 00273 CRYPTOPP_DLL_TEMPLATE_CLASS DL_Algorithm_GDSA<ECP::Point>; 00274 CRYPTOPP_DLL_TEMPLATE_CLASS DL_Algorithm_GDSA<EC2N::Point>; 00275 CRYPTOPP_DLL_TEMPLATE_CLASS DL_PrivateKey_WithSignaturePairwiseConsistencyTest<DL_PrivateKey_EC<ECP>, ECDSA<ECP, SHA256> >; 00276 CRYPTOPP_DLL_TEMPLATE_CLASS DL_PrivateKey_WithSignaturePairwiseConsistencyTest<DL_PrivateKey_EC<EC2N>, ECDSA<EC2N, SHA256> >; 00277 00278 NAMESPACE_END 00279 00280 #endif