Java AES 256 Decrypt不会解密前16个字节

时间:2018-11-28 15:53:33

标签: aes

问题:下面的代码似乎可以正确进行AES 256加密,但是在解密时,前16个字节是不可读的“字节”,或者是未解密的或其他。前16个字节后的文本已正确解密。


我已经看到很多关于此问题的帖子,其中在解密AES 256时,前16个字节仍然是字节而不是文本。我已经尝试过这里建议的操作,例如将IV字节合并到Base64Encodeing之前的加密字节,但这没有用。我还确保我的两个Web方法(加密和解密)使用相同的IV字节。

我的独立逻辑(Java应用程序)按预期工作。经过数小时的艰辛工作和搜索尝试之后,我还是会问这里的一些专家。

对于以下代码可能存在的问题,我将不胜感激。

下面显示了两种Web服务GET方法,一种用于加密,另一种用于解密。

预先感谢

get("/AESEncrypt/:stringToEncrypt/:Base64SecretKey", (request, response) ->
        {
            String myKey = request.params("secretKey");
            byte[]  ivBytes = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };

            // assume encoded since string could be any characters
            String str2Encrypt = URLDecoder.decode(request.params("stringToEncrypt"), "UTF-8");

            //Salt please.
            String salt = "somesalt";
            final byte[] saltBytes = salt.getBytes("UTF-8");

            // Use SHA 256.
            final SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
            final PBEKeySpec spec = new PBEKeySpec(
                    myKey.toCharArray(),
                    saltBytes,
                    65536,
                    256);

            final SecretKey secretKey = factory.generateSecret(spec);
            final SecretKeySpec secret = new SecretKeySpec(secretKey.getEncoded(), "AES");

            //encrypt the message
            final Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            cipher.init(Cipher.ENCRYPT_MODE, secret);
            final AlgorithmParameters params = cipher.getParameters();

            final byte[] encryptedTextBytes = cipher.doFinal(str2Encrypt.getBytes("UTF-8"));
            return Base64.encodeBase64String(encryptedTextBytes);
        });

        //-----------

        get("/AESDecrypt/:stringToDecrypt/:decryptKey", (request, response) ->
        {
            String base64Key = request.params("decryptKey");
            String strToDecrypt =request.params("stringToDecrypt");
            String decryptedString = null;

            //Salt please.
            String salt = "somesalt";
            final byte[] saltBytes = salt.getBytes("UTF-8");

            // Derive the key
            final SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
            final PBEKeySpec spec = new PBEKeySpec(
                    base64Key.toCharArray(),
                    saltBytes,
                    65536,
                    256
            );
            final SecretKey secretKey = factory.generateSecret(spec);
            final SecretKeySpec secret = new SecretKeySpec(secretKey.getEncoded(), "AES");

            // Decrypt the message
            final Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");

            final AlgorithmParameters params = cipher.getParameters();
           // byte[] ivBytes = params.getParameterSpec(IvParameterSpec.class).getIV();
            byte[] ivBytes = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };

            cipher.init(Cipher.DECRYPT_MODE, secret, new IvParameterSpec(ivBytes));
            byte[] decryptedTextBytes = null;
            try
            {
                decryptedTextBytes = cipher.doFinal(Base64.decodeBase64(strToDecrypt));
            }
            catch (IllegalBlockSizeException e)
            {
                e.printStackTrace();
            }
            catch (BadPaddingException e)
            {
                e.printStackTrace();
            }

            return new String(decryptedTextBytes);
        });

1 个答案:

答案 0 :(得分:1)

您在解密过程中通过了IV,但是在加密过程中没有通过它。因此IV是随机的,导致解密时第一个块损坏(因为您使用的是其他IV)。您的意思是:

cipher.init(Cipher.ENCRYPT_MODE, secret, new IvParameterSpec(ivBytes));

请注意,使用相同的密钥和IV加密多封邮件是不安全的。您确实确实想要一个随机IV,而不是固定IV。但是无论如何,您都必须使用相同的