【问题标题】:Converting an int to a String and then encrypt it with XOR将 int 转换为 String,然后使用 XOR 对其进行加密
【发布时间】:2012-11-14 21:43:17
【问题描述】:

我正在尝试将 Integer 转换为 String,然后使用 XOR 加密对 String 进行加密。但是当我再次解密我的 Strin 时,我得到了一个不同的答案,即我在加密之前输入的字符串,我不知道我做错了什么?

public class Krypte {
public static void main (String [] args) {
    int i = 12345;

    String k = Integer.toString(i);
    String G = secure(k.getBytes());
    System.out.println("Encrypted: " + G);

    String U = secure(G.getBytes());
    System.out.println("Decrypted: " + U);
    int X = Integer.parseInt(U);
    System.out.println("As an int: " + X);

}

public static String secure(byte[] msg) {
    // Variables
    int outLength = msg.length;
    byte secret = (byte) 0xAC; // same as 10101100b (Key)
    // XOR kryptering
    for (int i = 0; i < outLength; i++) {
        // encrypting each byte with XOR (^)
        msg[i] = (byte) (msg[i] ^ secret);
    }
    return new String(msg);
}
}

【问题讨论】:

  • 对不起,我的错。但是你能帮我解决我的编码问题,而不是我对加密的理解(误解)吗?
  • 问问自己:“什么是字符串”?字符串是 not 任意字节的序列。阅读String 的 Java 文档以帮助回答这个问题,您将开始理解为什么您的代码不起作用。

标签: java string encryption character-encoding int


【解决方案1】:

charbyte 类型之间存在细微(但非常重要)的区别。考虑一下:

class Krypte {
    public static void main (String [] args) {
        int i = 12345;
        String k = Integer.toString(i);
        System.out.println("Before: " + k);    
        String G = secure(k.toCharArray());
        System.out.println("Encrypted: " + G);
        String U = secure(G.toCharArray());
        System.out.println("Decrypted: " + U);
        int X = Integer.parseInt(U);
        System.out.println("As an int: " + X);
    }

    public static String secure(char[] msg) {
        // Variables
        int outLength = msg.length;
        byte secret = (byte) 0xAC; // same as 10101100b (Key)
        // XOR kryptering
        for (int i = 0; i < outLength; i++) {
            // encrypting each byte with XOR (^)
            System.out.println("Byte before: " + msg[i]);
            msg[i] = (char) (msg[i] ^ secret);
            System.out.println("Byte after: " + msg[i]);
        }
        return new String(msg);
    }
}

这行得通 (proof),因为将某些 character 值与一个字节进行异或运算 (most probably) 会给你一个有效的 character

让我们看看the original snippet 中发生了什么——通过将此调试输出添加到secure 方法的主循环中:

 System.out.println("Byte before: " + msg[i]);
 msg[i] = (byte) (msg[i] ^ secret);
 System.out.println("Byte after: " + msg[i]);

输出将是:

Byte before: 49
Byte after: -99
Byte before: 50
Byte after: -98
Byte before: 51
Byte after: -97
Byte before: 52
Byte after: -104
Byte before: 53
Byte after: -103

没关系:首先getBytes 函数编码 使用平台的默认字符集 将字符串赋予字节数组。字符'1' 被编码为49 字节值; '2' 变为 50 等。

然后我们用我们的键对这些值进行异或运算 - 并得到这个字节序列:

-99 -98 -97 -104 -103

最后一步似乎很简单:我们只是从这个字节序列中创建(并返回)一个新字符串,这里会出现什么问题?但事实上,这正是风扇受到打击的那一步。 )

看,String 构造函数尝试使用平台的默认字符集处理这个字节序列。事实上,对于某些字符集,这些字节代表一系列有效字符就可以了——但对于 UTF-8 则不行!

...您可能已经猜到接下来会发生什么。对于每个“不可解码”的字节序列,如described here第一个字节被转换为所谓的Replacement character,然后重试其他字节。在此特定示例中,第一个 secure 调用返回的字符串中将有五个失败迹象。

解码这个字符串是毫无意义的——因为它不存储关于目标字符串的任何信息(长度除外)。这就是原始代码最终失败的原因。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-07-14
    • 2016-04-14
    • 2016-02-08
    • 1970-01-01
    • 1970-01-01
    • 2021-09-14
    • 2014-07-29
    相关资源
    最近更新 更多