00001
00002
00003 #include "pch.h"
00004 #include "blumgold.h"
00005 #include "asn.h"
00006 #include "nbtheory.h"
00007 #include "blumshub.h"
00008
00009 NAMESPACE_BEGIN(CryptoPP)
00010
00011 BlumGoldwasserPublicKey::BlumGoldwasserPublicKey(const Integer &n)
00012 : n(n), modulusLen(n.ByteCount())
00013 {
00014 }
00015
00016 BlumGoldwasserPublicKey::BlumGoldwasserPublicKey(BufferedTransformation &bt)
00017 {
00018 BERSequenceDecoder seq(bt);
00019 n.BERDecode(seq);
00020 seq.MessageEnd();
00021 modulusLen = n.ByteCount();
00022 }
00023
00024 void BlumGoldwasserPublicKey::DEREncode(BufferedTransformation &bt) const
00025 {
00026 DERSequenceEncoder seq(bt);
00027 n.DEREncode(seq);
00028 seq.MessageEnd();
00029 }
00030
00031 unsigned int BlumGoldwasserPublicKey::MaxPlainTextLength(unsigned int cipherTextLength) const
00032 {
00033 return cipherTextLength > modulusLen ? cipherTextLength - modulusLen : 0;
00034 }
00035
00036 unsigned int BlumGoldwasserPublicKey::CipherTextLength(unsigned int plainTextLength) const
00037 {
00038 return modulusLen + plainTextLength;
00039 }
00040
00041 void BlumGoldwasserPublicKey::Encrypt(RandomNumberGenerator &rng, const byte *input, unsigned int inputLen, byte *output)
00042 {
00043 Integer seed(rng, 1, n-1);
00044 PublicBlumBlumShub bbs(n, seed);
00045 bbs.ProcessString(output+modulusLen, input, inputLen);
00046 bbs.modn.Square(bbs.current).Encode(output, modulusLen);
00047 }
00048
00049
00050
00051
00052 BlumGoldwasserPrivateKey::BlumGoldwasserPrivateKey(const Integer &n, const Integer &p, const Integer &q, const Integer &u)
00053 : BlumGoldwasserPublicKey(n),
00054 p(p), q(q), u(u)
00055 {
00056 assert(n == p*q);
00057 assert(u == EuclideanMultiplicativeInverse(p, q));
00058 }
00059
00060
00061 BlumGoldwasserPrivateKey::BlumGoldwasserPrivateKey(RandomNumberGenerator &rng, unsigned int keybits)
00062 {
00063 assert(keybits >= 16);
00064
00065 if (keybits%2==0)
00066 {
00067 const Integer minP = Integer(182) << (keybits/2-8);
00068 const Integer maxP = Integer::Power2(keybits/2)-1;
00069 p.Randomize(rng, minP, maxP, Integer::PRIME, 3, 4);
00070 q.Randomize(rng, minP, maxP, Integer::PRIME, 3, 4);
00071 }
00072 else
00073 {
00074 const Integer minP = Integer::Power2((keybits-1)/2);
00075 const Integer maxP = Integer(181) << ((keybits+1)/2-8);
00076 p.Randomize(rng, minP, maxP, Integer::PRIME, 3, 4);
00077 q.Randomize(rng, minP, maxP, Integer::PRIME, 3, 4);
00078 }
00079
00080 n = p*q;
00081 u = EuclideanMultiplicativeInverse(p, q);
00082 modulusLen = n.ByteCount();
00083 }
00084
00085 BlumGoldwasserPrivateKey::BlumGoldwasserPrivateKey(BufferedTransformation &bt)
00086 {
00087 BERSequenceDecoder seq(bt);
00088 n.BERDecode(seq);
00089 p.BERDecode(seq);
00090 q.BERDecode(seq);
00091 u.BERDecode(seq);
00092 seq.MessageEnd();
00093
00094 modulusLen = n.ByteCount();
00095
00096 assert(n == p*q);
00097 assert(u == EuclideanMultiplicativeInverse(p, q));
00098 }
00099
00100 void BlumGoldwasserPrivateKey::DEREncode(BufferedTransformation &bt) const
00101 {
00102 DERSequenceEncoder seq(bt);
00103 n.DEREncode(seq);
00104 p.DEREncode(seq);
00105 q.DEREncode(seq);
00106 u.DEREncode(seq);
00107 seq.MessageEnd();
00108 }
00109
00110 unsigned int BlumGoldwasserPrivateKey::Decrypt(const byte *input, unsigned int cipherTextLength, byte *output)
00111 {
00112 if (cipherTextLength <= modulusLen)
00113 return 0;
00114
00115 Integer xt(input, modulusLen);
00116 PublicBlumBlumShub bbs(n, Integer::Zero());
00117 unsigned int plainTextLength = cipherTextLength - modulusLen;
00118 unsigned int t = ((plainTextLength)*8 + bbs.maxBits-1) / bbs.maxBits;
00119 Integer dp = a_exp_b_mod_c((p+1)/4, t, p-1);
00120 Integer dq = a_exp_b_mod_c((q+1)/4, t, q-1);
00121 Integer xp = a_exp_b_mod_c(xt%p, dp, p);
00122 Integer xq = a_exp_b_mod_c(xt%q, dq, q);
00123 bbs.current = CRT(xp, p, xq, q, u);
00124 bbs.bitsLeft = bbs.maxBits;
00125
00126 bbs.ProcessString(output, input+modulusLen, plainTextLength);
00127 return plainTextLength;
00128 }
00129
00130 NAMESPACE_END