|
require 'socket' |
|
|
|
#http://www.scribd.com/doc/34203336/How-to-Implement-RSA-in-Ruby#download |
|
# Calculate a modular exponentiation eg: b^p mod m |
|
def mod_pow(base, power, mod) |
|
result = 1 |
|
while power > 0 |
|
result = (result * base) % mod if power & 1 == 1 |
|
base = (base * base) % mod |
|
power >>= 1 |
|
end |
|
result |
|
end |
|
|
|
# Convert a string into a big number |
|
def str_to_bignum(s) |
|
n = 0 |
|
s.each_byte {|b|n=n*256+b} |
|
n |
|
end |
|
|
|
# Convert a bignum to a string |
|
def bignum_to_str(n) |
|
s="" |
|
while n>0 |
|
s = (n&0xff).chr + s |
|
n >>= 8 |
|
end |
|
s |
|
end |
|
|
|
#http://rosettacode.org/wiki/Modular_inverse#Ruby |
|
#based on pseudo code from http://en.wikipedia.org/wiki/Extended_Euclidean_algorithm#Iterative_method_2 and from translating the python implementation. |
|
def extended_gcd(a, b) |
|
last_remainder, remainder = a.abs, b.abs |
|
x, last_x, y, last_y = 0, 1, 1, 0 |
|
while remainder != 0 |
|
last_remainder, (quotient, remainder) = remainder, last_remainder.divmod(remainder) |
|
x, last_x = last_x - quotient*x, x |
|
y, last_y = last_y - quotient*y, y |
|
end |
|
|
|
return last_remainder, last_x * (a < 0 ? -1 : 1) |
|
end |
|
|
|
def invmod(e, et) |
|
g, x = extended_gcd(e, et) |
|
if g != 1 |
|
raise 'Teh maths are broken!' |
|
end |
|
x % et |
|
end |
|
|
|
|
|
#puts variable name and value |
|
def debug(sym) |
|
puts "#{sym} is #{eval sym.to_s, TOPLEVEL_BINDING}" |
|
end |
|
|
|
if ARGV.size < 2 |
|
puts "usages: ruby socialist_milli.rb <ip address> <secret> <optional:your port:default 44444> <optional:their_port:default 44444>" |
|
exit 1 |
|
end |
|
|
|
begin |
|
socket = TCPSocket.new ARGV[0], ARGV[3] || 44444 |
|
guy2 = true |
|
rescue |
|
server = TCPServer.new ARGV[2] || 44444 |
|
socket = server.accept |
|
guy2 = false |
|
end |
|
|
|
# A prime and a generator (primitive root) for that prime. |
|
# Can be same as OTR: http://www.ietf.org/rfc/rfc3526.txt |
|
#prime = 0xFFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA237327FFFFFFFFFFFFFFFF |
|
prime = 97 |
|
h = 5 |
|
|
|
x = str_to_bignum ARGV[1] |
|
puts "your secret num is #{x}" |
|
|
|
a = guy2 ? 4 : 2 |
|
alpha = guy2 ? 5 : 3 |
|
r = guy2 ? 6 : 9 |
|
|
|
h_to_the_a = mod_pow(h,a,prime) |
|
socket.puts h_to_the_a |
|
|
|
h_to_the_b = socket.gets.to_i |
|
g = mod_pow(h_to_the_b, a, prime) |
|
debug :g |
|
|
|
h_to_the_alpha = mod_pow(h,alpha,prime) |
|
socket.puts h_to_the_alpha |
|
|
|
h_to_the_beta = socket.gets.to_i |
|
gamma = mod_pow(h_to_the_beta, alpha, prime) |
|
debug :gamma |
|
|
|
p = mod_pow(gamma,r,prime) |
|
socket.puts p |
|
|
|
q = socket.gets.to_i |
|
|
|
debug :p |
|
debug :q |
|
|
|
t = q*invmod(p, prime) % prime |
|
debug :t |
|
|
|
p_prime = (mod_pow(h,r,prime)*mod_pow(h,x,prime)) % prime |
|
socket.puts p_prime |
|
|
|
q_prime = socket.gets.to_i |
|
debug :p_prime |
|
debug :q_prime |
|
|
|
|
|
p_prime_q_prime_inverse_to_the_alpha = mod_pow(((p_prime*invmod(q_prime, prime)) % prime),alpha, prime) |
|
socket.puts p_prime_q_prime_inverse_to_the_alpha |
|
|
|
p_prime_q_prime_inverse_to_the_beta = socket.gets.to_i |
|
debug :p_prime_q_prime_inverse_to_the_beta |
|
c = mod_pow(p_prime_q_prime_inverse_to_the_beta,alpha,prime) |
|
debug :c |
|
|
|
puts c == t |