简体   繁体   English

Java / Groovy:更好地将加密字符串随机化

[英]Java/Groovy: Randomize Encryption String Better

I use encryption to create query parameters that get emailed to individuals with download links to various files. 我使用加密来创建查询参数,这些查询参数通过各种文件的下载链接发送给个人。 However, I've noticed that the encrypted strings are fairly similar for similar file names. 但是,我注意到对于相似的文件名,加密的字符串非常相似。 I'd like to change that. 我想改变一下。

Here's the code I'm currently using: 这是我当前正在使用的代码:

Cipher cipher = Cipher.getInstance('AES/CBC/PKCS5Padding')
cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec('****************' as byte[], AES'),
    new IvParameterSpec('***************' as byte[]))
String fileId = Base64.encodeBase64String(
    IOUtils.toByteArray(
        new CipherInputStream(
            new DeflaterInputStream(
                new ByteArrayInputStream(
                    ('File: ' + filename).getBytes('UTF-8')
                )
            ), cipher
        )
    )
)

For example if I have a file called Something_8.3.0.1471.exe and Something_8.3.0.1471_License.txt I would get the following two strings: 例如,如果我有一个名为Something_8.3.0.1471.exe和Something_8.3.0.1471_License.txt的文件,我将获得以下两个字符串:

mVjCmP2GCyxMJ1i5GHT1OOZEYXy1%2Buz%2BQ53QMelR4QU%2FTowMdjNcMjojlbjuTJEd

and

mVjCmP2GCyxMJ1i5GHT1OB%2F5S1rolp%2BwK9dATPdPtHn3uQiXnYUhLmym6hMI65TVfjA5IzSYInI9iIjZn9eExg%3D%3D

The first 20 or so characters of the encrypted string are identical, obviously because the beginning of the file names is identical. 加密字符串的前20个左右字符是相同的,显然是因为文件名的开头是相同的。 I was wondering if it's possible to remove this identicallity (if that's a word). 我想知道是否有可能消除这种相同性(如果这是一个词)。 Is it possible to have any change in the unencrypted string more prominently impact the whole encrypted string? 未加密字符串中的任何更改是否可能对整个加密字符串产生更明显的影响? If so, how would I go about making this change in Java/Groovy in the above code? 如果是这样,我将如何在上述代码中在Java / Groovy中进行此更改?

The same key and same plain text will always produce the same cipher text when used in deterministic encryption scheme. 确定性加密方案中使用相同的密钥和相同的纯文本将始终产生相同的密文。 Probabilistic encryption schemes introduce some randomness factor so that continuous invocations of encryption with the same key and same plain text produce different cipher texts. 概率加密方案引入了一些随机性因素,因此使用相同密钥和相同明文进行的连续加密调用会产生不同的密文。

Some crypto algorithms (like EC signatures) generate random values internally and do not even expose them to the user as they do not need to store the value of that randomness factor in order to decrypt the cipher text (or validate a signature) but in most ciphers the user is trusted to provide a random factor like initialization vector or nonce. 一些加密算法(例如EC签名)在内部生成随机值,甚至不向用户公开它们,因为它们不需要存储该随机性因子的值即可解密密文(或验证签名),但大多数情况下用户可信任的密码提供一个随机因素,例如初始化向量或随机数。

AES has a block size of 16 bytes, meaning that it splits the input into 16-byte chunks and processes each chunk separately (in ECB mode) or mixing in the previous processing results in some way (in most other cipher modes). AES的块大小为16个字节,这意味着它将输入分成16个字节的块,并分别处理每个块(在ECB模式下),或以某种方式在以前的处理结果中混合(在大多数其他密码模式下)。 For the very first block regardless of the cipher mode used the only inputs are the key, the IV and the first 16 bytes of the input. 对于第一个块,无论使用哪种加密方式,唯一的输入都是密钥,IV和输入的前16个字节。

In your example the first 16 bytes are the same in both cases, and it seems that you use the same key and same IV (one of the greatest crypto sins, by the way). 在您的示例中,前两种情况的前16个字节是相同的,并且似乎您使用了相同的密钥和相同的IV(顺便说一下,这是最大的加密罪过之一)。 As expected, the first 16 bytes (or, equivalently, first 20 Base64 characters) are the same. 如预期的那样,前16个字节(或等效地,前20个Base64字符)相同。 The next 16 bytes of the input are different, which leads to completely different second block of cipher text. 输入的接下来的16个字节是不同的,这导致密文的第二个块完全不同。

You must not use the same IV value twice. 您不得重复使用相同的IV值。 Use SecureRandom to generate unique IV values for each encryption attempt. 使用SecureRandom为每次加密尝试生成唯一的IV值。

SecureRandom random = new SecureRandom();
byte bytes[] = new byte[16]; // use the proper IV size for selected cipher
random.nextBytes(bytes);

When using a single storage entity (a single file, for example) storing the IV before the cipher text is the de facto standard, but it is not required (you can store the IV and the cipher text in a separate database columns, for example). 当使用单个存储实体(例如,单个文件)在密文之前存储IV是事实上的标准,但是不是必需的(您可以将IV和密文存储在单独的数据库列中,例如)。

You must not use keys created by simply converting a character sequence into a byte sequence. 您不得使用仅通过将字符序列转换为字节序列而创建的键。 Such keys have predictable properties (for example, for ASCII text your key will never contain bytes in the range of [0..31]). 这样的键具有可预测的属性(例如,对于ASCII文本,您的键将永远不会包含[0..31]范围内的字节)。 If you need a password-based key then use the proper key derivation function like PBKDF2. 如果您需要基于密码的密钥,请使用适当的密钥派生功能,例如PBKDF2。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM