Java和c ++加密的结果不匹配

时间:2012-06-20 14:23:50

标签: java c++ security base64

我有一个现有的c ++代码,它将加密一个字符串。现在我做了相同的加密。    某些加密字符串匹配。有些是一两个字符不匹配。

我无法弄清楚为什么会这样。我在调试模式下运行了两个代码,直到它们调用它们的库都有相同的密钥,salt,iv字符串进行加密。

我知道即使单字节填充更改也会大幅修改加密字符串。但在这里我只看到一两个角色改变了。这是一个示例(星星之间的粗体字符是错误匹配的部分)

java:

  

U2FsdGVkX18xMjM0NTY3OGEL9nxFlHrWvodMqar82NT53krNkqat0rrgeV5FAJFs1vBsZIJPZ08DJVrQ *的 Pw的 * yV15HEoyECBeAZ6MTeN + ZYHRitKanY5jiRU2J0KP0Fzola

C ++:

  

U2FsdGVkX18xMjM0NTY3OGEL9nxFlHrWvodMqar82NT53krNkqat0rrgeV5FAJFs1vBsZIJPZ08DJVrQ *的 JQ * yV15HEoyECBeAZ6MTeN + ZYHRitKanY5jiRU2J0KP0Fzola

我正在使用AES加密。提供商是SunJCE 1.6版。我尝试将提供商改为Bouncy Castle。即便如此,结果也一样。

添加了一个样本:

C ++:

  

U2FsdGVkX18xMjM0NTY3O *的 I * / BMu11HkHgnkx + dLPDU1lbfRwb + aCRrwkk7e9dy ++ MK + / 94dKLPXaZDDlWlA3gdUNyh / FXV *的 * STgl3QgpS0XU =

的java:

  

U2FsdGVkX18xMjM0NTY3O *的 d * / BMu11HkHgnkx + dLPDU1lbfRwb + aCRrwkk7e9dy ++ MK + / 94dKLPXaZDDlWlA3gdUNyh / FXV *的 J9 * STgl3QgpS0XU =

更新

根据评论,我觉得基础64加密是罪魁祸首。我在两个地方使用Latin-1字符集。还有其他我可以查看的内容

2 个答案:

答案 0 :(得分:7)

嗟!!

问题几乎可以肯定的是,在加密数据并以字节字符串接收加密数据之后,您正在对数据进行某种字符转换,然后通过Base-64转换发送它

请注意,如果您加密字符串“ABC _ D _ EFG”和“ABC_ G _EFG “,加密输出将从第4个字符开始完全不同,并持续到最后。换句话说,Base-64输出类似于(使用组合值):

U2FsdGVkX18xMj

U2FsdGXt91mJpz

在上面的例子中,在每种情况下只有两个孤立的Base-64字符(一个字节)混乱的事实几乎证明了加密后发生了损坏。

加密过程的输出是字节序列,而不是字符序列。观察到的损坏与将字节错误地解释为字符并尝试对它们执行代码页转换(在将它们馈送到Base-64转换器中)一致。加密器的输出应直接馈入Base-64转换器,无需任何转换。

你说你在两个地方都使用了“Latin-1字符集”,这清楚地表明你正在进行一些你不应该做的转换 - 应该没有必要使用字符集。

答案 1 :(得分:2)

首先是一些代码:

import javax.xml.bind.DatatypeConverter;

...

public static void main(String[] args) {
    String s1j = "U2FsdGVkX18xMjM0NTY3OGEL9nxFlHrWvodMqar82NT53krNkqat0rrgeV5FAJFs1vBsZIJPZ08DJVrQPwyV15HEoyECBeAZ6MTeN+ZYHRitKanY5jiRU2J0KP0Fzola";
    String s1c = "U2FsdGVkX18xMjM0NTY3OGEL9nxFlHrWvodMqar82NT53krNkqat0rrgeV5FAJFs1vBsZIJPZ08DJVrQjQyV15HEoyECBeAZ6MTeN+ZYHRitKanY5jiRU2J0KP0Fzola";
    byte[] bytesj = DatatypeConverter.parseBase64Binary(s1j);
    byte[] bytesc = DatatypeConverter.parseBase64Binary(s1c);
    int nmax = Math.max(bytesj.length, bytesc.length);
    int nmin = Math.min(bytesj.length, bytesc.length);
    for (int i = 0; i < nmax; ++i) {
        if (i >= nmin) {
            boolean isj = i < bytesj.length;
            byte b = isj? bytesj[i] : bytesc[i];
            System.out.printf("%s [%d] %x%n", (isj? "J" : "C++"), i, (int)b & 0xFF);
        } else {
            byte bj = bytesj[i];
            byte bc = bytesc[i];
            if (bj != bc) {
                System.out.printf("[%d] J %x != C++ %x%n", i, (int)bj & 0xFF, (int)bc & 0xFF);
            }
        }
    }
}

这提供了

[60] J 3f != C++ 8d

现在0x3f是问号的代码。

错误是,0x80 - 0xBF在Latin-1中,正式为ISO-8859-1,控制字符。 Windows Latin-1,正式Windows-1252,将这些代码用于其他字符。

因此,你应该在Java中使用“Windows-1252”或“Cp1252”(代码页)。


Blundly

在加密中,0x80 .. 0xBF范围内的原始字节被替换为问号,因为有些转换为ISO-8859-1而不是Windows-1252转换为byte []。< / p>