在api 18中使用密钥库时如何解决“ java.security.InvalidKeyException:不支持的密钥算法:EC。仅支持RSA”

时间:2019-05-23 15:04:22

标签: java android android-keystore

我需要使用API​​ 18将敏感数据存储在本地存储中,我选择使用Keystore。我尝试了几种解决方案,但都没有用。

我尝试在不进行强制转换的情况下在PrivateKey中创建我的RSAPrivateKey,但是它不起作用。 我也尝试使用其他加密算法,但是我无法成功使它们在API 18中工作

public String decryptString(String alias, String encryptedText) {
        KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
        keyStore.load(null);
String decryptedText = "";
        try {
            KeyStore.PrivateKeyEntry privateKeyEntry = (KeyStore.PrivateKeyEntry)keyStore.getEntry(alias, null);
            RSAPrivateKey privateKey = (RSAPrivateKey) privateKeyEntry.getPrivateKey();

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

            CipherInputStream cipherInputStream = new CipherInputStream(
                    new ByteArrayInputStream(Base64.decode(encryptedText, 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();
            }

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

        } catch (Exception e) {
            Log.e(TAG, Log.getStackTraceString(e));
        }
        return decryptedText;
    }
public String encryptString(String alias, String initialText) {
KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
        keyStore.load(null);
        String encryptedText = "";
        try {
            KeyStore.PrivateKeyEntry privateKeyEntry = (KeyStore.PrivateKeyEntry)keyStore.getEntry(alias, null);
            PublicKey publicKey = privateKeyEntry.getCertificate().getPublicKey();
            // Encrypt the text
            if(initialText.isEmpty()) {
                Log.e(TAG, "initialText is Empty");
                return "";
            }

            Cipher input = Cipher.getInstance("RSA/ECB/PKCS1Padding");
            input.init(Cipher.ENCRYPT_MODE, publicKey);//Need RSA private or public key

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

            byte [] vals = outputStream.toByteArray();
            encryptedText = Base64.encodeToString(vals, Base64.DEFAULT);
        } catch (Exception e) {
            Log.e(TAG, Log.getStackTraceString(e));
        }
        return encryptedText;
    }

这是我得到的性爱。我想成功地将数据保存在安全的地方

java.security.InvalidKeyException: Unsupported key algorithm: EC. Only RSA supported
at com.cryptor.Cryptor.encryptString(Cryptor.java:108)

1 个答案:

答案 0 :(得分:0)

当您生成RSA密钥时,我看不到哪里。就我而言,我已完成以下步骤:

  1. 创建/获取Keystore
  2. 使用KeyPairGenerator生成RSA密钥(请注意:自Android M起采用不同的方法)

val generator = KeyPairGenerator.getInstance(ALGORITHM, CryptoConstants.ANDROID_KEY_STORE)

在这里, ALGORITHM =“ RSA” ,而不是“ RSA / ECB / PKCS1Padding”和CryptoConstants。ANDROID_KEY_STORE=“ AndroidKeyStore”(例如)

  1. 将密钥保存在Keystore
  2. 使用公钥加密
  3. 使用私钥解密

通过这些步骤,我的加密方法是

fun encrypt(publicKey: PublicKey, rawText: ByteArray): String {
    try {
        val cipher = CipherUtil.getStandardCipherInstance(TRANSFORMATION) // TRANSFORMATION = "RSA/ECB/PKCS1Padding"
        cipher.init(Cipher.ENCRYPT_MODE, publicKey)
        val bytes = cipher.doFinal(rawText)
        return Base64.encodeToString(bytes, BASE64_SETTINGS) // BASE64_SETTINGS = Base64.NO_WRAP
    } catch (e: GeneralSecurityException) {
        throw SecurityException(e)
    }
}

fun decrypt(privateKey: PrivateKey, base64CipherBytes: ByteArray): ByteArray {
    try {
        val cipher = CipherUtil.getStandardCipherInstance(TRANSFORMATION) // TRANSFORMATION = "RSA/ECB/PKCS1Padding"
        cipher.init(Cipher.DECRYPT_MODE, privateKey)
        val encryptedData = Base64.decode(base64CipherBytes, BASE64_SETTINGS) // BASE64_SETTINGS
        return cipher.doFinal(encryptedData)
    } catch (e: GeneralSecurityException) {
        throw SecurityException(e)
    }
}

顺便说一句,如果不需要,您可以绕过Base64编码。