Class: Code0::License::Encryptor

Inherits:
Object
  • Object
show all
Defined in:
lib/code0/license/encryptor.rb

Overview

Contains the encryption logic. Decoupled from actual license logic

Defined Under Namespace

Classes: DecryptionError, Error, KeyError

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(key) ⇒ Encryptor

Returns a new instance of Encryptor.

Raises:



13
14
15
16
17
# File 'lib/code0/license/encryptor.rb', line 13

def initialize(key)
  raise KeyError, "No RSA encryption key provided." if key && !key.is_a?(OpenSSL::PKey::RSA)

  @key = key
end

Instance Attribute Details

#keyObject

Returns the value of attribute key.



11
12
13
# File 'lib/code0/license/encryptor.rb', line 11

def key
  @key
end

Instance Method Details

#decrypt(data) ⇒ Object

Raises:



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
83
84
85
86
87
88
89
90
91
92
93
# File 'lib/code0/license/encryptor.rb', line 43

def decrypt(data)
  raise KeyError, "Provided key is not a public key." unless key.public?
  raise DecryptionError, "Provided data is nil" if data.nil?

  json_data = Base64.decode64(data.chomp)

  begin
    encryption_data = JSON.parse(json_data)
  rescue JSON::ParserError
    raise DecryptionError, "Encryption data is invalid JSON."
  end

  unless %w[data key iv].all? { |key| encryption_data[key] }
    raise DecryptionError, "Required field missing from encryption data."
  end

  encrypted_data  = Base64.decode64(encryption_data["data"])
  encrypted_key   = Base64.decode64(encryption_data["key"])
  aes_iv          = Base64.decode64(encryption_data["iv"])

  begin
    # Decrypt the AES key using asymmetric RSA encryption.
    aes_key = self.key.public_decrypt(encrypted_key)
  rescue OpenSSL::PKey::RSAError
    raise DecryptionError, "AES encryption key could not be decrypted."
  end

  # Decrypt the data using symmetric AES encryption.
  cipher = OpenSSL::Cipher.new("aes-128-cbc")
  cipher.decrypt

  begin
    cipher.key = aes_key
  rescue OpenSSL::Cipher::CipherError
    raise DecryptionError, "AES encryption key is invalid."
  end

  begin
    cipher.iv = aes_iv
  rescue OpenSSL::Cipher::CipherError
    raise DecryptionError, "AES IV is invalid."
  end

  begin
    data = cipher.update(encrypted_data) + cipher.final
  rescue OpenSSL::Cipher::CipherError
    raise DecryptionError, "Data could not be decrypted."
  end

  data
end

#encrypt(data) ⇒ Object

Raises:



19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
# File 'lib/code0/license/encryptor.rb', line 19

def encrypt(data)
  raise KeyError, "Provided key is not a private key." unless key.private?

  # Encrypt the data using symmetric AES encryption.
  cipher = OpenSSL::Cipher.new("aes-128-cbc")
  cipher.encrypt
  aes_key = cipher.random_key
  aes_iv  = cipher.random_iv

  encrypted_data = cipher.update(data) + cipher.final

  # Encrypt the AES key using asymmetric RSA encryption.
  encrypted_key = key.private_encrypt(aes_key)

  encryption_data = {
    "data" => Base64.encode64(encrypted_data),
    "key" => Base64.encode64(encrypted_key),
    "iv" => Base64.encode64(aes_iv)
  }

  json_data = JSON.dump(encryption_data)
  Base64.encode64(json_data)
end