Получение объекта PrivateKey из файла .p12 в Java

Как следует из названия, у меня есть файл .p12, необходимый для доступа к api учетной записи службы Google. Чтобы получить учетные данные для подключения к api, есть поле .setServiceAccountPrivateKey (PrivateKey privateKey). Итак, как я могу это сделать проще всего? У меня есть папка ресурсов, которая находится в моем пути к классам, поэтому, если я добавлю туда файл p12, я могу получить ресурс из getClass (). GetResource () как inputStream или URL-адрес. Я пробовал использовать метод URL, но он не работает (я получаю сообщение об ошибке «URI не иерархический» при попытке создать объект File из URL.toURI ()).


person gratsby    schedule 04.09.2013    source источник


Ответы (4)


Вы можете загрузить файл .p12 с помощью метода ClassLoader.getResourceAsStream(String), загрузить его в хранилище ключей, и они получат ключ из хранилища ключей.

KeyStore keystore = KeyStore.getInstance("PKCS12");
keystore.load(this.getClass().getClassLoader().getResourceAsStream("keyFile.p12"), p12Password.toCharArray());
PrivateKey key = (PrivateKey)keystore.getKey(keyAlias, p12Password.toCharArray());

ClassLoader.getResourceAsStream(String) загружает ресурсы из любого места, при условии, что они уже находятся в пути к классам, нет необходимости указывать путь к файлу.

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

Если вы не уверены, какой псевдоним для вашего закрытого ключа, вы можете использовать утилиту keytool из командной строки, чтобы просмотреть содержимое вашего файла p12. Этот инструмент включен во все установки JRE и JDK.

keytool -list -keystore keyFile.p12 -storepass password -storetype PKCS12

Выход

Keystore type: PKCS12
Keystore provider: SunJSSE

Your keystore contains 1 entry

yourKeyAlias, Sep 4, 2013, PrivateKeyEntry,
Certificate fingerprint (MD5): 48:A8:C4:12:8E:4A:8A:AD:58:81:26:90:E7:3D:C8:04
person Syon    schedule 04.09.2013
comment
Не знаком с этим методом шифрования ... что такое keyAlias? - person gratsby; 04.09.2013
comment
Добавлена ​​информация о том, как вывести список содержимого вашего хранилища ключей, чтобы найти псевдоним. - person Syon; 04.09.2013
comment
@Syon Можно ли создать хранилище ключей из его содержимого, а не из файла java.io.File? - person DarRay; 29.04.2014
comment
Я не совсем понимаю, что вы имеете в виду под этим содержанием. Класс KeyStore может загружать ключ различными способами. Вы можете сделать keystore.load(new ByteArrayInputStream(someByteArray)) или использовать один из SetKeyEntry методов. - person Syon; 29.04.2014
comment
Откуда берется p12Password.toCharArray ()? - person Tom; 14.07.2015
comment
@TomWilkins p12Password - это пароль, предоставленный Google. сохранить пароль в строке и преобразовать его в массив символов. Подсказка, что Google использует тот же пароль открытого ключа. - person Sagar Rout; 14.12.2015

Я думаю, что проще напрямую вызвать Google SecurityUtils, например:

PrivateKey privateKey = SecurityUtils.loadPrivateKeyFromKeyStore(SecurityUtils.getPkcs12KeyStore(), this.getClass().getResourceAsStream("keyFile.p12"), "notasecret", "privatekey", "notasecret")

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

person Robert Watts    schedule 24.07.2014
comment
Спасибо, что ввел пароль прямо там, я волновался, что забыл его. - person dhakim; 12.08.2014
comment
@Robert Watts. Итак, в этом вызове вы используете privatekey в качестве псевдонима. Это потому, что privateKey является псевдонимом по умолчанию для ключей pkcs12? Я искал, но не нашел никакой документации по этому поводу. Я запустил keytool, и мой псевдоним на самом деле privatekey, но я хотел бы быть уверен, что он всегда будет для новых ключей. - person Usman Mutawakil; 11.09.2016
comment
@UsmanMutawakil Я не верю, что существует стандартный псевдоним по умолчанию для формата файла pkcs12. Keytool может по умолчанию использовать этот псевдоним, и, возможно, другие инструменты / программы тоже, но это не является неотъемлемой частью формата файла. - person Vivek Chavda; 31.10.2016
comment
@Robert Watts На самом деле четвертый параметр - это псевдоним. - person Антон Антонов; 07.03.2017
comment
Мне действительно смешно, что класс SecurityUtils принимает пароль в виде строки. - person Syon; 28.09.2017

Если вы получаете null от getKey() (например, вы используете BouncyCastle в качестве провайдера), вы должны найти последний элемент keyAlias:

KeyStore keystore = KeyStore.getInstance("PKCS12", "BC");
keystore.load(this.getClass().getClassLoader().getResourceAsStream("keyFile.p12"), p12Password.toCharArray());
Enumeration aliases = keystore.aliases();
String keyAlias = "";
while (aliases.hasMoreElements()) {
    keyAlias = (String) aliases.nextElement();
}
PrivateKey key = (PrivateKey)keystore.getKey(keyAlias, pass);
person Stocki    schedule 06.06.2014
comment
Это то, что мне в итоге помогло. У моего хранилища ключей был странный псевдоним: getkey всегда возвращал null. Итерация с использованием вышеуказанного метода решила проблему. - person Nikhil Kumar; 12.02.2020
comment
Это мне очень помогло. Спасибо. keytool показывает, что у меня есть псевдоним с именем 1 (по умолчанию при создании с openssl. Не уверен, что это int или string). Однако keystore.aliases() возвращает длинную странную строку для этого псевдонима. - person Phạm Tuấn Anh; 15.12.2020

Вышеупомянутые предложения не сработали для меня. Затем я попробовал один на http://www.java2s.com/Code/Java/Security/RetrievingaKeyPairfromaKeyStore.htm, и это сработало. Скопируйте, вставив его ниже

import java.io.FileInputStream;
import java.security.Key;
import java.security.KeyPair;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.cert.Certificate;

public class Main {
  public static void main(String[] argv) throws Exception {
    FileInputStream is = new FileInputStream("your.keystore");

    KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
    keystore.load(is, "my-keystore-password".toCharArray());

    String alias = "myalias";

    Key key = keystore.getKey(alias, "password".toCharArray());
    if (key instanceof PrivateKey) {
      // Get certificate of public key
      Certificate cert = keystore.getCertificate(alias);

      // Get public key
      PublicKey publicKey = cert.getPublicKey();

      // Return a key pair
      new KeyPair(publicKey, (PrivateKey) key);
    }
  }
}
person sdm    schedule 31.01.2017