如何将公钥 RSA 保存到“AndroidKeyStore”

问题描述

如何将公钥 RSA 保存到“AndroidKeyStore”密钥库?

我开发了一个应用程序,该应用程序使用 RSA-AES 来加密两个对等方之间的数据。这有两个步骤,第一步是将公钥交换给其他对等方。然后使用AES会话密钥加密数据并使用RSA密钥加密AES会话密钥。 我研究了公钥可以与密钥存储中的证书一起保存,所以我执行以下代码

    KeyPairGenerator kpg = KeyPairGenerator.getInstance(KeyProperties.KEY_ALGORITHM_RSA,"AndroidKeyStore");
    kpg.initialize(new KeyGenParameterSpec.Builder("key",KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
                    .setKeySize(2048)
                    .build());
    KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
    keyStore.load(null);

    Certificate x509Certificate = CertificateFactory.getInstance("X.509").generateCertificate(new ByteArrayInputStream(keyStore.getCertificate("key").getEncoded()));

    keyStore.setCertificateEntry("key-new",x509Certificate);
    
    Certificate certificate = keyStore.getCertificate("key-new");

当我getCertificate(KeyStore:KeyStore异常 android.os.ServiceSpecificException: (代码 7))。 所以我编码错误,或者“AndroidKeyStore”不能用来保存其他人的公钥。

解决方法

我有两种使用 RSA 密钥加密和解密的方法,也许可以帮助您加密 AES 会话密钥。

private static final String ANDROID_KEY_STORE_NAME = "AndroidKeyStore";
private static final String KEY_ALIAS = "Milad";
private static final String RSA_MODE = "RSA/ECB/PKCS1Padding";
private static final String CIPHER_PROVIDER_NAME_ENCRYPTION_DECRYPTION_RSA = "AndroidOpenSSL";
private final Context mContext;

public Cryptography(Context context) {
    mContext = context;
}

private byte[] rsaEncryptKey(byte[] secret) throws KeyStoreException,CertificateException,NoSuchAlgorithmException,IOException,NoSuchProviderException,NoSuchPaddingException,UnrecoverableEntryException,InvalidKeyException {

    KeyStore keyStore = KeyStore.getInstance(ANDROID_KEY_STORE_NAME);
    keyStore.load(null);

    KeyStore.PrivateKeyEntry privateKeyEntry = (KeyStore.PrivateKeyEntry) keyStore.getEntry(KEY_ALIAS,null);
    Cipher inputCipher = Cipher.getInstance(RSA_MODE,CIPHER_PROVIDER_NAME_ENCRYPTION_DECRYPTION_RSA);
    inputCipher.init(Cipher.ENCRYPT_MODE,privateKeyEntry.getCertificate().getPublicKey());

    ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
    CipherOutputStream cipherOutputStream = new CipherOutputStream(outputStream,inputCipher);
    cipherOutputStream.write(secret);
    cipherOutputStream.close();

    byte[] encryptedKeyAsByteArray = outputStream.toByteArray();
    return encryptedKeyAsByteArray;
}

private byte[] rsaDecryptKey(byte[] encrypted) throws KeyStoreException,null);
    Cipher output = Cipher.getInstance(RSA_MODE,CIPHER_PROVIDER_NAME_ENCRYPTION_DECRYPTION_RSA);
    output.init(Cipher.DECRYPT_MODE,privateKeyEntry.getPrivateKey());
    CipherInputStream cipherInputStream = new CipherInputStream(
            new ByteArrayInputStream(encrypted),output);
    ArrayList<Byte> values = new ArrayList<>();
    int nextByte;
    while ((nextByte = cipherInputStream.read()) != -1) {
        values.add((byte) nextByte);
    }

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