Java 让AES/GCM使用密码时遇到问题
我正在尝试使用Java的加密库来实现使用GCM模式的AES加密(因为这是一个AEAD方案,我希望确保数据完整无缺地到达),但为了方便用户,我希望使用密码。让程序无误地编译是一件困难的事情,直到我把头撞在砖墙上读了几遍 现在,不幸的是,程序可以编译,但它返回的密文只是消息中字节数的一小部分(我怀疑GCM使用的只是头,而实际的消息根本没有被写入)。有人能帮忙吗 以下是一些程序变量:Java 让AES/GCM使用密码时遇到问题,java,encryption,cryptography,Java,Encryption,Cryptography,我正在尝试使用Java的加密库来实现使用GCM模式的AES加密(因为这是一个AEAD方案,我希望确保数据完整无缺地到达),但为了方便用户,我希望使用密码。让程序无误地编译是一件困难的事情,直到我把头撞在砖墙上读了几遍 现在,不幸的是,程序可以编译,但它返回的密文只是消息中字节数的一小部分(我怀疑GCM使用的只是头,而实际的消息根本没有被写入)。有人能帮忙吗 以下是一些程序变量: private static final byte[] SALT = {(byte)0x3b,(byte)0x12,(
private static final byte[] SALT = {(byte)0x3b,(byte)0x12,(byte)0x44,(byte)0x61,
(byte)0xec,(byte)0xc0,(byte)0xa1,(byte)0x82,
(byte)0x4d, (byte)0x97, (byte)0x4d, (byte)0x3c,
(byte)0x57, (byte)0xd9, (byte)0x94, (byte)0x52};
private static final String CIPHER_ALG = "AES/GCM/PKCS5Padding";
private static final String SEC_RANDOM_ALG = "SHA1PRNG";
private static final String S_KEY_FACTORY_ALG = "PBKDF2WithHmacSHA1";
private static final int AES_KEY_SIZE = 128; //num bits
private static final int GCM_NONCE_LENGTH = 16; //num bytes
private static final int GCM_TAG_LENGTH = 16; //num bytes
private static final int KEY_SPEC_ROUNDS = 65536;
下面是加密方法:
//FIXME somehow the cipher is truncating the message or something
private byte[] encrypt(File file, String password) throws IOException{
Path path = Paths.get(file.toURI());
byte[] messageBytes = Files.readAllBytes(path);
//Message bytes: 3253
System.out.printf("Message bytes: %d%n", messageBytes.length);
byte[] messageName = path.getFileName().toString().getBytes();
byte[] cipherBytes = {};
byte[] iv = {};
try{
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(S_KEY_FACTORY_ALG);
PBEKeySpec pbeKeySpec = new PBEKeySpec(password.toCharArray(), SALT, KEY_SPEC_ROUNDS, AES_KEY_SIZE);
SecretKey key = keyFactory.generateSecret(pbeKeySpec);
System.out.printf("Secret key take 1: " + Arrays.toString(key.getEncoded()) + "%n");
SecretKeySpec secretKeySpec = new SecretKeySpec(key.getEncoded(), "AES");
//FIXME this is not encrypting the message correctly
Cipher cipher = Cipher.getInstance(CIPHER_ALG);
final byte[] nonce = new byte[GCM_NONCE_LENGTH];
SecureRandom random = SecureRandom.getInstanceStrong();
random.nextBytes(nonce);
GCMParameterSpec paramSpec = new GCMParameterSpec(GCM_TAG_LENGTH * 8, nonce);
iv = paramSpec.getIV();
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, paramSpec);
cipher.updateAAD(messageName);
cipher.update(messageBytes);
cipherBytes = cipher.doFinal();
}catch(NoSuchAlgorithmException e){
e.printStackTrace();
}catch(NoSuchPaddingException e){
e.printStackTrace();
}catch(InvalidKeyException e){
e.printStackTrace();
}catch(InvalidAlgorithmParameterException e){
e.printStackTrace();
}catch(InvalidKeySpecException e){
e.printStackTrace();
}catch(BadPaddingException e){
e.printStackTrace();
}catch(IllegalBlockSizeException e){
e.printStackTrace();
}
//IV bytes: 16
System.out.printf("IV bytes: %d%n", iv.length);
//Cipher bytes: 21
System.out.printf("Cipher bytes: %d%n", cipherBytes.length);
//Cipher bytes: [121, 68, 7, -69, -35, -9, -83, 101, -60, -80, 42, 59, -67, 126, 18, -82, 79, -60, 34, -125, 12]
System.out.printf("Cipher bytes: " + Arrays.toString(cipherBytes) + "%n");
//FIXME somehow the cipher is shortening the message or something
return cipherBytes;
}
不应忽略
cipher.update(messageBytes)的返回值代码>。此外,GCM在下面使用CTR模式。CTR模式不需要填充,因此您应该使用“AES/GCM/NoPadding”
此时,您可能正在取回密文的最后一部分和身份验证标记(即尾部而不是头部)。您可能想看看我关于加密相关异常的介绍。那么我是否应该将返回值导入cipher.doFinal()方法?或者我可以跳过这一行,直接调用cipher.doFinal(messageBytes);我想也是这样。