Module: NdrPseudonymise::NdrEncrypt::EncryptedObject
- Defined in:
- lib/ndr_pseudonymise/ndr_encrypt/encrypted_object.rb
Overview
Defines utility methods for encrypting / decrypting objects
Class Method Summary collapse
-
.blob(data) ⇒ Object
rubocop:disable Style/SlicingWithRange.
-
.compress(blob) ⇒ Object
Create zlib-compressed version of the content.
-
.decompress(contents) ⇒ Object
Unpack zlib-compressed content.
-
.decrypt(rawdata, private_key: nil, passin: nil) ⇒ Object
Decrypt sensitive secret data, given a private key and its password Returns the decrypted output data TODO: write equivalent command-line method using only openssl and shell scripts TODO: Refactor with code from era UnifiedSources::ApiRetrieval::Extractor.
- .digest(blob) ⇒ Object
-
.encrypt(secret_data, pub_key: nil) ⇒ Object
Encrypt sensitive secret data, given a public key file as a String Returns the encrypted output data Result can either be decrypted using the decrypt method on this class.
- .encrypted_id(git_blobid, key_name: nil) ⇒ Object
- .get_passphrase(private_key: nil, passin: nil) ⇒ Object
- .unpack_blob(blob) ⇒ Object
Class Method Details
.blob(data) ⇒ Object
rubocop:disable Style/SlicingWithRange
11 12 13 |
# File 'lib/ndr_pseudonymise/ndr_encrypt/encrypted_object.rb', line 11 def self.blob(data) "blob #{data.size}\0#{data}" end |
.compress(blob) ⇒ Object
Create zlib-compressed version of the content
30 31 32 |
# File 'lib/ndr_pseudonymise/ndr_encrypt/encrypted_object.rb', line 30 def self.compress(blob) Zlib::Deflate.deflate(blob) end |
.decompress(contents) ⇒ Object
Unpack zlib-compressed content
35 36 37 |
# File 'lib/ndr_pseudonymise/ndr_encrypt/encrypted_object.rb', line 35 def self.decompress(contents) Zlib::Inflate.inflate(contents) end |
.decrypt(rawdata, private_key: nil, passin: nil) ⇒ Object
Decrypt sensitive secret data, given a private key and its password Returns the decrypted output data TODO: write equivalent command-line method using only openssl and shell scripts TODO: Refactor with code from era UnifiedSources::ApiRetrieval::Extractor
71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 |
# File 'lib/ndr_pseudonymise/ndr_encrypt/encrypted_object.rb', line 71 def self.decrypt(rawdata, private_key: nil, passin: nil) # We need to support ruby 2.0 so cannot use required keyword arguments syntax raise(ArgumentError, 'missing keyword: :private_key') unless private_key return nil unless rawdata password = get_passphrase(private_key: private_key, passin: passin) private_key_data = File.read(private_key) cipher = OpenSSL::Cipher.new('aes-256-cbc') cipher.decrypt private_key = OpenSSL::PKey::RSA.new(private_key_data, password) key_size = private_key.n.num_bytes cipher.key = private_key.private_decrypt(rawdata[0..key_size - 1]) cipher.iv = rawdata[key_size..key_size + 15] decrypted_data = cipher.update(rawdata[key_size + 16..-1]) decrypted_data << cipher.final end |
.digest(blob) ⇒ Object
25 26 27 |
# File 'lib/ndr_pseudonymise/ndr_encrypt/encrypted_object.rb', line 25 def self.digest(blob) Digest::SHA256.hexdigest(blob) end |
.encrypt(secret_data, pub_key: nil) ⇒ Object
Encrypt sensitive secret data, given a public key file as a String Returns the encrypted output data Result can either be decrypted using the decrypt method on this class. TODO: write equivalent command-line method using only openssl and shell scripts
51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 |
# File 'lib/ndr_pseudonymise/ndr_encrypt/encrypted_object.rb', line 51 def self.encrypt(secret_data, pub_key: nil) # We need to support ruby 2.0 so cannot use required keyword arguments syntax raise(ArgumentError, 'missing keyword: :pub_key') unless pub_key return nil unless secret_data public_key_data = File.read(pub_key) cipher = OpenSSL::Cipher.new('aes-256-cbc') cipher.encrypt cipher.key = random_key = cipher.random_key cipher.iv = random_iv = cipher.random_iv rawdata = cipher.update(secret_data) rawdata << cipher.final public_key = OpenSSL::PKey::RSA.new(public_key_data) public_key.public_encrypt(random_key) + random_iv + rawdata end |
.encrypted_id(git_blobid, key_name: nil) ⇒ Object
39 40 41 42 43 44 45 |
# File 'lib/ndr_pseudonymise/ndr_encrypt/encrypted_object.rb', line 39 def self.encrypted_id(git_blobid, key_name: nil) # We need to support ruby 2.0 so cannot use required keyword arguments syntax raise(ArgumentError, 'missing keyword: :key_name') unless key_name temp_id = "ndr_encrypt #{git_blobid} #{key_name}" digest(blob(temp_id)) end |
.get_passphrase(private_key: nil, passin: nil) ⇒ Object
88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 |
# File 'lib/ndr_pseudonymise/ndr_encrypt/encrypted_object.rb', line 88 def self.get_passphrase(private_key: nil, passin: nil) # We need to support ruby 2.0 so cannot use required keyword arguments syntax raise(ArgumentError, 'missing keyword: :private_key') unless private_key @passphrase_cache ||= {} return @passphrase_cache[private_key] if @passphrase_cache.key?(private_key) raise(ArgumentError, 'Missing private key file') unless File.exist?(private_key) # Implement a subset of the openssl -passin options in # https://www.openssl.org/docs/man3.0/man1/openssl-passphrase-options.html result = case passin when nil, '' msg = "Enter passphrase for #{private_key}: " if IO.console.respond_to?(:getpass) IO.console.getpass msg else $stdout.print msg password = $stdin.noecho(&:gets).chomp puts password end when /\Apass:/ passin[5..-1] when /\Aenv:/ ENV[passin[4..-1]] when 'stdin' $stdin.readline.chomp else raise(ArgumentError, 'Unsupported passin option') end @passphrase_cache[private_key] = result end |
.unpack_blob(blob) ⇒ Object
15 16 17 18 19 20 21 22 23 |
# File 'lib/ndr_pseudonymise/ndr_encrypt/encrypted_object.rb', line 15 def self.unpack_blob(blob) prefix, data = blob.split("\x00", 2) raise(ArgumentError, 'Invalid blob format') unless /\Ablob [0-9]+\z/ =~ prefix size = prefix[5..-1].to_i raise(ArgumentError, 'Incorrect blob size') unless size == data.size data end |