# class OpenSSL::PKey::PKey

An abstract class that bundles signature creation (PKey#sign) and validation (PKey#verify) that is common to all implementations except `OpenSSL::PKey::DH`

- `OpenSSL::PKey::RSA`

- `OpenSSL::PKey::DSA`

- `OpenSSL::PKey::EC`

### Public Class Methods

new → self click to toggle source

Because `PKey` is an abstract class, actually calling this method explicitly will raise a `NotImplementedError`.

    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;
    }

### Public Instance Methods

sign(digest, data) → String click to toggle source

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::SHA256.new
    pkey = OpenSSL::PKey::RSA.new(2048)
    signature = pkey.sign(digest, data)

    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;
    }

verify(digest, signature, data) → String click to toggle source

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::SHA256.new
    pkey = OpenSSL::PKey::RSA.new(2048)
    signature = pkey.sign(digest, data)
    pub_key = pkey.public_key
    puts pub_key.verify(digest, signature, data) # => true

    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");
        }
    }