【问题标题】:Android Encryption RSA InvalidKeyExceptionAndroid 加密 RSA InvalidKeyException
【发布时间】:2017-02-15 21:40:20
【问题描述】:

亲爱的,

我需要帮助来理解为什么 decryptString 不起作用并抛出“java.security.InvalidKeyException:需要 RSA 私钥或公钥”。当调用加密方法时,我通过私钥/证书使用公钥。

感谢您的帮助!

public class KeysHandler {

    /***
     * Generate and store in AndroidKeyStore a security KeyPair keys.
     * @param alias - Alias to create the key.
     * @return KeyPair object with: private and public key.
     */
    public static KeyPair generateKeyPair(String alias) {
        KeyPair kp = null;
        if (alias != null) {
            try {

                KeyPairGenerator kpg = KeyPairGenerator.getInstance(KeyProperties.KEY_ALGORITHM_RSA, "AndroidKeyStore");
                kpg.initialize(new KeyGenParameterSpec.Builder(alias,
                        KeyProperties.PURPOSE_SIGN |
                        KeyProperties.PURPOSE_VERIFY |
                        KeyProperties.PURPOSE_ENCRYPT |
                        KeyProperties.PURPOSE_DECRYPT)
                        .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_RSA_PKCS1)
                        .build());

                kp = kpg.generateKeyPair();

            } catch (NoSuchProviderException | NoSuchAlgorithmException | InvalidAlgorithmParameterException ex) {
                kp = null;
            }
        }
        return kp;
    }

    public static String encryptString(String alias, String textToEncrypt) {
        String cipheredText = null;

        try {
            KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
            keyStore.load(null);

            KeyStore.PrivateKeyEntry privateKeyEntry = (KeyStore.PrivateKeyEntry)keyStore.getEntry(alias, null);

            // Encrypt the text
            if(textToEncrypt != null && textToEncrypt.length() > 0) {

                Cipher input = Cipher.getInstance("RSA/ECB/PKCS1Padding", "AndroidOpenSSL");
                input.init(Cipher.ENCRYPT_MODE, privateKeyEntry.getCertificate().getPublicKey());

                ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
                CipherOutputStream cipherOutputStream = new CipherOutputStream(
                        outputStream, input);
                cipherOutputStream.write(textToEncrypt.getBytes("UTF-8"));
                cipherOutputStream.close();

                byte[] vals = outputStream.toByteArray();
                cipheredText = Base64.encodeToString(vals, Base64.DEFAULT);
            }
        } catch (Exception e) {
            cipheredText = null;
        }

        return cipheredText;
    }


    public static String decryptString(String alias, String cipheredText) {

        String clearText = null;
        try {
            KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
            keyStore.load(null);

            KeyStore.PrivateKeyEntry privateKeyEntry = (KeyStore.PrivateKeyEntry)keyStore.getEntry(alias, null);

            Cipher output = Cipher.getInstance("RSA/ECB/PKCS1Padding", "AndroidOpenSSL");
            output.init(Cipher.DECRYPT_MODE, privateKeyEntry.getPrivateKey());

            CipherInputStream cipherInputStream = new CipherInputStream(
                    new ByteArrayInputStream(Base64.decode(cipheredText, Base64.DEFAULT)), output);
            ArrayList<Byte> values = new ArrayList<>();
            int nextByte;
            while ((nextByte = cipherInputStream.read()) != -1) {
                values.add((byte)nextByte);
            }

            byte[] bytes = new byte[values.size()];
            for(int i = 0; i < bytes.length; i++) {
                bytes[i] = values.get(i).byteValue();
            }

            clearText = new String(bytes, 0, bytes.length, "UTF-8");

        } catch (Exception e) {
            clearText = null;
        }

        return clearText;
    }
}

【问题讨论】:

    标签: java android security encryption rsa


    【解决方案1】:

    尝试省略密码提供程序:

    Cipher output = Cipher.getInstance("RSA/ECB/PKCS1Padding");
    

    其次,您可以先实例化提供程序以确保其正常工作,然后将其作为第二个参数传递给Cipher.getInstance(). 第二个参数可以是字符串(提供程序名称)或提供程序(对象)。使用第二个可能会使调试更容易。

    【讨论】:

    • @FrederikHV 真的很感谢,它在省略“AndroidOpenSSL”时就像一个魅力。祝您度过愉快的一周!
    • 你在哪里省略了?在加密和解密这两个地方都省略了吗?谢谢。
    • @sandeepmaaram 无论你在哪里调用 Cipher.getInstance
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-27
    • 1970-01-01
    • 2012-09-10
    • 1970-01-01
    • 2019-11-07
    • 1970-01-01
    相关资源
    最近更新 更多