Невозможно преобразовать PrivateKey в строку

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

я попытался преобразовать закрытый ключ с помощью Base64, но выдал ошибку, указывающую, что PrivateKey.getEncoded() имеет значение null

Итак, я попробовал до Base64 и снова получил null .

public String newKey() throws
            NoSuchAlgorithmException,
            NoSuchProviderException,
            InvalidAlgorithmParameterException, KeyStoreException, CertificateEncodingException, UnrecoverableEntryException {

        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(ALGORITHM, KEYSTORE);
        KeyGenParameterSpec keyGenParameterSpec = new KeyGenParameterSpec
                .Builder(alias, KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
                .setBlockModes(KeyProperties.BLOCK_MODE_ECB)
                .setEncryptionPaddings(PADDING)
                .build();

        keyPairGenerator.initialize(keyGenParameterSpec);
        PrivateKey key = keyPairGenerator.generateKeyPair().getPrivate();

        KeyStore.PrivateKeyEntry entry = (KeyStore.PrivateKeyEntry) keyStore.getEntry(alias,null);
        String a = privateKeyEntryToString(entry,key);
        //  java.util.Base64.getDecoder().decode(entry)
        //  Log.d("tag",entry);


        Log.d("tag", "done in new Key returning keypublic");
        return a;
       // return keyPairGenerator.generateKeyPair().getPublic();

    }
    private String privateKeyEntryToString(KeyStore.PrivateKeyEntry privateKeyEntry,PrivateKey key) throws CertificateEncodingException {

 Certificate certificate = privateKeyEntry.getCertificate();
        if (key.getEncoded().length == 0){ // but here we get exception that it is null.
            return "its empty";
        }
        
        

        // Convert PrivateKey and Certificate to String
        String privateKeyString = Base64.encodeToString(key.getEncoded(), Base64.DEFAULT);
        String certificateString = Base64.encodeToString(certificate.getEncoded(), Base64.DEFAULT);

        // Combine both strings with a separator for later use
        return privateKeyString + "-----BEGIN CERTIFICATE-----\n" + certificateString;

Трассировки стека :

FATAL EXCEPTION: main
Process: com.leo.nopasswordforyou, PID: 9525
java.lang.NullPointerException: Attempt to get length of null array

Хранилище ключей Android защищает закрытые ключи и не позволяет экспортировать их из защищенной среды.

President James K. Polk 05.03.2024 18:35

@PresidentJamesK.Polk вы можете получить закрытый ключ во время его создания. И этот вопрос не о том, как получить закрытый ключ из хранилища ключей. ключ анализируется иначе, чем Entry.

Rudra 05.03.2024 18:44

Я предположил, что используемое хранилище ключей — это хранилище ключей Android. Если это неверно, вам потребуется предоставить дополнительный код, показывающий, откуда берутся аргументы вашей функции privateKeyEntryToString(). Вы можете получить объект PrivateKey из этого хранилища ключей, но он не содержит конфиденциальной информации о закрытом ключе и getEncoded(), вызванный по нему, вернет null.

President James K. Polk 05.03.2024 18:56

@PresidentJamesK.Polk Я отредактировал исходный вопрос. и добавлена ​​функция PrivateKeyEntryToString

Rudra 05.03.2024 19:12

А какова ценность KEYSTORE в KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(ALGORITHM, KEYSTORE);?

President James K. Polk 05.03.2024 19:22

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

Rudra 05.03.2024 19:28

Android содержит несколько реализаций хранилища ключей, которые можно использовать через один и тот же API. Одним из них является AndroidKeystore, который не позволяет экспортировать ключ, а другие реализации просто сохраняют пароль ключа, защищенный в файле, поэтому вы можете делать с закрытым ключом все, что хотите. Поэтому нам нужно знать значение KEYSTORE.

Robert 05.03.2024 19:46

окончательная строка KEYSTORE = "AndroidKeyStore"; ,final String ALGORITHM = "RSA";

Rudra 05.03.2024 19:49

Тогда все происходит именно так, как предполагал Джеймс. Вы используете аппаратное хранилище, которое защищает ключи. Вам не нужно их где-либо хранить, они уже сохранены в безопасном виде и защищены аппаратной мерой безопасности. getEndcoded для таких ключей никогда не подойдет.

Robert 05.03.2024 19:52

@Роберт, дело в том, что я получаю закрытый ключ из keyPairGenerator.generateKeyPair(), значит ли это, что после создания пары ключей он сохраняет их в KeyPair и при появлении запроса на получение пересылает ключ хранилища ключей. например: keyPairGenerator.generateKeyPair().getPrivate();

Rudra 05.03.2024 19:54

Вы не читали то, что я пишу.

President James K. Polk 05.03.2024 20:07

Итак, есть ли другой способ (кроме KeyStore), где я могу получить оба ключа, а позже, получив ключи, я могу поместить их в KeyStore. @PresidentJamesK.Polk, извини, я не понял, что ты сказал.

Rudra 05.03.2024 20:11

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

Rudra 05.03.2024 20:12

Если вам нужен закрытый ключ, просто не используйте AndroidKeystore. Просто найдите в Stackoverflow, как сгенерировать ключ RSA на Java без Android. Способ Java также будет работать на Android.

Robert 05.03.2024 20:21
1
14
68
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

дело в том, что я получаю закрытый ключ из keyPairGenerator.generateKeyPair(), значит ли это, что после генерации keyPair он сохраняет их в KeyPair и при появлении запроса на получение пересылает ключ хранилища ключей. например: keyPairGenerator.generateKeyPair().getPrivate();

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

Если вы хотите создать ключи в программном обеспечении, вы можете просто попробовать полностью удалить неправильно названный аргумент KEYSTORE; по умолчанию поставщик Android не будет использоваться. И да, это немного странный API, возможно, вы не сможете просто установить его на null и остаться совместимым; вам также, возможно, придется удалить NoSuchProviderException из любого пункта catch, если вы это сделаете.

Другие вопросы по теме