在 Java 中快速、简单地使用对称密码进行整数加密
Fast, simple to use symmetric cipher for integer encryption in Java
Java 具有这些属性的整数加密的密码函数是什么?:
- 快
- 对称密钥算法
- 使用简单(即只需几行代码即可使用,无需包含外部库)
可以指定输出长度(例如20个字符)
我只需要将它用于 encrypt/decrypt 个整数。
如果你想要 任何 安全,你永远不应该自己实施密码。可能出错的地方太多了。
但是您可以将数字写入 byte[]
并使用 Java 提供的密码,如 this answer 中所述。
没有外部库的要求将列表减少到 DES、3DES 和 AES。 DES 和 3DES 的块大小为 64 位,而 AES 的块大小为 128 位。有不同的方面,可以看这个。
密文大小
DES 和 3DES 最适用于最多 56 位宽(非全长)的整数,因为由于填充,结果将是一个 8 字节的块。如果您加密一个完整的 long 值,则会添加一个额外的填充块。
AES 将始终为任何 long 值的 int 生成 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 会将密文炸毁一个额外的块。
如果您不需要安全解决方案,而只需要快速,请考虑XOR cipher:
int key = ...
....
int b = a ^ key;
int c = b ^ key;
assert (c == a);
Java 具有这些属性的整数加密的密码函数是什么?:
- 快
- 对称密钥算法
- 使用简单(即只需几行代码即可使用,无需包含外部库)
可以指定输出长度(例如20个字符)
我只需要将它用于 encrypt/decrypt 个整数。
如果你想要 任何 安全,你永远不应该自己实施密码。可能出错的地方太多了。
但是您可以将数字写入 byte[]
并使用 Java 提供的密码,如 this answer 中所述。
没有外部库的要求将列表减少到 DES、3DES 和 AES。 DES 和 3DES 的块大小为 64 位,而 AES 的块大小为 128 位。有不同的方面,可以看这个。
密文大小
DES 和 3DES 最适用于最多 56 位宽(非全长)的整数,因为由于填充,结果将是一个 8 字节的块。如果您加密一个完整的 long 值,则会添加一个额外的填充块。
AES 将始终为任何 long 值的 int 生成 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 会将密文炸毁一个额外的块。
如果您不需要安全解决方案,而只需要快速,请考虑XOR cipher:
int key = ...
....
int b = a ^ key;
int c = b ^ key;
assert (c == a);