Class: Slosilo::Key

Inherits:
Object
  • Object
show all
Defined in:
lib/slosilo/key.rb

Constant Summary collapse

SIGNATURE_LEN =
256

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(raw_key = nil) ⇒ Key

Returns a new instance of Key.



8
9
10
11
12
13
14
15
16
# File 'lib/slosilo/key.rb', line 8

def initialize raw_key = nil
  @key = if raw_key.is_a? OpenSSL::PKey::RSA
    raw_key
  elsif !raw_key.nil?
    OpenSSL::PKey.read raw_key
  else
    OpenSSL::PKey::RSA.new 2048
  end
end

Instance Attribute Details

#keyObject (readonly)

Returns the value of attribute key.



18
19
20
# File 'lib/slosilo/key.rb', line 18

def key
  @key
end

Instance Method Details

#==(other) ⇒ Object Also known as: eql?



92
93
94
# File 'lib/slosilo/key.rb', line 92

def == other
  to_der == other.to_der
end

#cipherObject



20
21
22
# File 'lib/slosilo/key.rb', line 20

def cipher
  @cipher ||= Slosilo::Symmetric.new
end

#decrypt(ciphertext, skey) ⇒ Object



36
37
38
39
# File 'lib/slosilo/key.rb', line 36

def decrypt ciphertext, skey
  key = @key.private_decrypt skey
  cipher.decrypt ciphertext, key: key
end

#decrypt_message(ciphertext) ⇒ Object



41
42
43
44
# File 'lib/slosilo/key.rb', line 41

def decrypt_message ciphertext
  k, c = ciphertext.unpack("A256A*")
  decrypt c, k
end

#encrypt(plaintext) ⇒ Object



24
25
26
27
28
29
# File 'lib/slosilo/key.rb', line 24

def encrypt plaintext
  key = cipher.random_key
  ctxt = cipher.encrypt plaintext, key: key
  key = @key.public_encrypt key
  [ctxt, key]
end

#encrypt_message(plaintext) ⇒ Object



31
32
33
34
# File 'lib/slosilo/key.rb', line 31

def encrypt_message plaintext
  c, k = encrypt plaintext
  k + c
end

#fingerprintObject



88
89
90
# File 'lib/slosilo/key.rb', line 88

def fingerprint
  @fingerprint ||= OpenSSL::Digest::MD5.hexdigest key.public_key.to_der
end

#hashObject



98
99
100
# File 'lib/slosilo/key.rb', line 98

def hash
  to_der.hash
end

#private?Boolean

checks if the keypair contains a private key

Returns:

  • (Boolean)


108
109
110
# File 'lib/slosilo/key.rb', line 108

def private?
  @key.private?
end

#publicObject

return a new key with just the public part of this



103
104
105
# File 'lib/slosilo/key.rb', line 103

def public
  Key.new(@key.public_key)
end

#sign(value) ⇒ Object



54
55
56
# File 'lib/slosilo/key.rb', line 54

def sign value
  sign_string(stringify value)
end

#sign_string(value) ⇒ Object



83
84
85
86
# File 'lib/slosilo/key.rb', line 83

def sign_string value
  salt = shake_salt
  key.private_encrypt(hash_function.digest(salt + value)) + salt
end

#signed_token(data) ⇒ Object

create a new timestamped and signed token carrying data



68
69
70
71
72
73
# File 'lib/slosilo/key.rb', line 68

def signed_token data
  token = { "data" => data, "timestamp" => Time.new.utc.to_s }
  token["signature"] = Base64::urlsafe_encode64(sign token)
  token["key"] = fingerprint
  token
end

#to_derObject



50
51
52
# File 'lib/slosilo/key.rb', line 50

def to_der
  @to_der ||= @key.to_der
end

#to_sObject



46
47
48
# File 'lib/slosilo/key.rb', line 46

def to_s
  @key.public_key.to_pem
end

#token_valid?(token, expiry = 8 * 60) ⇒ Boolean

Returns:

  • (Boolean)


75
76
77
78
79
80
81
# File 'lib/slosilo/key.rb', line 75

def token_valid? token, expiry = 8 * 60
  token = token.clone
  expected_key = token.delete "key"
  return false if (expected_key and (expected_key != fingerprint))
  signature = Base64::urlsafe_decode64(token.delete "signature")
  (Time.parse(token["timestamp"]) + expiry > Time.now) && verify_signature(token, signature)
end

#verify_signature(data, signature) ⇒ Object



60
61
62
63
64
65
# File 'lib/slosilo/key.rb', line 60

def verify_signature data, signature
  signature, salt = signature.unpack("a#{SIGNATURE_LEN}a*")
  key.public_decrypt(signature) == hash_function.digest(salt + stringify(data))
rescue
  false
end