当前位置: 首页 > 知识库问答 >
问题:

AES解密时未正确填充给定的最终块

吴炎彬
2023-03-14

首先,我会告诉你我的主要目标是什么。在客户端使用AES加密部分内容,然后使用RSA公钥加密重要的AES规范,并将AES加密数据和RSA加密的AES规范发送到服务器端。所以在服务器端,我将使用RSA私钥解密AES密钥规范,然后使用这些AES规范,我将解密AES加密数据。通过测试加密和解密,我成功地使RSA部分工作。在此实现RSa之前,我必须使AES art工作。

对于客户端,我使用crypto-js

<script src="http://crypto-js.googlecode.com/svn/tags/3.1.2/build/rollups/aes.js"></script>
<script src="http://crypto-js.googlecode.com/svn/tags/3.1.2/build/rollups/pbkdf2.js"></script>
<script src="http://crypto-js.googlecode.com/svn/tags/3.1.2/build/components/enc-base64-min.js"></script>
<script type="text/javascript" src="jquery-1.7.1.js"></script>
<script type="text/javascript">

    $("#submit").click(function() {
        var salt = CryptoJS.lib.WordArray.random(16);
        var iv = CryptoJS.lib.WordArray.random(16);
        var pass = CryptoJS.lib.WordArray.random(16);
        var message = "Test Message for encryption";
        var key128Bits = CryptoJS.PBKDF2(pass, salt, { keySize: 128 }); 
        var key128Bits10Iterations = CryptoJS.PBKDF2(pass, salt, { keySize: 128, iterations: 10 });
        var encrypted = CryptoJS.AES.encrypt(message, key128Bits10Iterations, { iv: iv, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7  });
        var cipherData = encrypted.toString()+":"+salt.toString()+":"+iv.toString()+":"+pass.toString();
        console.log(cipherData);

        $.ajax({
            url: 'encryption',
            type: 'POST',
            data: {
                cipherData: cipherData
            },
            success: function(data) {
                console.log(data);
            },
            failure: function(data) {

            }
        });
    });

</script>
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    String encryptedData = request.getParameter("cipherData");
    String data[] = encryptedData.split(":");

    String encrypted = data[0];     
    String salt = data[1];
    String iv = data[2];
    String password = data[3];

    byte[] saltBytes = hexStringToByteArray(salt);
    byte[] ivBytes = hexStringToByteArray(iv);
    IvParameterSpec ivParameterSpec = new IvParameterSpec(ivBytes);        
    SecretKeySpec sKey = null;
    try {
        sKey = (SecretKeySpec) generateKeyFromPassword(password, saltBytes);
    } catch (GeneralSecurityException e) {
        e.printStackTrace();
    }
    try {
        System.out.println( decrypt( encrypted , sKey ,ivParameterSpec));
    } catch (Exception e) {
        e.printStackTrace();
    }
}

public static SecretKey generateKeyFromPassword(String password, byte[] saltBytes) throws GeneralSecurityException {

    KeySpec keySpec = new PBEKeySpec(password.toCharArray(), saltBytes, 10, 128);
    SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
    SecretKey secretKey = keyFactory.generateSecret(keySpec);

    return new SecretKeySpec(secretKey.getEncoded(), "AES");
}

public static byte[] hexStringToByteArray(String s) {

    int len = s.length();
    byte[] data = new byte[len / 2];

    for (int i = 0; i < len; i += 2) {
        data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
                + Character.digit(s.charAt(i+1), 16));
    }

    return data;

}

public static String decrypt(String encryptedData, SecretKeySpec sKey, IvParameterSpec ivParameterSpec) throws Exception { 

    Cipher c = Cipher.getInstance("AES/CBC/PKCS5Padding");
    c.init(Cipher.DECRYPT_MODE, sKey, ivParameterSpec);
    byte[] decordedValue = Base64.decodeBase64(encryptedData);
    byte[] decValue = c.doFinal(decordedValue);
    String decryptedValue = new String(decValue);

    return decryptedValue;
}
byte[] decValue = c.doFinal(decordedValue);

javax.crypto.BadPaddingException: Given final block not properly padded
at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:966)
at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:824)
at com.sun.crypto.provider.AESCipher.engineDoFinal(AESCipher.java:436)
at javax.crypto.Cipher.doFinal(Cipher.java:2121)
at com.Encryption.decrypt(Encryption.java:95)
at com.Encryption.doPost(Encryption.java:60)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:644)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:725)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:291)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:219)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:503)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:136)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:610)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:526)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1078)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:655)
at org.apache.coyote.http11.Http11NioProtocol$Http11ConnectionHandler.process(Http11NioProtocol.java:222)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1566)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1523)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:745)

共有1个答案

阳福
2023-03-14

由于您希望使用RSA并且已经实现了它,因此不需要使用密码派生。创建随机密钥和随机IV:

var key = CryptoJS.lib.WordArray.random(16); // 128bit
var iv = CryptoJS.lib.WordArray.random(16);  // 128bit
var encrypted = CryptoJS.AES.encrypt(message, key, { iv: iv }); // CBC/PKCS#7 is default

然后您将iv.toString(crypto.enc.base64)encrypted.ciphertext.toString(crypto.enc.base64)和“rsaencrypt(key)”发送到服务器,对base64编码的iv和密文进行解码,对RSA密文进行解密得到AES密钥,并将它们组合起来对密文进行解密。

您最初的问题可能在于您使用的尺寸。CryptoJS有一个由每个字4个字节组成的内部表示形式。这就是为什么需要除以32来获得128位散列的原因:

var key128Bits = CryptoJS.PBKDF2(pass, salt, { keySize: 128/32 });

另一方面,WordArray只处理字节,这就是为什么除以8:

var key = CryptoJS.lib.WordArray.random(128/8);
 类似资料:
  • 我正在尝试编写方法来加密或解密字符串(大部分是数字)。它适用于某些文本(例如-'1010000011'、'1010000012'、'1010000013'),但也适用于其他文本(例如-'1010000014'、'1010000018'): javax.crypto.BadPadding异常:给定最后一个块没有正确填充 这是我的代码: 要加密的字符串从文件中读取,并在加密后写入其他文件。这些加密的文

  • 我正在做一个简单的加密文件传输系统,现在停止运行时异常: 我试图用一个字符串调试我的代码,用相同的密钥加密和解密,它是有效的。然而,当我试图从文件传输流时,这个异常总是出现。 以下是双方的代码。首先,他们将通过RSA交换对称密钥(AES密钥),然后通过AES加密传输大型文件。我们可以关注每段代码的最后一部分,其中文件通过AES密钥进行加密和解密。 服务器端: 客户端:

  • 问题内容: 我需要有关此错误的帮助:给最终块未正确填充。从标题中可以看到,我正在使用AES。 这是错误的行代码: 这是完整的代码: } 问题答案: 根据您的评论,您几乎可以使加密工作。 您需要将IV生成代码从您的加密/解密方法移动到其他地方,就像这样 然后将该ivspec传递到加密和解密方法中(使它们看起来像),这样您就可以为加密和解密使用相同的iv。 另外,不要调用decryptedByteAr

  • 我想加密EnteredDetails(java bean)类型的arraylist,并将其序列化到一个文件中。我正在关注AES-128位加密的链接:http://www . code 2 learn . com/2011/06/encryption-and-decryption-of-data-using . html 要使用aes class的encrypt方法,我必须将arrarylist转换

  • 问题内容: 我正在尝试实现基于密码的加密算法,但出现此异常: javax.crypto.BadPaddingException:给定的最终块未正确填充 可能是什么问题? 这是我的代码: (JUnit测试) 问题答案: 如果尝试使用错误的密钥解密填充了PKCS5的数据,然后取消填充(由Cipher类自动完成),则很可能会收到BadPaddingException(可能略小于255/256,约为99.