Разница в шифровании Blowfish между Perl и Java
Мы пишем и применяем приложения на Java и Perl, сохраняя зашифрованный CBC Blowfish в одной базе данных. Оба будут шифровать и дешифровать, поэтому они должны иметь возможность получить простой текст, зашифрованный другим.
а) Я пошел в некоторые онлайн-инструменты, чтобы зашифровать некоторый текст с вектором CBC и IV. Один такой сайт это
открытый текст HELLOYOUHELLOYOUHELLOYOUHELLOYOUHELLOYOUHELLOYOUHELLOYOUHELLOYOUHELLOYOUHELLOYOU
ключ 1234567890
поскольку сайт не позволяет ввести вектор IV, мы предполагали, что он будет обнулен, что оказалось правильным:
шифротекста
P4mtWDzIIc2x/Taqc9T46A3T0aTCelmANBRf6RgEzSF29DLdMRiEhck98jac04+Tg0q7HpLalow0J6nZNUW+HWtRvYmLnt92UuIZ1ckaBEa9TSdR2YP9rQ==
б) Следующий код Java выполняет шифрование:
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.*;
import org.apache.commons.codec.binary.*;
public class simple {
public static void main(String[] args) {
String Key = "1234567890";
byte[] KeyData = Key.getBytes();
String IV = "\0\0\0\0\0\0\0\0";
try {
SecretKeySpec KS = new SecretKeySpec(KeyData, "Blowfish");
// modo CBC
Cipher cipher = Cipher.getInstance("Blowfish/CBC/PKCS5Padding");
try {
try {
IvParameterSpec IVparam = new javax.crypto.spec.IvParameterSpec(IV.getBytes());
cipher.init(Cipher.ENCRYPT_MODE, KS,IVparam);
} catch (InvalidAlgorithmParameterException e) {System.out.println(e);};
} catch (InvalidKeyException e) {System.out.println(e);};
// get the text to encrypt
String inputText = "HELLOYOUHELLOYOUHELLOYOUHELLOYOUHELLOYOUHELLOYOUHELLOYOUHELLOYOUHELLOYOUHELLOYOU";
// encrypt message
try {
byte[] encrypted = cipher.doFinal(inputText.getBytes());
Base64 b64 = new Base64();
System.out.println("Java Ciphertext\n" + b64.encodeAsString(encrypted));
} catch (IllegalBlockSizeException e) {System.out.println(e);}
catch (BadPaddingException e) {System.out.println(e);}
}
catch (NoSuchPaddingException e) {}
catch (NoSuchAlgorithmException e) {}
}
}
Выход:
Java Ciphertext
P4mtWDzIIc2x / Taqc9T46A3T0aTCelmANBRf6RgEzSF29DLdMRiEhck98jac04 + Tg0q7HpLalow0J6nZNUW + HWtRvYmLnt92UuIZ1ckaBEaLkpDfHZfp8g ==
Как вы можете видеть, оба выхода "почти" одинаковы (возможно, из-за заполнения, но в данный момент это не актуально. Однако это странно, поскольку открытый текст преднамеренно составляет 80 символов, чтобы избежать заполнения)
в) Мы написали эту маленькую программу на Perl:
#!/usr/bin/perl -w
use strict;
use Crypt::Blowfish;
use MIME::Base64;
use Crypt::CBC;
my $cipher = Crypt::CBC->new(-key => "1234567890\0\0\0\0\0\0", -cipher => "Blowfish", -iv => "\0\0\0\0\0\0\0\0", -literal_key => 1, -header => "none", -keysize => 16);
my $ciphertext = $cipher->encrypt("HELLOYOUHELLOYOUHELLOYOUHELLOYOUHELLOYOUHELLOYOUHELLOYOUHELLOYOUHELLOYOUHELLOYOU");
print "Perl Base64: ",encode_base64($ciphertext),"\n";
print "Descrifrado: ", $cipher->decrypt($ciphertext);
Но эта программа производит следующее:
Perl Base64: AW0AYJfIp1Lg5L + zTM0nZj07U6ETlxxIg3CKiZItg8wkA1Jqx79ZckzWfYwzN26ZPyCDnlfh0b37 0ZK61ng8MaMc9RFgtuXTeYLBOJMMPP
Descrifrado: HELLOYOUHELLOYOUHELLOYOUHELLOYOUHELLOYOUHELLOYOUHELLOYOUHELLOYOUHELLOYOUHELLOYOU
Это не то же самое, что Java-программа (что согласуется с онлайн-инструментами), хотя она может правильно получать простой текст
Поэтому, возможно, мы не запрашиваем одни и те же параметры при создании объекта. Особенно:
my $cipher = Crypt::CBC->new(-key => "1234567890\0\0\0\0\0\0", -cipher => "Blowfish", -iv => "\0\0\0\0\0\0\0\0", -literal_key => 1, -header => "none", -keysize => 16);
После проверки кода я могу только предположить, что Java и Perl используют разные размеры ключей, поэтому мой вопрос
Size Какой размер ключа использует Java? После просмотра исходного кода SecretKeySpec здесь мы не смогли определить такой размер, поэтому было принято 128 битов, отсюда размер 16 (16 x 8 = 128) и заполнение ключа \0 в коде Perl.
Конечно, если вы заметите что-то еще не так, это будет с благодарностью.
1 ответ
В Java вы используете
String Key = "1234567890";
В Perl вы используете
my $key = "1234567890\0\0\0\0\0\0";
Если бы вы на самом деле использовали один и тот же ключ, вы бы получили тот же результат.
my $key = "1234567890";
-literal_key => 1, -key => $key, -keysize => length($key)