forked from hotsh/rstat.us
-
Notifications
You must be signed in to change notification settings - Fork 0
/
crypto.rb
82 lines (62 loc) · 1.75 KB
/
crypto.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
71
72
73
74
75
76
77
78
79
80
81
82
require 'openssl'
require 'rsa'
KeyPair = Struct.new(:public_key, :private_key)
module Crypto
extend self
def generate_keypair
keypair = KeyPair.new
key = RSA::KeyPair.generate(2048)
public_key = key.public_key
m = public_key.modulus
e = public_key.exponent
modulus = ""
until m == 0 do
modulus << [m % 256].pack("C")
m >>= 8
end
modulus.reverse!
exponent = ""
until e == 0 do
exponent << [e % 256].pack("C")
e >>= 8
end
exponent.reverse!
keypair.public_key = "RSA.#{Base64::urlsafe_encode64(modulus)}.#{Base64::urlsafe_encode64(exponent)}"
tmp_private_key = key.private_key
m = tmp_private_key.modulus
e = tmp_private_key.exponent
modulus = ""
until m == 0 do
modulus << [m % 256].pack("C")
m >>= 8
end
modulus.reverse!
exponent = ""
until e == 0 do
exponent << [e % 256].pack("C")
e >>= 8
end
exponent.reverse!
keypair.private_key = "RSA.#{Base64::urlsafe_encode64(modulus)}.#{Base64::urlsafe_encode64(exponent)}"
keypair
end
# We don't yet do anything with the public key, but I added it so that when we
# need to, it'll be there.
def self.make_rsa_keypair(public_key, private_key)
private_key = generate_key(private_key)
public_key = generate_key(public_key)
RSA::KeyPair.new(private_key, public_key)
end
private
def generate_key(key_string)
return nil unless key_string
key_string.match /^RSA\.(.*?)\.(.*)$/
modulus = decode_key($1)
exponent = decode_key($2)
RSA::Key.new(modulus, exponent)
end
def decode_key(encoded_key_part)
modulus = Base64::urlsafe_decode64(encoded_key_part)
modulus.bytes.inject(0) {|num, byte| (num << 8) | byte }
end
end