Java:AES/CFB/nop使用Base64编码添加加密

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

我想使用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 {
    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后跟密文放在单个缓冲区中
Java解密的摘要:

  • 从缓冲区中取出第一个块,并将其用作IV来解密缓冲区的其余部分,然后对其进行解基
这些是比赛

Java加密概述:

  • 使用固定(全零)IV加密,并返回一个仅包含密文的缓冲区,而不包含任何位置的IV
这不匹配。解密尝试从没有IV的缓冲区中删除IV。事实上,你的密文只有9个字节(尽管我不明白为什么不是4的倍数);这比一个AES块短,因此
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;