модуль OpenSSL::PKey
Ассиметричные алгоритмы с открытым ключом
Ассиметричные алгоритмы с открытым ключом решают проблему установления и обмена секретными ключами для шифрования/расшифрования сообщений. Ключ в таком алгоритме состоит из двух частей: открытый ключ, который можно распространять другим, и закрытый ключ, который должен оставаться в секрете.
Сообщения, зашифрованные открытым ключом, могут быть расшифрованы только получателями, обладающими соответствующим закрытым ключом. Поскольку ассиметричные алгоритмы значительно медленнее, чем симметричные алгоритмы (см. OpenSSL::Cipher), их часто используют для установления симметричного ключа между двумя сторонами, которые обладают открытыми ключами друг друга.
Ассиметричные алгоритмы предлагают множество полезных функций, которые используются в различных областях. Очень распространённое применение — создание и проверка цифровых подписей. Для подписания документа подписывающий обычно использует алгоритм хеширования (см. OpenSSL::Digest), чтобы вычислить хеш документа, который затем шифруется (т.е. подписывается) с помощью закрытого ключа. Любой, у кого есть открытый ключ, может затем проверить подпись, вычислив хеш исходного документа самостоятельно, расшифровав подпись с помощью открытого ключа подписывающего и сравнив результат с вычисленным хешем. Подпись является действительной только в том случае, если расшифрованная подпись равна этому хешу.
Модуль PKey поддерживает три популярных алгоритма с открытым/закрытым ключом:
-
Криптография эллиптических кривых (
OpenSSL::PKey::EC)
Каждая из этих реализаций фактически является подклассом абстрактного класса PKey, который предоставляет интерфейс для поддержки цифровых подписей в виде методов PKey#sign и PKey#verify.
Обмен ключами Diffie-Hellman
Наконец, PKey также содержит OpenSSL::PKey::DH, реализацию протокола обмена ключами Diffie-Hellman, основанную на дискретных логарифмах в конечных полях, на том же основании, что и DSA. Протокол Diffie-Hellman можно использовать для обмена (симметричными) ключами по незащищённым каналам без предварительного совместного знания между участвующими сторонами. Поскольку безопасность DH требует относительно длинных «открытых ключей» (т.е. части, которая явно передаётся между участниками), DH обычно довольно медленная. Если безопасность или скорость являются для вас первоочередными, OpenSSL::PKey::EC предлагает другую реализацию протокола Diffie-Hellman.
Методы публичного класса
Исходный код
static VALUE
ossl_pkey_s_generate_key(int argc, VALUE *argv, VALUE self)
{
return pkey_generate(argc, argv, self, 0);
} Генерирует новый ключ (пару).
Если в качестве первого аргумента передано строковое значение, генерируется новый случайный ключ для алгоритма, указанного по имени, также как и в ::generate_parameters. Если вместо этого передан объект OpenSSL::PKey::PKey, генерируется новый случайный ключ для того же алгоритма, что и у ключа, с использованием параметров, содержащихся в ключе.
Подробности о параметрах options и передаваемом блоке см. в ::generate_parameters.
Пример
pkey_params = OpenSSL::PKey.generate_parameters("DSA", "dsa_paramgen_bits" => 2048)
pkey_params.priv_key #=> nil
pkey = OpenSSL::PKey.generate_key(pkey_params)
pkey.priv_key #=> #<OpenSSL::BN 6277...
Исходный код
static VALUE
ossl_pkey_s_generate_parameters(int argc, VALUE *argv, VALUE self)
{
return pkey_generate(argc, argv, self, 1);
} Генерирует новые параметры для алгоритма. algo_name — строка, представляющая алгоритм. Необязательный аргумент options — хеш, содержащий параметры, специфичные для алгоритма. Порядок параметров может иметь значение.
Необязательно можно передать блок. Значение аргументов, передаваемых блоку, зависит от реализации алгоритма. Блок может быть вызван один раз или несколько раз, или вообще не вызываться.
Подробные сведения о поддерживаемых параметрах см. в документации для утилиты «openssl genpkey».
Пример
pkey = OpenSSL::PKey.generate_parameters("DSA", "dsa_paramgen_bits" => 2048)
p pkey.p.num_bits #=> 2048
Исходный код
static VALUE
ossl_pkey_new_raw_private_key(VALUE self, VALUE type, VALUE key)
{
EVP_PKEY *pkey;
const EVP_PKEY_ASN1_METHOD *ameth;
int pkey_id;
size_t keylen;
StringValue(type);
StringValue(key);
ameth = EVP_PKEY_asn1_find_str(NULL, RSTRING_PTR(type), RSTRING_LENINT(type));
if (!ameth)
ossl_raise(ePKeyError, "algorithm %"PRIsVALUE" not found", type);
EVP_PKEY_asn1_get0_info(&pkey_id, NULL, NULL, NULL, NULL, ameth);
keylen = RSTRING_LEN(key);
pkey = EVP_PKEY_new_raw_private_key(pkey_id, NULL, (unsigned char *)RSTRING_PTR(key), keylen);
if (!pkey)
ossl_raise(ePKeyError, "EVP_PKEY_new_raw_private_key");
return ossl_pkey_new(pkey);
} См. документацию OpenSSL для EVP_PKEY_new_raw_private_key()
Исходный код
static VALUE
ossl_pkey_new_raw_public_key(VALUE self, VALUE type, VALUE key)
{
EVP_PKEY *pkey;
const EVP_PKEY_ASN1_METHOD *ameth;
int pkey_id;
size_t keylen;
StringValue(type);
StringValue(key);
ameth = EVP_PKEY_asn1_find_str(NULL, RSTRING_PTR(type), RSTRING_LENINT(type));
if (!ameth)
ossl_raise(ePKeyError, "algorithm %"PRIsVALUE" not found", type);
EVP_PKEY_asn1_get0_info(&pkey_id, NULL, NULL, NULL, NULL, ameth);
keylen = RSTRING_LEN(key);
pkey = EVP_PKEY_new_raw_public_key(pkey_id, NULL, (unsigned char *)RSTRING_PTR(key), keylen);
if (!pkey)
ossl_raise(ePKeyError, "EVP_PKEY_new_raw_public_key");
return ossl_pkey_new(pkey);
} См. документацию OpenSSL для EVP_PKEY_new_raw_public_key()
Исходный код
static VALUE
ossl_pkey_new_from_data(int argc, VALUE *argv, VALUE self)
{
EVP_PKEY *pkey;
BIO *bio;
VALUE data, pass;
rb_scan_args(argc, argv, "11", &data, &pass);
bio = ossl_obj2bio(&data);
pkey = ossl_pkey_read_generic(bio, ossl_pem_passwd_value(pass));
BIO_free(bio);
if (!pkey)
ossl_raise(ePKeyError, "Could not parse PKey");
return ossl_pkey_new(pkey);
} Считывает закодированную в DER или PEM строку из string или io и возвращает экземпляр соответствующего класса PKey.
Параметры
-
string — строка DER или PEM, содержащая произвольный закрытый или открытый ключ.
-
io — экземпляр
IO, содержащий закодированный в DER или PEM произвольный закрытый или открытый ключ. -
pwd — необязательный пароль в случае, если string или io — зашифрованный PEM-ресурс.
Ruby Core © 1993–2024 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.