Class: Cryptograpi::Decryption
- Inherits:
-
Object
- Object
- Cryptograpi::Decryption
- Defined in:
- lib/cryptograpi_ruby/decrypt.rb
Instance Method Summary collapse
- #begin_decryption ⇒ Object
- #close_decryption ⇒ Object
- #endpoint ⇒ Object
- #endpoint_base ⇒ Object
- #finish_decryption ⇒ Object
-
#initialize(creds) ⇒ Decryption
constructor
A new instance of Decryption.
- #update_decryption(data) ⇒ Object
Constructor Details
#initialize(creds) ⇒ Decryption
Returns a new instance of Decryption.
11 12 13 14 15 16 17 18 19 20 21 |
# File 'lib/cryptograpi_ruby/decrypt.rb', line 11 def initialize(creds) raise 'Some credentials are missing' unless validate_credentials(creds) @papi = creds.access_key_id @sapi = creds.signing_key @srsa = creds.secret_access_key @host = creds.host.blank? ? CRYPTOGRAPI_HOST : creds.host @decryption_started = false @decryption_ready = true end |
Instance Method Details
#begin_decryption ⇒ Object
23 24 25 26 27 28 29 30 31 32 |
# File 'lib/cryptograpi_ruby/decrypt.rb', line 23 def begin_decryption raise ' Decryption is not ready' unless @decryption_ready raise ' Decryption already started' if @decryption_started raise 'Decryption already in progress' if @key.present? && @key.key?('dec') @decryption_started = true @data = '' end |
#close_decryption ⇒ Object
154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 |
# File 'lib/cryptograpi_ruby/decrypt.rb', line 154 def close_decryption raise 'Decryption currently running' if @decryption_started # Reset the decryption object if @key.present? if @key['uses'].positive? query_url = "#{endpoint}/#{@key['finger_print']}/#{@key['session']}" url = "#{endpoint_base}/decryption/key/#{@key['finger_print']}/#{@key['session']}" query = { uses: @key['uses'] } headers = Signature.headers(query_url, @host, 'patch', @papi, query, @sapi) response = HTTParty.patch( url, body: query.to_json, headers: headers ) remove_instance_variable(:@data) remove_instance_variable(:@key) end end end |
#endpoint ⇒ Object
177 178 179 |
# File 'lib/cryptograpi_ruby/decrypt.rb', line 177 def endpoint '/api/v0/encryption/key' end |
#endpoint_base ⇒ Object
181 182 183 |
# File 'lib/cryptograpi_ruby/decrypt.rb', line 181 def endpoint_base "#{@host}/api/v0" end |
#finish_decryption ⇒ Object
128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 |
# File 'lib/cryptograpi_ruby/decrypt.rb', line 128 def finish_decryption raise 'Decryption is not started' unless @decryption_started # Update maintains tag-size bytes in the buffer # When this function is called, all data must already be # in the decryption object sz = @data.length - @cipher[:tag_length] raise 'Invalid Tag!' if sz.negative? if sz.zero? @key['dec'].auth_tag = @data begin plain_text = @key['dec'].final # Delete the context @key.delete('dec') # Return the plain text @decryption_started = false plain_text rescue Exception print 'Invalid cipher data or tag!' '' end end end |
#update_decryption(data) ⇒ Object
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 83 84 85 86 87 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 121 122 123 124 125 126 |
# File 'lib/cryptograpi_ruby/decrypt.rb', line 34 def update_decryption(data) raise ' Decryption is not started' unless @decryption_started # Act as a buffer for data @data += data # If there is no key or dec member of key, a header is still being built if !@key.present? || !@key.key?('dec') struct_length = [1, 1, 1, 1, 1].pack('CCCCn').length packed_struct = @data[0...struct_length] # Does the buffer contain enough of the header to determine # the lengths of the initialization vector and the key? if @data.length > struct_length version, flags, algorithm_id, iv_length, key_length = packed_struct.unpack('CCCCn') raise 'Invalid encryption header' if (version != 0) || ((flags & ~Cipher::CRYPTOFLAG) != 0) if @data.length > struct_length + iv_length + key_length # Extract the initialization vector iv = @data[struct_length...iv_length + struct_length] # Extract the encrypted key enc_key = @data[struct_length + iv_length..key_length + struct_length + iv_length] # Remove the header from the buffer @data = @data[struct_length + iv_length + key_length..-1] # Generate a key identifier hash_sha512 = OpenSSL::Digest.new('SHA512') hash_sha512 << enc_key client_id = hash_sha512.digest if @key.present? close if @key['client_id'] != client_id end unless @key.present? url = endpoint_base + '/decrypt/key' query = { encrypted_data_key: Base64.strict_encode64(enc_key) } headers = Signature.headers(endpoint, @host, 'post', @papi, query, @sapi) response = HTTParty.post( url, body: query.to_json, headers: headers ) if response.code == WEBrick::HTTPStatus::RC_OK @key = {} @key['finger_print'] = response[key_fingerprint] @key['client_id'] = client_id @key['session'] = response['encryption_session'] # Get the cipher name @key['algorithm'] = Cipher.new.find_algorithm(algorithm_id) encrypted_private_key = response['encrypted_private_key'] # Decrypt WDK from base64 wdk = Base64.strict_decode64(wrapped_data_key) # Use private key to decrypt the wdk dk = private_key.private_decrypt(wdk, OpenSSL::PKey::RSA::PKCS1_OAEP_PADDING) @key['raw'] = dk @key['uses'] = 0 else raise "HTTPError response: Expected 201 got #{response.code}" end end # If the key object exists, create a new decryptor. # Increment the key usage if @key.present? @cipher = Cipher.new.get_algorithm(@key['algorithm']) @key['dec'] = Cipher.new.decryptor(@cipher, @key['raw'], iv) if (flags & Cipher::CRYPTOFLAG) != 0 @key['dec'].auth_data = packed_struct + iv + enc_key end @key['uses'] += 1 end end end end plain_text = '' if @key.present? && @key.key?('dec') size = @data.length - @cipher[:tag_length] if size.positive? plain_text = @key['dec'].update(@data[0..size - 1]) @data = @data[size..-1] end plain_text end end |