SSL-соединение с частными ключами в HSM - PullRequest
1 голос
/ 07 января 2020

Я хотел бы реализовать соединение ssl, пара ключей RSA которого хранится в модуле аппаратной безопасности (HSM) в Java.

Используя механизм openssl pkcs11, я установил соединение TLS с следующая конфигурация движка.

[openssl_def]
engines = engine_section

[engine_section]
pkcs11 = pkcs11_section

[pkcs11_section]
engine_id = pkcs11
MODULE_PATH = /home/ubuntu/Desktop/vendorlib.so
PIN = "123456"
init = 0

[req]
distinguished_name = test_name
[req_distinguished_name]

и затем я создаю сертификат, используя этот движок, с помощью следующей команды, где ssl_key хранится в устройстве HSM.

OPENSSL_CONF=engine.conf openssl req -new -x509 -days 365 -subj '/CN=test/' -sha256 -config engine.conf -engine pkcs11 -keyform engine -key slot_2-label_ssl_key -out cert.pem

Я могу подтвердить сертификат и ключ Выполните сопряжение со следующими командами сервера openssl и клиента.

Для сервера:

OPENSSL_CONF=engine.conf openssl s_server -engine pkcs11 -keyform engine -key slot_2-label_ssl_key -cert cert.pem -accept 44330

Для клиента:

OPENSSL_CONF=engine.conf openssl s_client -connect localhost:44330 -engine pkcs11

Однако мне нужно, чтобы это соединение было установлено в Vertx (3.81) Java 8 соединение.

Когда я просматриваю документацию vertx, есть OpenSSLEngineOptions, которые могут быть установлены как serverOptions, но я не мог понять, куда поместить параметры, такие как имя ключа, номер слота и идентификатор движка и т. Д. c , Фактически, OpenSSLEngineOptions имеет конструктор, который принимает JsonObject, но я не смог найти никакого примера для этого JsonObject.

Вот фрагмент кода, в котором я создаю экземпляр Vertx ssl option

HttpServerOptions serverOptions = jerseyServerOptions.getServerOptions();
OpenSSLEngineOptions openSSLOptions = new OpenSSLEngineOptions();
serverOptions.setOpenSslEngineOptions(openSSLOptions);
serverOptions.setPort(1234);
serverOptions.setSsl(true);

String certCopy = "-----BEGIN CERTIFICATE-----
MIICMzCCAZygAwIBAgIJALiPnVsvq8dsMA0GCSqGSIb3DQEBBQUAMFMxCzAJBgNV
BAYTAlVTMQwwCgYDVQQIEwNmb28xDDAKBgNVBAcTA2ZvbzEMMAoGA1UEChMDZm9v
MQwwCgYDVQQLEwNmb28xDDAKBgNVBAMTA2ZvbzAeFw0xMzAzMTkxNTQwMTlaFw0x
ODAzMTgxNTQwMTlaMFMxCzAJBgNVBAYTAlVTMQwwCgYDVQQIEwNmb28xDDAKBgNV
BAcTA2ZvbzEMMAoGA1UEChMDZm9vMQwwCgYDVQQLEwNmb28xDDAKBgNVBAMTA2Zv
bzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAzdGfxi9CNbMf1UUcvDQh7MYB
OveIHyc0E0KIbhjK5FkCBU4CiZrbfHagaW7ZEcN0tt3EvpbOMxxc/ZQU2WN/s/wP
xph0pSfsfFsTKM4RhTWD2v4fgk+xZiKd1p0+L4hTtpwnEw0uXRVd0ki6muwV5y/P
+5FHUeldq+pgTcgzuK8CAwEAAaMPMA0wCwYDVR0PBAQDAgLkMA0GCSqGSIb3DQEB
BQUAA4GBAJiDAAtY0mQQeuxWdzLRzXmjvdSuL9GoyT3BF/jSnpxz5/58dba8pWen
v3pj4P3w5DoOso0rzkZy2jEsEitlVM2mLSbQpMM+MUVQCQoiG6W9xuCFuxSrwPIS
pAqEAuV4DNoxQKKWmhVv+J0ptMWD25Pnpxeq5sXzghfJnslJlQND
-----END CERTIFICATE-----";
PemKeyCertOptions pemKeyCertOptions = new PemKeyCertOptions().setCertValue(Buffer.buffer(certValue));
serverOptions.setPemKeyCertOptions(pemKeyCertOptions);

TLDR; Как мы можем установить sh SSL-соединение в Vertx, где закрытый ключ хранится только в HSM и не может быть извлечен?

Редактировать: I нашел синтаксический анализатор jsonObject в конструкторе OpenSSLEngineOptions здесь . К сожалению, он читает только параметр sessionCacheEnabled.

1 Ответ

1 голос
/ 13 января 2020

Я предложил решение с использованием провайдера безопасности и Java Keystore. Вот пример кода:

/*
pkcs11.cfg example:
name=PKCS11
library=vendor provided library absolute path
slot=0
*/
String propertyPath = "/root/IdeaProjects/ssl/pkcs11.cfg;
char[] pin = "1234".toCharArray();
Provider p = new SunPKCS11(propertyPath);
Security.removeProvider("IAIK");
Security.addProvider(p);
KeyStore ks = KeyStore.getInstance("PKCS11",p);
ks.load(null,pin);

После инициализации KeyStore вы можете направить свой SSLContext в KeyStore. Но согласно документации Java 8 PKCS11 атрибут CKA_ID сертификата и личного ключа должен совпадать. Если механизм pkcs11 соответствует паре сертификата и ключа, он должен отображаться как псевдоним.

//Showing aliases
Enumeration<String> aliases = ks.aliases();
for (; aliases.hasMoreElements(); ){
   System.out.println(aliases.nextElement());
}

После проверки псевдонимов мы будем использовать SSLContext для привязки нашего KeyManager.

SSLContext ctx = SSLContext.getInstane("TLS");
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
keyManagerFactory.init(ks,pin);
ctx.init(keyManagerFactory.getKeyManagers(), null, null);
...