Java:AES/CFB/nop使用Base64编码添加加密
我想使用AES/CFB/NoPadding在Java中加密字节 我在Stackoverflow上发现了以下问题,但仅涉及解密函数: 我将如何在Java中编写与以下go代码类似的加密函数Java:AES/CFB/nop使用Base64编码添加加密,java,go,aes,Java,Go,Aes,我想使用AES/CFB/NoPadding在Java中加密字节 我在Stackoverflow上发现了以下问题,但仅涉及解密函数: 我将如何在Java中编写与以下go代码类似的加密函数 package main import ( "io" "crypto/aes" "crypto/cipher" "encoding/base64" "crypto/rand" ) func encrypt(key, data []byte) string { b
package main
import (
"io"
"crypto/aes"
"crypto/cipher"
"encoding/base64"
"crypto/rand"
)
func encrypt(key, data []byte) string {
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
encoded := base64.StdEncoding.EncodeToString(data)
ciphertext := make( []byte, aes.BlockSize+len(encoded) )
iv := ciphertext[:aes.BlockSize]
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
return nil, err
}
cfb := cipher.NewCFBEncrypter(block, iv)
cfb.XORKeyStream( ciphertext[aes.BlockSize:], []byte(encoded) )
return ciphertext, nil
}
我的Golang解密函数如下所示(它应该返回base64代码):
我的加密代码如下所示(在Golang和Java中都可以正常工作):
当我在Java中加密某些内容,然后尝试在Java中使用我的解密程序时,会出现以下解密错误:
04-13 14:16:48.382 3791-3791/com.domain.interpretest W/System.err: java.lang.IllegalArgumentException: 16 > 9
04-13 14:16:48.388 3791-3791/com.domain.interpretest W/System.err: at java.util.Arrays.copyOfRange(Arrays.java:3447)
您的Go加密摘要:
- 使用随机IV(以及您没有描述的密钥)加密base64加密数据,将IV后跟密文放在单个缓冲区中
- 从缓冲区中取出第一个块,并将其用作IV来解密缓冲区的其余部分,然后对其进行解基
- 使用固定(全零)IV加密,并返回一个仅包含密文的缓冲区,而不包含任何位置的IV
Arrays.copyOfRange
会彻底失败
解决方案:Java加密应该使用随机IV并返回一个缓冲区,该缓冲区包含IV,后跟密文,就像Go加密一样。一种与你的围棋非常相似的方法:
// once, during initialization
SecureRandom rand = new SecureRandom(); // or .getInstance* as you prefer
// unchanged
SecretKeySpec key_spec = new SecretKeySpec(current_encryption_key, "AES");
Cipher cipher = Cipher.getInstance("AES/CFB/NoPadding");
byte[] encoded_payload = Base64.encode(payload, Base64.DEFAULT);
// changed
int block_size = cipher.getBlockSize();
// create random IV
byte[] buffer = new byte[block_size];
rand.nextBytes(buffer);
IvParameterSpec iv = new IvParameterSpec (buffer);
// expand buffer already containing IV to make room for ciphertext
buffer = Arrays.copyOf (buffer, block_size+encoded_payload.length);
// unchanged
cipher.init(Cipher.ENCRYPT_MODE, key_spec, iv);
// changed
// do encryption into correct part of existing buffer
cipher.doFinal(encoded_payload,0,encoded_payload.length, buffer,block_size);
return buffer;
PS:你为什么费心对你的明文进行base64编码和解码?AES和所有现代密码一样,可以很好地处理任何比特组合。当其他代码不能以位/二进制方式处理密文和IV时,使用base64更为常见 可能是特雷弗的复制品,请仔细阅读我的问题。我不想要CBC加密,我想要CFB加密。我的问题也没有表明我想使用我自己的IVStackoverflow不是代码翻译服务。密码是标准化的,你自己试试吧,为什么不呢?麻烦的一个提示是:如果“CFB”在Java中不起作用,请尝试“CFB8”。祝你好运。嗨,马丁,谢谢你回答我的问题。然而,它没有起作用。我可以成功地解密使用上述Golang代码加密的数据。我不知道你为什么告诉我这不是代码翻译服务,我认为添加代码示例是绝对详细地描述我的问题的最好/唯一方法。@MaartenBodewes,即使你只是评论一下简单的步骤(不是代码),我应该如何使用Java中的XORstream创建AES/CFB/NoPadding,非常感谢,但我仍然无法使用Golang函数对使用您提出的Java代码加密的数据进行解密。据我所知,Java中的解密和加密现在运行良好。为了清晰起见,我添加了Golang decrypt函数。我的密钥是32字节。
private byte[] decrypt(byte[] payload) {
try {
SecretKeySpec key_spec = new SecretKeySpec(current_encryption_key, "AES");
Cipher cipher = Cipher.getInstance("AES/CFB/NoPadding");
int block_size = cipher.getBlockSize();
IvParameterSpec iv = new IvParameterSpec( Arrays.copyOf(payload, block_size) );
byte[] decryption_data = Arrays.copyOfRange(payload, block_size, payload.length);
cipher.init(Cipher.DECRYPT_MODE, key_spec, iv);
byte[] decrypted_payload = cipher.doFinal(decryption_data);
return Base64.decode(decrypted_payload, Base64.DEFAULT);
} catch (Exception e) {
e.printStackTrace();
}
return new byte[0];
}
04-13 14:16:48.382 3791-3791/com.domain.interpretest W/System.err: java.lang.IllegalArgumentException: 16 > 9
04-13 14:16:48.388 3791-3791/com.domain.interpretest W/System.err: at java.util.Arrays.copyOfRange(Arrays.java:3447)
// once, during initialization
SecureRandom rand = new SecureRandom(); // or .getInstance* as you prefer
// unchanged
SecretKeySpec key_spec = new SecretKeySpec(current_encryption_key, "AES");
Cipher cipher = Cipher.getInstance("AES/CFB/NoPadding");
byte[] encoded_payload = Base64.encode(payload, Base64.DEFAULT);
// changed
int block_size = cipher.getBlockSize();
// create random IV
byte[] buffer = new byte[block_size];
rand.nextBytes(buffer);
IvParameterSpec iv = new IvParameterSpec (buffer);
// expand buffer already containing IV to make room for ciphertext
buffer = Arrays.copyOf (buffer, block_size+encoded_payload.length);
// unchanged
cipher.init(Cipher.ENCRYPT_MODE, key_spec, iv);
// changed
// do encryption into correct part of existing buffer
cipher.doFinal(encoded_payload,0,encoded_payload.length, buffer,block_size);
return buffer;