【问题标题】:Fast, simple to use symmetric cipher for integer encryption in JavaJava 中用于整数加密的快速、简单易用的对称密码
【发布时间】:2015-04-26 16:08:27
【问题描述】:

什么是 Java 中具有这些属性的整数加密密码函数?:

  • 快速
  • 对称密钥算法
  • 使用简单(即几行代码即可使用,无需包含外部库)
  • 可以指定输出长度(例如20个字符)

我只需要用它来加密/解密整数。

【问题讨论】:

  • 恒等函数适用于此,速度快,对称,使用超级简单,并且可以通过传递给定长度的输入来指定输出长度。
  • @BenjaminGruenbaum 我需要加密我的整数,如何使用身份函数?
  • 你永远不能指定输出长度。它是从明文推断出来的。
  • @ArtjomB。好的.. 那么,让我删除这个要求.. 其他三个呢?

标签: java encryption encryption-symmetric


【解决方案1】:

没有外部库的要求将列表缩减为 DES、3DES 和 AES。 DES 和 3DES 的块大小为 64 位,而 AES 的块大小为 128 位。有不同的方面,可以检查一下。

密文大小

DES 和 3DES 最适合用于最多 56 位宽(非全长)的整数,因为由于填充,结果将是 8 字节的单个块。如果您加密一个完整的长值,则会添加一个额外的填充块。

AES 将始终为任何长整型值生成 16 字节密文。

速度

根据this analysis,AES (Rijndael-128) 的速度是 DES/3DES 的两倍多,并且密钥大小更大(更安全)。当 CPU 支持 AES-NI 时,AES 甚至可以比 DES 或 3DES 快得多。当前所有的 CPU 都支持这一点。这是我当前从openssl speed 命令获取的结果。

AES 对 16 字节有效负载达到 127MB/s,而 3DES 仅达到 27MB/s。 Here 是要查找的数据。

安全

不要将 DES 用于任何严重的事情,因为它只有一个 56 位密钥(64 位奇偶校验)。暴力破解成本为 256。 3DES 也不是很好,因为暴力破解成本是2112。 AES 的暴力破解成本为 2128、2192、2256,具体取决于使用的密钥大小。

代码

可能使用 AES:

private final String CIPHER_NAME = "AES/ECB/PKCS5Padding";
private final String ALGORITHM_NAME = "AES"; // keySizes 128, 192, 256
// private final String CIPHER_NAME = "DES/ECB/PKCS5Padding";
// private final String ALGORITHM_NAME = "DES"; // keySize 56
// private final String CIPHER_NAME = "DESede/ECB/PKCS5Padding";
// private final String ALGORITHM_NAME = "DESede"; // keySize 168

byte[] encrypt(SecretKey key, long num) {
    BigInteger bignum = BigInteger.valueOf(num);
    Cipher cipher = Cipher.getInstance(CIPHER_NAME);
    cipher.init(Cipher.ENCRYPT_MODE, key);
    return cipher.doFinal(bignum.toByteArray());
}

long decrypt(SecretKey key, byte[] ct) {
    Cipher cipher = Cipher.getInstance(CIPHER_NAME);
    cipher.init(Cipher.DECRYPT_MODE, key);
    byte[] pt = cipher.doFinal(ct);
    BigInteger bignum = new BigInteger(pt);
    return bignum.longValue();
}

SecretKey keyGen(String algorithm, int keySize) {
    KeyGenerator keygen = KeyGenerator.getInstance(algorithm);
    keygen.init(keySize);
    return keygen.generateKey();
}

操作模式

这里我使用 ECB 模式。使用它通常不是一个好主意。它有一个问题,即用相同的密钥加密相同的明文会导致相同的密文。这可能不是可接受的属性。如果它不可接受,那么您需要使用例如带有新随机 IV 的 CBC 模式。 With 会将密文炸毁一个额外的块。

【讨论】:

  • 我假设整数实际上意味着 32 位整数。
  • 我正在使用 Java Long 类型.. 但您的答案仍然有效,我看到加密/解密函数以 long 作为参数.. 不是吗?
  • 无论如何它对我有用!.. 我使用了 keySize = 128 位和固定的 SecretKey。
  • “此分析”链接似乎与您声称的相反......他们得出结论认为 AES 是最慢的。
  • @Gus 我只声称 AES 比 3DES 快得多,您可以从表 1 到表 3 中的数字看到这一点。请记住,3DES 仅提供 112 位安全性,因为可能会遇到- 中间攻击。 AES-128 在当前研究中提供至少 126 位的安全性,同时速度更快。如果我们假设当前处理器一代的 AES-NI 指令集,AES 可以被认为更快。
【解决方案2】:

如果您不需要安全的解决方案,而只需要快速,请考虑XOR cipher

int key = ...
....
int b = a ^ key;
int c = b ^ key;
assert (c == a);

【讨论】:

  • 在这个问题的特定情况下,XOR 密码也可能是最安全的解决方案(因为密码长度与消息长度相同——它们都是整数——实际上不可能解密不知道密钥的消息)。仅当加密的消息/整数彼此独立并且不具有众所周知的属性(例如,一条特定消息非常频繁)时,这才是正确的。
  • XOR 可能是最安全的选项,如果密钥是随机生成的,大于消息,并且在其生命周期内仅使用一次。如果您多次使用该键,您会得到一个可以推导出原始值的多次填充。
【解决方案3】:

如果您想要任何安全性,您永远不应该自己实现密码。出错的地方太多了。

但是您可以将您的数字写入byte[] 并使用Java 提供的密码,如this answer 中所述。

【讨论】:

    猜你喜欢
    • 2011-07-10
    • 2015-05-27
    • 2010-09-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多