gpt4 book ai didi

java - AES 加密 IV

转载 作者:搜寻专家 更新时间:2023-10-31 08:14:43 25 4
gpt4 key购买 nike

我在下面的 (E.1) 中使用这个作为我的应用程序,其中显然存在一个我认识和理解的巨大明显的安全漏洞。我对加密越来越感兴趣,想更好地理解它,我需要生成一个随 secret 钥和一个 IV,但不确定如何正确执行) 所以我以后能更好地理解和应用我的知识,本质上我只是想让代码更安全,谢谢。

(E.1)

    byte[] key = "mykey".getBytes("UTF-8");

private byte[] getKeyBytes(final byte[] key) throws Exception {
byte[] keyBytes = new byte[16];
System.arraycopy(key, 0, keyBytes, 0, Math.min(key.length, keyBytes.length));
return keyBytes;
}

public Cipher getCipherEncrypt(final byte[] key) throws Exception {
byte[] keyBytes = getKeyBytes(key);
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
SecretKeySpec secretKeySpec = new SecretKeySpec(keyBytes, "AES");
IvParameterSpec ivParameterSpec = new IvParameterSpec(keyBytes);
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec);
return cipher;
}

public void encrypt(File in, File output, byte[] key) throws Exception {

Cipher cipher = getCipherEncrypt(key);
FileOutputStream fos = null;
CipherOutputStream cos = null;
FileInputStream fis = null;
try {
fis = new FileInputStream(in);
fos = new FileOutputStream(output);
cos = new CipherOutputStream(fos, cipher);
byte[] data = new byte[1024];
int read = fis.read(data);
while (read != -1) {
cos.write(data, 0, read);
read = fis.read(data);
System.out.println(new String(data, "UTF-8").trim());

}
cos.flush();

} finally {

System.out.println("performed encrypt method now closing streams:\n" + output.toString());
cos.close();
fos.close();
fis.close();


}
}


public void watchMeEncrypt(){

encrypt(file, new File ("example.txt),key);

最佳答案

AES key 仅由随机字节组成。对于 CBC 模式,IV 模式也应该是随机的(至少对于攻击者而言)。所以一般来说,您可以简单地使用 SecureRandom 实例来创建 key 和 IV。然后可以将 IV 包含在密文中;通常它只是简单地放在它前面。

不过,对于 Java,最好使用 KeyGenerator。如果您查看它在 SUN 提供程序中的实现,它可能相当于同一件事。然而,使用 KeyGenerator 与各种 key 和提供程序更兼容。这很可能是生成 key 的要求,例如智能卡和 HSM。

那么让我们展示一个包含三个简单方法的类:

package nl.owlstead.stackoverflow;

import static java.nio.charset.StandardCharsets.UTF_8;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.NoSuchAlgorithmException;
import java.security.Provider;
import java.security.SecureRandom;
import java.util.Optional;

import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.CipherOutputStream;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;

public class CreateKeyAndIVForAES_CBC {

public static SecretKey createKey(final String algorithm, final int keysize, final Optional<Provider> provider, final Optional<SecureRandom> rng) throws NoSuchAlgorithmException {
final KeyGenerator keyGenerator;
if (provider.isPresent()) {
keyGenerator = KeyGenerator.getInstance(algorithm, provider.get());
} else {
keyGenerator = KeyGenerator.getInstance(algorithm);
}

if (rng.isPresent()) {
keyGenerator.init(keysize, rng.get());
} else {
// not really needed for the Sun provider which handles null OK
keyGenerator.init(keysize);
}

return keyGenerator.generateKey();
}

public static IvParameterSpec createIV(final int ivSizeBytes, final Optional<SecureRandom> rng) {
final byte[] iv = new byte[ivSizeBytes];
final SecureRandom theRNG = rng.orElse(new SecureRandom());
theRNG.nextBytes(iv);
return new IvParameterSpec(iv);
}

public static IvParameterSpec readIV(final int ivSizeBytes, final InputStream is) throws IOException {
final byte[] iv = new byte[ivSizeBytes];
int offset = 0;
while (offset < ivSizeBytes) {
final int read = is.read(iv, offset, ivSizeBytes - offset);
if (read == -1) {
throw new IOException("Too few bytes for IV in input stream");
}
offset += read;
}
return new IvParameterSpec(iv);
}

public static void main(String[] args) throws Exception {
final SecureRandom rng = new SecureRandom();
// you somehow need to distribute this key
final SecretKey aesKey = createKey("AES", 128, Optional.empty(), Optional.of(rng));
final byte[] plaintext = "owlstead".getBytes(UTF_8);

final byte[] ciphertext;
{
final ByteArrayOutputStream baos = new ByteArrayOutputStream();

final Cipher aesCBC = Cipher.getInstance("AES/CBC/PKCS5Padding");
final IvParameterSpec ivForCBC = createIV(aesCBC.getBlockSize(), Optional.of(rng));
aesCBC.init(Cipher.ENCRYPT_MODE, aesKey, ivForCBC);

baos.write(ivForCBC.getIV());

try (final CipherOutputStream cos = new CipherOutputStream(baos, aesCBC)) {
cos.write(plaintext);
}

ciphertext = baos.toByteArray();
}

final byte[] decrypted;
{
final ByteArrayInputStream bais = new ByteArrayInputStream(ciphertext);

final Cipher aesCBC = Cipher.getInstance("AES/CBC/PKCS5Padding");
final IvParameterSpec ivForCBC = readIV(aesCBC.getBlockSize(), bais);
aesCBC.init(Cipher.DECRYPT_MODE, aesKey, ivForCBC);

final byte[] buf = new byte[1_024];
try (final CipherInputStream cis = new CipherInputStream(bais, aesCBC);
final ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
int read;
while ((read = cis.read(buf)) != -1) {
baos.write(buf, 0, read);
}
decrypted = baos.toByteArray();
}
}

System.out.println(new String(decrypted, UTF_8));
}
}

请注意,您可能并不总是希望“带外”生成和分发 AES key 。这里是a few other methods of generating a key (从第 2 部分开始)。您可能还想看看 more advanced exception handling for the cryptographic operation .

关于java - AES 加密 IV,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35907877/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com