Logstash パイプラインの暗号化

概要

Javaには以下のコードがあり、AESを使用して入力データを暗号化します

SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
        KeySpec spec = new PBEKeySpec(secretKey.toCharArray(), salt.getBytes(), 65536, 256);
        SecretKey secret = new SecretKeySpec(factory.generateSecret(spec).getEncoded(), "AES");

        if (data == null)
            return encryptedText;

        Cipher encryptCipher = Cipher.getInstance("AES/GCM/NoPadding");

        // get IV
        byte[] iv = getRandomNonce(12);
        encryptCipher.init(Cipher.ENCRYPT_MODE, secret, new GCMParameterSpec(128, iv));
        // encrypted data:
        byte[] encryptedBytes = encryptCipher.doFinal(data.getBytes("UTF-8"));

        // prefix IV and Salt to cipher text
        byte[] cipherTextWithIvSalt = ByteBuffer.allocate(iv.length + salt.length() + encryptedBytes.length).put(iv)
                .put(salt.getBytes()).put(encryptedBytes).array();

        encryptedText = Base64.getEncoder().encodeToString(cipherTextWithIvSalt);

logstash パイプラインがあり、暗号化のために Ruby で以下のコードを試していますが、機能しません

  ruby {
code => "
  require 'openssl'
  require 'base64'

  password = 'secret_key'
  salt = 'random_salt'
  iterations = 65536
  key_len = OpenSSL::Cipher.new('aes-256-gcm').key_len
  key = OpenSSL::PKCS5.pbkdf2_hmac(password, salt, iterations, key_len, 'sha256')

  cipher = OpenSSL::Cipher.new('aes-256-gcm')
  cipher.encrypt
  cipher.key = key
  iv = Random.new.bytes(12)
  encrypted = cipher.update(event.get('secret')) + cipher.final
  length=iv.length+salt.length+encrypted.length
  
    // buffer =IO::Buffer.new(10)// not working
    
    
  encrypted_text = Base64.encode64(buffer).strip

  event.set('message_encrypted', encrypted_text)
"
add_field => {
      "new_secret" => "%{[message_encrypted]}"
    }

}

誰かがコードの欠落部分を見つけるのを手伝ってくれますか?

解決策

問題は、Buffer インスタンスで暗黙的な文字列変換が行われないことのようです。プログラムをそのまま実行すると、次のように表示されます。

ただし、エンコード時にインスタンスで to_s を明示的に呼び出すと、問題は解決します。

require "openssl"
require "base64"

password = "secret_key"
salt = "random_salt"
iterations = 65536
key_len = OpenSSL::Cipher.new("aes-256-gcm").key_len
key = OpenSSL::PKCS5.pbkdf2_hmac(password, salt, iterations, key_len, "sha256")

cipher = OpenSSL::Cipher.new("aes-256-gcm")
cipher.encrypt
cipher.key = key
iv = Random.new.bytes(12)
encrypted = cipher.update(event.get("secret")) + cipher.final
length = iv.length + salt.length + encrypted.length

buffer = IO::Buffer.new(10)
# It looks like you're using JRuby, so you may need to do the following instead:
# require 'java'
# buffer = java.nio.ByteBuffer.allocate(10)

encrypted_text = Base64.encode64(buffer.to_s).strip
puts encrypted_text # IzxJTzo6QnVmZmVyIDB4MDAwMDU1NjhjN2Q1NDViMCsxMCBJTlRFUk5BTD4=

event.set('message_encrypted', encrypted_text)

関連がある場合に備えて、これは Ruby 3.3.0 を使用して実行されました。