Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/271.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么Java和PHP中的河豚输出只相差2个字符?_Java_Php_Encryption_Interop_Blowfish - Fatal编程技术网

为什么Java和PHP中的河豚输出只相差2个字符?

为什么Java和PHP中的河豚输出只相差2个字符?,java,php,encryption,interop,blowfish,Java,Php,Encryption,Interop,Blowfish,我有一个用PHP和JAVA编写的blowfish加密脚本,反之亦然,直到今天我遇到了一个问题,它一直工作得很好 同样的内容在Java和PHP中只加密了2个字符,这真的很奇怪 PHP 爪哇 正如您所看到的,这两个位置不匹配。不幸的是,该值是一个真实的电子邮件地址,我无法共享它。另外,我无法用我测试过的其他几个值重现这个问题。我曾尝试在Java上更改Base64编码类,但这两种方法都没有帮助 和的源代码 我能做些什么来解决这个问题呢?我觉得你的代码很正确 看起来在其中一个程序的输入中有一个尾随空格,

我有一个用PHP和JAVA编写的blowfish加密脚本,反之亦然,直到今天我遇到了一个问题,它一直工作得很好

同样的内容在Java和PHP中只加密了2个字符,这真的很奇怪

PHP

爪哇

正如您所看到的,这两个位置不匹配。不幸的是,该值是一个真实的电子邮件地址,我无法共享它。另外,我无法用我测试过的其他几个值重现这个问题。我曾尝试在Java上更改Base64编码类,但这两种方法都没有帮助

和的源代码


我能做些什么来解决这个问题呢?

我觉得你的代码很正确

看起来在其中一个程序的输入中有一个尾随空格,而且只有一个。我来告诉你原因:

这些4字符块中的每个块表示加密字符串中的3个字符。不同的部分(第7格中的JA和D8)实际上来自一个不同的角色

wTHz xfxL HdMm/JMF noh0 hciS/JAD vFFg

wTHz xfxL HdMm/JMF noh0 hciS/D8D vFFg


如果我没弄错的话,你的电子邮件地址有19个字符长。输入字符串中的第20个字符是空白。

问题:您是否尝试使用相关的PHP解密库对PHP生成的加密文本进行解密?您是否尝试过使用关联的JAVA解密库对JAVA加密文本进行解密

如果两者产生不同的输出,则其中一个必须解密失败

这是PHP还是Java

无论是哪一个--我都会尝试用一个可公开共享的字符串复制另一个这样的失败。。。将该字符串作为单元测试提供给使用往返加密/解密失败的语言创建加密/解密代码的开发人员

然后。。。等他们把它修好


不确定是否有更快的解决方案--除了可能更改加密/解密库提供程序。。。或者推出自己的…

让我们看看您的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()));
你在这里做的是:

  • 使用系统的默认编码将明文字符串转换为字节
  • 使用系统的默认编码将密钥转换为字节
  • 加密字节
  • 使用系统的默认编码将加密的字节转换回字符串
  • 使用系统默认编码将加密字符串转换回字节
  • 使用Base64对这些加密字节进行编码
  • 问题在第4步。它假定一个任意字节数组表示系统默认编码中的一个字符串,对该字符串进行编码返回相同的字节[]。这对某些编码(例如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));
    
    (还要注意,我在这里删除了多余的
    新字符串(“…”)
    构造函数调用,尽管这与您的问题无关。)

    要记住的一点是:永远不要将非编码字符串产生的任意字节[]转换为字符串。加密算法(以及除解密外的大多数其他加密算法)的输出肯定属于不应转换为字符串的数据类别


    如果你想要便携程序,千万不要使用系统的默认编码。

    可能与Java和PHP中用来表示电子邮件地址的字符编码有关吗?地址中有非ASCII字符吗?没有,只有字母和点。只有河豚会这样做吗?md5/sha呢?当base64解码时,差正好是一个字节,即第20个字节。我查看了代码,并没有立即注意到任何问题。您的PHP代码说明文中填充了NULL,但在Java中您使用了PKCS5Padding。我已经尝试了这些方法,它们工作得很好。对于1000个值和随机值,此问题只发生1次,但对于这些值,所有时间都会发生。只有一个输出字节出错的观察结果是好的(这有助于写下我的答案),但这不会转移到一个错误的输入字节-Blowfish是一种分组密码,在CBC模式下使用,例如,输入中的一个不同位将在输出中获得完全不同的64位块(8字节)。(对于计数器模式,你的观察是正确的)。CBC的要点是,一旦你有了不同的东西,剩下的结果密码文本就会不同。但在同一块(比如8字节)中,第一个字节不一定会受到同一块中后面的字节不同的影响。。。这意味着改变输入中的一位会改变(平均)输出中的一半位。CBC将分组密码应用于纯文本(以及前一个块的密文),因此我们将有一个完全不可识别的块。当然,下列街区也将被摧毁。作为比较:ECB将只“销毁”一个块,而CTR模式将只交换输出中的该位(因为分组密码不应用于明文)。CFB将交换一位并销毁以下块。OFB就像这里的CTR。谢谢帕罗的解释。
    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()));
    
    byte[] encrypted = Test.encrypt("thevalue".getBytes(),
                                    "mykey".getBytes());
    System.out.println("Base64 encoded String:"+ new sun.misc.BASE64Encoder().encode(encrypted));