Lorsqu'il s'agit d'informations sensibles, il est courant de crypter du texte brut, de l'enregistrer dans une base de données et de le décrypter lors de sa récupération.
Dans mon travail, j'ai examiné les méthodes de chiffrement et de déchiffrement avec Ruby, et j'ai eu l'occasion de faire un test de référence avec chaque méthode, j'ai donc résumé le contenu à ce moment-là.
Deux méthodes sont envisagées: la bibliothèque standard Ruby OpenSSL (propre implémentation) et AWS Key Management Service (KMS).
Votre propre implémentation est susceptible d'être coûteuse en calcul, et KMS est susceptible d'être coûteux en réseau, donc l'accent sera mis sur la façon dont cela en résultera.
Une méthode dans laquelle l'expéditeur et le destinataire partagent une clé secrètement et utilisent une clé commune pour le cryptage et le décryptage. Si les mêmes données sont toujours remplacées par le même chiffre, le texte brut est déduit de la fréquence, définissez donc le vecteur d'initialisation (ou sel) de sorte que les mêmes données puissent être remplacées par un chiffre différent. Cette fois, j'ai utilisé le vecteur d'initialisation.
Cela ressemble à ceci lorsque vous utilisez la bibliothèque Ruby standard ʻOpenSSL :: Cipher`.
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
#Les données déchiffrées sont ASCII-Puisqu'il s'agit de 8BIT, corriger l'encodage de force
decrypted_data.force_encoding("UTF-8")
end
plaintext = "Chaîne de caractères à chiffrer"
key = "Clé commune"
iv = "Vecteur d'initialisation"
#Cryptage des données
encrypted_data = encrypt(plaintext, key, iv)
#Décryptage des données
decrypt(encrypted_data, key, iv)
Une méthode dans laquelle le cryptage est effectué avec une clé publique et le décryptage est effectué avec une clé privée.
Cela ressemble à ceci lorsque vous utilisez la bibliothèque Ruby standard ʻOpenSSL :: Cipher`.
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
)
#Les données déchiffrées sont ASCII-Puisqu'il s'agit de 8BIT, corriger l'encodage de force
decrypted_data.force_encoding("UTF-8")
end
plaintext = "Chaîne de caractères à chiffrer"
public_key = OpenSSL::PKey::RSA.new(File.read(public_key_file))
private_key = OpenSSL::PKey::RSA.new(File.read(private_key_file))
#Cryptage des données
encrypted_data = encrypt(plaintext, public_key)
#Décryptage des données
decrypt(encrypted_data, private_key)
Cette fois, comme le texte brut à chiffrer est un texte long de plusieurs centaines de caractères, le chiffrement à clé publique ne peut pas être utilisé (il peut être utilisé avec un peu d'ingéniosité, mais ce n'est pas recommandé), nous avons donc décidé d'utiliser un chiffrement à clé commune.
Utilisez la bibliothèque Benchmark
pour l'analyse comparative
https://docs.ruby-lang.org/ja/latest/class/Benchmark.html
require 'benchmark'
result = Benchmark.realtime do
#Le processus à mesurer est décrit ici.
end
puts "#{result}s"
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
Longue phrase ...
EOS
key = "Clé commune"
iv = "Vecteur d'initialisation"
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 = 'Nom d'alias KMS'
def initialize
@client = Aws::KMS::Client.new(
region: REGION,
#Si vous avez défini un point de terminaison VPC, spécifiez-le à la place de la région
# 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
Longue phrase ...
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
Longue phrase ...
EOS
key = "Clé commune"
iv = "Vecteur d'initialisation"
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 = 'Nom d'alias KMS'
def initialize
@client = Aws::KMS::Client.new(
region: REGION,
#Si vous avez défini un point de terminaison VPC, spécifiez-le à la place de la région
# 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
Longue phrase ...
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"
Méthode | Le nombre de secondes |
---|---|
Bibliothèque standard Ruby OpenSSL | 0.006588994991034269 |
KMS | 8.035557514987886 |
KMS (point de terminaison VPC) | 7.766658762935549 |
Méthode | Le nombre de secondes |
---|---|
Bibliothèque standard Ruby OpenSSL | 0.0037274740170687437 |
KMS | 8.964495759923011 |
KMS (point de terminaison VPC) | 7.9086791928857565 |
Après tout, KMS semble lent en raison du coût important du réseau. Je pense que c'est le résultat de l'accès réseau à AWS chaque fois que la méthode de cryptage / décryptage est appelée. Définir un point de terminaison VPC et lui permettre de se connecter au sein du VPC l'améliorerait un peu, mais il ne semble toujours pas battre sa propre implémentation. Cependant, si vous allongez la clé utilisée pour le chiffrement pour améliorer la sécurité, le coût du calcul augmentera même si vous l'implémentez vous-même, il semble donc que vous deviez faire attention à ce point.
Recommended Posts