【问题标题】:AES-128 Encrypted String not properly paddedAES-128 加密字符串未正确填充
【发布时间】:2014-11-14 17:10:10
【问题描述】:

我在使用 AES/CBC/PKCS5Padding128 位密钥 创建加密字符串时遇到问题。我有解密加密字符串的代码。我有一个来自另一个成功解密的系统的示例加密字符串,但是当我尝试创建自己的加密字符串时,由于某种原因它没有正确填充。当我解密我的加密字符串时,它只显示 16 字节之后的字符。

我发现的所有示例都假设首先发生加密,然后在加密期间设置变量,然后立即进行解密,或者它们随机生成密钥,但在我的情况下,我想使用已知密钥。

我真的被困住了,所以任何帮助都将不胜感激,非常感谢您的时间和努力!

示例:

原文: 01234567891234565

加密: zmb16qyYrdoW6akBdcJv7DXCzlw0qU7A2ea5q4YQWUo=

密钥长度: 16

解密: 5(这是原始文本字符串中的最后一个数字)

示例代码:

package com.company.encrypt.tests;

import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

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

public class TestEncryptDecrypt {

    private static final String characterEncoding = "UTF-8";
    private static final String cipherTransformation = "AES/CBC/PKCS5Padding";
    private static final String aesEncryptionAlgorithm = "AES";

    public static void main(String[] args) throws Exception {
        String key1 = "1234567812345678";
        String text = "01234567891234565";
        System.out.println("Original Text: " + text);
        String encrypted = encrypt(text, key1);
        System.out.println("Encrypted: " + encrypted);
        String decrypted = decrypt(encrypted, key1);
        System.out.println("Decrypted: " + decrypted);

    }

    public static String decrypt(String encryptedText, String key) throws Exception {
        String plainText = null;

        int keyLength = key.length();
        System.out.println("Key length: " + String.valueOf(keyLength));
        byte[] encryptedTextBytes = Base64.decodeBase64(encryptedText.getBytes());
        byte[] keyBytes = key.getBytes();

        byte[] initialVector = Arrays.copyOfRange(encryptedTextBytes, 0, keyLength);
        byte[] trimmedCipherText = Arrays.copyOfRange(encryptedTextBytes, keyLength, encryptedTextBytes.length);

        try {
            Cipher cipher = Cipher.getInstance(cipherTransformation);
            SecretKeySpec secretKeySpec = new SecretKeySpec(keyBytes, aesEncryptionAlgorithm);
            IvParameterSpec ivParameterSpec = new IvParameterSpec(initialVector);
            cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParameterSpec);

            byte[] clearText;
            clearText = cipher.doFinal(trimmedCipherText);

            plainText = new String(clearText, characterEncoding);
        } catch(NoSuchAlgorithmException | NoSuchPaddingException | IllegalBlockSizeException | BadPaddingException
                | InvalidKeyException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return plainText;

    }

    public static String encrypt(String plainText, String encryptionKey) throws Exception {

        SecretKeySpec key = new SecretKeySpec(encryptionKey.getBytes("UTF-8"), aesEncryptionAlgorithm);
        Cipher cipher = Cipher.getInstance(cipherTransformation);
        cipher.init(Cipher.ENCRYPT_MODE, key);

        byte[] plainTextBytes = plainText.getBytes("UTF-8");

        byte[] encrypted = cipher.doFinal(plainTextBytes);

        return new String(Base64.encodeBase64(encrypted));
    }

}

【问题讨论】:

  • 密钥不是字符串,它由位组成。您应该使用 byte[] 的所有可能值 - 可能使用十六进制表示,或者您应该使用基于密码的加密。
  • 欢迎来到 StackOverflow!我看到一个新用户被另一个新用户回答的次数并不多:)
  • 非常感谢!我使用过 StackOverflow,但直到现在还没有机会发布问题。我不得不承认我有点兴奋终于发布了! :)

标签: java encryption aes


【解决方案1】:

我注意到在decrypt() 函数中,您将加密数组分成两部分:前 16 个字节,其余部分。您使用前 16 个字节作为 IV 进行解密,但是,您没有将 16 字节 IV 预先添加到 encrypt() 中加密消息的开头。这会导致明文的前 16 个字节丢失。我假设您认为 doFinal() 会自动为您执行此操作,但事实并非如此。

要解决此问题,请在返回加密消息之前添加 IV,可以使用 cipher.getIV() 检索它。您可以使用 Apache Commons Lang 库中的 ArrayUtils.addAll() 来完成此操作,或者只需编写自己的函数来完成此操作。另一件需要注意的是,IV 将始终是块大小,对于 AES,无论密钥大小如何,它都是 16 字节。

希望这个答案有帮助!

【讨论】:

  • 谢谢你,owlstead。很高兴来到这里!
  • 非常感谢您的欢迎,更感谢您的回答!这成功了,你不知道我为了这个把头撞在墙上多久了。再次感谢,非常感谢您的帮助!
猜你喜欢
  • 2018-06-12
  • 2014-07-26
  • 1970-01-01
  • 2015-05-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-10-24
  • 1970-01-01
相关资源
最近更新 更多