使用以下代码行使用 BouncyCastle 进行加密和解密,以解密从基于 C 的第 3 方源接收的数据。第一次加密和解密工作正常(基于他们要求使用的第 3 方共享的初始密钥和 iv)在整个会话期间),第二次加密和解密失败..主要是因为我再次使用相同的IV,如果你注意到的话。寻找新 IV 创建的逻辑是什么,以及我应该如何将其发送给第 3 方(如果我不发送它,他们如何在不知道创建的 IV 的情况下解密)
public byte[] encrypt(byte[] plainBytes) {
byte[] encryptedBytes = new byte[0];
try {
GCMBlockCipher cipher = new GCMBlockCipher(new AESFastEngine());
AEADParameters parameters =
new AEADParameters(new KeyParameter(key), MacBitSize, iv);
cipher.init(true, parameters);
encryptedBytes = new byte[cipher.getOutputSize(plainBytes.length)];
int retLen = cipher.processBytes
(plainBytes, 0, plainBytes.length, encryptedBytes, 0);
cipher.doFinal(encryptedBytes, retLen);
} catch (IllegalArgumentException |
IllegalStateException | DataLengthException |
InvalidCipherTextException ex) {
System.out.println(ex.getMessage());
}
System.arraycopy(aad, 0, encryptedBytes, plainBytes.length, 16);
byte[] final_encr = new byte[plainBytes.length];
System.arraycopy(encryptedBytes, 0, final_encr, 0, plainBytes.length);
return final_encr;
}
public byte[] decrypt(byte[] encryptedBytes) {
byte[] plainBytes = new byte[0];
try {
GCMBlockCipher cipher = new GCMBlockCipher(new AESFastEngine());
AEADParameters parameters =
new AEADParameters(new KeyParameter(key), MacBitSize, iv);
cipher.init(false, parameters);
cipher.processAADBytes(aad, 0, aad.length);
plainBytes = new byte[encryptedBytes.length];
int retLen = cipher.processBytes
(encryptedBytes, 0, encryptedBytes.length, plainBytes, 0);
retLen += cipher.processBytes(aad, 0, aad.length, plainBytes, retLen);
retLen += cipher.doFinal(plainBytes, retLen);
} catch (IllegalArgumentException | IllegalStateException |
DataLengthException | InvalidCipherTextException ex) {
System.out.println(ex.getMessage());
}
return plainBytes;
}
文档中第三方提供的方法
对于对称加密/解密方法 –
加密:
初始化→
void encrypt_EVP_aes_256_cbc_init(EVP_CIPHER_CTX ** ctx, unsigned char * key,
unsigned char * iv) {
if (!( * ctx = EVP_CIPHER_CTX_new()))
handleErrors();
if (1 != EVP_EncryptInit_ex( * ctx, EVP_aes_256_gcm(), NULL, key, iv))
handleErrors();
}
加密→
void encrypt(EVP_CIPHER_CTX * ctx, unsigned char * plaintext, int plaintext_len,
unsigned char * ciphertext, int * ciphertext_len) {
int len;
if (1 != EVP_EncryptUpdate(ctx, ciphertext, & len, plaintext, plaintext_len))
handleErrors();
* ciphertext_len = len;
}
解密:
初始化→
void decrypt_EVP_aes_256_cbc_init(EVP_CIPHER_CTX ** ctx, unsigned char * key,
unsigned char * iv) {
if (!( * ctx = EVP_CIPHER_CTX_new()))
handleErrors();
if (1 != EVP_DecryptInit_ex( * ctx, EVP_aes_256_gcm(), NULL, key, iv))
handleErrors();
}
解密→
int decrypt(EVP_CIPHER_CTX * ctx, unsigned char * ciphertext, int ciphertext_len,
unsigned char * plaintext, int * plaintext_len) {
int len;
if (1 != EVP_DecryptUpdate(ctx, plaintext, & len, ciphertext, ciphertext_len))
handleErrors();
* plaintext_len = len;
}
注意 –
看一下加密和解密的部分:
在加密中添加aad
System.arraycopy(aad, 0, encryptedBytes, plainBytes.length, 16);
在解密时您不使用这些数据
cipher.processAADBytes(aad, 0, aad.length);
请更新您的代码,不使用全局变量。
可能
[16 byte AAD || 12 byte IV || ciphertext]
是一个很好的加密输出吗?解密时读取aad,然后读取iv,然后执行解密。
使用inputstream和outputstream进行简单的读写。