Dans un certain projet, j'ai été obligé de déchiffrer le texte chiffré en utilisant OpenSSL cli avec divers langages de script, et c'était un peu gênant dans le cas de Java et PHP, j'ai donc résumé les informations.
Avec OpenSSL cli, par exemple, vous pouvez facilement crypter du texte à un rythme de mot de passe en utilisant l'option enc comme indiqué ci-dessous, mais si vous essayez de décrypter cela en utilisant Java, il ajoutera et analysera les informations d'en-tête compatibles OpenSSL Il n'a pas pu être décrypté tel quel car il n'y a pas de fonction correspondante.
Lors du cryptage du contenu d'un fichier texte avec OpenSSL cli, vous pouvez facilement obtenir une chaîne de caractères cryptée simplement en donnant la méthode de cryptage et le mot de passe comme options, comme indiqué dans l'exemple ci-dessous.
cat plain.txt | openssl enc -e -aes-128-cbc -base64 -k <mot de passe>
Normalement, si AES est spécifié comme méthode de cryptage, il est nécessaire de donner Salt et IV (Initialization Vector) en plus du mot de passe lors du cryptage et du décryptage, mais dans OpenSSL ce Salt et Le IV est automatiquement généré et intégré dans l'en-tête des données chiffrées, de sorte que l'utilisateur n'a qu'à connaître le mot de passe. Comme le montre l'exemple de script de cet article, la bibliothèque OpenSSL de Perl et Ruby a un mécanisme de génération Salt et IV qui est chiffré avec OpenSSL cli, il est donc relativement facile d'utiliser du texte chiffré avec OpenSSL cli. Cependant, dans le cas de la bibliothèque OpenSSL pour Java et PHP, puisqu'elle ne disposait pas de ce mécanisme compatible OpenSSL cli, il était nécessaire d'incorporer seul le mécanisme de génération Salt et IV.
À propos, lorsque le chiffrement est effectué par la méthode AES à l'aide de l'option enc avec OpenSSL cli, Salt a une chaîne de bits aléatoire de 8 octets (64 bits) et IV a 16 octets (16 octets) générés par la méthode suivante. 128 bits) une chaîne de bits est utilisée.
Formule de génération IV Clé = mot de passe + Salt MD5 IV = clé + mot de passe + Salt MD5
Ceux-ci sont ajoutés en tant qu'informations d'en-tête au début des données cryptées et renvoyés sous forme de données cryptées.
Chaîne "Salted__" (8 octets) + Salt (8 octets) + IV (16 octets) + [données chiffrées]
Lors du décryptage, si vous confirmez que le début des données cryptées est "Salted__", utilisez les 8 octets de données suivants comme Salt, et à partir du mot de passe, Salt comme dans le cas du cryptage Génère un IV et décrypte le corps des données cryptées qui suivent Salt.
L'exemple de code suivant est écrit en l'incorporant.
Le getKeyAndGenerateIv
dans ce code est utilisé pour générer Salt et IV d'une manière compatible OpenSSL Cli.
EncryptDecryptText.java
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import java.security.spec.KeySpec;
import java.security.SecureRandom;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.Arrays;
import java.io.BufferedReader;
import java.io.InputStreamReader;
class EncryptDecryptText {
public static boolean getKeyAndGenerateIv(String password, byte[] salt, byte[] key_bytes, byte[] iv_bytes) {
try {
byte[] password_bytes = password.getBytes(StandardCharsets.UTF_8);
int length = password_bytes.length + salt.length;
ByteBuffer byte_buffer = ByteBuffer.allocate(length);
byte_buffer.put(password_bytes);
byte_buffer.put(salt);
byte_buffer.rewind();
byte[] byte_array = new byte[length];
byte_buffer.get(byte_array);
System.arraycopy(MessageDigest.getInstance("MD5").digest(byte_array), 0, key_bytes, 0, key_bytes.length);
length = password_bytes.length + salt.length + key_bytes.length;
byte_buffer = ByteBuffer.allocate(length);
byte_buffer.put(key_bytes);
byte_buffer.put(password_bytes);
byte_buffer.put(salt);
byte_buffer.rewind();
byte_array = new byte[length];
byte_buffer.get(byte_array);
System.arraycopy(MessageDigest.getInstance("MD5").digest(byte_array), 0, iv_bytes, 0, iv_bytes.length);
}
catch ( NoSuchAlgorithmException e ) {
return false;
}
return true;
}
public static String encrypt(String plaintext, String password) throws Exception {
// Generate random salt.
byte[] random_bytes = new byte[8];
new SecureRandom().nextBytes(random_bytes);
byte[] key_bytes = new byte[16];
byte[] iv_bytes = new byte[16];
getKeyAndGenerateIv(password, random_bytes, key_bytes, iv_bytes);
SecretKey secret = new SecretKeySpec(key_bytes, "AES");
IvParameterSpec ivspec = new IvParameterSpec(iv_bytes);
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, secret, ivspec);
byte[] encrypted_bytes = cipher.doFinal(plaintext.getBytes(StandardCharsets.UTF_8));
final String header_string = "Salted__";
byte[] header_bytes = header_string.getBytes(StandardCharsets.UTF_8);
int length = header_bytes.length + random_bytes.length + encrypted_bytes.length;
ByteBuffer byte_buffer = ByteBuffer.allocate(length);
byte_buffer.put(header_bytes);
byte_buffer.put(random_bytes);
byte_buffer.put(encrypted_bytes);
byte_buffer.rewind();
byte[] byte_array = new byte[length];
byte_buffer.get(byte_array);
return new String(Base64.getEncoder().encodeToString(byte_array));
}
public static String decrypt(String payload, String password) throws Exception {
byte[] payload_bytes = Base64.getDecoder().decode(payload.getBytes(StandardCharsets.UTF_8));
byte[] header_bytes = new byte[8];
byte[] salt_bytes = new byte[8];
int length = payload_bytes.length;
ByteBuffer byte_buffer = ByteBuffer.allocate(length);
byte_buffer.put(payload_bytes);
byte_buffer.rewind();
byte_buffer.get(header_bytes);
byte_buffer.get(salt_bytes);
length = payload_bytes.length - header_bytes.length - salt_bytes.length;
byte[] data_bytes = new byte[length];
byte_buffer.get(data_bytes);
byte[] key_byte = new byte[16];
byte[] iv_bytes = new byte[16];
getKeyAndGenerateIv(password, salt_bytes, key_byte, iv_bytes);
SecretKey secret = new SecretKeySpec(key_byte, "AES");
IvParameterSpec ivspec = new IvParameterSpec(iv_bytes);
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, secret, ivspec);
byte[] decrypted = cipher.doFinal(data_bytes);
return new String(decrypted);
}
public static void main(String[] args) throws Exception {
//Lire les données / mot de passe à chiffrer
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
System.out.print("Plain text: ");
System.out.flush();
String plain_text = br.readLine();
System.out.print("Password: ");
System.out.flush();
String password = br.readLine();
//Processus de cryptage
String encrypted = EncryptorDecryptor.encrypt(plain_text, password);
System.out.print("encrypted:" + encrypted);
System.out.println();
//Processus de décryptage
String decrypted = EncryptorDecryptor.decrypt(encrypted, password);
System.out.print("decrypted:" + decrypted);
System.out.println();
}
}
python
<?php
function encrypt($plain_text, $password) {
//Générer un sel aléatoire de 8 octets
$random_salt = openssl_random_pseudo_bytes(8);
//Générer la clé et l'IV à partir du mot de passe et du sel
$key_data = $password.$random_salt;
$raw_key = md5($key_data, true);
$iv_data = $raw_key.$password.$random_salt;
$iv = md5($iv_data, true);
//chiffrement
$encrypted = openssl_encrypt($plain_text, 'aes-128-cbc', $raw_key, OPENSSL_RAW_DATA, $iv);
return ( base64_encode("Salted__".$random_salt.$encrypted) );
}
function decrypt($encrypted_text, $password) {
//Décryptage
$payload_text = base64_decode($encrypted_text);
$header = substr($payload_text, 0, 7);
$salt = substr($payload_text, 8, 8);
$data = substr($payload_text, 16);
//Générer la clé et l'IV à partir du mot de passe et du sel
$key_data = $password.$salt;
$raw_key = md5($key_data, true);
$iv_data = $raw_key.$password.$salt;
$iv = md5($iv_data, true);
$decrypted_text = openssl_decrypt($data, 'aes-128-cbc', $raw_key, OPENSSL_RAW_DATA, $iv);
return ( $decrypted_text );
}
// Usage:
$str = file_get_contents('php://stdin');
print "Plain text: " . $str . "\n";
$password = $argv[1];
print "Password: " . $password . "\n";
//Processus de cryptage
$encrypted = encrypt($str, $password);
print "encrypted:" . $encrypted . "\n";
//Processus de décryptage
$decrypted = decrypt($encrypted, $password);
print "decrypted:" . $decrypted . "\n";
python
#!/usr/bin/perl
use MIME::Base64;
use strict;
use Crypt::CBC;
use Config;
sub encrypt {
my ($plain_text, $passphrase) = @_;
my $pbe = Crypt::CBC->new(
-key => $passphrase,
-cipher => 'Crypt::Rijndael',
-keysize => 128/8,
);
my $cipher_text = $pbe->encrypt($plain_text);
my $encrypted_text = encode_base64($cipher_text);
return $encrypted_text;
}
sub decrypt {
my ($encrypted_text, $passphrase) = @_;
my $cipher_text = decode_base64($encrypted_text);
my $pbe = Crypt::CBC->new(
-key => $passphrase,
-cipher => 'Crypt::Rijndael',
-keysize => 128/8,
);
my $plain_text = $pbe->decrypt($cipher_text);
return $plain_text;
}
# Usage:
#Processus de cryptage
my $str = (scalar <>);
print "Plain text: " . $str . "\n";
my $password = $ARGV[0];
print "Password: " . $password . "\n";
#Processus de cryptage
my $encrypted = encrypt($str, $password);
print "encrypted:" . $encrypted . "\n";
#Processus de décryptage
my $decrypted = decrypt($encrypted, $password);
print "decrypted:" . $decrypted . "\n";
python
#!/usr/bin/ruby
require "openssl"
require "base64"
def encrypt(plain_text, password)
salt = OpenSSL::Random.random_bytes(8)
cipher = OpenSSL::Cipher.new("aes-128-cbc")
cipher.encrypt()
cipher.pkcs5_keyivgen(
password,
salt,
1
)
#Dans le cas de Ruby, vous devez ajouter vous-même les informations d'en-tête à la chaîne de caractères.
encrypted_text = "Salted__" + salt + cipher.update(plain_text) + cipher.final
return Base64.encode64(encrypted_text)
end
def decrypt(encrypted_text, password)
decoded_str = Base64.decode64(encrypted_text)
#Dans le cas de Ruby, vous devez également décomposer vous-même les informations d'en-tête
@cipher_text = decoded_str.unpack("a8a8a*")
cipher = OpenSSL::Cipher.new("aes-128-cbc")
cipher.pkcs5_keyivgen(
password,
@cipher_text[1],
1
)
cipher.decrypt()
decrypted_text = cipher.update(@cipher_text[2]) + cipher.final
return decrypted_text
end
# Usage:
str = gets
print "Plain text: " + str + "\n";
password = ARGV[0]
print "Password: " + password + "\n";
#Processus de cryptage
encrypted = encrypt(str, password);
print "encrypted:" + encrypted + "\n";
#Processus de décryptage
decrypted = decrypt(encrypted, password);
print "decrypted:" + decrypted + "\n";
python
#!/bin/bash
function encrypt() {
plain_text=$1
password=$2
encrypted_text=`echo -n "$plain_text" | openssl enc -e -aes-128-cbc -base64 -k "$password"`
echo $encrypted_text
}
function decrypt() {
encrypted_text=$1
password=$2
plain_text=`echo "$encrypted_text" | openssl enc -d -aes-128-cbc -base64 -k "$password"`
echo $plain_text
}
# Useage:
str="$(cat -)"
echo "Plain text: $str"
password=$1
echo "Password: $password"
#Processus de cryptage
encrypted=`encrypt "$str" "$password"`
echo "encrypted:$encrypted"
#Processus de décryptage
decrypted=`decrypt "$encrypted" "$password"`
echo "decrypted:$decrypted"
Recommended Posts