Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members

gfpcrypt.h

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

Generated on Fri Aug 13 09:56:53 2004 for Crypto++ by doxygen 1.3.7