Android-кодировать и декодировать RSA с помощью закрытого ключа?

Я пытаюсь кодировать и декодировать строки на Android, используя закрытый ключ, сгенерированный и сохраненный с помощью поставщика магазина ключей Android, который был представлен в Android 4.3

Я могу успешно создать и получить закрытый ключ, используя следующий код:

 private void generatePrivateKey(Activity context, String alias){
    /** Generate a new entry in the KeyStore by using the  * KeyPairGenerator API. We have to specify the attributes for a  * self-signed X.509 certificate here so the KeyStore can attach  * the public key part to it. It can be replaced later with a  * certificate signed by a Certificate Authority (CA) if needed.  */

    Calendar cal = Calendar.getInstance();
    Date now = cal.getTime();
    cal.add(Calendar.YEAR, 1);
    Date end = cal.getTime();

    KeyPairGenerator kpg = null;
    try {
        kpg = KeyPairGenerator.getInstance("RSA", "AndroidKeyStore");
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    } catch (NoSuchProviderException e) {
        e.printStackTrace();
    }
    try {
        kpg.initialize(new KeyPairGeneratorSpec.Builder(context)
                .setAlias(alias)
                .setStartDate(now)
                .setEndDate(end)
                .setSerialNumber(BigInteger.valueOf(1))
                .setSubject(new X500Principal("CN=" + alias))
                .build());
    } catch (InvalidAlgorithmParameterException e) {
        e.printStackTrace();
    }

    KeyPair kp = kpg.generateKeyPair();

    /*
 * Load the Android KeyStore instance using the the
 * "AndroidKeyStore" provider to list out what entries are
 * currently stored.
 */
    KeyStore ks = null;
    try {
        ks = KeyStore.getInstance("AndroidKeyStore");
        ks.load(null);
        Enumeration<String> aliases = ks.aliases();
    } catch (KeyStoreException e) {
        e.printStackTrace();
    } catch (CertificateException e) {
        e.printStackTrace();
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }

    /*
 * Use a PrivateKey in the KeyStore to create a signature over
 * some data.
 */

    KeyStore.Entry entry = null;
    try {
        entry = ks.getEntry(alias, null);
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    } catch (UnrecoverableEntryException e) {
        e.printStackTrace();
    } catch (KeyStoreException e) {
        e.printStackTrace();
    }
    if (!(entry instanceof KeyStore.PrivateKeyEntry)) {
        Log.w("E", "Not an instance of a PrivateKeyEntry");
    }
    else{
        Log.w("E", "Got Key!");
        privateKeyEntry = ((KeyStore.PrivateKeyEntry) entry).getPrivateKey();
    }

}

и вот код, который я использую для шифрования (кодирования) и расшифровки (декодирования):

private String encryptString(String value){
    byte[] encodedBytes = null;
    try {
        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding", "AndroidOpenSSL");
        cipher.init(Cipher.ENCRYPT_MODE,  privateKeyEntry );
        encodedBytes = cipher.doFinal(value.getBytes());
    } catch (Exception e) {
        e.printStackTrace();
    }

    return Base64.encodeToString(encodedBytes, Base64.DEFAULT);
}

private String decryptString(String value){
    byte[] decodedBytes = null;
    try {
        Cipher c = Cipher.getInstance("RSA/ECB/PKCS1Padding", "AndroidOpenSSL");
        c.init(Cipher.DECRYPT_MODE,  privateKeyEntry );
        decodedBytes = c.doFinal(Base64.decode(value, Base64.DEFAULT));
    } catch (Exception e) {
        e.printStackTrace();
    }

    return new String(decodedBytes);
}

шифрование работает нормально, но когда я пытаюсь расшифровать его, я получаю следующее ошибка:

javax.crypto.BadPaddingException: error:0407106B:rsa routines:RSA_padding_check_PKCS1_type_2:block type is not 02

Googling это, кажется, предполагает, что закрытый ключ, используемый для дешифрования, отличается от того, который используется для дешифрования, но в моем коде я использую один и тот же закрытый ключ для обоих. Я также видел, что он предложил установить размер ключа вручную, но делать это в KeyPairGenerator builder следующим образом:

.setKeySize(1024);

не работал и, похоже, доступен только на API 19, мне нужно настроить API 18.

может ли кто-нибудь помочь указать мне в правильном направлении что касается решения?

2 ответов


вы не С помощью публичный ключ для шифрования.

когда вы используете асимметричные алгоритмы шифрования, вам нужно использовать общественные ключ to шифровать ваши данные, и частная ключ только расшифровать это снова.

помимо шифрования, вы также можете использовать закрытый ключ для подписания, но это не то, что вы хотите здесь, так что давайте забудь об этом на время.

Если взять публичный ключ из сгенерированной пары при шифровании строки и закрытого ключа при расшифровке вы должны получить желаемый результат. Открытый ключ можно извлечь, обратившись к сертификат из хранилища ключей-объект, который содержит ваш закрытый ключ.

в качестве альтернативы вы также можете использовать симметричного алгоритм, как AES, и это делает вашу работу много облегчающий. Кроме того, симметричные алгоритмы обычно намного быстрее, поэтому асимметричные алгоритмы никогда не используются чисто, а в сочетании с симметричными алгоритмами строят так называемые гибридные алгоритмы.


генерации подписи-это не то же самое, что шифрование. Вам нужно зашифровать с помощью открытого ключа и расшифровать с помощью закрытого ключа, если вы хотите шифрования. Если вы хотите создать подпись, вам нужно подписать с помощью закрытого ключа и проверить с помощью открытого ключа. Этот порядок не может быть отменен или смешан (надежно).