An abstract class that bundles signature creation (PKey#sign
) and validation (PKey#verify
) that is common to all implementations except OpenSSL::PKey::DH
static VALUE
ossl_pkey_initialize(VALUE self)
{
if (rb_obj_is_instance_of(self, cPKey)) {
ossl_raise(rb_eTypeError, "OpenSSL::PKey::PKey can't be instantiated directly");
}
return self;
}
Because PKey
is an abstract class, actually calling this method explicitly will raise a NotImplementedError
.
static VALUE
ossl_pkey_inspect(VALUE self)
{
EVP_PKEY *pkey;
int nid;
GetPKey(self, pkey);
nid = EVP_PKEY_id(pkey);
return rb_sprintf("#<%"PRIsVALUE":%p oid=%s>",
rb_class_name(CLASS_OF(self)), (void *)self,
OBJ_nid2sn(nid));
}
Returns a string describing the PKey
object.
static VALUE
ossl_pkey_oid(VALUE self)
{
EVP_PKEY *pkey;
int nid;
GetPKey(self, pkey);
nid = EVP_PKEY_id(pkey);
return rb_str_new_cstr(OBJ_nid2sn(nid));
}
Returns the short name of the OID associated with pkey.
static VALUE
ossl_pkey_private_to_der(int argc, VALUE *argv, VALUE self)
{
return do_pkcs8_export(argc, argv, self, 1);
}
Serializes the private key to DER-encoded PKCS #8 format. If called without arguments, unencrypted PKCS #8 PrivateKeyInfo format is used. If called with a cipher name and a password, PKCS #8 EncryptedPrivateKeyInfo format with PBES2 encryption scheme is used.
static VALUE
ossl_pkey_private_to_pem(int argc, VALUE *argv, VALUE self)
{
return do_pkcs8_export(argc, argv, self, 0);
}
Serializes the private key to PEM-encoded PKCS #8 format. See private_to_der
for more details.
static VALUE
ossl_pkey_public_to_der(VALUE self)
{
return do_spki_export(self, 1);
}
Serializes the public key to DER-encoded X.509 SubjectPublicKeyInfo format.
static VALUE
ossl_pkey_public_to_pem(VALUE self)
{
return do_spki_export(self, 0);
}
Serializes the public key to PEM-encoded X.509 SubjectPublicKeyInfo format.
static VALUE
ossl_pkey_sign(VALUE self, VALUE digest, VALUE data)
{
EVP_PKEY *pkey;
const EVP_MD *md;
EVP_MD_CTX *ctx;
unsigned int buf_len;
VALUE str;
int result;
pkey = GetPrivPKeyPtr(self);
md = ossl_evp_get_digestbyname(digest);
StringValue(data);
str = rb_str_new(0, EVP_PKEY_size(pkey));
ctx = EVP_MD_CTX_new();
if (!ctx)
ossl_raise(ePKeyError, "EVP_MD_CTX_new");
if (!EVP_SignInit_ex(ctx, md, NULL)) {
EVP_MD_CTX_free(ctx);
ossl_raise(ePKeyError, "EVP_SignInit_ex");
}
if (!EVP_SignUpdate(ctx, RSTRING_PTR(data), RSTRING_LEN(data))) {
EVP_MD_CTX_free(ctx);
ossl_raise(ePKeyError, "EVP_SignUpdate");
}
result = EVP_SignFinal(ctx, (unsigned char *)RSTRING_PTR(str), &buf_len, pkey);
EVP_MD_CTX_free(ctx);
if (!result)
ossl_raise(ePKeyError, "EVP_SignFinal");
rb_str_set_len(str, buf_len);
return str;
}
To sign the String
data, digest, an instance of OpenSSL::Digest
, must be provided. The return value is again a String
containing the signature. A PKeyError
is raised should errors occur. Any previous state of the Digest
instance is irrelevant to the signature outcome, the digest instance is reset to its initial state during the operation.
Example
data = 'Sign me!' digest = OpenSSL::Digest.new('SHA256') pkey = OpenSSL::PKey::RSA.new(2048) signature = pkey.sign(digest, data)
static VALUE
ossl_pkey_verify(VALUE self, VALUE digest, VALUE sig, VALUE data)
{
EVP_PKEY *pkey;
const EVP_MD *md;
EVP_MD_CTX *ctx;
int siglen, result;
GetPKey(self, pkey);
ossl_pkey_check_public_key(pkey);
md = ossl_evp_get_digestbyname(digest);
StringValue(sig);
siglen = RSTRING_LENINT(sig);
StringValue(data);
ctx = EVP_MD_CTX_new();
if (!ctx)
ossl_raise(ePKeyError, "EVP_MD_CTX_new");
if (!EVP_VerifyInit_ex(ctx, md, NULL)) {
EVP_MD_CTX_free(ctx);
ossl_raise(ePKeyError, "EVP_VerifyInit_ex");
}
if (!EVP_VerifyUpdate(ctx, RSTRING_PTR(data), RSTRING_LEN(data))) {
EVP_MD_CTX_free(ctx);
ossl_raise(ePKeyError, "EVP_VerifyUpdate");
}
result = EVP_VerifyFinal(ctx, (unsigned char *)RSTRING_PTR(sig), siglen, pkey);
EVP_MD_CTX_free(ctx);
switch (result) {
case 0:
ossl_clear_error();
return Qfalse;
case 1:
return Qtrue;
default:
ossl_raise(ePKeyError, "EVP_VerifyFinal");
}
}
To verify the String
signature, digest, an instance of OpenSSL::Digest
, must be provided to re-compute the message digest of the original data, also a String
. The return value is true
if the signature is valid, false
otherwise. A PKeyError
is raised should errors occur. Any previous state of the Digest
instance is irrelevant to the validation outcome, the digest instance is reset to its initial state during the operation.
Example
data = 'Sign me!' digest = OpenSSL::Digest.new('SHA256') pkey = OpenSSL::PKey::RSA.new(2048) signature = pkey.sign(digest, data) pub_key = pkey.public_key puts pub_key.verify(digest, signature, data) # => true