-
Notifications
You must be signed in to change notification settings - Fork 0
/
rsa.rb
70 lines (61 loc) · 1.48 KB
/
rsa.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
require 'openssl'
require_relative 'util'
class RSA
def initialize(prime_size=1024)
p = OpenSSL::BN::generate_prime(prime_size)
q = OpenSSL::BN::generate_prime(prime_size)
#p = OpenSSL::BN::generate_prime(100) # small numbers for testing - however it won't work if the message will be greater than n
#q = OpenSSL::BN::generate_prime(100)
@n = p*q
#puts p.to_i.to_s(2).length
#puts q.to_i.to_s(2).length
#puts @n.to_i.to_s(2).length
et = (p-1)*(q-1) # number of elements in Z_n*
@e = 3 # gcd(e, et) should be 1
@d = Util.invmod(et, @e)
# public key: [e, n]
# private key: [d, n]
end
def n
return @n
end
def e
return @e
end
def encrypt(m)
num = m.unpack("H*").join
num = num.to_i(16)
#c = num.to_bn.mod_exp(@e, @n)
c = num**@e % @n
c
end
def decrypt(c)
p = c.to_bn.mod_exp(@d, @n)
#p = c**@d % @n # seems that d is too big
p = p.to_s(16)
p = [p].pack("H*")
return p
end
def sign(m)
num = m.unpack("H*").join
num = num.to_i(16)
c = num.to_bn.mod_exp(@d, @n)
c
end
def verify(signature, hash)
p = signature.to_bn.mod_exp(@e, @n)
p = p.to_s(16)
p = [p].pack("H*")
pattern = '(?<=\xff\xff\xff\x00).*'
reg = Regexp.new(pattern, Regexp::MULTILINE, 'n')
m = reg.match(p)[0]
m = m[14..-1] # asn.1
hash_length = m[0].ord
extracted_hash = m[1..hash_length]
if extracted_hash == hash
return true
else
return false
end
end
end