00001 #ifndef CRYPTOPP_GFPCRYPT_H
00002 #define CRYPTOPP_GFPCRYPT_H
00003
00004
00005
00006
00007
00008 #include "pubkey.h"
00009 #include "modexppc.h"
00010 #include "sha.h"
00011 #include "algparam.h"
00012 #include "asn.h"
00013 #include "smartptr.h"
00014 #include "hmac.h"
00015
00016 #include <limits.h>
00017
00018 NAMESPACE_BEGIN(CryptoPP)
00019
00020 CRYPTOPP_DLL_TEMPLATE_CLASS DL_GroupParameters<Integer>;
00021
00022
00023 class CRYPTOPP_DLL DL_GroupParameters_IntegerBased : public DL_GroupParameters<Integer>, public ASN1CryptoMaterial
00024 {
00025 typedef DL_GroupParameters_IntegerBased ThisClass;
00026
00027 public:
00028 void Initialize(const DL_GroupParameters_IntegerBased ¶ms)
00029 {Initialize(params.GetModulus(), params.GetSubgroupOrder(), params.GetSubgroupGenerator());}
00030 void Initialize(RandomNumberGenerator &rng, unsigned int pbits)
00031 {GenerateRandom(rng, MakeParameters("ModulusSize", (int)pbits));}
00032 void Initialize(const Integer &p, const Integer &g)
00033 {SetModulusAndSubgroupGenerator(p, g); SetSubgroupOrder(ComputeGroupOrder(p)/2);}
00034 void Initialize(const Integer &p, const Integer &q, const Integer &g)
00035 {SetModulusAndSubgroupGenerator(p, g); SetSubgroupOrder(q);}
00036
00037
00038 void BERDecode(BufferedTransformation &bt);
00039 void DEREncode(BufferedTransformation &bt) const;
00040
00041
00042
00043 void GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs &alg);
00044 bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const;
00045 void AssignFrom(const NameValuePairs &source);
00046
00047
00048 const Integer & GetSubgroupOrder() const {return m_q;}
00049 Integer GetGroupOrder() const {return GetFieldType() == 1 ? GetModulus()-Integer::One() : GetModulus()+Integer::One();}
00050 bool ValidateGroup(RandomNumberGenerator &rng, unsigned int level) const;
00051 bool ValidateElement(unsigned int level, const Integer &element, const DL_FixedBasePrecomputation<Integer> *precomp) const;
00052 bool FastSubgroupCheckAvailable() const {return GetCofactor() == 2;}
00053 void EncodeElement(bool reversible, const Element &element, byte *encoded) const
00054 {element.Encode(encoded, GetModulus().ByteCount());}
00055 unsigned int GetEncodedElementSize(bool reversible) const {return GetModulus().ByteCount();}
00056 Integer DecodeElement(const byte *encoded, bool checkForGroupMembership) const;
00057 Integer ConvertElementToInteger(const Element &element) const
00058 {return element;}
00059 Integer GetMaxExponent() const;
00060
00061 OID GetAlgorithmID() const;
00062
00063 virtual const Integer & GetModulus() const =0;
00064 virtual void SetModulusAndSubgroupGenerator(const Integer &p, const Integer &g) =0;
00065
00066 void SetSubgroupOrder(const Integer &q)
00067 {m_q = q; ParametersChanged();}
00068
00069 protected:
00070 Integer ComputeGroupOrder(const Integer &modulus) const
00071 {return modulus-(GetFieldType() == 1 ? 1 : -1);}
00072
00073
00074 virtual int GetFieldType() const =0;
00075 virtual unsigned int GetDefaultSubgroupOrderSize(unsigned int modulusSize) const;
00076
00077 private:
00078 Integer m_q;
00079 };
00080
00081
00082 template <class GROUP_PRECOMP, class BASE_PRECOMP = DL_FixedBasePrecomputationImpl<CPP_TYPENAME GROUP_PRECOMP::Element> >
00083 class DL_GroupParameters_IntegerBasedImpl : public DL_GroupParametersImpl<GROUP_PRECOMP, BASE_PRECOMP, DL_GroupParameters_IntegerBased>
00084 {
00085 typedef DL_GroupParameters_IntegerBasedImpl<GROUP_PRECOMP, BASE_PRECOMP> ThisClass;
00086
00087 public:
00088 typedef typename GROUP_PRECOMP::Element Element;
00089
00090
00091 bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const
00092 {return GetValueHelper<DL_GroupParameters_IntegerBased>(this, name, valueType, pValue).Assignable();}
00093
00094 void AssignFrom(const NameValuePairs &source)
00095 {AssignFromHelper<DL_GroupParameters_IntegerBased>(this, source);}
00096
00097
00098 const DL_FixedBasePrecomputation<Element> & GetBasePrecomputation() const {return m_gpc;}
00099 DL_FixedBasePrecomputation<Element> & AccessBasePrecomputation() {return m_gpc;}
00100
00101
00102 const Integer & GetModulus() const {return m_groupPrecomputation.GetModulus();}
00103 const Integer & GetGenerator() const {return m_gpc.GetBase(GetGroupPrecomputation());}
00104
00105 void SetModulusAndSubgroupGenerator(const Integer &p, const Integer &g)
00106 {m_groupPrecomputation.SetModulus(p); m_gpc.SetBase(GetGroupPrecomputation(), g); ParametersChanged();}
00107
00108
00109 bool operator==(const DL_GroupParameters_IntegerBasedImpl<GROUP_PRECOMP, BASE_PRECOMP> &rhs) const
00110 {return GetModulus() == rhs.GetModulus() && GetGenerator() == rhs.GetGenerator() && GetSubgroupOrder() == rhs.GetSubgroupOrder();}
00111 bool operator!=(const DL_GroupParameters_IntegerBasedImpl<GROUP_PRECOMP, BASE_PRECOMP> &rhs) const
00112 {return !operator==(rhs);}
00113 };
00114
00115 CRYPTOPP_DLL_TEMPLATE_CLASS DL_GroupParameters_IntegerBasedImpl<ModExpPrecomputation>;
00116
00117
00118 class CRYPTOPP_DLL DL_GroupParameters_GFP : public DL_GroupParameters_IntegerBasedImpl<ModExpPrecomputation>
00119 {
00120 public:
00121
00122 bool IsIdentity(const Integer &element) const {return element == Integer::One();}
00123 void SimultaneousExponentiate(Element *results, const Element &base, const Integer *exponents, unsigned int exponentsCount) const;
00124
00125
00126 bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const
00127 {
00128 return GetValueHelper<DL_GroupParameters_IntegerBased>(this, name, valueType, pValue).Assignable();
00129 }
00130
00131
00132 Element MultiplyElements(const Element &a, const Element &b) const;
00133 Element CascadeExponentiate(const Element &element1, const Integer &exponent1, const Element &element2, const Integer &exponent2) const;
00134
00135 protected:
00136 int GetFieldType() const {return 1;}
00137 };
00138
00139
00140 class CRYPTOPP_DLL DL_GroupParameters_GFP_DefaultSafePrime : public DL_GroupParameters_GFP
00141 {
00142 public:
00143 typedef NoCofactorMultiplication DefaultCofactorOption;
00144
00145 protected:
00146 unsigned int GetDefaultSubgroupOrderSize(unsigned int modulusSize) const {return modulusSize-1;}
00147 };
00148
00149
00150 template <class T>
00151 class DL_Algorithm_GDSA : public DL_ElgamalLikeSignatureAlgorithm<T>
00152 {
00153 public:
00154 static const char * StaticAlgorithmName() {return "DSA-1363";}
00155
00156 Integer EncodeDigest(unsigned int modulusBits, const byte *digest, unsigned int digestLen) const
00157 {
00158 return DSA_EncodeDigest(modulusBits, digest, digestLen);
00159 }
00160
00161 bool Sign(const DL_GroupParameters<T> ¶ms, const Integer &x, const Integer &k, const Integer &e, Integer &r, Integer &s) const
00162 {
00163 const Integer &q = params.GetSubgroupOrder();
00164 r = params.ConvertElementToInteger(params.ExponentiateBase(k)) % q;
00165 Integer kInv = k.InverseMod(q);
00166 s = (kInv * (x*r + e)) % q;
00167 return (!!r && !!s);
00168 }
00169
00170 bool Verify(const DL_GroupParameters<T> ¶ms, const DL_PublicKey<T> &publicKey, const Integer &e, const Integer &r, const Integer &s) const
00171 {
00172 const Integer &q = params.GetSubgroupOrder();
00173 if (r>=q || r<1 || s>=q || s<1)
00174 return false;
00175
00176 Integer w = s.InverseMod(q);
00177 Integer u1 = (e * w) % q;
00178 Integer u2 = (r * w) % q;
00179
00180 return r == params.ConvertElementToInteger(publicKey.CascadeExponentiateBaseAndPublicElement(u1, u2)) % q;
00181 }
00182 };
00183
00184 CRYPTOPP_DLL_TEMPLATE_CLASS DL_Algorithm_GDSA<Integer>;
00185
00186
00187 template <class T>
00188 class DL_Algorithm_NR : public DL_ElgamalLikeSignatureAlgorithm<T>
00189 {
00190 public:
00191 static const char * StaticAlgorithmName() {return "NR";}
00192
00193 Integer EncodeDigest(unsigned int modulusBits, const byte *digest, unsigned int digestLen) const
00194 {
00195 return NR_EncodeDigest(modulusBits, digest, digestLen);
00196 }
00197
00198 bool Sign(const DL_GroupParameters<T> ¶ms, const Integer &x, const Integer &k, const Integer &e, Integer &r, Integer &s) const
00199 {
00200 const Integer &q = params.GetSubgroupOrder();
00201 r = (params.ConvertElementToInteger(params.ExponentiateBase(k)) + e) % q;
00202 s = (k - x*r) % q;
00203 return !!r;
00204 }
00205
00206 bool Verify(const DL_GroupParameters<T> ¶ms, const DL_PublicKey<T> &publicKey, const Integer &e, const Integer &r, const Integer &s) const
00207 {
00208 const Integer &q = params.GetSubgroupOrder();
00209 if (r>=q || r<1 || s>=q)
00210 return false;
00211
00212
00213 return r == (params.ConvertElementToInteger(publicKey.CascadeExponentiateBaseAndPublicElement(s, r)) + e) % q;
00214 }
00215 };
00216
00217
00218
00219 template <class GP>
00220 class DL_PublicKey_GFP : public DL_PublicKeyImpl<GP>
00221 {
00222 public:
00223 void Initialize(const DL_GroupParameters_IntegerBased ¶ms, const Integer &y)
00224 {AccessGroupParameters().Initialize(params); SetPublicElement(y);}
00225 void Initialize(const Integer &p, const Integer &g, const Integer &y)
00226 {AccessGroupParameters().Initialize(p, g); SetPublicElement(y);}
00227 void Initialize(const Integer &p, const Integer &q, const Integer &g, const Integer &y)
00228 {AccessGroupParameters().Initialize(p, q, g); SetPublicElement(y);}
00229
00230
00231 void BERDecodeKey(BufferedTransformation &bt)
00232 {SetPublicElement(Integer(bt));}
00233 void DEREncodeKey(BufferedTransformation &bt) const
00234 {GetPublicElement().DEREncode(bt);}
00235 };
00236
00237
00238 template <class GP>
00239 class DL_PrivateKey_GFP : public DL_PrivateKeyImpl<GP>
00240 {
00241 public:
00242 void Initialize(RandomNumberGenerator &rng, unsigned int modulusBits)
00243 {GenerateRandomWithKeySize(rng, modulusBits);}
00244 void Initialize(RandomNumberGenerator &rng, const Integer &p, const Integer &g)
00245 {GenerateRandom(rng, MakeParameters("Modulus", p)("SubgroupGenerator", g));}
00246 void Initialize(RandomNumberGenerator &rng, const Integer &p, const Integer &q, const Integer &g)
00247 {GenerateRandom(rng, MakeParameters("Modulus", p)("SubgroupOrder", q)("SubgroupGenerator", g));}
00248 void Initialize(const DL_GroupParameters_IntegerBased ¶ms, const Integer &x)
00249 {AccessGroupParameters().Initialize(params); SetPrivateExponent(x);}
00250 void Initialize(const Integer &p, const Integer &g, const Integer &x)
00251 {AccessGroupParameters().Initialize(p, g); SetPrivateExponent(x);}
00252 void Initialize(const Integer &p, const Integer &q, const Integer &g, const Integer &x)
00253 {AccessGroupParameters().Initialize(p, q, g); SetPrivateExponent(x);}
00254 };
00255
00256
00257 struct DL_SignatureKeys_GFP
00258 {
00259 typedef DL_GroupParameters_GFP GroupParameters;
00260 typedef DL_PublicKey_GFP<GroupParameters> PublicKey;
00261 typedef DL_PrivateKey_GFP<GroupParameters> PrivateKey;
00262 };
00263
00264
00265 struct DL_CryptoKeys_GFP
00266 {
00267 typedef DL_GroupParameters_GFP_DefaultSafePrime GroupParameters;
00268 typedef DL_PublicKey_GFP<GroupParameters> PublicKey;
00269 typedef DL_PrivateKey_GFP<GroupParameters> PrivateKey;
00270 };
00271
00272
00273 template <class BASE>
00274 class DL_PublicKey_GFP_OldFormat : public BASE
00275 {
00276 public:
00277 void BERDecode(BufferedTransformation &bt)
00278 {
00279 BERSequenceDecoder seq(bt);
00280 Integer v1(seq);
00281 Integer v2(seq);
00282 Integer v3(seq);
00283
00284 if (seq.EndReached())
00285 {
00286 AccessGroupParameters().Initialize(v1, v1/2, v2);
00287 SetPublicElement(v3);
00288 }
00289 else
00290 {
00291 Integer v4(seq);
00292 AccessGroupParameters().Initialize(v1, v2, v3);
00293 SetPublicElement(v4);
00294 }
00295
00296 seq.MessageEnd();
00297 }
00298
00299 void DEREncode(BufferedTransformation &bt) const
00300 {
00301 DERSequenceEncoder seq(bt);
00302 GetGroupParameters().GetModulus().DEREncode(seq);
00303 if (GetGroupParameters().GetCofactor() != 2)
00304 GetGroupParameters().GetSubgroupOrder().DEREncode(seq);
00305 GetGroupParameters().GetGenerator().DEREncode(seq);
00306 GetPublicElement().DEREncode(seq);
00307 seq.MessageEnd();
00308 }
00309 };
00310
00311
00312 template <class BASE>
00313 class DL_PrivateKey_GFP_OldFormat : public BASE
00314 {
00315 public:
00316 void BERDecode(BufferedTransformation &bt)
00317 {
00318 BERSequenceDecoder seq(bt);
00319 Integer v1(seq);
00320 Integer v2(seq);
00321 Integer v3(seq);
00322 Integer v4(seq);
00323
00324 if (seq.EndReached())
00325 {
00326 AccessGroupParameters().Initialize(v1, v1/2, v2);
00327 SetPrivateExponent(v4 % (v1/2));
00328 }
00329 else
00330 {
00331 Integer v5(seq);
00332 AccessGroupParameters().Initialize(v1, v2, v3);
00333 SetPrivateExponent(v5);
00334 }
00335
00336 seq.MessageEnd();
00337 }
00338
00339 void DEREncode(BufferedTransformation &bt) const
00340 {
00341 DERSequenceEncoder seq(bt);
00342 GetGroupParameters().GetModulus().DEREncode(seq);
00343 if (GetGroupParameters().GetCofactor() != 2)
00344 GetGroupParameters().GetSubgroupOrder().DEREncode(seq);
00345 GetGroupParameters().GetGenerator().DEREncode(seq);
00346 GetGroupParameters().ExponentiateBase(GetPrivateExponent()).DEREncode(seq);
00347 GetPrivateExponent().DEREncode(seq);
00348 seq.MessageEnd();
00349 }
00350 };
00351
00352
00353 template <class H>
00354 struct GDSA : public DL_SSA<DL_SignatureKeys_GFP, DL_Algorithm_GDSA<Integer>, H>
00355 {
00356 };
00357
00358
00359 template <class H>
00360 struct NR : public DL_SSA<DL_SignatureKeys_GFP, DL_Algorithm_NR<Integer>, H>
00361 {
00362 };
00363
00364
00365 class CRYPTOPP_DLL DL_GroupParameters_DSA : public DL_GroupParameters_GFP
00366 {
00367 public:
00368
00369 bool ValidateGroup(RandomNumberGenerator &rng, unsigned int level) const;
00370
00371
00372 void GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs &alg);
00373 };
00374
00375 struct DSA;
00376
00377 CRYPTOPP_DLL_TEMPLATE_CLASS DL_PublicKey_GFP<DL_GroupParameters_DSA>;
00378 CRYPTOPP_DLL_TEMPLATE_CLASS DL_PrivateKey_GFP<DL_GroupParameters_DSA>;
00379 CRYPTOPP_DLL_TEMPLATE_CLASS DL_PrivateKey_WithSignaturePairwiseConsistencyTest<DL_PrivateKey_GFP<DL_GroupParameters_DSA>, DSA>;
00380
00381
00382 struct DL_Keys_DSA
00383 {
00384 typedef DL_PublicKey_GFP<DL_GroupParameters_DSA> PublicKey;
00385 typedef DL_PrivateKey_WithSignaturePairwiseConsistencyTest<DL_PrivateKey_GFP<DL_GroupParameters_DSA>, DSA> PrivateKey;
00386 };
00387
00388
00389 struct CRYPTOPP_DLL DSA : public DL_SSA<DL_Keys_DSA, DL_Algorithm_GDSA<Integer>, SHA, DSA>
00390 {
00391 static std::string StaticAlgorithmName() {return std::string("DSA");}
00392
00393
00394
00395
00396
00397
00398 static bool GeneratePrimes(const byte *seed, unsigned int seedLength, int &counter,
00399 Integer &p, unsigned int primeLength, Integer &q, bool useInputCounterValue = false);
00400
00401 static bool IsValidPrimeLength(unsigned int pbits)
00402 {return pbits >= MIN_PRIME_LENGTH && pbits <= MAX_PRIME_LENGTH && pbits % PRIME_LENGTH_MULTIPLE == 0;}
00403
00404 enum {
00405 #if (DSA_1024_BIT_MODULUS_ONLY)
00406 MIN_PRIME_LENGTH = 1024,
00407 #else
00408 MIN_PRIME_LENGTH = 512,
00409 #endif
00410 MAX_PRIME_LENGTH = 1024, PRIME_LENGTH_MULTIPLE = 64};
00411 };
00412
00413
00414 template <class MAC, bool DHAES_MODE>
00415 class DL_EncryptionAlgorithm_Xor : public DL_SymmetricEncryptionAlgorithm
00416 {
00417 public:
00418 unsigned int GetSymmetricKeyLength(unsigned int plainTextLength) const
00419 {return plainTextLength + MAC::DEFAULT_KEYLENGTH;}
00420 unsigned int GetSymmetricCiphertextLength(unsigned int plainTextLength) const
00421 {return plainTextLength + MAC::DIGESTSIZE;}
00422 unsigned int GetMaxSymmetricPlaintextLength(unsigned int cipherTextLength) const
00423 {return SaturatingSubtract(cipherTextLength, (unsigned int)MAC::DIGESTSIZE);}
00424 void SymmetricEncrypt(RandomNumberGenerator &rng, const byte *key, const byte *plainText, unsigned int plainTextLength, byte *cipherText) const
00425 {
00426 const byte *cipherKey, *macKey;
00427 if (DHAES_MODE)
00428 {
00429 macKey = key;
00430 cipherKey = key + MAC::DEFAULT_KEYLENGTH;
00431 }
00432 else
00433 {
00434 cipherKey = key;
00435 macKey = key + plainTextLength;
00436 }
00437
00438 xorbuf(cipherText, plainText, cipherKey, plainTextLength);
00439 MAC(macKey).CalculateDigest(cipherText + plainTextLength, cipherText, plainTextLength);
00440 }
00441 DecodingResult SymmetricDecrypt(const byte *key, const byte *cipherText, unsigned int cipherTextLength, byte *plainText) const
00442 {
00443 unsigned int plainTextLength = GetMaxSymmetricPlaintextLength(cipherTextLength);
00444 const byte *cipherKey, *macKey;
00445 if (DHAES_MODE)
00446 {
00447 macKey = key;
00448 cipherKey = key + MAC::DEFAULT_KEYLENGTH;
00449 }
00450 else
00451 {
00452 cipherKey = key;
00453 macKey = key + plainTextLength;
00454 }
00455
00456 if (!MAC(macKey).VerifyDigest(cipherText + plainTextLength, cipherText, plainTextLength))
00457 return DecodingResult();
00458 xorbuf(plainText, cipherText, cipherKey, plainTextLength);
00459 return DecodingResult(plainTextLength);
00460 }
00461 };
00462
00463
00464 template <class T, bool DHAES_MODE, class KDF>
00465 class DL_KeyDerivationAlgorithm_P1363 : public DL_KeyDerivationAlgorithm<T>
00466 {
00467 public:
00468 void Derive(const DL_GroupParameters<T> ¶ms, byte *derivedKey, unsigned int derivedLength, const T &agreedElement, const T &ephemeralPublicKey) const
00469 {
00470 SecByteBlock agreedSecret;
00471 if (DHAES_MODE)
00472 {
00473 agreedSecret.New(params.GetEncodedElementSize(true) + params.GetEncodedElementSize(false));
00474 params.EncodeElement(true, ephemeralPublicKey, agreedSecret);
00475 params.EncodeElement(false, agreedElement, agreedSecret + params.GetEncodedElementSize(true));
00476 }
00477 else
00478 {
00479 agreedSecret.New(params.GetEncodedElementSize(false));
00480 params.EncodeElement(false, agreedElement, agreedSecret);
00481 }
00482
00483 KDF::DeriveKey(derivedKey, derivedLength, agreedSecret, agreedSecret.size());
00484 }
00485 };
00486
00487
00488 template <class COFACTOR_OPTION = NoCofactorMultiplication, bool DHAES_MODE = true>
00489 struct DLIES
00490 : public DL_ES<
00491 DL_CryptoKeys_GFP,
00492 DL_KeyAgreementAlgorithm_DH<Integer, COFACTOR_OPTION>,
00493 DL_KeyDerivationAlgorithm_P1363<Integer, DHAES_MODE, P1363_KDF2<SHA1> >,
00494 DL_EncryptionAlgorithm_Xor<HMAC<SHA1>, DHAES_MODE>,
00495 DLIES<> >
00496 {
00497 static std::string StaticAlgorithmName() {return "DLIES";}
00498 };
00499
00500 NAMESPACE_END
00501
00502 #endif