在Golang中进行AES加密,在Java中进行解密

5
我有以下用Golang编写的AES加密函数。
func encrypt(key []byte, text string) string {
    plaintext := []byte(text)

    block, err := aes.NewCipher(key)
    if err != nil {
        panic(err)
    }

    ciphertext := make([]byte, aes.BlockSize+len(plaintext))
    iv := ciphertext[:aes.BlockSize]
    if _, err := io.ReadFull(rand.Reader, iv); err != nil {
        panic(err)
    }

    stream := cipher.NewCFBEncrypter(block, iv)
    stream.XORKeyStream(ciphertext[aes.BlockSize:], plaintext)

    return base64.URLEncoding.EncodeToString(ciphertext)
}

我很难理解如何使用Java解密生成的文本流。非常感谢您能提供任何帮助!

这里是Scala代码,不确定其中存在什么问题。

def decode(input:String) = {
    val keyBytes = Hex.decodeHex("someKey".toCharArray)
    val inputWithoutPadding = input.substring(0,input.size - 2)
    val inputArr:Seq[Byte] = Hex.decodeHex(inputWithoutPadding.toCharArray)

    val skSpec = new SecretKeySpec(keyBytes, "AES")
    val iv = new IvParameterSpec(inputArr.slice(0,16).toArray)
    val dataToDecrypt = inputArr.slice(16,inputArr.size)

    val cipher = Cipher.getInstance("AES/CFB/NoPadding")
    cipher.init(Cipher.DECRYPT_MODE, skSpec, iv)
    cipher.doFinal(dataToDecrypt.toArray)
}

1
已经在这里复制了您的代码:https://glot.io/snippets/een965dgb3,但仍然没有得到一个可行的Java解决方案。 - Kevin Deenanauth
1
Java代码在哪里?请注意,在流上下文中使用CFB模式:XORKeyStream - zaph
@Ripul,你找到解决方案了吗? - SunnyShah
1个回答

4

Java解码器 (另请参见在线可运行演示,打开并点击“执行”):

String decode(String base64Text, byte[] key) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
    byte[] inputArr = Base64.getUrlDecoder().decode(base64Text);
    SecretKeySpec skSpec = new SecretKeySpec(key, "AES");
    Cipher cipher = Cipher.getInstance("AES/CFB/NoPadding");
    int blockSize = cipher.getBlockSize();
    IvParameterSpec iv = new IvParameterSpec(Arrays.copyOf(inputArr, blockSize));
    byte[] dataToDecrypt = Arrays.copyOfRange(inputArr, blockSize, inputArr.length);
    cipher.init(Cipher.DECRYPT_MODE, skSpec, iv);
    byte[] result = cipher.doFinal(dataToDecrypt);
    return new String(result, StandardCharsets.UTF_8);
}

评论区的Kevin提供了这个原始Go编码器的演示,我们可以看到以下结果:

encrypt([]byte("0123456789abcdef"), "test text 123")

这是一个名为c1bpFhxn74yzHQs-vgLcW6E5yL8zJfgceEQgYl0=的编码。

让我们看一下上面的Java解码器如何处理该输入:

String text = "c1bpFhxn74yzHQs-vgLcW6E5yL8zJfgceEQgYl0=";
byte[] key = "0123456789abcdef".getBytes();
System.out.println(decode(text, key));

打印 test text 123


Scala 版本 (在线可运行演示):

def decode(input:String, key:String) = {
    val cipher = Cipher.getInstance("AES/CFB/NoPadding")
    val blockSize = cipher.getBlockSize()
    val keyBytes = key.getBytes()
    val inputArr = Base64.getUrlDecoder().decode(input)
    val skSpec = new SecretKeySpec(keyBytes, "AES")
    val iv = new IvParameterSpec(inputArr.slice(0, blockSize).toArray)
    val dataToDecrypt = inputArr.slice(blockSize, inputArr.size)
    cipher.init(Cipher.DECRYPT_MODE, skSpec, iv)
    new String(cipher.doFinal(dataToDecrypt.toArray))
}

def main(args: Array[String]) {
    print(decode("c1bpFhxn74yzHQs-vgLcW6E5yL8zJfgceEQgYl0=", "0123456789abcdef"));
}

我认为Scala版本中唯一的错误是使用了Hex.decodeHex。你需要一个使用RFC 4648中所描述的URL安全字母表的Base64解码器,而java.util.Base64(自Java 8以来)通过其getUrlDecoder()提供了这个功能。


非常棒,非常感谢! - SunnyShah
@Hugues 非常有用,你能提交Java的加密代码吗?我的意思是从Java加密,然后在Golang上解密?谢谢。 - Asad

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接