Вопрос или проблема
Я хотел бы изменить программу, написанную на Java. Программа должна уметь создавать открытые и закрытые ключи на HSM и также уметь их удалять. Я хотел бы выполнять эти задачи, используя Sun PKCS#11 Provider. Мне удалось создать и сохранить ключи и соответствующие сертификаты, а также удалить закрытый ключ и сертификаты. Однако я не понимаю, как удалить открытый ключ.
Java код, создающий и сохраняющий ключи и сертификаты, похож на этот:
KeyStore keyStore = KeyStore.getInstance("PKCS11", "SunPKCS11-libtpm2");
keyStore.load(null, "userpin".toCharArray());
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA", "SunPKCS11-libtpm2");
keyPairGenerator.initialize(2048);
KeyPair keyPair = keyPairGenerator.generateKeyPair();
keyStore.setKeyEntry("WorkstationAuthentication", keyPair.getPrivate(), null, getCertificates());
После выполнения этого Java кода утилита pkcs11-tool показывает, что пара ключей и сертификаты хранятся:
# pkcs11-tool --module /usr/lib/x86_64-linux-gnu/pkcs11/libtpm2_pkcs11.so --slot-index=0 --list-objects --login
Используя слот с индексом 0 (0x1)
Вход в "myfirsttoken".
Пожалуйста, введите PIN-код пользователя:
Объект открытого ключа; RSA 2048 бит
метка:
Использование: шифрование, проверка
Доступ: локальный
Объект закрытого ключа; RSA
метка:
ID: 534b5332303038576f726b73746174696f6e41757468656e7469636174696f6e
Использование: расшифровка, подпись
Доступ: всегда чувствительный, никогда не извлекаемый, локальный
Допустимые механизмы: RSA-X-509,RSA-PKCS-OAEP,RSA-PKCS,SHA1-RSA-PKCS,SHA256-RSA-PKCS,SHA384-RSA-PKCS,SHA512-RSA-PKCS,RSA-PKCS-PSS,SHA1-RSA-PKCS-PSS,SHA256-RSA-PKCS-PSS,SHA384-RSA-PKCS-PSS,SHA512-RSA-PKCS-PSS
Объект сертификата; тип = X.509 сертификат
метка: WorkstationAuthentication
субъект: DN:
ID: 534b5332303038576f726b73746174696f6e41757468656e7469636174696f6e
Объект сертификата; тип = X.509 сертификат
метка:
субъект: DN: DC=com, DC=example, CN=example-CA
ID: 636e3d736173636572742d63612c64633d233136303737333631373336333635373237342c64633d2331363032366636392f636e3d736173636572742d63612c64633d233136303737333631373336333635373237342c64633d2331363032366636392f3332333331303437363031363137343435323138303332383239393236343439353035313332
Я смог удалить закрытый ключ и сертификаты в Java следующим образом:
if (keyStore.containsAlias("WorkstationAuthentication")) {
keyStore.deleteEntry("WorkstationAuthentication");
}
pkcs11-tool показывает, что закрытый ключ и сертификаты удалены, но открытый ключ остался на токене:
# pkcs11-tool --module /usr/lib/x86_64-linux-gnu/pkcs11/libtpm2_pkcs11.so --slot-index=0 --list-objects --login
Используя слот с индексом 0 (0x1)
Вход в "myfirsttoken".
Пожалуйста, введите PIN-код пользователя:
Объект открытого ключа; RSA 2048 бит
метка:
Использование: шифрование, проверка
Доступ: локальный
Я не смог найти ни одного метода в Java, цель которого — удалить этот открытый ключ. Что более интересно, как мы можем видеть в выводе pkcs11-tool, ни метка, ни ID не имеют значения, так что даже если бы существовал метод, цель которого — удалить открытый ключ, мы не смогли бы идентифицировать открытый ключ.
Я смог удалить открытый ключ с помощью pkcs11-tool, но я хотел бы удалить его в Java.
Итак, как можно удалить открытый ключ из токена в Java? Или как можно предотвратить хранение открытого ключа на токене? Если я правильно понимаю, нет смысла хранить открытый ключ на токене, потому что сертификат содержит открытый ключ.
Ответ или решение
Для удаления общедоступного ключа из токена PKCS#11 в Java, вам необходимо понимать, что PKCS#11 не всегда позволяет напрямую удалить только общедоступный ключ, так как он обычно связается с закрытым ключом. В вашем случае, раз вы уже удалили закрытый ключ и соответствующие сертификаты, общедоступный ключ может оставаться на токене, если он не был предназначен для автоматического удаления вместе с закрытым ключом.
Тем не менее, вот шаги, которые вы можете предпринять для решения проблемы:
- Поиск публичного ключа: Для удаления общедоступного ключа необходимо сначала найти его. Вы можете использовать
KeyStore
и методы для перебора объектов. Для этого вы можете воспользоваться следующими шагами:
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.Security;
import sun.security.pkcs11.SunPKCS11;
public class DeletePublicKey {
public static void main(String[] args) throws Exception {
// Инициализация KeyStore
KeyStore keyStore = KeyStore.getInstance("PKCS11", "SunPKCS11-libtpm2");
keyStore.load(null, "userpin".toCharArray());
// Поиск и удаление
String publicKeyAlias = findPublicKeyAlias(keyStore);
if (publicKeyAlias != null) {
keyStore.deleteEntry(publicKeyAlias);
System.out.println("Публичный ключ с alias " + publicKeyAlias + " удален.");
} else {
System.out.println("Публичный ключ не найден.");
}
}
private static String findPublicKeyAlias(KeyStore keyStore) throws KeyStoreException {
// Просто перебор всех ключей для поиска неиспользуемого (публичного) ключа
for (String alias : keyStore.aliases()) {
if (keyStore.isCertificateEntry(alias)) {
continue; // Пропускаем сертификаты
}
// Проверяем, является ли это публичным ключом
// Важно понимать, что нужно использовать дополнительные проверки, чтобы определить тип ключа
// Это место, где может понадобиться ваша логика для определения, что это именно публичный ключ
// Например, проверка на наличие его в закрытых ключах
return alias; // Если нашли, возвращаем alias
}
return null; // Если ничего не найдено
}
}
-
Удаление публичного ключа: Если вы нашли alias публичного ключа, вы можете использовать
keyStore.deleteEntry(publicKeyAlias)
. -
Работа с механизмами PKCS#11: Некоторые механизмы PKCS#11 могут не позволить вам удалить публичные ключи, а хранить их независимо от закрытых ключей. Это зависит от конкретного HSM, который вы используете. Убедитесь, что вы проверили документацию к вашему HSM на предмет того, как управлять ключами.
-
Создание конфигурации HSM: Если публичные ключи не являются необходимыми на вашем HSM, вы можете настроить его так, чтобы он не сохранял их. Это требует изменений в конфигурациях вашего HSM и возможно, изменения логики применения ключей в вашем приложении.
-
Использование команд PKCS#11 напрямую: Если Java API не предоставляет необходимую функциональность, вы всегда можете использовать команды, определенные в вашем PKCS#11 модуле, через соответствующую библиотеку, которая взаимодействует с HSM. Это может включать вызовы низкоуровневых API или использование JNI.
Таким образом, если ваш HSM не позволяет удалять только общедоступные ключи, вам может потребоваться пересмотреть, как вы генерируете и храните ключи, чтобы определить, действительно ли необходимость сохранять публичные ключи на токене оправдана.
Не забывайте протестировать ваше решение в безопасной среде, прежде чем развертывать его в рабочей среде, чтобы избежать случайной потери данных.