Beim Umgang mit vertraulichen Informationen ist es üblich, einfachen Text zu verschlüsseln, in einer Datenbank zu speichern und beim Abrufen zu entschlüsseln.
In meiner Arbeit untersuchte ich die Methoden zum Ver- und Entschlüsseln mit Ruby und hatte die Möglichkeit, mit jeder Methode einen Benchmark-Test durchzuführen, sodass ich den Inhalt zu diesem Zeitpunkt zusammenfasste.
Es werden zwei Methoden berücksichtigt: die Ruby-Standardbibliothek OpenSSL (eigene Implementierung) und der AWS Key Management Service (KMS).
Ihre eigene Implementierung ist wahrscheinlich rechenintensiv, und KMS ist wahrscheinlich netzwerkintensiv. Daher liegt der Fokus darauf, wie sich dies auswirken wird.
Eine Methode, bei der Sender und Empfänger einen Schlüssel heimlich gemeinsam nutzen und einen gemeinsamen Schlüssel zum Ver- und Entschlüsseln verwenden. Wenn immer dieselben Daten durch dieselbe Verschlüsselung ersetzt werden, wird der Klartext aus der Häufigkeit abgeleitet. Stellen Sie daher den Initialisierungsvektor (oder das Salz) so ein, dass dieselben Daten durch eine andere Verschlüsselung ersetzt werden können. Diesmal habe ich den Initialisierungsvektor verwendet.
Bei Verwendung der Standard-Ruby-Bibliothek "OpenSSL :: Cipher" sieht es so aus.
def encrypt(plaintext, key, iv)
enc = OpenSSL::Cipher.new('AES-256-CBC')
enc.encrypt
enc.key = key
enc.iv = iv
enc.update(plaintext) + enc.final
end
def decrypt(encrypted_data, key, iv)
dec = OpenSSL::Cipher.new('AES-256-CBC')
dec.decrypt
dec.key = key
dec.iv = iv
decrypted_data = dec.update(encrypted_data) + dec.final
#Die entschlüsselten Daten sind ASCII-Da es sich um 8 Bit handelt, korrigieren Sie die Codierung zwangsweise
decrypted_data.force_encoding("UTF-8")
end
plaintext = "Zu verschlüsselnde Zeichenfolge"
key = "Gemeinsamer Schlüssel"
iv = "Initialisierungsvektor"
#Datenverschlüsselung
encrypted_data = encrypt(plaintext, key, iv)
#Entschlüsselung von Daten
decrypt(encrypted_data, key, iv)
Eine Methode, bei der die Verschlüsselung mit einem öffentlichen Schlüssel und die Entschlüsselung mit einem privaten Schlüssel durchgeführt wird.
Bei Verwendung der Standard-Ruby-Bibliothek "OpenSSL :: Cipher" sieht es so aus.
def encrypt(plaintext, public_key)
Base64.encode64(
public_key.public_encrypt(
data,
OpenSSL::PKey::RSA::PKCS1_OAEP_PADDING
)
)
end
def decrypt(encrypted_data, private_key)
decrypted_data = private_key.private_decrypt(
Base64.decode64(encrypted_data),
OpenSSL::PKey::RSA::PKCS1_OAEP_PADDING
)
#Die entschlüsselten Daten sind ASCII-Da es sich um 8 Bit handelt, korrigieren Sie die Codierung zwangsweise
decrypted_data.force_encoding("UTF-8")
end
plaintext = "Zu verschlüsselnde Zeichenfolge"
public_key = OpenSSL::PKey::RSA.new(File.read(public_key_file))
private_key = OpenSSL::PKey::RSA.new(File.read(private_key_file))
#Datenverschlüsselung
encrypted_data = encrypt(plaintext, public_key)
#Entschlüsselung von Daten
decrypt(encrypted_data, private_key)
Da es sich bei dem zu verschlüsselnden Klartext um einen Langtext mit mehreren hundert Zeichen handelt, kann die Verschlüsselung mit öffentlichen Schlüsseln nicht verwendet werden (sie kann mit ein wenig Einfallsreichtum verwendet werden, wird jedoch nicht empfohlen). Daher haben wir uns für die Verwendung der allgemeinen Schlüsselverschlüsselung entschieden.
Verwenden Sie die Benchmark-Bibliothek zum Benchmarking https://docs.ruby-lang.org/ja/latest/class/Benchmark.html
require 'benchmark'
result = Benchmark.realtime do
#Der zu messende Prozess wird hier beschrieben.
end
puts "#{result}s"
--Ruby Standardbibliothek OpenSSL
--Messen Sie die Gesamtzahl der Sekunden bei 1000-maliger Ausführung --Messen Sie jeweils nur die Verschlüsselung und nur die Entschlüsselung
require 'openssl'
require 'base64'
require 'benchmark'
def encrypt(plaintext, key, iv)
enc = OpenSSL::Cipher.new('AES-256-CBC')
enc.encrypt
enc.key = key
enc.iv = iv
enc.update(comment) + enc.final
end
data = <<-EOS
Langer Satz ...
EOS
key = "Gemeinsamer Schlüssel"
iv = "Initialisierungsvektor"
result = Benchmark.realtime do
1000.times do
encrypt(plaintext, key, iv)
end
end
KMS
require 'aws-sdk-s3'
require 'base64'
require 'benchmark'
class KMSClient
REGION = 'ap-northeast-1'
ALIAS_NAME = 'KMS-Aliasname'
def initialize
@client = Aws::KMS::Client.new(
region: REGION,
#Wenn Sie einen VPC-Endpunkt festgelegt haben, geben Sie diesen anstelle der Region an
# endpoint: 'https://vpce-xxxxx.kms.ap-northeast-1.vpce.amazonaws.com',
access_key_id: '',
secret_access_key: '',
)
@alias = @client.list_aliases.aliases.find { |a| a.alias_name == ALIAS_NAME }
end
def encrypt(plaintext)
ciphertext = @client.encrypt(
key_id: @alias.target_key_id,
plaintext: plaintext
)
Base64.encode64(ciphertext.ciphertext_blob)
end
end
plaintext = <<-EOS
Langer Satz ...
EOS
client = KMSClient.new
result = Benchmark.realtime do
1000.times do
client.encrypt(plaintext)
end
end
puts "#{result}s"
require 'openssl'
require 'base64'
require 'benchmark'
def decrypt(encrypted_data, key, iv)
dec = OpenSSL::Cipher.new('AES-256-CBC')
dec.decrypt
dec.key = key
dec.iv = iv
decrypted_data = dec.update(encrypted_data) + dec.final
decrypted_data.force_encoding("UTF-8")
end
plaintext = <<-EOS
Langer Satz ...
EOS
key = "Gemeinsamer Schlüssel"
iv = "Initialisierungsvektor"
encrypted_data = encrypt(plaintext, key, iv)
result = Benchmark.realtime do
1000.times do
decrypt(encrypted_data, key, iv)
end
end
puts "#{result}s"
KMS
require 'aws-sdk-s3'
require 'base64'
require 'benchmark'
class KMSClient
REGION = 'ap-northeast-1'
ALIAS_NAME = 'KMS-Aliasname'
def initialize
@client = Aws::KMS::Client.new(
region: REGION,
#Wenn Sie einen VPC-Endpunkt festgelegt haben, geben Sie diesen anstelle der Region an
# endpoint: 'https://vpce-xxxxx.kms.ap-northeast-1.vpce.amazonaws.com',
access_key_id: '',
secret_access_key: '',
)
@alias = @client.list_aliases.aliases.find { |a| a.alias_name == ALIAS_NAME }
p @alias
end
def encrypt(plaintext)
ciphertext = @client.encrypt(
key_id: @alias.target_key_id,
plaintext: plaintext
)
Base64.encode64(ciphertext.ciphertext_blob)
end
def decrypt(ciphertext_blob)
@client.decrypt(ciphertext_blob: Base64.decode64(ciphertext_blob)).plaintext
end
end
plaintext = <<-EOS
Langer Satz ...
EOS
client = KMSClient.new
encrypted_data = client.encrypt(plaintext)
result = Benchmark.realtime do
1000.times do
client.decrypt(encrypted_data)
end
end
puts "#{result}s"
Methode | Die Anzahl der Sekunden |
---|---|
Ruby Standardbibliothek OpenSSL | 0.006588994991034269 |
KMS | 8.035557514987886 |
KMS (VPC-Endpunkt) | 7.766658762935549 |
Methode | Die Anzahl der Sekunden |
---|---|
Ruby Standardbibliothek OpenSSL | 0.0037274740170687437 |
KMS | 8.964495759923011 |
KMS (VPC-Endpunkt) | 7.9086791928857565 |
Schließlich scheint KMS aufgrund der erheblichen Netzwerkkosten langsam zu sein. Ich denke, dies ist das Ergebnis des Netzwerkzugriffs auf AWS bei jedem Aufruf der Verschlüsselungs- / Entschlüsselungsmethode. Das Einrichten eines VPC-Endpunkts und das Zulassen einer Verbindung innerhalb der VPC würde ihn ein wenig verbessern, aber es scheint seine eigene Implementierung immer noch nicht zu übertreffen. Wenn Sie jedoch den für die Verschlüsselung verwendeten Schlüssel verlängern, um die Sicherheit zu verbessern, erhöhen sich die Berechnungskosten, selbst wenn Sie ihn selbst implementieren. Daher müssen Sie in diesem Punkt anscheinend vorsichtig sein.
Recommended Posts