【发布时间】:2015-06-30 05:30:22
【问题描述】:
我们正在使用 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==
描述: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 代码。
当然,如果您能发现其他错误,将不胜感激。
【问题讨论】:
-
提示:使用
encode_base64($ciphertext, '')代替encode_base64($ciphertext)可以防止在中间添加换行符。
标签: java perl encryption blowfish