Skip to content

Instantly share code, notes, and snippets.

@PRotondo
Created April 17, 2013 02:24
Show Gist options
  • Save PRotondo/98d4fe29ada864c8beac to your computer and use it in GitHub Desktop.
Save PRotondo/98d4fe29ada864c8beac to your computer and use it in GitHub Desktop.
Chat in Ruby using a home-made RSA.
%w(socket net/http thread monitor cmath ./rsa).map(&method(:require))
from_server = RSA.new
n,e = from_server.get_params
puts "Encryption system ready!"
server = TCPSocket.new 'localhost', 2000 # change this part
a = server.gets.to_i
b = server.gets.to_i
server.puts n, e
to_server = RSA.new(a,b)
puts "Welcome to the chat!", "What is your name?"
name = gets.strip
server.puts to_server.encrypt(name)
puts "Welcome #{name}"
id = Thread.start(server) do |server|
loop do
s = server.gets.strip
s = from_server.decrypt(s)
puts s
end
end
loop do
s = gets.strip
s = to_server.encrypt(s)
server.puts s
end
%w(socket net/http thread cmath ./rsa).map(&method(:require))
server = TCPServer.new 2000 # choose your port
mutex = Mutex.new
keys = []
users = []
from_client = RSA.new
n,e = from_client.get_params
id = 0
puts "Server ready!"
loop do
Thread.start(server.accept,id) do |client,id|
client.puts n,e
mutex.synchronize { users << Queue.new; keys << RSA.new(client.gets.to_i,client.gets.to_i) }
name = from_client.decrypt(client.gets.strip)
puts name
mutex.synchronize do
users.each do |q|
q << ["System",-1,"#{name} has entered the room."]
end
end
writer = Thread.new do
loop do
user, src, message = users[id].pop
mutex.synchronize do
client.puts keys[id].encrypt("#{user}> #{message}") if src != id
end
end
end
loop do
s = client.gets.strip
s = from_client.decrypt(s)
puts "#{name}> #{s}"
mutex.synchronize do
users.each do |q|
q << [name,id,s]
end
end
end
end
id += 1
end
class RSA
NUM = 100
MAX = 10**NUM
LEN = (NUM / CMath::log10(256)).floor
def initialize(*args)
if args.length == 0
arr = []
while arr.size < 2
p = rand(MAX..(2*MAX))
arr << p if prime(p)
end
@n = arr.inject(1,:*)
@m = (arr[0]-1)*(arr[1]-1)
loop do
a = rand(2..MAX)
if @m.gcd(a) == 1
@e = a
break
end
end
@u = euclid(@e,@m).first % @m
@mode = :decrypt
else
@n = args[0]; @e = args[1]; @mode = :encrypt
end
end
def encrypt(s)
raise "Wrong mode!" if @mode != :encrypt
s.bytes.to_a.each_slice(LEN).map{|r| ex r.to_a.reverse.inject(0){|ac,x| ac*256 + x }, @e, @n }.map(&:to_s).join(" ")
end
def decrypt(s)
raise "Wrong mode!" if @mode != :decrypt
res = s.split.map(&:to_i).map do |x|
y = ex x, @u, @n
ans = []
while y > 0
ans.unshift (y % 256).chr
y /= 256
end
ans.join.reverse
end
res.join
end
def get_params
raise "Wrong mode!" if @mode != :decrypt
[@n,@e]
end
private
def ex(a,n,m)
ans = 1
while n > 0
ans = (ans*a) % m if (n & 1) == 1
a = (a*a)%m
n >>= 1
end
ans
end
def prime(p)
k = p - 1
50.times do
a = rand(2..k)
return false if ex(a,k,p) != 1
end
true
end
def euclid(x,y)
return euclid(y,x).reverse if y > x
return [0,1] if (x % y) == 0
b,a = euclid(y,x%y)
[a,b-a*(x/y)]
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment