OKlibrary
0.2.1.6
|
00001 // Oliver Kullmann, 6.11.2004 (Swansea) 00002 /* Copyright 2004 - 2007 Oliver Kullmann 00003 This file is part of the OKlibrary. OKlibrary is free software; you can redistribute 00004 it and/or modify it under the terms of the GNU General Public License as published by 00005 the Free Software Foundation and included in this library; either version 3 of the 00006 License, or any later version. */ 00007 00018 #ifndef ALGEBRAWAECHTER_jbbZ3y7 00019 00020 #define ALGEBRAWAECHTER_jbbZ3y7 00021 00022 #include <functional> 00023 #include <cassert> 00024 #include <ostream> 00025 00026 #include <OKlib/General/NumberTheory_Models.hpp> 00027 #include <OKlib/General/Algorithms.hpp> 00028 00029 namespace Algebra { 00030 00031 // OK, 7.11.2004 00032 template <typename Int> 00033 struct Normed_remainder : std::unary_function<Int, Int> { 00034 const Int n; 00035 Normed_remainder(const Int n) : n(n) { 00036 assert(n > 0); 00037 } 00038 Int operator() (Int x) const { 00039 if (x < 0) { 00040 x = -x; x %= n; 00041 if (x != 0) 00042 x = n - x; 00043 } 00044 else 00045 x %= n; 00046 assert(x >= 0); 00047 assert(x < n); 00048 return x; 00049 } 00050 }; 00051 template <typename Int> 00052 inline Int normed_remainder(const Int x, const Int n) { 00053 return (Normed_remainder<Int>(n))(x); 00054 } 00055 00056 // ##################################################### 00057 00058 template <unsigned long int modulus, typename Int> 00059 class Z_mod_n { 00060 // TO IMPROVE: Generalising "unsigned long int". 00061 // TO IMPROVE: Recognising moduli which are too large (at compile time). 00062 Int x; 00063 typedef NumberTheory::Gcd_extended<Int> Gcd_e; 00064 public : 00065 Z_mod_n() : x(Int(0)) {} 00066 explicit Z_mod_n(Int x) : x(normed_remainder(x, Int(modulus))) {} 00067 00068 Z_mod_n& operator +=(Z_mod_n y) { 00069 assert(x >= 0); 00070 assert(x < Int(modulus)); 00071 x += y.x; 00072 if (x >= Int(modulus)) 00073 x -= Int(modulus); 00074 return *this; 00075 } 00076 Z_mod_n& operator *=(Z_mod_n y) { 00077 assert(x >= 0); 00078 assert(x < Int(modulus)); 00079 x *= y.x; 00080 x %= Int(modulus); 00081 return *this; 00082 } 00083 Z_mod_n& operator -=(Z_mod_n y) { 00084 assert(x >= 0); 00085 assert(x < Int(modulus)); 00086 x -= y.x; 00087 if (x < Int(0)) 00088 x += Int(modulus); 00089 return *this; 00090 } 00091 bool invert() { 00092 assert(x >= 0); 00093 assert(x < Int(modulus)); 00094 const typename Gcd_e::result_type gcd_extended = Gcd_e()(x, Int(modulus)); 00095 if (gcd_extended.c != Int(1)) 00096 return false; 00097 x = gcd_extended.x; 00098 if (x < Int(0)) 00099 x += Int(modulus); 00100 return true; 00101 } 00102 Z_mod_n& operator /=(Z_mod_n y) { 00103 assert(x >= 0); 00104 assert(x < Int(modulus)); 00105 const bool invertible = y.invert(); 00106 assert(invertible); 00107 x *= y.x; 00108 x %= Int(modulus); 00109 return *this; 00110 } 00111 static const Z_mod_n null() { 00112 return Z_mod_n(Int(0)); 00113 } 00114 static const Z_mod_n unit() { 00115 return Z_mod_n(Int(1)); 00116 } 00117 00118 friend inline bool operator ==(const Z_mod_n lhs, const Z_mod_n rhs) { 00119 return lhs.x == rhs.x; 00120 } 00121 00122 friend inline std::ostream& operator <<(std::ostream& out, Z_mod_n<modulus, Int> x) { 00123 return out << x.x; 00124 } 00125 00126 }; 00127 00128 template <unsigned long int modulus, typename Int> 00129 inline Z_mod_n<modulus, Int> operator +(const Z_mod_n<modulus, Int> a, const Z_mod_n<modulus, Int> b) { 00130 Z_mod_n<modulus, Int> r(a); 00131 r += b; 00132 return r; 00133 } 00134 template <unsigned long int modulus, typename Int> 00135 inline Z_mod_n<modulus, Int> operator *(const Z_mod_n<modulus, Int> a, const Z_mod_n<modulus, Int> b) { 00136 Z_mod_n<modulus, Int> r(a); 00137 r *= b; 00138 return r; 00139 } 00140 template <unsigned long int modulus, typename Int> 00141 inline Z_mod_n<modulus, Int> operator -(const Z_mod_n<modulus, Int> a, const Z_mod_n<modulus, Int> b) { 00142 Z_mod_n<modulus, Int> r(a); 00143 r -= b; 00144 return r; 00145 } 00146 template <unsigned long int modulus, typename Int> 00147 inline Z_mod_n<modulus, Int> operator -(const Z_mod_n<modulus, Int> a) { 00148 Z_mod_n<modulus, Int> r(Int(0)); 00149 r -= a; 00150 return r; 00151 } 00152 template <unsigned long int modulus, typename Int> 00153 inline Z_mod_n<modulus, Int> operator /(const Z_mod_n<modulus, Int> a, const Z_mod_n<modulus, Int> b) { 00154 assert((Z_mod_n<modulus, Int>(b).invert())); 00155 Z_mod_n<modulus, Int> r(a); 00156 r /= b; 00157 return r; 00158 } 00159 00160 template <unsigned long int modulus, typename Int> 00161 inline bool operator !=(const Z_mod_n<modulus, Int> a, const Z_mod_n<modulus, Int> b) { 00162 return not(a == b); 00163 } 00164 00165 00166 } 00167 00168 namespace Algebra_Traits { 00169 00170 template <unsigned long int modulus, typename Int> 00171 struct MultiplicativeGroupoid_traits<Algebra::Z_mod_n<modulus, Int> > { 00172 typedef Algebra::Z_mod_n<modulus, Int> value_type; 00173 static value_type identity() { return value_type(1); } 00174 static bool invertible(value_type x) { return x.invert(); } 00175 static value_type inverse (value_type x) { 00176 const bool invertible = x.invert(); 00177 assert(invertible); 00178 return x; 00179 } 00180 }; 00181 } 00182 00183 // ##################################################### 00184 00185 namespace Algebra { 00186 00187 template <typename Int = long int> 00188 class Zmodn { 00189 // TO IMPROVE: Needs proper design. 00190 Int x; 00191 typedef NumberTheory::Gcd_extended<Int> Gcd_e; 00192 public : 00193 static Int modulus; 00194 Zmodn() : x(Int(0)) {} 00195 explicit Zmodn(Int x) : x(normed_remainder(x, Int(modulus))) {} 00196 Int rem() const { return x; } 00197 00198 Zmodn& operator +=(Zmodn y) { 00199 assert(x >= 0); 00200 assert(x < Int(modulus)); 00201 x += y.x; 00202 if (x >= Int(modulus)) 00203 x -= Int(modulus); 00204 return *this; 00205 } 00206 Zmodn& operator *=(Zmodn y) { 00207 assert(x >= 0); 00208 assert(x < Int(modulus)); 00209 x *= y.x; 00210 x %= Int(modulus); 00211 return *this; 00212 } 00213 Zmodn& operator -=(Zmodn y) { 00214 assert(x >= 0); 00215 assert(x < Int(modulus)); 00216 x -= y.x; 00217 if (x < Int(0)) 00218 x += Int(modulus); 00219 return *this; 00220 } 00221 bool invert() { 00222 assert(x >= 0); 00223 assert(x < Int(modulus)); 00224 const typename Gcd_e::result_type gcd_extended = Gcd_e()(x, Int(modulus)); 00225 if (gcd_extended.c != Int(1)) 00226 return false; 00227 x = gcd_extended.x; 00228 if (x < Int(0)) 00229 x += Int(modulus); 00230 return true; 00231 } 00232 Zmodn& operator /=(Zmodn y) { 00233 assert(x >= 0); 00234 assert(x < Int(modulus)); 00235 assert(y.invert()); 00236 x *= y.x; 00237 x %= Int(modulus); 00238 return *this; 00239 } 00240 static const Zmodn null() { 00241 return Zmodn(Int(0)); 00242 } 00243 static const Zmodn unit() { 00244 return Zmodn(Int(1)); 00245 } 00246 00247 friend inline bool operator ==(const Zmodn lhs, const Zmodn rhs) { 00248 return lhs.x == rhs.x; 00249 } 00250 00251 friend inline std::ostream& operator <<(std::ostream& out, Zmodn<Int> x) { 00252 return out << x.x; 00253 } 00254 00255 }; 00256 00257 template <typename Int> 00258 Int Zmodn<Int>::modulus(1); 00259 00260 template <typename Int> 00261 inline Zmodn<Int> operator +(const Zmodn<Int> a, const Zmodn<Int> b) { 00262 Zmodn<Int> r(a); 00263 r += b; 00264 return r; 00265 } 00266 template <typename Int> 00267 inline Zmodn<Int> operator *(const Zmodn<Int> a, const Zmodn<Int> b) { 00268 Zmodn<Int> r(a); 00269 r *= b; 00270 return r; 00271 } 00272 template <typename Int> 00273 inline Zmodn<Int> operator -(const Zmodn<Int> a, const Zmodn<Int> b) { 00274 Zmodn<Int> r(a); 00275 r -= b; 00276 return r; 00277 } 00278 template <typename Int> 00279 inline Zmodn<Int> operator -(const Zmodn<Int> a) { 00280 Zmodn<Int> r(Int(0)); 00281 r -= a; 00282 return r; 00283 } 00284 template <typename Int> 00285 inline Zmodn<Int> operator /(const Zmodn<Int> a, const Zmodn<Int> b) { 00286 assert((Zmodn<Int>(b).invert())); 00287 Zmodn<Int> r(a); 00288 r /= b; 00289 return r; 00290 } 00291 00292 template <typename Int> 00293 inline bool operator !=(const Zmodn<Int> a, const Zmodn<Int> b) { 00294 return not(a == b); 00295 } 00296 00297 00298 } 00299 00300 namespace Algebra_Traits { 00301 00302 template <typename Int> 00303 struct MultiplicativeGroupoid_traits<Algebra::Zmodn<Int> > { 00304 typedef Algebra::Zmodn<Int> value_type; 00305 static value_type identity() { return value_type(1); } 00306 static bool invertible(value_type x) { return x.invert(); } 00307 static value_type inverse (value_type x) { 00308 const bool invertible = x.invert(); 00309 assert(invertible); 00310 return x; 00311 } 00312 }; 00313 } 00314 00315 // ##################################################### 00316 00317 namespace Algebra { 00318 00319 template <typename Int = long int> 00320 struct RSA { 00321 00322 typedef Int int_type; 00323 const int_type p, q; 00324 const int_type n, N; 00325 00326 typedef Zmodn<Int> mod_type; // We need *two* different types or objects here (for the 2 moduli) ! 00327 bool dummy; 00328 00329 const mod_type e, d; 00330 00331 RSA(const int_type p_, const int_type q_, const int_type e_) : p(p_), q(q_), n(p * q), N((p-1) * (q-1)), dummy(set_temp_modulus()), e(e_), d(mod_type(1) / e) { 00332 // assert p, q are prime numbers 00333 mod_type::modulus = n; 00334 } 00335 00336 mod_type encrypt(const int_type plaintext) const { 00337 return Algorithms::power_natural(mod_type(plaintext), e.rem()); 00338 } 00339 mod_type decrypt(const int_type plaintext) const { 00340 return Algorithms::power_natural(mod_type(plaintext), d.rem()); 00341 } 00342 00343 private : 00344 00345 bool set_temp_modulus() { 00346 mod_type::modulus = N; 00347 return true; 00348 } 00349 }; 00350 00351 } 00352 00353 #endif