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
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 ¶ms)
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
00036
void BERDecode(
BufferedTransformation &bt);
00037
void DEREncode(
BufferedTransformation &bt)
const;
00038
00039
00040
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
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
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
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
00096
const DL_FixedBasePrecomputation<Element> & GetBasePrecomputation()
const {
return m_gpc;}
00097 DL_FixedBasePrecomputation<Element> & AccessBasePrecomputation() {
return m_gpc;}
00098
00099
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)
00104 {m_groupPrecomputation.SetModulus(p); m_gpc.SetBase(GetGroupPrecomputation(), g); ParametersChanged();}
00105
00106
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
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
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
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> ¶ms,
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> ¶ms,
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
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> ¶ms,
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> ¶ms,
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
00202
return r == (params.
ConvertElementToInteger(publicKey.
CascadeExponentiateBaseAndPublicElement(s, r)) + e) % q;
00203 }
00204 };
00205
00206
00207
00208
template <
class GP>
00209 class DL_PublicKey_GFP :
public DL_PublicKeyImpl<GP>
00210 {
00211
public:
00212
void Initialize(
const DL_GroupParameters_IntegerBased ¶ms,
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
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 ¶ms,
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
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
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));
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
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
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
00366
bool ValidateGroup(
RandomNumberGenerator &rng,
unsigned int level)
const;
00367
00368
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
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
00392
00393
00394
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> ¶ms, 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
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";}
00511 };
00512
00513 NAMESPACE_END
00514
00515
#endif