我们在Java和Perl中编写和应用程序将加密的CBC Blowfish存储在同一个数据库中。两者都将加密和解密,因此他们需要能够获得另一个加密的纯文本。
a)我去了一些在线工具用CBC和IV矢量加密一些文本。一个这样的网站is this
明文HELLOYOUHELLOYOUHELLOYOUHELLOYOUHELLOYOUHELLOYOUHELLOYOUHELLOYOUHELLOYOUHELLOYOU
关键1234567890
由于该网站不允许输入IV矢量,我们假设它将归零,结果证明是正确的:
密文
P4mtWDzIIc2x / Taqc9T46A3T0aTCelmANBRf6RgEzSF29DLdMRiEhck98jac04 + Tg0q7HpLalow0J6nZNUW + HWtRvYmLnt92UuIZ1ckaBEa9TSdR2YP9rQ ==
b)以下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个字符以避免填充)
c)我们写了这个小的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
0ZK61ng8MaMc9RFgtuXTeYLBOJC7LGYCHlMddmPwUQ ==
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使用不同的密钥大小,所以我的问题是
¿Java使用的密钥大小是多少?浏览 SecretKeySpec here的源代码后,我们无法确定这样的大小,因此假定为128位,因此16位大小(16 x 8 = 128)和键的\ 0填充在Perl代码中。
当然,如果你能发现别的错误,我们将不胜感激。
答案 0 :(得分:4)
在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)