Android加密RSA InvalidKeyException

时间:2017-02-15 12:57:14

标签: java android security encryption rsa

亲爱的,

我需要帮助才能理解为什么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;
    }
}

1 个答案:

答案 0 :(得分:3)

尝试省略密码提供程序:

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

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