93 lines
2.7 KiB
Ruby
93 lines
2.7 KiB
Ruby
![]() |
module Gitlab
|
||
|
class License
|
||
|
class Encryptor
|
||
|
class Error < StandardError; end
|
||
|
class KeyError < Error; end
|
||
|
class DecryptionError < Error; end
|
||
|
|
||
|
attr_accessor :key
|
||
|
|
||
|
def initialize(key)
|
||
|
raise KeyError, 'No RSA encryption key provided.' if key && !key.is_a?(OpenSSL::PKey::RSA)
|
||
|
|
||
|
@key = key
|
||
|
end
|
||
|
|
||
|
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::AES128.new(: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
|
||
|
|
||
|
def decrypt(data)
|
||
|
raise KeyError, 'Provided key is not a public key.' unless key.public?
|
||
|
|
||
|
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::AES128.new(: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
|
||
|
end
|
||
|
end
|
||
|
end
|