00001 #ifndef CRYPTOPP_ECCRYPTO_H
00002 #define CRYPTOPP_ECCRTPTO_H
00003
00027 #include "pubkey.h"
00028 #include "integer.h"
00029 #include "asn.h"
00030 #include "hmac.h"
00031 #include "sha.h"
00032
00033 NAMESPACE_BEGIN(CryptoPP)
00034
00038 enum ECSignatureScheme
00039 {
00040 ECNR,
00041 ECDSA
00042 };
00043
00044 template <class T> class EcPrecomputation;
00045
00047
00050 template <class EC>
00051 class ECParameters : virtual public PK_Precomputation
00052 {
00053 public:
00054 typedef typename EC::Point Point;
00055
00056 ECParameters() : m_compress(false), m_encodeAsOID(false) {}
00057 ECParameters(const OID &oid)
00058 : m_compress(false), m_encodeAsOID(false) {LoadRecommendedParameters(oid);}
00059 ECParameters(const EC &ec, const Point &G, const Integer &n)
00060 : m_ec(ec), m_G(G), m_Gpc(*m_ec, G), m_n(n), m_cofactorPresent(false), m_compress(false), m_encodeAsOID(false) {}
00061 ECParameters(const EC &ec, const Point &G, const Integer &n, const Integer &k)
00062 : m_ec(ec), m_G(G), m_Gpc(*m_ec, G), m_n(n), m_cofactorPresent(true), m_compress(false), m_encodeAsOID(false), m_k(k) {}
00063 ECParameters(BufferedTransformation &bt)
00064 : m_compress(false), m_encodeAsOID(false) {BERDecode(bt);}
00065
00066
00067 static OID GetNextRecommendedParametersOID(const OID &oid);
00068 void LoadRecommendedParameters(const OID &oid);
00069
00070 void BERDecode(BufferedTransformation &bt);
00071 void DEREncode(BufferedTransformation &bt) const;
00072
00073 bool ValidateParameters(RandomNumberGenerator &rng) const;
00074
00075 void Precompute(unsigned int precomputationStorage=16);
00076 void LoadPrecomputation(BufferedTransformation &storedPrecomputation);
00077 void SavePrecomputation(BufferedTransformation &storedPrecomputation) const;
00078
00079 void SetPointCompression(bool compress) {m_compress = compress;}
00080 bool GetPointCompression() const {return m_compress;}
00081
00082 void SetEncodeAsOID(bool encodeAsOID) {m_encodeAsOID = encodeAsOID;}
00083 bool GetEncodeAsOID() const {return m_encodeAsOID;}
00084
00085 const EC& GetCurve() const {return *m_ec;}
00086 const Point& GetBasePoint() const {return m_G;}
00087 const Integer& GetBasePointOrder() const {return m_n;}
00088 const bool CofactorPresent() const {return m_cofactorPresent;}
00089 const Integer& GetCofactor() const {return m_k;}
00090
00091 protected:
00092 unsigned int EncodedPointSize() const {return m_ec->EncodedPointSize(m_compress);}
00093 void EncodePoint(byte *encodedPoint, const Point &P) const {m_ec->EncodePoint(encodedPoint, P, m_compress);}
00094 unsigned int FieldElementLength() const {return m_ec->GetField().MaxElementByteLength();}
00095 unsigned int ExponentLength() const {return m_n.ByteCount();}
00096 unsigned int ExponentBitLength() const {return m_n.BitCount();}
00097
00098 OID m_oid;
00099 value_ptr<EC> m_ec;
00100 Point m_G;
00101 EcPrecomputation<EC> m_Gpc;
00102 Integer m_n;
00103 bool m_cofactorPresent, m_compress, m_encodeAsOID;
00104 Integer m_k;
00105 };
00106
00107 #define EC_PARAMETERS_CONSTRUCTORS(Self, Base) \
00108 Self(const ECParameters<EC> ¶ms) \
00109 : Base(params) {} \
00110 Self(const OID &oid) \
00111 : Base(oid) {} \
00112 Self(const EC &ec, const Point &G, const Integer &n, const Integer &k) \
00113 : Base(ec, G, n, k) {} \
00114 Self(BufferedTransformation &bt) \
00115 : Base(bt) {}
00116
00118 template <class EC>
00119 class ECDHC : public ECParameters<EC>, public PK_WithPrecomputation<PK_SimpleKeyAgreementDomain>
00120 {
00121 public:
00122 typedef typename EC::Point Point;
00123
00124 EC_PARAMETERS_CONSTRUCTORS(ECDHC, ECParameters<EC>)
00125
00126 bool ValidateDomainParameters(RandomNumberGenerator &rng) const
00127 {return ValidateParameters(rng);}
00128 unsigned int AgreedValueLength() const {return FieldElementLength();}
00129 unsigned int PrivateKeyLength() const {return ExponentLength();}
00130 unsigned int PublicKeyLength() const {return EncodedPointSize();}
00131
00132 void GenerateKeyPair(RandomNumberGenerator &rng, byte *privateKey, byte *publicKey) const;
00133 bool Agree(byte *agreedValue, const byte *privateKey, const byte *otherPublicKey, bool validateOtherPublicKey=true) const;
00134 };
00135
00137 template <class EC>
00138 class ECMQVC : public ECParameters<EC>, public PK_WithPrecomputation<PK_AuthenticatedKeyAgreementDomain>
00139 {
00140 public:
00141 typedef typename EC::Point Point;
00142
00143 EC_PARAMETERS_CONSTRUCTORS(ECMQVC, ECParameters<EC>)
00144
00145 bool ValidateDomainParameters(RandomNumberGenerator &rng) const
00146 {return ValidateParameters(rng);}
00147 unsigned int AgreedValueLength() const {return FieldElementLength();}
00148
00149 unsigned int StaticPrivateKeyLength() const {return ExponentLength();}
00150 unsigned int StaticPublicKeyLength() const {return EncodedPointSize();}
00151 void GenerateStaticKeyPair(RandomNumberGenerator &rng, byte *privateKey, byte *publicKey) const;
00152
00153 unsigned int EphemeralPrivateKeyLength() const {return ExponentLength()+EncodedPointSize();}
00154 unsigned int EphemeralPublicKeyLength() const {return EncodedPointSize();}
00155 void GenerateEphemeralKeyPair(RandomNumberGenerator &rng, byte *privateKey, byte *publicKey) const;
00156
00157 bool Agree(byte *agreedValue,
00158 const byte *staticPrivateKey, const byte *ephemeralPrivateKey,
00159 const byte *staticOtherPublicKey, const byte *ephemeralOtherPublicKey,
00160 bool validateStaticOtherPublicKey=true) const;
00161 };
00162
00164 template <class EC>
00165 class ECPublicKey : public ECParameters<EC>, virtual public PK_Precomputation
00166 {
00167 public:
00168 typedef typename EC::Point Point;
00169
00170 ECPublicKey(const ECParameters<EC> ¶ms, const Point &Q)
00171 : ECParameters<EC>(params), m_Q(Q), m_Qpc(GetCurve(), m_Q) {}
00172 ECPublicKey(const OID &oidParams, const Point &Q)
00173 : ECParameters<EC>(oidParams), m_Q(Q), m_Qpc(GetCurve(), m_Q) {}
00174 ECPublicKey(const EC &ec, const Point &G, const Integer &n, const Point &Q)
00175 : ECParameters<EC>(ec, G, n), m_Q(Q), m_Qpc(ec, m_Q) {}
00176
00177 ECPublicKey(BufferedTransformation &bt);
00178
00179
00180 void DEREncode(BufferedTransformation &bt) const;
00181
00182 void Precompute(unsigned int precomputationStorage=16);
00183 void LoadPrecomputation(BufferedTransformation &storedPrecomputation);
00184 void SavePrecomputation(BufferedTransformation &storedPrecomputation) const;
00185
00186 const Point& GetPublicPoint() const {return m_Q;}
00187
00188 protected:
00189 ECPublicKey() {}
00190 Integer EncodeDigest(ECSignatureScheme ss, const byte *digest, unsigned int digestLen) const;
00191
00192 Point m_Q;
00193 EcPrecomputation<EC> m_Qpc;
00194 };
00195
00196 #define EC_PUBLIC_KEY_CONSTRUCTORS(Self, Base) \
00197 Self(const ECPublicKey<EC> &key) \
00198 : Base(key) {} \
00199 Self(const ECParameters<EC> ¶ms, const Point &Q) \
00200 : Base(params, Q) {} \
00201 Self(const OID &oid, const Point &Q) \
00202 : Base(oid, Q) {} \
00203 Self(const EC &ec, const Point &G, const Integer &n, const Point &Q) \
00204 : Base(ec, G, n, Q) {} \
00205 Self(BufferedTransformation &bt) \
00206 : Base(bt) {}
00207
00209 template <class EC>
00210 class ECPrivateKey : public ECPublicKey<EC>
00211 {
00212 public:
00213 typedef typename EC::Point Point;
00214
00215 ECPrivateKey(const ECParameters<EC> ¶ms, const Point &Q, const Integer &d)
00216 : ECPublicKey<EC>(params, Q), m_d(d) {}
00217 ECPrivateKey(const OID &oid, const Point &Q, const Integer &d)
00218 : ECPublicKey<EC>(oid, Q), m_d(d) {}
00219 ECPrivateKey(const EC &ec, const Point &G, const Integer &n, const Point &Q, const Integer &d)
00220 : ECPublicKey<EC>(ec, G, n, Q), m_d(d) {}
00221
00222 ECPrivateKey(RandomNumberGenerator &rng, const ECParameters<EC> ¶ms)
00223 : ECPublicKey<EC>(params, Point()) {Randomize(rng);}
00224 ECPrivateKey(RandomNumberGenerator &rng, const OID &oid)
00225 : ECPublicKey<EC>(oid, Point()) {Randomize(rng);}
00226 ECPrivateKey(RandomNumberGenerator &rng, const EC &ec, const Point &G, const Integer &n)
00227 : ECPublicKey<EC>(ec, G, n, Point()) {Randomize(rng);}
00228
00229 ECPrivateKey(BufferedTransformation &bt);
00230
00231 void DEREncode(BufferedTransformation &bt) const;
00232
00233 const Integer& GetPrivateExponent() const {return m_d;}
00234
00235 protected:
00236 typedef typename EC::FieldElement FieldElement;
00237 void Randomize(RandomNumberGenerator &rng);
00238 void RawDecode(BERSequenceDecoder &bt, bool needParameters);
00239
00240 Integer m_d;
00241 };
00242
00243 #define EC_PRIVATE_KEY_CONSTRUCTORS(Self, Base) \
00244 Self(const ECPrivateKey<EC> &key) \
00245 : Base(key) {} \
00246 Self(const ECParameters<EC> ¶ms, const Point &Q, const Integer &d) \
00247 : Base(params, Q, d) {} \
00248 Self(const OID& oid, const Point &Q, const Integer &d) \
00249 : Base(oid, Q, d) {} \
00250 Self(const EC &ec, const Point &G, const Integer &n, const Point &Q, const Integer &d) \
00251 : Base(ec, G, n, Q, d) {} \
00252 Self(RandomNumberGenerator &rng, const ECParameters<EC> ¶ms) \
00253 : Base(rng, params) {} \
00254 Self(RandomNumberGenerator &rng, const OID& oid) \
00255 : Base(rng, oid) {} \
00256 Self(RandomNumberGenerator &rng, const EC &ec, const Point &G, const Integer &n) \
00257 : Base(rng, ec, G, n) {} \
00258 Self(BufferedTransformation &bt) \
00259 : Base(bt) {}
00260
00262 template <class EC, ECSignatureScheme SS = ECNR>
00263 class ECDigestVerifier : public ECPublicKey<EC>, public PK_WithPrecomputation<DigestVerifier>
00264 {
00265 public:
00266 typedef typename EC::Point Point;
00267
00268 EC_PUBLIC_KEY_CONSTRUCTORS(ECDigestVerifier, ECPublicKey<EC>)
00269
00270 bool VerifyDigest(const byte *digest, unsigned int digestLen, const byte *signature) const;
00271
00272 unsigned int MaxDigestLength() const {return 0xffff;}
00273 unsigned int DigestSignatureLength() const {return 2*ExponentLength();}
00274
00275
00276 bool RawVerify(const Integer &e, const Integer &n, const Integer &s) const;
00277 };
00278
00280 template <class EC, ECSignatureScheme SS = ECNR>
00281 class ECDigestSigner : public ECPrivateKey<EC>, public PK_WithPrecomputation<DigestSigner>
00282 {
00283 public:
00284 typedef typename EC::Point Point;
00285
00286 EC_PRIVATE_KEY_CONSTRUCTORS(ECDigestSigner, ECPrivateKey<EC>)
00287
00288 void SignDigest(RandomNumberGenerator &, const byte *digest, unsigned int digestLen, byte *signature) const;
00289
00290 unsigned int MaxDigestLength() const {return 0xffff;}
00291 unsigned int DigestSignatureLength() const {return 2*ExponentLength();}
00292
00294 void RawSign(const Integer &k, const Integer &e, Integer &n, Integer &s) const;
00295 };
00296
00298 template <class EC, class H, ECSignatureScheme SS = ECNR>
00299 class ECSigner : public SignerTemplate<ECDigestSigner<EC, SS>, H>, public PK_WithPrecomputation<PK_Signer>
00300 {
00301 typedef ECDigestSigner<EC, SS> Base;
00302 public:
00303 typedef typename EC::Point Point;
00304
00305 EC_PRIVATE_KEY_CONSTRUCTORS(ECSigner, Base)
00306 };
00307
00309 template <class EC, class H, ECSignatureScheme SS = ECNR>
00310 class ECVerifier : public VerifierTemplate<ECDigestVerifier<EC, SS>, H>, public PK_WithPrecomputation<PK_Verifier>
00311 {
00312 typedef ECDigestVerifier<EC, SS> Base;
00313 public:
00314 typedef typename EC::Point Point;
00315
00316 EC_PUBLIC_KEY_CONSTRUCTORS(ECVerifier, Base)
00317 };
00318
00320 template <class EC, class MAC = HMAC<SHA>, class KDF = P1363_KDF2<SHA> >
00321 class ECEncryptor : public ECPublicKey<EC>, public PK_WithPrecomputation<PK_Encryptor>
00322 {
00323 public:
00324 typedef typename EC::Point Point;
00325
00326 EC_PUBLIC_KEY_CONSTRUCTORS(ECEncryptor, ECPublicKey<EC>)
00327
00328 unsigned int MaxPlainTextLength(unsigned int cipherTextLength) const
00329 {return cipherTextLength < CipherTextLength(0) ? 0 : cipherTextLength - CipherTextLength(0);}
00330 unsigned int CipherTextLength(unsigned int plainTextLength) const
00331 {return plainTextLength + MAC::DIGESTSIZE + EncodedPointSize();}
00332
00333 void Encrypt(RandomNumberGenerator &rng, const byte *plainText, unsigned int plainTextLength, byte *cipherText)
00334 {
00335 Integer x(rng, 1, m_n-1);
00336 Point Q = m_Gpc.Multiply(x);
00337
00338 EncodePoint(cipherText, Q);
00339 cipherText += EncodedPointSize();
00340
00341 SecByteBlock agreedSecret(FieldElementLength());
00342 Point Q1 = m_Qpc.Multiply(x);
00343 Q1.x.Encode(agreedSecret, agreedSecret.size);
00344
00345 SecByteBlock derivedKey(plainTextLength + MAC::DEFAULT_KEYLENGTH);
00346 KDF::DeriveKey(derivedKey, derivedKey.size, agreedSecret, agreedSecret.size);
00347 xorbuf(cipherText, plainText, derivedKey, plainTextLength);
00348
00349 MAC mac(derivedKey + plainTextLength);
00350 mac.CalculateDigest(cipherText + plainTextLength, cipherText, plainTextLength);
00351 }
00352 };
00353
00355 template <class EC, class MAC = HMAC<SHA>, class KDF = P1363_KDF2<SHA> >
00356 class ECDecryptor : public ECPrivateKey<EC>, public PK_Decryptor
00357 {
00358 public:
00359 typedef typename EC::Point Point;
00360
00361 EC_PRIVATE_KEY_CONSTRUCTORS(ECDecryptor, ECPrivateKey<EC>)
00362
00363 unsigned int MaxPlainTextLength(unsigned int cipherTextLength) const
00364 {return cipherTextLength < CipherTextLength(0) ? 0 : cipherTextLength - CipherTextLength(0);}
00365 unsigned int CipherTextLength(unsigned int plainTextLength) const
00366 {return plainTextLength + MAC::DIGESTSIZE + EncodedPointSize();}
00367
00368 unsigned int Decrypt(const byte *cipherText, unsigned int cipherTextLength, byte *plainText)
00369 {
00370 Point Q;
00371 if (!GetCurve().DecodePoint(Q, cipherText, EncodedPointSize()) || !GetCurve().VerifyPoint(Q) || Q.identity)
00372 return 0;
00373 cipherText += EncodedPointSize();
00374
00375 const Integer e[2] = {m_n, m_d};
00376 Point R[2];
00377 GetCurve().SimultaneousMultiply(R, Q, e, 2);
00378
00379 if (!R[0].identity || R[1].identity)
00380 return 0;
00381
00382 SecByteBlock agreedSecret(FieldElementLength());
00383 R[1].x.Encode(agreedSecret, agreedSecret.size);
00384
00385 unsigned int plainTextLength = MaxPlainTextLength(cipherTextLength);
00386 SecByteBlock derivedKey(plainTextLength + MAC::DEFAULT_KEYLENGTH);
00387 KDF::DeriveKey(derivedKey, derivedKey.size, agreedSecret, agreedSecret.size);
00388
00389 MAC mac(derivedKey + plainTextLength);
00390 if (!mac.VerifyDigest(cipherText + plainTextLength, cipherText, plainTextLength))
00391 return 0;
00392
00393 xorbuf(plainText, cipherText, derivedKey, plainTextLength);
00394 return plainTextLength;
00395 }
00396 };
00397
00398 NAMESPACE_END
00399
00400 #endif