【问题标题】:Length of Strings regarding XOR operation for byte array字节数组异或运算的字符串长度
【发布时间】:2012-03-21 07:22:07
【问题描述】:

我正在创建一个加密算法并对两个字符串进行异或。虽然我知道如何对两个字符串进行异或,但问题是长度。我有两个字节数组,一个用于可变大小的纯文本,然后可以说是 56 字节的密钥。我想知道的是对两个字符串进行异或的正确方法是什么。将它们连接成一个二进制字符串并对这两个值进行异或?让每个字节数组位置 XOR 一个连接的键的二进制值等。非常感谢任何帮助。

问候, 米琳达

【问题讨论】:

  • 您是出于学术好奇心还是为了实际使用而创建它?因为如果要实际使用,正确的做法是不使用。无论如何,您需要将所有内容转换为纯字节,然后循环遍历并对所有内容进行异或。
  • 纯粹的学术好奇心。如果我循环它,但如果它们的密钥大小和明文相同,一些字节将未处理或未异或正确?我应该复制密钥或明文值以匹配最高长度吗?

标签: java encryption xor


【解决方案1】:

要编码,只需从纯文本中移动字节数组,根据需要使用 mod % 运算符重复键。确保在两端使用相同的字符集。 从概念上讲,我们像这样重复密钥,忽略编码。

hello world, there are sheep
secretsecretsecretsecretsecr

加密

String plainText = "hello world, there are sheep";
Charset charSet = Charset.forName("UTF-8");
byte[] plainBytes = plainText.getBytes(charSet);
String key = "secret";
byte[] keyBytes = key.getBytes(charSet);

byte[] cipherBytes = new byte[plainBytes.length];
for (int i = 0; i < plainBytes.length; i++) {

    cipherBytes[i] = (byte) (plainBytes[i] ^ keyBytes[i
            % keyBytes.length]);
}
String cipherText = new String(cipherBytes, charSet);
System.out.println(cipherText);

要解密只需反转过程。

// decode
for (int i = 0; i < cipherBytes.length; i++) {

    plainBytes[i] = (byte) (cipherBytes[i] ^ keyBytes[i
            % keyBytes.length]);
}
plainText = new String(plainBytes, charSet); // <= make sure same charset both ends
System.out.println(plainText);

【讨论】:

  • 我强烈建议反对使用这种方法。 1) 您使用 ISO-8859-1 进行初始转换,这将丢失该编码未表示的任何字符的数据。我建议改用 UTF-8。 2) 您正在使用 platform default 编码将加密字节转换为文本。这在两个方面是一个坏主意 - 首先,平台默认编码可能因平台而异;其次,您没有 编码文本。您有任意二进制数据。在这里使用字符串构造函数是不合适的,IMO。它很容易丢失数据。
  • 我使用的是 UTF-8,所以在这方面还可以。我正在寻找的是有帮助的 keyBytes[i % keyBytes.length] 部分。
【解决方案2】:

(如 cmets 中所述,您不应该将其用于任何真正的事情。正确的密码学很难从头开始正确地完成 - 不要自己动手,使用现有的实现。)

对于字符串,真的没有“XOR”这样的概念。 XOR 指定给定两个 的结果,并且文本不是由位组成的 - 它是由 字符 组成的。

现在您可以只取每个字符(一个整数)的 Unicode 表示并将这些整数异或在一起 - 但结果很可能是一个整数序列,不是 任何有效字符串的有效 Unicode 表示。

不清楚您是否在以正确的方式开始思考 - 您谈到有字符串,但也有 56 个字节。您可能有一个字符串的编码表示(例如,将字符串转换为 UTF-8 的结果),但这不是一回事。

如果您有两个字节数组,您可以轻松地将它们异或在一起 - 如果其中一个比另一个短,则可能会循环回到其中一个的开头,以便结果始终与较长数组的长度相同.但是,即使两个 输入 都是(比如说)UTF-8 编码文本,结果通常也不是有效的 UTF-8 编码文本。如果您必须获得文本形式的结果,我建议此时使用 Base64 - public domain base64 encoder 有一个简单的 API。

【讨论】:

  • 是的,抱歉,我确实忘记提及我正在将字符串转换为 UTF-8。好吧,我的问题是,假设明文的字节数组长度为 124,密钥数组的长度为 56。问题是,由于在对每个位进行异或运算时,两个值都不相同,因此某些位不会被异或,应该如何我接近这个?
  • @MilindaD:正如我在答案中建议的那样,您可以循环回到密钥的开头。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-09-21
  • 2019-02-11
  • 1970-01-01
  • 2019-01-05
相关资源
最近更新 更多