lib/kms_encrypted/model.rb in kms_encrypted-0.2.0 vs lib/kms_encrypted/model.rb in kms_encrypted-0.3.0

- old
+ new

@@ -51,26 +51,40 @@ elsif key_id.start_with?("projects/") # generate random AES-256 key plaintext_key = OpenSSL::Random.random_bytes(32) # encrypt it + # load client first to ensure namespace is loaded + client = KmsEncrypted.google_client request = ::Google::Apis::CloudkmsV1::EncryptRequest.new( plaintext: plaintext_key, additional_authenticated_data: context.to_json ) - response = KmsEncrypted::Google.kms_client.encrypt_crypto_key(key_id, request) + response = client.encrypt_crypto_key(key_id, request) key_version = response.name # shorten key to save space - short_key_id = Base64.encode64(key_version.split("/").select.with_index { |p, i| i.odd? }.join("/")) + short_key_id = Base64.encode64(key_version.split("/").select.with_index { |_, i| i.odd? }.join("/")) # build encrypted key # we reference the key in the field for easy rotation encrypted_key = "$gc$#{short_key_id}$#{[response.ciphertext].pack(default_encoding)}" + elsif key_id.start_with?("vault/") + # generate random AES-256 key + plaintext_key = OpenSSL::Random.random_bytes(32) + + # encrypt it + response = KmsEncrypted.vault_client.logical.write( + "transit/encrypt/#{key_id.sub("vault/", "")}", + plaintext: Base64.encode64(plaintext_key), + context: Base64.encode64(context.to_json) + ) + + encrypted_key = response.data[:ciphertext] else # generate data key from API - resp = KmsEncrypted.kms_client.generate_data_key( + resp = KmsEncrypted.aws_client.generate_data_key( key_id: key_id, encryption_context: context, key_spec: "AES_256" ) plaintext_key = resp.plaintext @@ -90,11 +104,11 @@ key_id: key_id, context: context } ActiveSupport::Notifications.instrument("decrypt_data_key.kms_encrypted", event) do if encrypted_key.start_with?("insecure-data-key-") - plaintext_key = "00000000000000000000000000000000" + plaintext_key = "00000000000000000000000000000000".encode("BINARY") elsif encrypted_key.start_with?("$gc$") _, _, short_key_id, ciphertext = encrypted_key.split("$", 4) # restore key, except for cryptoKeyVersion stored_key_id = Base64.decode64(short_key_id).split("/")[0..3] @@ -102,16 +116,26 @@ stored_key_id.insert(2, "locations") stored_key_id.insert(4, "keyRings") stored_key_id.insert(6, "cryptoKeys") stored_key_id = stored_key_id.join("/") + # load client first to ensure namespace is loaded + client = KmsEncrypted.google_client request = ::Google::Apis::CloudkmsV1::DecryptRequest.new( ciphertext: ciphertext.unpack(default_encoding).first, additional_authenticated_data: context.to_json ) - plaintext_key = KmsEncrypted::Google.kms_client.decrypt_crypto_key(stored_key_id, request).plaintext + plaintext_key = client.decrypt_crypto_key(stored_key_id, request).plaintext + elsif encrypted_key.start_with?("vault:") + response = KmsEncrypted.vault_client.logical.write( + "transit/decrypt/#{key_id.sub("vault/", "")}", + ciphertext: encrypted_key, + context: Base64.encode64(context.to_json) + ) + + plaintext_key = Base64.decode64(response.data[:plaintext]) else - plaintext_key = KmsEncrypted.kms_client.decrypt( + plaintext_key = KmsEncrypted.aws_client.decrypt( ciphertext_blob: encrypted_key.unpack(default_encoding).first, encryption_context: context ).plaintext end end