【问题标题】:Difference in blowfish encryption between Perl and JavaPerl 和 Java 之间河豚加密的区别
【发布时间】: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


【解决方案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)

【讨论】:

  • 感谢池上。我对 -keysize 参数 here 感到困惑: -keysize 将密码密钥大小强制为指定的字节数。
  • Blowfish 需要广泛的密钥大小 (8..56),因为它确实需要密码。 Crypt::CBC 期望每个算法总是需要一个相同大小的密钥,因此它会询问算法它想要什么大小以验证所提供的密钥。后端 Crypt::Blowfish 需要告诉 Crypt::CBC 一些东西,所以它说它需要一个大小为 0 的密钥。您必须通过说出您提供的长度的 -keysize 来覆盖 Crypt::CBC 的检查。 Crypt::Blowfish 仍然验证密钥的大小。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-01-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-04-30
相关资源
最近更新 更多