00001
00002
00003 #include "pch.h"
00004 #include "elgamal.h"
00005 #include "asn.h"
00006 #include "nbtheory.h"
00007
00008 NAMESPACE_BEGIN(CryptoPP)
00009
00010 ElGamalEncryptor::ElGamalEncryptor(const Integer &p, const Integer &g, const Integer &y)
00011 : m_p(p), m_g(g), m_y(y), m_gpc(p, g), m_ypc(p, y)
00012 {
00013 }
00014
00015 ElGamalEncryptor::ElGamalEncryptor(BufferedTransformation &bt)
00016 {
00017 BERSequenceDecoder seq(bt);
00018 m_p.BERDecode(seq);
00019 m_g.BERDecode(seq);
00020 m_y.BERDecode(seq);
00021 seq.MessageEnd();
00022
00023 m_gpc.SetModulusAndBase(m_p, m_g);
00024 m_ypc.SetModulusAndBase(m_p, m_y);
00025 }
00026
00027 void ElGamalEncryptor::DEREncode(BufferedTransformation &bt) const
00028 {
00029 DERSequenceEncoder seq(bt);
00030 m_p.DEREncode(seq);
00031 m_g.DEREncode(seq);
00032 m_y.DEREncode(seq);
00033 seq.MessageEnd();
00034 }
00035
00036 void ElGamalEncryptor::Precompute(unsigned int precomputationStorage)
00037 {
00038 m_gpc.Precompute(ExponentBitLength(), precomputationStorage);
00039 m_ypc.Precompute(ExponentBitLength(), precomputationStorage);
00040 }
00041
00042 void ElGamalEncryptor::LoadPrecomputation(BufferedTransformation &bt)
00043 {
00044 m_gpc.Load(bt);
00045 m_ypc.Load(bt);
00046 }
00047
00048 void ElGamalEncryptor::SavePrecomputation(BufferedTransformation &bt) const
00049 {
00050 m_gpc.Save(bt);
00051 m_ypc.Save(bt);
00052 }
00053
00054 void ElGamalEncryptor::Encrypt(RandomNumberGenerator &rng, const byte *plainText, unsigned int plainTextLength, byte *cipherText)
00055 {
00056 assert(plainTextLength <= MaxPlainTextLength());
00057
00058 unsigned int modulusLen = m_p.ByteCount();
00059 SecByteBlock block(modulusLen-1);
00060 rng.GetBlock(block, modulusLen-2-plainTextLength);
00061 memcpy(block+modulusLen-2-plainTextLength, plainText, plainTextLength);
00062 block[modulusLen-2] = plainTextLength;
00063
00064 Integer m(block, modulusLen-1);
00065 Integer a,b;
00066 RawEncrypt(Integer(rng, ExponentBitLength()), m, a, b);
00067
00068 a.Encode(cipherText, modulusLen);
00069 b.Encode(cipherText+modulusLen, modulusLen);
00070 }
00071
00072 void ElGamalEncryptor::RawEncrypt(const Integer &k, const Integer &m, Integer &a, Integer &b) const
00073 {
00074 a = m_gpc.Exponentiate(k);
00075 b = m * m_ypc.Exponentiate(k) % m_p;
00076 }
00077
00078 unsigned int ElGamalEncryptor::ExponentBitLength() const
00079 {
00080 return 2*DiscreteLogWorkFactor(m_p.BitCount());
00081 }
00082
00083
00084
00085 ElGamalDecryptor::ElGamalDecryptor(const Integer &p, const Integer &g, const Integer &y, const Integer &x)
00086 : ElGamalEncryptor(p, g, y), m_x(x)
00087 {
00088 }
00089
00090 ElGamalDecryptor::ElGamalDecryptor(RandomNumberGenerator &rng, unsigned int pbits)
00091 {
00092 PrimeAndGenerator pg(1, rng, pbits);
00093 m_p = pg.Prime();
00094 m_g = pg.Generator();
00095 m_x.Randomize(rng, ExponentBitLength());
00096 m_gpc.SetModulusAndBase(m_p, m_g);
00097 m_y = m_gpc.Exponentiate(m_x);
00098 m_ypc.SetModulusAndBase(m_p, m_y);
00099 }
00100
00101 ElGamalDecryptor::ElGamalDecryptor(RandomNumberGenerator &rng, const Integer &pIn, const Integer &gIn)
00102 {
00103 m_p = pIn;
00104 m_g = gIn;
00105 m_x.Randomize(rng, ExponentBitLength());
00106 m_gpc.SetModulusAndBase(m_p, m_g);
00107 m_y = m_gpc.Exponentiate(m_x);
00108 m_ypc.SetModulusAndBase(m_p, m_y);
00109 }
00110
00111 ElGamalDecryptor::ElGamalDecryptor(BufferedTransformation &bt)
00112 {
00113 BERSequenceDecoder seq(bt);
00114 m_p.BERDecode(seq);
00115 m_g.BERDecode(seq);
00116 m_y.BERDecode(seq);
00117 m_x.BERDecode(seq);
00118 seq.MessageEnd();
00119
00120 m_gpc.SetModulusAndBase(m_p, m_g);
00121 m_ypc.SetModulusAndBase(m_p, m_y);
00122 }
00123
00124 void ElGamalDecryptor::DEREncode(BufferedTransformation &bt) const
00125 {
00126 DERSequenceEncoder seq(bt);
00127 m_p.DEREncode(seq);
00128 m_g.DEREncode(seq);
00129 m_y.DEREncode(seq);
00130 m_x.DEREncode(seq);
00131 seq.MessageEnd();
00132 }
00133
00134 unsigned int ElGamalDecryptor::Decrypt(const byte *cipherText, byte *plainText)
00135 {
00136 unsigned int modulusLen = m_p.ByteCount();
00137 Integer a(cipherText, modulusLen);
00138 Integer b(cipherText+modulusLen, modulusLen);
00139 Integer m;
00140
00141 RawDecrypt(a, b, m);
00142 m.Encode(plainText, 1);
00143 unsigned int plainTextLength = plainText[0];
00144 if (plainTextLength > MaxPlainTextLength())
00145 return 0;
00146 m >>= 8;
00147 m.Encode(plainText, plainTextLength);
00148 return plainTextLength;
00149 }
00150
00151 void ElGamalDecryptor::RawDecrypt(const Integer &a, const Integer &b, Integer &m) const
00152 {
00153 if (m_x.BitCount()+20 < m_p.BitCount())
00154 m = b * EuclideanMultiplicativeInverse(a_exp_b_mod_c(a, m_x, m_p), m_p) % m_p;
00155 else
00156 m = b * a_exp_b_mod_c(a, m_p-1-m_x, m_p) % m_p;
00157 }
00158
00159 NAMESPACE_END