aescfb加密_使用AES-CFB在Java中加密并解密

I am aware of a question very similar to this (How do I encrypt in Python and decrypt in Java?) but I have a different problem.

My problem is, I am not able to decrypt in Java correctly. Despite using the correct key and IV, I still get garbage characters after decryption. I don't have any compile/run-time errors or exceptions in Java so I believe I am using the right parameters for decryption.

Python Encryption Code -

from Crypto.Cipher import AES

import base64

key = '0123456789012345'

iv = 'RandomInitVector'

raw = 'samplePlainText'

cipher = AES.new(key,AES.MODE_CFB,iv)

encrypted = base64.b64encode(iv + cipher.encrypt(raw))

Java Decryption Code -

private static String KEY = "0123456789012345";

public static String decrypt(String encrypted_encoded_string) throws NoSuchAlgorithmException, NoSuchPaddingException,

InvalidKeyException, IllegalBlockSizeException, BadPaddingException {

String plain_text = "";

try{

byte[] encrypted_decoded_bytes = Base64.getDecoder().decode(encrypted_encoded_string);

String encrypted_decoded_string = new String(encrypted_decoded_bytes);

String iv_string = encrypted_decoded_string.substring(0,16); //IV is retrieved correctly.

IvParameterSpec iv = new IvParameterSpec(iv_string.getBytes());

SecretKeySpec skeySpec = new SecretKeySpec(KEY.getBytes("UTF-8"), "AES");

Cipher cipher = Cipher.getInstance("AES/CFB/NoPadding");

cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);

plain_text = new String(cipher.doFinal(encrypted_decoded_bytes));//Returns garbage characters

return plain_text;

} catch (Exception e) {

System.err.println("Caught Exception: " + e.getMessage());

}

return plain_text;

}

Is there anything obvious that I am missing?

解决方案

The Cipher Feedback (CFB) mode of operation is a family of modes. It is parametrized by the segment size (or register size). PyCrypto has a default segment size of 8 bit and Java (actually OpenJDK) has a default segment size the same as the block size (128 bit for AES).

If you want CFB-128 in pycrypto, you can use AES.new(key, AES.MODE_CFB, iv, segment_size=128). If you want CFB-8 in Java, you can use Cipher.getInstance("AES/CFB8/NoPadding");.

Now that we have that out the way, you have other problems:

Always specify the character set you're using, because it can change between different JVMs: new String(someBytes, "UTF-8") and someString.getBytes("UTF-8"). When you do, be consistent.

Never use a String to store binary data (new String(encrypted_decoded_bytes);). You can copy the bytes directly: IvParameterSpec iv = new IvParameterSpec(Arrays.copyOf(encrypted_decoded_bytes, 16)); and cipher.doFinal(Arrays.copyOfRange(encrypted_decoded_bytes, 16, encrypted_decoded_bytes.length)).

In Java, you're assuming that the IV is written in front of the ciphertext and then encoded together, but in Python, you're never doing anything with the IV. I guess you posted incomplete code.

It is crucial for CFB mode to use a different IV every time if the key stays the same. If you don't change the IV for every encryption, you will create a multi-time pad which enables an attacker to deduce the plaintext even without knowing the key.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值