为什么Java和PHP中的Blowfish输出仅相差2个字符?

Pen*_*m10 13 php java encryption interop blowfish

我在PHP中有一个blowfish加密脚本,而JAVA反之亦然,直到今天我才遇到问题.

Java和PHP中相同的内容加密方式只有2个字符,这真的很奇怪.

PHP

wTHzxfxLHdMm/JMFnoh0hciS/JADvFFg
Run Code Online (Sandbox Code Playgroud)

Java的

wTHzxfxLHdMm/JMFnoh0hciS/D8DvFFg
-------------------------^^
Run Code Online (Sandbox Code Playgroud)

如你所见,这两个位置不匹配.不幸的是,该值是一个真实的电子邮件地址,我不能分享它.此外,我无法用我测试的其他几个值重现问题.我已经尝试在Java上更改Base64编码类,但这都没有帮助.

PHP的源代码在这里,Java就在这里.

我该怎么办才能解决这个问题?

Paŭ*_*ann 7

我们来看看你的Java代码:

String c = new String(Test.encrypt((new String("thevalue")).getBytes(),
                                   (new String("mykey")).getBytes()));
...
System.out.println("Base64 encoded String:" +
                   new sun.misc.BASE64Encoder().encode(c.getBytes()));
Run Code Online (Sandbox Code Playgroud)

你在这做的是:

  1. 使用系统的默认编码将纯文本字符串转换为字节
  2. 使用系统的默认编码将密钥转换为字节
  3. 加密字节
  4. 使用系统的默认编码将加密的字节转换回字符串
  5. 使用系统的默认编码将加密的字符串转换回字节
  6. 使用Base64编码这些加密的字节.

问题出在第4步.它假定一个任意字节数组表示系统默认编码中的字符串,并且将此字符串编码返回给出相同的byte [].这适用于某些编码(ISO-8859例如系列),但不适用于其他编码.在Java中,当某个字节(或字节序列)在给定编码中不可表示时,它将被其他一些字符替换,后来用于重新转换将被映射到字节63(ASCII ?).实际上,文档甚至说:

未指定给定字节在默认字符集中无效时此构造函数的行为.

在您的情况下,没有理由这样做 - 只需使用您的encrypt方法直接输出的字节将它们转换为Base64.

byte[] encrypted = Test.encrypt("thevalue".getBytes(),
                                "mykey".getBytes());
System.out.println("Base64 encoded String:"+ new sun.misc.BASE64Encoder().encode(encrypted));
Run Code Online (Sandbox Code Playgroud)

(另请注意,我在new String("...")这里删除了多余的构造函数调用,但这与您的问题无关.)

要记住的要点:永远不要将任何不是来自编码字符串的任意字节[]转换为字符串.加密算法(以及除解密之外的大多数其他加密算法)的输出当然属于不应转换为字符串的数据类别.

如果你想要便携式程序,永远不要使用系统的默认编码.