【问题标题】:BadPaddingException while decrypting RSA from other client从其他客户端解密 RSA 时出现 BadPaddingException
【发布时间】:2016-11-18 17:42:01
【问题描述】:

我正在编写一个 Android 应用程序,它将其 RSA 公钥广播到网络,并允许其他客户端通过 TCP 连接到它。我有自己的自定义协议和数据包结构,然后我对其进行加密并发送给客户端(数据包 -> AES -> 带有客户端公钥的 RSA -> 客户端)。

private String encryptPacket(String packet, String pubKey)
{
    PublicKey clientPub = KeyFunctions.stringToKey(pubKey);
    String aesEncryptedData = null;
    byte[] rsaEncryptedData = null;
    String temp = null;

    try
    {
        // AES
        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
        final SecretKeySpec secretKey = new SecretKeySpec(Constants.KEY.getBytes(), "AES");
        cipher.init(Cipher.ENCRYPT_MODE, secretKey);
        aesEncryptedData = Base64.encodeToString(cipher.doFinal(packet.getBytes()), Base64.NO_PADDING|Base64.NO_WRAP);   //base64 the aes

        // RSA
        Cipher c = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        c.init(Cipher.ENCRYPT_MODE, clientPub);
        rsaEncryptedData = c.doFinal(aesEncryptedData.getBytes());
        temp = Base64.encodeToString(rsaEncryptedData, Base64.NO_PADDING|Base64.NO_WRAP);  // base 64 the rsa
        Log.d("ENC SEND", temp);
    } catch (Exception e)
    {
        e.printStackTrace();
    }
    return temp;
}

public String decryptPacket(String encryptedData, Context context)
{
    // get the keys
    PrivateKey pri = KeyFunctions.getPrivateKey(context);
    byte[] packet = null;
    byte[] decrypted = null;
    String temp = null;

    try
    {
        //RSA
        Cipher c = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        c.init(Cipher.DECRYPT_MODE, pri);
        byte[] rsaTempArray = Base64.decode(encryptedData, Base64.NO_PADDING|Base64.NO_WRAP);
        packet = c.doFinal(rsaTempArray);

        // AES
        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
        final SecretKeySpec secretKey = new SecretKeySpec(Constants.KEY.getBytes(), "AES");
        cipher.init(Cipher.DECRYPT_MODE, secretKey);
        final String decryptedString = new String(cipher.doFinal(Base64.decode(packet, Base64.NO_PADDING|Base64.NO_WRAP)));
        temp =  decryptedString;
    } catch (Exception e)
    {
        e.printStackTrace();
    }
    Log.d("ENC REC", temp);
    return temp;
}

当客户端将数据发送给自己时,此代码起作用。但是,将它发送到另一个客户端时它不起作用,给我以下错误:javax.crypto.BadPaddingException: error:0407106B:rsa routines:RSA_padding_check_PKCS1_type_2:block type is not 02

decryptPacket 调用时引发此异常,packet = c.doFinal(rsaTempArray);

我尝试通过调试验证公钥的值是否正确,那里似乎没有任何问题。

更新

这是更新的代码

private byte[] encryptPacket(Packet packet, String pubKey)
{
    PublicKey clientPub = KeyFunctions.stringToKey(pubKey);
    byte[] aesEncryptedData = null;
    byte[] rsaEncryptedData = null;
    byte[] temp = null;

    Log.d("START", "==========ENCRYPT==========");
    try
    {
        // AES
        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
        final SecretKeySpec secretKey = new SecretKeySpec(Constants.KEY.getBytes(), "AES");
        cipher.init(Cipher.ENCRYPT_MODE, secretKey);
        byte aesTempArray[] = cipher.doFinal(packet.getBytes());
        Log.d("ENC AES TEMP", new String(aesTempArray, "UTF-8"));
        aesEncryptedData = Base64.encode(aesTempArray, Base64.NO_PADDING | Base64.NO_WRAP);   //base64 the aes
        Log.d("ENC AES ENCR", new String(aesEncryptedData, "UTF-8"));

        // RSA
        Cipher c = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        c.init(Cipher.ENCRYPT_MODE, clientPub);
        rsaEncryptedData = c.doFinal(aesEncryptedData);
        Log.d("ENC RSA ENCR", new String(rsaEncryptedData, "UTF-8"));
        temp = Base64.encode(rsaEncryptedData, Base64.NO_PADDING | Base64.NO_WRAP);  // base 64 the rsa
        Log.d("ENC RSA TEMP", new String(temp, "UTF-8"));
    } catch (Exception e)
    {
        e.printStackTrace();
    }
    return temp;
}

public Packet decryptPacket(byte[] encryptedData, Context context)
{
    // get the keys
    PrivateKey pri = KeyFunctions.getPrivateKey(context);
    Packet p = null;
    byte[] aesDecryptedData = null;
    byte[] rsaDecryptedData = null;


    Log.d("START", "==========DECRYPT==========");
    try
    {
        //RSA
        Log.d("DEC INIT", new String(encryptedData, "UTF-8"));
        Cipher c = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        c.init(Cipher.DECRYPT_MODE, pri);
        byte[] rsaTempArray = Base64.decode(encryptedData, Base64.NO_PADDING | Base64.NO_WRAP);
        Log.d("DEC RSA TEMP", new String(rsaTempArray, "UTF-8"));
        rsaDecryptedData = c.doFinal(rsaTempArray);
        Log.d("DEC RSA ENCR", new String(rsaDecryptedData, "UTF-8"));

        // AES
        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
        final SecretKeySpec secretKey = new SecretKeySpec(Constants.KEY.getBytes(), "AES");
        cipher.init(Cipher.DECRYPT_MODE, secretKey);
        byte[] aesTempArray = Base64.decode(rsaDecryptedData, Base64.NO_PADDING | Base64.NO_WRAP);
        Log.d("DEC AES TEMP", new String(aesTempArray, "UTF-8"));
        aesDecryptedData = cipher.doFinal(aesTempArray);
        Log.d("DEC AES DEC", new String(aesDecryptedData, "UTF-8"));
        p = new Packet(aesDecryptedData);
    } catch (Exception e)
    {
        e.printStackTrace();
    }
    return p;
}

代码不再使用任何字符串,但仍然出现相同的异常。我现在已经确保接收者收到了与客户端发送的完全相同的数据。当客户端将数据发送到同一设备上的服务器时,该程序运行良好,但是当我尝试发送到另一台设备服务器时出现上述异常。两个设备都有自己的私钥/公钥对。每个设备都有彼此的公钥。

【问题讨论】:

  • 使用String.getBytes() 是一种非常常见且非常糟糕的方式来传递二进制数据。
  • 我已更新代码以使用字节数组而不是字符串。仍然有同样的问题。
  • “我有自己的自定义协议和数据包结构...” - 您可能还对 Google 的 Protocol Buffers 感兴趣。
  • 您可能希望为每条消息生成一个新的 AES 密钥。然后,您应该使用该密钥加密数据,然后使用 RSA 公钥加密该密钥。

标签: java android encryption cryptography rsa


【解决方案1】:

加密/解密代码很好,我使用了错误的 IP 地址来计算公钥。不过感谢您的帮助!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-08-04
    • 1970-01-01
    • 1970-01-01
    • 2015-10-29
    • 2011-02-24
    • 2018-09-15
    • 2012-02-07
    相关资源
    最近更新 更多