# # a full-ruby rsa implementation # (c) 01/2008 Yoann Guillot # this code is licenced under the terms of the WTFPL (sam.zoy.org/wtfpl/) # class RSA attr_accessor :privkey, :pubkey, :modulus # accepts bignums, hex strings or raw strings (check #bigint) def initialize(privkey, pubkey, modulus) @privkey = bigint privkey @pubkey = bigint pubkey @modulus = bigint modulus end def decode(msg) msg = bigint msg r = RSA.modexp(msg, @privkey, @modulus) RSA.bigint2str(r) end def encode(msg) msg = bigint msg r = RSA.modexp(msg, @pubkey, @modulus) RSA.bigint2str(r) end def self.str2bigint(str) res = 0 str.each_byte { |b| res <<= 8 res |= b } res end def self.bigint2str(i) str = '' while i > 0 str << (i & 0xff) i >>= 8 end str.reverse end # full ruby modular exponentiation # from a source found on some ruby-lang thread def self.modexp(x, e, n) return 1%n if e == 0 # bit size of e k = 0 k += 1 while (e >> k) > 0 y = x (k-2).downto(0) { |i| y = (y*y) % n y = (y*x) % n if e[i] == 1 } y end def self.hex2bigint(h) h = '0' + h if h.length % 2 == 1 RSA.str2bigint(h.scan(/../).map { |c| c.hex }.pack('C*')) end # calls hex2bigint or str2bigint def bigint(i) case i when /^[0-9a-fA-F]*$/: RSA.hex2bigint(i) when ::String: RSA.str2bigint(i) when ::Integer: i else raise end end end