Java AES/CBC 解密后的初始字节不正确 [英] Initial bytes incorrect after Java AES/CBC decryption

查看:41
本文介绍了Java AES/CBC 解密后的初始字节不正确的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

下面的例子有什么问题?

问题是解密后的字符串的第一部分是废话.不过,其他的都还好,我明白了……

<块引用>

结果:`£eB6O geS  我是你吗?祝你今天过得愉快.

@Test公共无效测试加密(){尝试 {String s = "你好.你好吗?祝你有美好的一天.";//生成密钥KeyGenerator kgen = KeyGenerator.getInstance("AES");kgen.init(128);SecretKey aesKey = kgen.generateKey();//加密密码Cipher encryptCipher = Cipher.getInstance("AES/CBC/PKCS5Padding");encryptCipher.init(Cipher.ENCRYPT_MODE, aesKey);//加密ByteArrayOutputStream outputStream = new ByteArrayOutputStream();CipherOutputStream cipherOutputStream = new CipherOutputStream(outputStream, encryptCipher);cipherOutputStream.write(s.getBytes());cipherOutputStream.flush();cipherOutputStream.close();byte[] encryptedBytes = outputStream.toByteArray();//解密密码密码解密密码 = Cipher.getInstance("AES/CBC/PKCS5Padding");IvParameterSpec ivParameterSpec = new IvParameterSpec(aesKey.getEncoded());解密密码.init(密码.DECRYPT_MODE, aesKey, ivParameterSpec);//解密outputStream = new ByteArrayOutputStream();ByteArrayInputStream inStream = new ByteArrayInputStream(encryptedBytes);CipherInputStream cipherInputStream = new CipherInputStream(inStream,decryptCipher);字节[] buf = 新字节[1024];int 字节读取;而 ((bytesRead = cipherInputStream.read(buf)) >= 0) {outputStream.write(buf, 0, bytesRead);}System.out.println("结果:" + new String(outputStream.toByteArray()));}捕获(异常前){ex.printStackTrace();}}

解决方案

由于缺少一些信息,例如忘记转换为 Base64、初始化向量、字符集等,包括我自己在内的很多人在完成这项工作时面临很多问题. 所以我想制作一个功能齐全的代码.

希望对大家有用:要编译,您需要额外的 Apache Commons Codec jar,可在此处获得:http://commons.apache.org/proper/commons-codec/download_codec.cgi

import javax.crypto.Cipher;导入 javax.crypto.spec.IvParameterSpec;导入 javax.crypto.spec.SecretKeySpec;导入 org.apache.commons.codec.binary.Base64;公共类加密器{公共静态字符串加密(字符串密钥,字符串初始化向量,字符串值){尝试 {IvParameterSpec iv = new IvParameterSpec(initVector.getBytes("UTF-8"));SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes("UTF-8"), "AES");Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);字节 [] 加密 = cipher.doFinal(value.getBytes());System.out.println("加密字符串:"+ Base64.encodeBase64String(加密));返回 Base64.encodeBase64String(加密);} 捕捉(异常前){ex.printStackTrace();}返回空;}公共静态字符串解密(字符串密钥,字符串初始化向量,字符串加密){尝试 {IvParameterSpec iv = new IvParameterSpec(initVector.getBytes("UTF-8"));SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes("UTF-8"), "AES");Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);byte[] original = cipher.doFinal(Base64.decodeBase64(encrypted));返回新字符串(原始);} 捕捉(异常前){ex.printStackTrace();}返回空;}公共静态无效主(字符串 [] args){String key = "Bar12345Bar12345";//128 位密钥String initVector = "RandomInitVector";//16 字节 IVSystem.out.println(decrypt(key, initVector,encrypt(key, initVector, "Hello World")));}}

What's wrong with the following example?

The problem is that the first part of the decrypted string is nonsense. However, the rest is fine, I get...

Result: `£eB6O�geS��i are you? Have a nice day.

@Test
public void testEncrypt() {
  try {
    String s = "Hello there. How are you? Have a nice day.";

    // Generate key
    KeyGenerator kgen = KeyGenerator.getInstance("AES");
    kgen.init(128);
    SecretKey aesKey = kgen.generateKey();

    // Encrypt cipher
    Cipher encryptCipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
    encryptCipher.init(Cipher.ENCRYPT_MODE, aesKey);

    // Encrypt
    ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
    CipherOutputStream cipherOutputStream = new CipherOutputStream(outputStream, encryptCipher);
    cipherOutputStream.write(s.getBytes());
    cipherOutputStream.flush();
    cipherOutputStream.close();
    byte[] encryptedBytes = outputStream.toByteArray();

    // Decrypt cipher
    Cipher decryptCipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
    IvParameterSpec ivParameterSpec = new IvParameterSpec(aesKey.getEncoded());
    decryptCipher.init(Cipher.DECRYPT_MODE, aesKey, ivParameterSpec);

    // Decrypt
    outputStream = new ByteArrayOutputStream();
    ByteArrayInputStream inStream = new ByteArrayInputStream(encryptedBytes);
    CipherInputStream cipherInputStream = new CipherInputStream(inStream, decryptCipher);
    byte[] buf = new byte[1024];
    int bytesRead;
    while ((bytesRead = cipherInputStream.read(buf)) >= 0) {
        outputStream.write(buf, 0, bytesRead);
    }

    System.out.println("Result: " + new String(outputStream.toByteArray()));

  } 
  catch (Exception ex) {
    ex.printStackTrace();
  }
}

解决方案

Lot of people including myself face lot of issues in making this work due to missing some information like, forgetting to convert to Base64, initialization vectors, character set, etc. So I thought of making a fully functional code.

Hope this will be useful to you all: To compile you need additional Apache Commons Codec jar, which is available here: http://commons.apache.org/proper/commons-codec/download_codec.cgi

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

import org.apache.commons.codec.binary.Base64;

public class Encryptor {
    public static String encrypt(String key, String initVector, String value) {
        try {
            IvParameterSpec iv = new IvParameterSpec(initVector.getBytes("UTF-8"));
            SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes("UTF-8"), "AES");

            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
            cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);

            byte[] encrypted = cipher.doFinal(value.getBytes());
            System.out.println("encrypted string: "
                    + Base64.encodeBase64String(encrypted));

            return Base64.encodeBase64String(encrypted);
        } catch (Exception ex) {
            ex.printStackTrace();
        }

        return null;
    }

    public static String decrypt(String key, String initVector, String encrypted) {
        try {
            IvParameterSpec iv = new IvParameterSpec(initVector.getBytes("UTF-8"));
            SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes("UTF-8"), "AES");

            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
            cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);

            byte[] original = cipher.doFinal(Base64.decodeBase64(encrypted));

            return new String(original);
        } catch (Exception ex) {
            ex.printStackTrace();
        }

        return null;
    }

    public static void main(String[] args) {
        String key = "Bar12345Bar12345"; // 128 bit key
        String initVector = "RandomInitVector"; // 16 bytes IV

        System.out.println(decrypt(key, initVector,
                encrypt(key, initVector, "Hello World")));
    }
}

这篇关于Java AES/CBC 解密后的初始字节不正确的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆