класс OpenSSL::PKey::DH
Реализация протокола обмена ключами Диффи — Хеллмана, основанного на дискретных логарифмах в конечных полях; на той же основе построен DSA.
Методы доступа к параметрам Диффи — Хеллмана
DH#p-
Простое число (объект
OpenSSL::BN) в параметрах Диффи — Хеллмана. - DH#g
-
Генератор g (объект
OpenSSL::BN) в параметрах Диффи — Хеллмана. - DH#pub_key
-
Открытый ключ сеанса (объект
OpenSSL::BN), соответствующий закрытому ключу. Его необходимо передать вDH#compute_key. - DH#priv_key
-
Закрытый ключ сеанса, объект
OpenSSL::BN.
Пример обмена ключами
# you may send the parameters (der) and own public key (pub1) publicly # to the participating party dh1 = OpenSSL::PKey::DH.new(2048) der = dh1.to_der pub1 = dh1.pub_key # the other party generates its per-session key pair dhparams = OpenSSL::PKey::DH.new(der) dh2 = OpenSSL::PKey.generate_key(dhparams) pub2 = dh2.pub_key symm_key1 = dh1.compute_key(pub2) symm_key2 = dh2.compute_key(pub1) puts symm_key1 == symm_key2 # => true
Открытые методы класса
# File ext/openssl/lib/openssl/pkey.rb, line 133
def generate(size, generator = 2, &blk)
dhparams = OpenSSL::PKey.generate_parameters("DH", {
"dh_paramgen_prime_len" => size,
"dh_paramgen_generator" => generator,
}, &blk)
OpenSSL::PKey.generate_key(dhparams)
end Создаёт новый экземпляр DH с нуля, генерируя случайные параметры и пару ключей.
См. также OpenSSL::PKey.generate_parameters и OpenSSL::PKey.generate_key.
size-
Требуемый размер ключа в битах.
generator-
Генератор.
static VALUE
ossl_dh_initialize(int argc, VALUE *argv, VALUE self)
{
EVP_PKEY *pkey;
int type;
DH *dh;
BIO *in = NULL;
VALUE arg;
TypedData_Get_Struct(self, EVP_PKEY, &ossl_evp_pkey_type, pkey);
if (pkey)
rb_raise(rb_eTypeError, "pkey already initialized");
/* The DH.new(size, generator) form is handled by lib/openssl/pkey.rb */
if (rb_scan_args(argc, argv, "01", &arg) == 0) {
#ifdef OSSL_HAVE_IMMUTABLE_PKEY
rb_raise(rb_eArgError, "OpenSSL::PKey::DH.new cannot be called " \
"without arguments; pkeys are immutable with OpenSSL 3.0");
#else
dh = DH_new();
if (!dh)
ossl_raise(ePKeyError, "DH_new");
goto legacy;
#endif
}
arg = ossl_to_der_if_possible(arg);
in = ossl_obj2bio(&arg);
/*
* On OpenSSL <= 1.1.1 and current versions of LibreSSL, the generic
* routine does not support DER-encoded parameters
*/
dh = d2i_DHparams_bio(in, NULL);
if (dh)
goto legacy;
OSSL_BIO_reset(in);
pkey = ossl_pkey_read_generic(in, Qnil);
BIO_free(in);
if (!pkey)
ossl_raise(ePKeyError, "could not parse pkey");
type = EVP_PKEY_base_id(pkey);
if (type != EVP_PKEY_DH) {
EVP_PKEY_free(pkey);
rb_raise(ePKeyError, "incorrect pkey type: %s", OBJ_nid2sn(type));
}
RTYPEDDATA_DATA(self) = pkey;
return self;
legacy:
BIO_free(in);
pkey = EVP_PKEY_new();
if (!pkey || EVP_PKEY_assign_DH(pkey, dh) != 1) {
EVP_PKEY_free(pkey);
DH_free(dh);
ossl_raise(ePKeyError, "EVP_PKEY_assign_DH");
}
RTYPEDDATA_DATA(self) = pkey;
return self;
} Создаёт новый экземпляр OpenSSL::PKey::DH.
При вызове без аргументов создаётся пустой экземпляр без параметров и компонентов ключа. Используйте set_pqg, чтобы задать параметры вручную (и, при необходимости, set_key, чтобы задать компоненты закрытого и открытого ключей). Эта форма несовместима с OpenSSL версии 3.0 и более поздних.
Если задан объект String, метод пытается разобрать его как параметры в формате DER или PEM. См. также OpenSSL::PKey.read, который может считывать ключи любых типов.
Форма DH.new(size [, generator]) является псевдонимом DH.generate.
string-
Объект
String, содержащий ключ в формате DER или PEM. size-
См.
DH.generate. generator-
См.
DH.generate.
Примеры:
# Creating an instance from scratch
# Note that this is deprecated and will result in ArgumentError when
# using OpenSSL 3.0 or later.
dh = OpenSSL::PKey::DH.new
dh.set_pqg(bn_p, nil, bn_g)
# Generating a parameters and a key pair
dh = OpenSSL::PKey::DH.new(2048) # An alias of OpenSSL::PKey::DH.generate(2048)
# Reading DH parameters from a PEM-encoded string
dh_params = OpenSSL::PKey::DH.new(File.read('parameters.pem')) # loads parameters only
dh = OpenSSL::PKey.generate_key(dh_params) # generates a key pair
Открытые методы экземпляра
# File ext/openssl/lib/openssl/pkey.rb, line 64
def compute_key(pub_bn)
# FIXME: This is constructing an X.509 SubjectPublicKeyInfo and is very
# inefficient
obj = OpenSSL::ASN1.Sequence([
OpenSSL::ASN1.Sequence([
OpenSSL::ASN1.ObjectId("dhKeyAgreement"),
OpenSSL::ASN1.Sequence([
OpenSSL::ASN1.Integer(p),
OpenSSL::ASN1.Integer(g),
]),
]),
OpenSSL::ASN1.BitString(OpenSSL::ASN1.Integer(pub_bn).to_der),
])
derive(OpenSSL::PKey.read(obj.to_der))
end Возвращает объект String, содержащий общий секрет, вычисленный на основе открытого значения другой стороны.
Этот метод предоставлен для обратной совместимости и внутри вызывает derive.
Параметры
-
pub_bn — это объект
OpenSSL::BN, а не экземплярDH, возвращаемый методомDH#public_key, поскольку он содержит только параметрыDH.
static VALUE
ossl_dh_export(VALUE self)
{
OSSL_3_const DH *dh;
BIO *out;
VALUE str;
GetDH(self, dh);
if (!(out = BIO_new(BIO_s_mem()))) {
ossl_raise(ePKeyError, NULL);
}
if (!PEM_write_bio_DHparams(out, dh)) {
BIO_free(out);
ossl_raise(ePKeyError, NULL);
}
str = ossl_membio2str(out);
return str;
} Сериализует параметры DH в кодировку PEM.
Обратите внимание: существующие открытые и закрытые ключи сеанса не будут закодированы — кодируются только параметры Диффи — Хеллмана.
Параметры в кодировке PEM будут выглядеть так:
-----BEGIN DH PARAMETERS----- [...] -----END DH PARAMETERS-----
См. также public_to_pem (X.509 SubjectPublicKeyInfo) и private_to_pem (PKCS #8 PrivateKeyInfo или EncryptedPrivateKeyInfo), если требуется сериализовать компоненты закрытого или открытого ключа.
# File ext/openssl/lib/openssl/pkey.rb, line 106
def generate_key!
if OpenSSL::OPENSSL_VERSION_NUMBER >= 0x30000000
raise PKeyError, "OpenSSL::PKey::DH is immutable on OpenSSL 3.0; " \
"use OpenSSL::PKey.generate_key instead"
end
unless priv_key
tmp = OpenSSL::PKey.generate_key(self)
set_key(tmp.pub_key, tmp.priv_key)
end
self
end Генерирует закрытый и открытый ключи, если закрытый ключ ещё не существует. Если этот экземпляр DH создан на основе открытых параметров DH (например, путём кодирования результата DH#public_key), перед фактическим обменом ключами сначала необходимо вызвать этот метод, чтобы сгенерировать ключи сеанса.
Устарел в версии 3.0. Этот метод несовместим с OpenSSL версии 3.0.0 и более поздних.
См. также OpenSSL::PKey.generate_key.
Пример:
# DEPRECATED USAGE: This will not work on OpenSSL 3.0 or later dh0 = OpenSSL::PKey::DH.new(2048) dh = dh0.public_key # #public_key only copies the DH parameters (contrary to the name) dh.generate_key! puts dh.private? # => true puts dh0.pub_key == dh.pub_key #=> false # With OpenSSL::PKey.generate_key dh0 = OpenSSL::PKey::DH.new(2048) dh = OpenSSL::PKey.generate_key(dh0) puts dh0.pub_key == dh.pub_key #=> false
# File ext/openssl/lib/openssl/pkey.rb, line 46
def params
%w{p q g pub_key priv_key}.map { |name|
[name, send(name)]
}.to_h
end Сохраняет все параметры ключа в объект Hash.
Ключи хеша: ‘p’, ‘q’, ‘g’, ‘pub_key’ и ‘priv_key’.
static VALUE
ossl_dh_check_params(VALUE self)
{
int ret;
#ifdef HAVE_EVP_PKEY_CHECK
EVP_PKEY *pkey;
EVP_PKEY_CTX *pctx;
GetPKey(self, pkey);
pctx = EVP_PKEY_CTX_new(pkey, /* engine */NULL);
if (!pctx)
ossl_raise(ePKeyError, "EVP_PKEY_CTX_new");
ret = EVP_PKEY_param_check(pctx);
EVP_PKEY_CTX_free(pctx);
#else
DH *dh;
int codes;
GetDH(self, dh);
ret = DH_check(dh, &codes) == 1 && codes == 0;
#endif
if (ret == 1)
return Qtrue;
else {
/* DH_check_ex() will put error entry on failure */
ossl_clear_error();
return Qfalse;
}
} Проверяет параметры Диффи — Хеллмана, связанные с этим экземпляром. Метод проверяет, используются ли безопасное простое число и подходящий генератор. Если это не так, возвращается false.
См. также справочную страницу EVP_PKEY_param_check(3).
static VALUE
ossl_dh_is_private(VALUE self)
{
OSSL_3_const DH *dh;
const BIGNUM *bn;
GetDH(self, dh);
DH_get0_key(dh, NULL, &bn);
#if !defined(OPENSSL_NO_ENGINE)
return (bn || DH_get0_engine((DH *)dh)) ? Qtrue : Qfalse;
#else
return bn ? Qtrue : Qfalse;
#endif
} Показывает, связан ли с этим экземпляром DH закрытый ключ. Закрытый ключ можно получить с помощью DH#priv_key.
static VALUE
ossl_dh_is_public(VALUE self)
{
OSSL_3_const DH *dh;
const BIGNUM *bn;
GetDH(self, dh);
DH_get0_key(dh, &bn, NULL);
return bn ? Qtrue : Qfalse;
} Показывает, связан ли с этим экземпляром DH открытый ключ. Открытый ключ можно получить с помощью DH#pub_key.
# File ext/openssl/lib/openssl/pkey.rb, line 36 def public_key DH.new(to_der) end
Возвращает новый экземпляр DH, содержащий только параметры DH.
Несмотря на название метода, возвращаемый объект DH содержит только параметры, а не открытый ключ.
Этот метод предоставлен для обратной совместимости. В большинстве случаев вызывать его не требуется.
Чтобы повторно сгенерировать пару ключей, сохранив параметры, см. OpenSSL::PKey.generate_key.
Пример:
# OpenSSL::PKey::DH.generate by default generates a random key pair dh1 = OpenSSL::PKey::DH.generate(2048) p dh1.priv_key #=> #<OpenSSL::BN 1288347...> dhcopy = dh1.public_key p dhcopy.priv_key #=> nil
Задаёт pub_key и priv_key для экземпляра DH. Значение priv_key может быть nil.
Задаёт p, q и g для экземпляра DH.
static VALUE
ossl_dh_to_der(VALUE self)
{
OSSL_3_const DH *dh;
unsigned char *p;
long len;
VALUE str;
GetDH(self, dh);
if((len = i2d_DHparams(dh, NULL)) <= 0)
ossl_raise(ePKeyError, NULL);
str = rb_str_new(0, len);
p = (unsigned char *)RSTRING_PTR(str);
if(i2d_DHparams(dh, &p) < 0)
ossl_raise(ePKeyError, NULL);
ossl_str_adjust(str, p);
return str;
} Сериализует параметры DH в кодировку DER.
Обратите внимание: существующие открытые и закрытые ключи сеанса не будут закодированы — кодируются только параметры Диффи — Хеллмана.
См. также public_to_der (X.509 SubjectPublicKeyInfo) и private_to_der (PKCS #8 PrivateKeyInfo или EncryptedPrivateKeyInfo), если требуется сериализовать компоненты закрытого или открытого ключа.
Сериализует параметры DH в кодировку PEM.
Обратите внимание: существующие открытые и закрытые ключи сеанса не будут закодированы — кодируются только параметры Диффи — Хеллмана.
Параметры в кодировке PEM будут выглядеть так:
-----BEGIN DH PARAMETERS----- [...] -----END DH PARAMETERS-----
См. также public_to_pem (X.509 SubjectPublicKeyInfo) и private_to_pem (PKCS #8 PrivateKeyInfo или EncryptedPrivateKeyInfo), если требуется сериализовать компоненты закрытого или открытого ключа.
Сериализует параметры DH в кодировку PEM.
Обратите внимание: существующие открытые и закрытые ключи сеанса не будут закодированы — кодируются только параметры Диффи — Хеллмана.
Параметры в кодировке PEM будут выглядеть так:
-----BEGIN DH PARAMETERS----- [...] -----END DH PARAMETERS-----
См. также public_to_pem (X.509 SubjectPublicKeyInfo) и private_to_pem (PKCS #8 PrivateKeyInfo или EncryptedPrivateKeyInfo), если требуется сериализовать компоненты закрытого или открытого ключа.
Ruby Core © 1993–2025 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.