класс OpenSSL::PKey::RSA
RSA — это асимметричный алгоритм с открытым ключом, формализованный в RFC 3447. Он широко используется в инфраструктурах открытых ключей (PKI), где сертификаты (см. OpenSSL::X509::Certificate) часто выдаются на основе пары открытого/закрытого RSA ключей. RSA используется в широком спектре приложений, таких как обмен защищёнными (симметричными) ключами, например, при установлении защищённого соединения TLS/SSL. Он также используется в различных схемах цифровых подписей.
Константы
- NO_PADDING
- PKCS1_OAEP_PADDING
- PKCS1_PADDING
- SSLV23_PADDING
Публичные методы класса
# File ext/openssl/lib/openssl/pkey.rb, line 343
def generate(size, exp = 0x10001, &blk)
OpenSSL::PKey.generate_key("RSA", {
"rsa_keygen_bits" => size,
"rsa_keygen_pubexp" => exp,
}, &blk)
end Генерирует пару ключей RSA.
См. также OpenSSL::PKey.generate_key.
-
size -
Требуемый размер ключа в битах.
-
exponent -
Нечётное целое число, обычно 3, 17 или 65537.
static VALUE
ossl_rsa_initialize(int argc, VALUE *argv, VALUE self)
{
EVP_PKEY *pkey;
RSA *rsa;
BIO *in = NULL;
VALUE arg, pass;
int type;
TypedData_Get_Struct(self, EVP_PKEY, &ossl_evp_pkey_type, pkey);
if (pkey)
rb_raise(rb_eTypeError, "pkey already initialized");
/* The RSA.new(size, generator) form is handled by lib/openssl/pkey.rb */
rb_scan_args(argc, argv, "02", &arg, &pass);
if (argc == 0) {
rsa = RSA_new();
if (!rsa)
ossl_raise(eRSAError, "RSA_new");
goto legacy;
}
pass = ossl_pem_passwd_value(pass);
arg = ossl_to_der_if_possible(arg);
in = ossl_obj2bio(&arg);
/* First try RSAPublicKey format */
rsa = d2i_RSAPublicKey_bio(in, NULL);
if (rsa)
goto legacy;
OSSL_BIO_reset(in);
rsa = PEM_read_bio_RSAPublicKey(in, NULL, NULL, NULL);
if (rsa)
goto legacy;
OSSL_BIO_reset(in);
/* Use the generic routine */
pkey = ossl_pkey_read_generic(in, pass);
BIO_free(in);
if (!pkey)
ossl_raise(eRSAError, "Neither PUB key nor PRIV key");
type = EVP_PKEY_base_id(pkey);
if (type != EVP_PKEY_RSA) {
EVP_PKEY_free(pkey);
rb_raise(eRSAError, "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_RSA(pkey, rsa) != 1) {
EVP_PKEY_free(pkey);
RSA_free(rsa);
ossl_raise(eRSAError, "EVP_PKEY_assign_RSA");
}
RTYPEDDATA_DATA(self) = pkey;
return self;
} Генерирует или загружает пару ключей RSA.
Если вызывается без аргументов, создаёт новый экземпляр без установленных компонентов ключа. Их можно установить индивидуально с помощью set_key, set_factors и set_crt_params.
Если вызывается со строкой, пытается разобрать её как кодировку DER или PEM ключа RSA. Обратите внимание, что если password не указан, но ключ зашифрован паролем, OpenSSL запросит его. См. также OpenSSL::PKey.read, который может разбирать ключи любого типа.
Если вызывается с числом, генерирует новую пару ключей. Этот вариант является алиасом RSA.generate.
Примеры:
OpenSSL::PKey::RSA.new 2048
OpenSSL::PKey::RSA.new File.read 'rsa.pem'
OpenSSL::PKey::RSA.new File.read('rsa.pem'), 'my password'
Методы публичного экземпляра
static VALUE
ossl_rsa_export(int argc, VALUE *argv, VALUE self)
{
if (can_export_rsaprivatekey(self))
return ossl_pkey_export_traditional(argc, argv, self, 0);
else
return ossl_pkey_export_spki(self, 0);
} Сериализует закрытый или открытый ключ в кодировку PEM.
- Когда ключ содержит только открытые компоненты
-
Сериализует его в X.509 SubjectPublicKeyInfo. Параметры cipher и password игнорируются.
PEM-закодированный ключ будет выглядеть так:
-----BEGIN PUBLIC KEY----- [...] -----END PUBLIC KEY-----
Рассмотрите использование
public_to_pemвместо этого. Это сериализует ключ в X.509 SubjectPublicKeyInfo независимо от того, является ли ключ открытым или закрытым. - Когда ключ содержит закрытые компоненты, и параметры не заданы
-
Сериализует его в PKCS #1 RSAPrivateKey.
PEM-закодированный ключ будет выглядеть так:
-----BEGIN RSA PRIVATE KEY----- [...] -----END RSA PRIVATE KEY-----
- Когда ключ содержит закрытые компоненты, и cipher и password заданы
-
Сериализует его в PKCS #1 RSAPrivateKey и шифрует его в традиционном формате шифрования PEM OpenSSL. cipher должен быть именем алгоритма шифрования, понятным для
OpenSSL::Cipher.new, или экземпляромOpenSSL::Cipher.Зашифрованный PEM-закодированный ключ будет выглядеть так:
-----BEGIN RSA PRIVATE KEY----- Proc-Type: 4,ENCRYPTED DEK-Info: AES-128-CBC,733F5302505B34701FC41F5C0746E4C0 [...] -----END RSA PRIVATE KEY-----
Обратите внимание, что этот формат использует MD5 для вывода ключа шифрования, и поэтому не будет доступен в системах, совместимых с FIPS.
Этот метод сохраняется для совместимости. Его следует использовать только тогда, когда требуется формат PKCS #1 RSAPrivateKey.
Рассмотрите использование public_to_pem (X.509 SubjectPublicKeyInfo) или private_to_pem (PKCS #8 PrivateKeyInfo или EncryptedPrivateKeyInfo) вместо этого.
HAVE_EVP_PKEY_DUP
static VALUE
ossl_rsa_initialize_copy(VALUE self, VALUE other)
{
EVP_PKEY *pkey;
RSA *rsa, *rsa_new;
TypedData_Get_Struct(self, EVP_PKEY, &ossl_evp_pkey_type, pkey);
if (pkey)
rb_raise(rb_eTypeError, "pkey already initialized");
GetRSA(other, rsa);
rsa_new = (RSA *)ASN1_dup((i2d_of_void *)i2d_RSAPrivateKey,
(d2i_of_void *)d2i_RSAPrivateKey,
(char *)rsa);
if (!rsa_new)
ossl_raise(eRSAError, "ASN1_dup");
pkey = EVP_PKEY_new();
if (!pkey || EVP_PKEY_assign_RSA(pkey, rsa_new) != 1) {
RSA_free(rsa_new);
ossl_raise(eRSAError, "EVP_PKEY_assign_RSA");
}
RTYPEDDATA_DATA(self) = pkey;
return self;
} static VALUE
ossl_rsa_get_params(VALUE self)
{
OSSL_3_const RSA *rsa;
VALUE hash;
const BIGNUM *n, *e, *d, *p, *q, *dmp1, *dmq1, *iqmp;
GetRSA(self, rsa);
RSA_get0_key(rsa, &n, &e, &d);
RSA_get0_factors(rsa, &p, &q);
RSA_get0_crt_params(rsa, &dmp1, &dmq1, &iqmp);
hash = rb_hash_new();
rb_hash_aset(hash, rb_str_new2("n"), ossl_bn_new(n));
rb_hash_aset(hash, rb_str_new2("e"), ossl_bn_new(e));
rb_hash_aset(hash, rb_str_new2("d"), ossl_bn_new(d));
rb_hash_aset(hash, rb_str_new2("p"), ossl_bn_new(p));
rb_hash_aset(hash, rb_str_new2("q"), ossl_bn_new(q));
rb_hash_aset(hash, rb_str_new2("dmp1"), ossl_bn_new(dmp1));
rb_hash_aset(hash, rb_str_new2("dmq1"), ossl_bn_new(dmq1));
rb_hash_aset(hash, rb_str_new2("iqmp"), ossl_bn_new(iqmp));
return hash;
} ЭТОТ МЕТОД НЕБЕЗОПАСЕН, КОНФИДЕНЦИАЛЬНАЯ ИНФОРМАЦИЯ МОЖЕТ ВЫТЕЧЬ!!!
Сохраняет все параметры ключа в хэш. Хэш имеет ключи ‘n’, ‘e’, ‘d’, ‘p’, ‘q’, ‘dmp1’, ‘dmq1’, ‘iqmp’.
Не используйте :-)) (Это зависит от вас)
static VALUE
ossl_rsa_is_private(VALUE self)
{
OSSL_3_const RSA *rsa;
GetRSA(self, rsa);
return RSA_PRIVATE(self, rsa) ? Qtrue : Qfalse;
} Содержит ли эта пара ключей закрытый ключ?
# File ext/openssl/lib/openssl/pkey.rb, line 439
def private_decrypt(data, padding = PKCS1_PADDING)
n or raise OpenSSL::PKey::RSAError, "incomplete RSA"
private? or raise OpenSSL::PKey::RSAError, "private key needed."
begin
decrypt(data, {
"rsa_padding_mode" => translate_padding_mode(padding),
})
rescue OpenSSL::PKey::PKeyError
raise OpenSSL::PKey::RSAError, $!.message
end
end Расшифровывает string, зашифрованное с использованием открытого ключа, с использованием закрытого ключа. padding по умолчанию PKCS1_PADDING, который, как известно, небезопасен, но сохраняется для обратной совместимости.
Устарело в версии 3.0. Рассмотрите использование PKey::PKey#encrypt и PKey::PKey#decrypt вместо этого.
# File ext/openssl/lib/openssl/pkey.rb, line 373
def private_encrypt(string, padding = PKCS1_PADDING)
n or raise OpenSSL::PKey::RSAError, "incomplete RSA"
private? or raise OpenSSL::PKey::RSAError, "private key needed."
begin
sign_raw(nil, string, {
"rsa_padding_mode" => translate_padding_mode(padding),
})
rescue OpenSSL::PKey::PKeyError
raise OpenSSL::PKey::RSAError, $!.message
end
end Шифрует string с использованием закрытого ключа. padding по умолчанию PKCS1_PADDING, который, как известно, небезопасен, но сохраняется для обратной совместимости. Зашифрованная выходная строка может быть расшифрована с помощью public_decrypt.
Устарело в версии 3.0. Рассмотрите использование PKey::PKey#sign_raw и PKey::PKey#verify_raw, а также PKey::PKey#verify_recover вместо этого.
static VALUE
ossl_rsa_is_public(VALUE self)
{
OSSL_3_const RSA *rsa;
GetRSA(self, rsa);
/*
* This method should check for n and e. BUG.
*/
(void)rsa;
return Qtrue;
} Значение возврата всегда true, так как каждый закрытый ключ также является открытым ключом.
# File ext/openssl/lib/openssl/pkey.rb, line 396
def public_decrypt(string, padding = PKCS1_PADDING)
n or raise OpenSSL::PKey::RSAError, "incomplete RSA"
begin
verify_recover(nil, string, {
"rsa_padding_mode" => translate_padding_mode(padding),
})
rescue OpenSSL::PKey::PKeyError
raise OpenSSL::PKey::RSAError, $!.message
end
end Расшифровывает string, зашифрованное с использованием закрытого ключа, с использованием открытого ключа. padding по умолчанию PKCS1_PADDING, который, как известно, небезопасен, но сохраняется для обратной совместимости.
Устарело в версии 3.0. Рассмотрите использование PKey::PKey#sign_raw и PKey::PKey#verify_raw, а также PKey::PKey#verify_recover вместо этого.
# File ext/openssl/lib/openssl/pkey.rb, line 418
def public_encrypt(data, padding = PKCS1_PADDING)
n or raise OpenSSL::PKey::RSAError, "incomplete RSA"
begin
encrypt(data, {
"rsa_padding_mode" => translate_padding_mode(padding),
})
rescue OpenSSL::PKey::PKeyError
raise OpenSSL::PKey::RSAError, $!.message
end
end Шифрует string с использованием открытого ключа. padding по умолчанию PKCS1_PADDING, который, как известно, небезопасен, но сохраняется для обратной совместимости. Зашифрованная выходная строка может быть расшифрована с помощью private_decrypt.
Устарело в версии 3.0. Рассмотрите использование PKey::PKey#encrypt и PKey::PKey#decrypt вместо этого.
# File ext/openssl/lib/openssl/pkey.rb, line 327 def public_key OpenSSL::PKey.read(public_to_der) end
Возвращает новый экземпляр RSA, который содержит только компоненты открытого ключа.
Этот метод предоставляется для обратной совместимости. В большинстве случаев вызывать этот метод не нужно.
Для сериализации открытого ключа в кодировку PEM или DER формата X.509 SubjectPublicKeyInfo см. PKey#public_to_pem и PKey#public_to_der.
Устанавливает значения dmp1, dmq1, iqmp для экземпляра RSA. Они вычисляются с помощью d mod (p - 1), d mod (q - 1) и q^(-1) mod p соответственно.
Устанавливает значения p, q для экземпляра RSA.
Устанавливает значения n, e, d для экземпляра RSA.
static VALUE
ossl_rsa_sign_pss(int argc, VALUE *argv, VALUE self)
{
VALUE digest, data, options, kwargs[2], signature;
static ID kwargs_ids[2];
EVP_PKEY *pkey;
EVP_PKEY_CTX *pkey_ctx;
const EVP_MD *md, *mgf1md;
EVP_MD_CTX *md_ctx;
size_t buf_len;
int salt_len;
if (!kwargs_ids[0]) {
kwargs_ids[0] = rb_intern_const("salt_length");
kwargs_ids[1] = rb_intern_const("mgf1_hash");
}
rb_scan_args(argc, argv, "2:", &digest, &data, &options);
rb_get_kwargs(options, kwargs_ids, 2, 0, kwargs);
if (kwargs[0] == ID2SYM(rb_intern("max")))
salt_len = -2; /* RSA_PSS_SALTLEN_MAX_SIGN */
else if (kwargs[0] == ID2SYM(rb_intern("digest")))
salt_len = -1; /* RSA_PSS_SALTLEN_DIGEST */
else
salt_len = NUM2INT(kwargs[0]);
mgf1md = ossl_evp_get_digestbyname(kwargs[1]);
pkey = GetPrivPKeyPtr(self);
buf_len = EVP_PKEY_size(pkey);
md = ossl_evp_get_digestbyname(digest);
StringValue(data);
signature = rb_str_new(NULL, (long)buf_len);
md_ctx = EVP_MD_CTX_new();
if (!md_ctx)
goto err;
if (EVP_DigestSignInit(md_ctx, &pkey_ctx, md, NULL, pkey) != 1)
goto err;
if (EVP_PKEY_CTX_set_rsa_padding(pkey_ctx, RSA_PKCS1_PSS_PADDING) != 1)
goto err;
if (EVP_PKEY_CTX_set_rsa_pss_saltlen(pkey_ctx, salt_len) != 1)
goto err;
if (EVP_PKEY_CTX_set_rsa_mgf1_md(pkey_ctx, mgf1md) != 1)
goto err;
if (EVP_DigestSignUpdate(md_ctx, RSTRING_PTR(data), RSTRING_LEN(data)) != 1)
goto err;
if (EVP_DigestSignFinal(md_ctx, (unsigned char *)RSTRING_PTR(signature), &buf_len) != 1)
goto err;
rb_str_set_len(signature, (long)buf_len);
EVP_MD_CTX_free(md_ctx);
return signature;
err:
EVP_MD_CTX_free(md_ctx);
ossl_raise(eRSAError, NULL);
} Подписывает data с помощью схемы вероятностного подписи (RSA-PSS) и возвращает вычисленную подпись.
RSAError будет поднята, если произошла ошибка.
См. verify_pss для операции проверки.
Параметры
- digest
-
A
Stringсодержащий имя алгоритма хэширования сообщения. - data
-
A
String. Данные, подлежащие подписи. - salt_length
-
Длина соли в октетах. Зарезервированы два специальных значения:
:digestозначает длину хэша сообщения, а:maxозначает максимальную возможную длину для комбинации закрытого ключа и выбранного алгоритма хэширования сообщения. - mgf1_hash
-
Алгоритм хэширования, используемый в MGF1 (текущая поддерживаемая функция генерации маски (MGF)).
Пример
data = "Sign me!"
pkey = OpenSSL::PKey::RSA.new(2048)
signature = pkey.sign_pss("SHA256", data, salt_length: :max, mgf1_hash: "SHA256")
pub_key = OpenSSL::PKey.read(pkey.public_to_der)
puts pub_key.verify_pss("SHA256", signature, data,
salt_length: :auto, mgf1_hash: "SHA256") # => true
static VALUE
ossl_rsa_to_der(VALUE self)
{
if (can_export_rsaprivatekey(self))
return ossl_pkey_export_traditional(0, NULL, self, 1);
else
return ossl_pkey_export_spki(self, 1);
} Сериализует закрытый или открытый ключ в кодировку DER.
См. to_pem для подробностей.
Этот метод сохранен для совместимости. Его следует использовать только тогда, когда требуется формат PKCS #1 RSAPrivateKey.
Рассмотрите использование public_to_der или private_to_der вместо этого.
Сериализует закрытый или открытый ключ в кодировку PEM.
- Когда ключ содержит только открытые компоненты
-
Сериализует его в X.509 SubjectPublicKeyInfo. Параметры cipher и password игнорируются.
Ключ в формате PEM будет выглядеть так:
-----BEGIN PUBLIC KEY----- [...] -----END PUBLIC KEY-----
Рассмотрите использование
public_to_pemвместо этого. Это сериализует ключ в X.509 SubjectPublicKeyInfo независимо от того, является ли ключ открытым или закрытым. - Когда ключ содержит закрытые компоненты и параметры не заданы
-
Сериализует его в PKCS #1 RSAPrivateKey.
Ключ в формате PEM будет выглядеть так:
-----BEGIN RSA PRIVATE KEY----- [...] -----END RSA PRIVATE KEY-----
- Когда ключ содержит закрытые компоненты и cipher и password заданы
-
Сериализует его в PKCS #1 RSAPrivateKey и шифрует его в традиционном формате шифрования PEM OpenSSL. cipher должен быть именем шифра, понятным
OpenSSL::Cipher.new, или экземпляромOpenSSL::Cipher.Зашифрованный ключ в формате PEM будет выглядеть так:
-----BEGIN RSA PRIVATE KEY----- Proc-Type: 4,ENCRYPTED DEK-Info: AES-128-CBC,733F5302505B34701FC41F5C0746E4C0 [...] -----END RSA PRIVATE KEY-----
Обратите внимание, что для вывода ключа шифрования используется MD5, поэтому этот формат не будет доступен в системах, соответствующих стандарту FIPS.
Этот метод сохранен для совместимости. Его следует использовать только тогда, когда требуется формат PKCS #1 RSAPrivateKey.
Рассмотрите использование public_to_pem (X.509 SubjectPublicKeyInfo) или private_to_pem (PKCS #8 PrivateKeyInfo или EncryptedPrivateKeyInfo) вместо этого.
Сериализует закрытый или открытый ключ в кодировку PEM.
- Когда ключ содержит только открытые компоненты
-
Сериализует его в X.509 SubjectPublicKeyInfo. Параметры cipher и password игнорируются.
Ключ в формате PEM будет выглядеть так:
-----BEGIN PUBLIC KEY----- [...] -----END PUBLIC KEY-----
Рассмотрите использование
public_to_pemвместо этого. Это сериализует ключ в X.509 SubjectPublicKeyInfo независимо от того, является ли ключ открытым или закрытым. - Когда ключ содержит закрытые компоненты и параметры не заданы
-
Сериализует его в PKCS #1 RSAPrivateKey.
Ключ в формате PEM будет выглядеть так:
-----BEGIN RSA PRIVATE KEY----- [...] -----END RSA PRIVATE KEY-----
- Когда ключ содержит закрытые компоненты и cipher и password заданы
-
Сериализует его в PKCS #1 RSAPrivateKey и шифрует его в традиционном формате шифрования PEM OpenSSL. cipher должен быть именем шифра, понятным
OpenSSL::Cipher.new, или экземпляромOpenSSL::Cipher.Зашифрованный ключ в формате PEM будет выглядеть так:
-----BEGIN RSA PRIVATE KEY----- Proc-Type: 4,ENCRYPTED DEK-Info: AES-128-CBC,733F5302505B34701FC41F5C0746E4C0 [...] -----END RSA PRIVATE KEY-----
Обратите внимание, что для вывода ключа шифрования используется MD5, поэтому этот формат не будет доступен в системах, соответствующих стандарту FIPS.
Этот метод сохранен для совместимости. Его следует использовать только тогда, когда требуется формат PKCS #1 RSAPrivateKey.
Рассмотрите использование public_to_pem (X.509 SubjectPublicKeyInfo) или private_to_pem (PKCS #8 PrivateKeyInfo или EncryptedPrivateKeyInfo) вместо этого.
static VALUE
ossl_rsa_verify_pss(int argc, VALUE *argv, VALUE self)
{
VALUE digest, signature, data, options, kwargs[2];
static ID kwargs_ids[2];
EVP_PKEY *pkey;
EVP_PKEY_CTX *pkey_ctx;
const EVP_MD *md, *mgf1md;
EVP_MD_CTX *md_ctx;
int result, salt_len;
if (!kwargs_ids[0]) {
kwargs_ids[0] = rb_intern_const("salt_length");
kwargs_ids[1] = rb_intern_const("mgf1_hash");
}
rb_scan_args(argc, argv, "3:", &digest, &signature, &data, &options);
rb_get_kwargs(options, kwargs_ids, 2, 0, kwargs);
if (kwargs[0] == ID2SYM(rb_intern("auto")))
salt_len = -2; /* RSA_PSS_SALTLEN_AUTO */
else if (kwargs[0] == ID2SYM(rb_intern("digest")))
salt_len = -1; /* RSA_PSS_SALTLEN_DIGEST */
else
salt_len = NUM2INT(kwargs[0]);
mgf1md = ossl_evp_get_digestbyname(kwargs[1]);
GetPKey(self, pkey);
md = ossl_evp_get_digestbyname(digest);
StringValue(signature);
StringValue(data);
md_ctx = EVP_MD_CTX_new();
if (!md_ctx)
goto err;
if (EVP_DigestVerifyInit(md_ctx, &pkey_ctx, md, NULL, pkey) != 1)
goto err;
if (EVP_PKEY_CTX_set_rsa_padding(pkey_ctx, RSA_PKCS1_PSS_PADDING) != 1)
goto err;
if (EVP_PKEY_CTX_set_rsa_pss_saltlen(pkey_ctx, salt_len) != 1)
goto err;
if (EVP_PKEY_CTX_set_rsa_mgf1_md(pkey_ctx, mgf1md) != 1)
goto err;
if (EVP_DigestVerifyUpdate(md_ctx, RSTRING_PTR(data), RSTRING_LEN(data)) != 1)
goto err;
result = EVP_DigestVerifyFinal(md_ctx,
(unsigned char *)RSTRING_PTR(signature),
RSTRING_LEN(signature));
switch (result) {
case 0:
ossl_clear_error();
EVP_MD_CTX_free(md_ctx);
return Qfalse;
case 1:
EVP_MD_CTX_free(md_ctx);
return Qtrue;
default:
goto err;
}
err:
EVP_MD_CTX_free(md_ctx);
ossl_raise(eRSAError, NULL);
} Проверяет data с помощью схемы вероятностной подписи (RSA-PSS).
Возвращаемое значение true , если подпись валидна, false в противном случае. RSAError будет поднята, если произошла ошибка.
См. sign_pss для операции подписи и примера кода.
Параметры
- digest
-
A
Stringсодержащий имя алгоритма хэширования сообщения. - data
-
A
String. Данные, подлежащие подписи. - salt_length
-
Длина соли в октетах. Зарезервированы два специальных значения:
:digestозначает длину хэша сообщения, а:autoозначает автоматическое определение длины на основе подписи. - mgf1_hash
-
Алгоритм хэширования, используемый в MGF1.
Приватные методы экземпляра
# File ext/openssl/lib/openssl/pkey.rb, line 456
def translate_padding_mode(num)
case num
when PKCS1_PADDING
"pkcs1"
when SSLV23_PADDING
"sslv23"
when NO_PADDING
"none"
when PKCS1_OAEP_PADDING
"oaep"
else
raise OpenSSL::PKey::PKeyError, "unsupported padding mode"
end
end
Ruby Core © 1993–2022 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.