Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

elgamal.cpp

00001 // elgamal.cpp - written and placed in the public domain by Wei Dai
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()) // if x is short
00154                 m = b * EuclideanMultiplicativeInverse(a_exp_b_mod_c(a, m_x, m_p), m_p) % m_p;
00155         else    // save a multiplicative inverse calculation
00156                 m = b * a_exp_b_mod_c(a, m_p-1-m_x, m_p) % m_p;
00157 }
00158 
00159 NAMESPACE_END

Generated at Mon Jan 15 01:16:31 2001 for Crypto++ by doxygen1.2.4 written by Dimitri van Heesch, © 1997-2000