安卓公钥加密

10

我的Android应用程序实现了RSA加密,但是后端无法解密应用程序生成的令牌。这是代码,调用之前已经删除了公钥的开头和结尾行,可能是什么问题?

String encryptedToken = Base64.encodeToString(encrypt(publicKey, "4111111111111111"), Base64.NO_WRAP);

public static byte[] encrypt(String publicKey, String data) {
        if (TextUtils.isEmpty(publicKey) || TextUtils.isEmpty(data)) {
            return null;
        }
        try {
            // Decode the modified public key into a byte[]
            byte[] publicKeyByteArray = Base64.decode(publicKey.getBytes("UTF-8"),Base64.NO_WRAP);

            Cipher mCipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding");
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(publicKeyByteArray);
            Key key = keyFactory.generatePublic(x509KeySpec);
            mCipher.init(Cipher.ENCRYPT_MODE, key);
            return mCipher.doFinal(data.getBytes("UTF-8"));
        }
        catch (UnsupportedEncodingException e) {
            Log.e("RSAKEY", e.getMessage());
        }
        catch (NoSuchPaddingException e) {
            Log.e("RSAKEY", e.getMessage());
        } catch (NoSuchAlgorithmException e) {
            Log.e("RSAKEY", e.getMessage());
        } catch (InvalidKeyException e) {
            Log.e("RSAKEY", e.getMessage());
        } catch (InvalidKeySpecException e) {
            Log.e("RSAKEY", e.getMessage());
        } catch (IllegalBlockSizeException e) {
            Log.e("RSAKEY", e.getMessage());
        } catch (BadPaddingException e) {
            Log.e("RSAKEY", e.getMessage());
        }
        return null;
    }

后端团队提供了以下可运行的示例代码,但它是针对桌面Java的。 Android库没有Base64.getEncoder方法。 它与我编写的代码非常相似,但我的代码只是不起作用。

 // Decode the modified public key into a byte[]
            byte[] publicKeyByteArray = Base64.getDecoder().decode(publicKey.getBytes(StandardCharsets.UTF_8));

            // Create a PublicKey from the byte array
            X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKeyByteArray);
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            PublicKey pubKey = keyFactory.generatePublic(keySpec);

            // Get an instance of the Cipher and perform the encryption
            Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding");
            cipher.init(Cipher.ENCRYPT_MODE, pubKey);
            byte[] cipherText = cipher.doFinal(ccNum.getBytes(StandardCharsets.UTF_8));

            // Get the encrypted value as a Base64-encoded String
            String encodeToStr = Base64.getEncoder().encodeToString(cipherText);

            // Print out the encoded, encrypted string
            System.out.println("Encrypted and Encoded String: " + encodeToStr);

我比较了每个步骤的字节数组值。桌面端加密和安卓加密获得了完全相同的输入。然而,来自安卓代码cipher.doFinal的结果无法被后端解密。如果我将桌面端的结果放在REST调用正文中,它们能够正常工作,因此这不是由REST调用引起的问题。

我还尝试在Android上创建公钥/私钥对,并使用生成的公钥进行加密,而不是使用我们后端的公钥进行加密,然后使用私钥进行解密,它可以工作。因此,加密器也是有效的,只是后端希望得到一些不同的东西。


问题是什么?也许如果您展示解密代码,有人可以回答这个问题。 - pedrofb
那就这么做吧。检查密钥。检查算法。检查填充方式。确认你需要发送base64编码。你的代码看起来是正确的。 - user207421
你为什么选择“RSA/ECB/OAEPWithSHA-256AndMGF1Padding”? - President James K. Polk
这就是所需的。我已经尝试了所有的Base64标志,但没有一个有效。Base64.NO_WRAP是唯一一个后端不会抱怨错误的base64格式,但它仍然无法解码。 - Ray
那么,您对后端需要什么有一些规范。也许您可以将其添加到问题中。 - President James K. Polk
显示剩余4条评论
1个回答

8

终于有人在团队中解决了这个问题。原因是Android操作系统使用Bouncy Castle,而后端使用Sun作为提供者,导致后端抛出BadPaddingException异常。为了使其正常工作,在Android上需要以以下方式初始化密码器:

 mCipher.init(Cipher.ENCRYPT_MODE, key, new
                    OAEPParameterSpec("SHA-256", "MGF1", MGF1ParameterSpec.SHA1,
                    PSource.PSpecified.DEFAULT));

请查看此贴获取更多详细信息: http://bouncy-castle.1462172.n4.nabble.com/Problems-with-OAEP-SHA-256-hash-crypto-td1466852.html


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接