aboutsummaryrefslogtreecommitdiffstats
path: root/src/engine/gnump/gmp_elg.cpp
diff options
context:
space:
mode:
authorlloyd <[email protected]>2008-10-08 17:15:15 +0000
committerlloyd <[email protected]>2008-10-08 17:15:15 +0000
commitb36e1472df7f2da610ae865460647e2951afe58b (patch)
tree17b7bf28600eee011796a2f8152f54d607ccdc99 /src/engine/gnump/gmp_elg.cpp
parent60e7a9bea4bca8d4c7905129bd98b643da895ed0 (diff)
Split up GNU MP analagously with the OpenSSL change. GNU MP module can
now be built with any or all public key algorithms disabled.
Diffstat (limited to 'src/engine/gnump/gmp_elg.cpp')
-rw-r--r--src/engine/gnump/gmp_elg.cpp90
1 files changed, 90 insertions, 0 deletions
diff --git a/src/engine/gnump/gmp_elg.cpp b/src/engine/gnump/gmp_elg.cpp
new file mode 100644
index 000000000..63e9440ff
--- /dev/null
+++ b/src/engine/gnump/gmp_elg.cpp
@@ -0,0 +1,90 @@
+/*************************************************
+* GMP ElGamal Engine Source File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#include <botan/eng_gmp.h>
+#include <botan/gmp_wrap.h>
+#include <gmp.h>
+
+namespace Botan {
+
+#if defined(BOTAN_HAS_ELGAMAL)
+
+namespace {
+
+/*************************************************
+* GMP ElGamal Operation *
+*************************************************/
+class GMP_ELG_Op : public ELG_Operation
+ {
+ public:
+ SecureVector<byte> encrypt(const byte[], u32bit, const BigInt&) const;
+ BigInt decrypt(const BigInt&, const BigInt&) const;
+
+ ELG_Operation* clone() const { return new GMP_ELG_Op(*this); }
+
+ GMP_ELG_Op(const DL_Group& group, const BigInt& y1, const BigInt& x1) :
+ x(x1), y(y1), g(group.get_g()), p(group.get_p()) {}
+ private:
+ GMP_MPZ x, y, g, p;
+ };
+
+/*************************************************
+* GMP ElGamal Encrypt Operation *
+*************************************************/
+SecureVector<byte> GMP_ELG_Op::encrypt(const byte in[], u32bit length,
+ const BigInt& k_bn) const
+ {
+ GMP_MPZ i(in, length);
+
+ if(mpz_cmp(i.value, p.value) >= 0)
+ throw Invalid_Argument("GMP_ELG_Op: Input is too large");
+
+ GMP_MPZ a, b, k(k_bn);
+
+ mpz_powm(a.value, g.value, k.value, p.value);
+ mpz_powm(b.value, y.value, k.value, p.value);
+ mpz_mul(b.value, b.value, i.value);
+ mpz_mod(b.value, b.value, p.value);
+
+ const u32bit p_bytes = p.bytes();
+ SecureVector<byte> output(2*p_bytes);
+ a.encode(output, p_bytes);
+ b.encode(output + p_bytes, p_bytes);
+ return output;
+ }
+
+/*************************************************
+* GMP ElGamal Decrypt Operation *
+*************************************************/
+BigInt GMP_ELG_Op::decrypt(const BigInt& a_bn, const BigInt& b_bn) const
+ {
+ if(mpz_cmp_ui(x.value, 0) == 0)
+ throw Internal_Error("GMP_ELG_Op::decrypt: No private key");
+
+ GMP_MPZ a(a_bn), b(b_bn);
+
+ if(mpz_cmp(a.value, p.value) >= 0 || mpz_cmp(b.value, p.value) >= 0)
+ throw Invalid_Argument("GMP_ELG_Op: Invalid message");
+
+ mpz_powm(a.value, a.value, x.value, p.value);
+ mpz_invert(a.value, a.value, p.value);
+ mpz_mul(a.value, a.value, b.value);
+ mpz_mod(a.value, a.value, p.value);
+ return a.to_bigint();
+ }
+
+}
+
+/*************************************************
+* Acquire an ElGamal op *
+*************************************************/
+ELG_Operation* GMP_Engine::elg_op(const DL_Group& group, const BigInt& y,
+ const BigInt& x) const
+ {
+ return new GMP_ELG_Op(group, y, x);
+ }
+#endif
+
+}