Class: OpenSSL::PKey::PKey

Inherits:
Object
  • Object
show all
Defined in:
ext/openssl/ossl_pkey.c,
ext/openssl/ossl_pkey.c

Overview

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

Direct Known Subclasses

DH, DSA, EC, RSA

Instance Method Summary collapse

Constructor Details

#newself

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



609
610
611
612
613
614
615
616
# File 'ext/openssl/ossl_pkey.c', line 609

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

Instance Method Details

#compare?(another_pkey) ⇒ Boolean

Used primarily to check if an OpenSSL::X509::Certificate#public_key compares to its private key.

Example

x509 = OpenSSL::X509::Certificate.new(pem_encoded_certificate)
rsa_key = OpenSSL::PKey::RSA.new(pem_encoded_private_key)

rsa_key.compare?(x509.public_key) => true | false

Returns:

  • (Boolean)


1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
# File 'ext/openssl/ossl_pkey.c', line 1051

static VALUE
ossl_pkey_compare(VALUE self, VALUE other)
{
    int ret;
    EVP_PKEY *selfPKey;
    EVP_PKEY *otherPKey;

    GetPKey(self, selfPKey);
    GetPKey(other, otherPKey);

    /* Explicitly check the key type given EVP_PKEY_ASN1_METHOD(3)
     * docs param_cmp could return any negative number.
     */
    if (EVP_PKEY_id(selfPKey) != EVP_PKEY_id(otherPKey))
        ossl_raise(rb_eTypeError, "cannot match different PKey types");

    ret = EVP_PKEY_eq(selfPKey, otherPKey);

    if (ret == 0)
        return Qfalse;
    else if (ret == 1)
        return Qtrue;
    else
        ossl_raise(ePKeyError, "EVP_PKEY_eq");
}

#decrypt(data[, options]) ⇒ String

Performs a public key decryption operation using pkey.

See #encrypt for a description of the parameters and an example.

Added in version 3.0. See also the man page EVP_PKEY_decrypt(3).

Returns:

  • (String)


1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
# File 'ext/openssl/ossl_pkey.c', line 1601

static VALUE
ossl_pkey_decrypt(int argc, VALUE *argv, VALUE self)
{
    EVP_PKEY *pkey;
    EVP_PKEY_CTX *ctx;
    VALUE data, options, str;
    size_t outlen;
    int state;

    GetPKey(self, pkey);
    rb_scan_args(argc, argv, "11", &data, &options);
    StringValue(data);

    ctx = EVP_PKEY_CTX_new(pkey, /* engine */NULL);
    if (!ctx)
        ossl_raise(ePKeyError, "EVP_PKEY_CTX_new");
    if (EVP_PKEY_decrypt_init(ctx) <= 0) {
        EVP_PKEY_CTX_free(ctx);
        ossl_raise(ePKeyError, "EVP_PKEY_decrypt_init");
    }
    if (!NIL_P(options)) {
        pkey_ctx_apply_options(ctx, options, &state);
        if (state) {
            EVP_PKEY_CTX_free(ctx);
            rb_jump_tag(state);
        }
    }
    if (EVP_PKEY_decrypt(ctx, NULL, &outlen,
                         (unsigned char *)RSTRING_PTR(data),
                         RSTRING_LEN(data)) <= 0) {
        EVP_PKEY_CTX_free(ctx);
        ossl_raise(ePKeyError, "EVP_PKEY_decrypt");
    }
    if (outlen > LONG_MAX) {
        EVP_PKEY_CTX_free(ctx);
        rb_raise(ePKeyError, "decrypted data would be too large");
    }
    str = ossl_str_new(NULL, (long)outlen, &state);
    if (state) {
        EVP_PKEY_CTX_free(ctx);
        rb_jump_tag(state);
    }
    if (EVP_PKEY_decrypt(ctx, (unsigned char *)RSTRING_PTR(str), &outlen,
                         (unsigned char *)RSTRING_PTR(data),
                         RSTRING_LEN(data)) <= 0) {
        EVP_PKEY_CTX_free(ctx);
        ossl_raise(ePKeyError, "EVP_PKEY_decrypt");
    }
    EVP_PKEY_CTX_free(ctx);
    rb_str_set_len(str, outlen);
    return str;
}

#derive(peer_pkey) ⇒ String

Derives a shared secret from pkey and peer_pkey. pkey must contain the private components, peer_pkey must contain the public components.

Returns:

  • (String)


1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
# File 'ext/openssl/ossl_pkey.c', line 1471

static VALUE
ossl_pkey_derive(int argc, VALUE *argv, VALUE self)
{
    EVP_PKEY *pkey, *peer_pkey;
    EVP_PKEY_CTX *ctx;
    VALUE peer_pkey_obj, str;
    size_t keylen;
    int state;

    GetPKey(self, pkey);
    rb_scan_args(argc, argv, "1", &peer_pkey_obj);
    GetPKey(peer_pkey_obj, peer_pkey);

    ctx = EVP_PKEY_CTX_new(pkey, /* engine */NULL);
    if (!ctx)
        ossl_raise(ePKeyError, "EVP_PKEY_CTX_new");
    if (EVP_PKEY_derive_init(ctx) <= 0) {
        EVP_PKEY_CTX_free(ctx);
        ossl_raise(ePKeyError, "EVP_PKEY_derive_init");
    }
    if (EVP_PKEY_derive_set_peer(ctx, peer_pkey) <= 0) {
        EVP_PKEY_CTX_free(ctx);
        ossl_raise(ePKeyError, "EVP_PKEY_derive_set_peer");
    }
    if (EVP_PKEY_derive(ctx, NULL, &keylen) <= 0) {
        EVP_PKEY_CTX_free(ctx);
        ossl_raise(ePKeyError, "EVP_PKEY_derive");
    }
    if (keylen > LONG_MAX)
        rb_raise(ePKeyError, "derived key would be too large");
    str = ossl_str_new(NULL, (long)keylen, &state);
    if (state) {
        EVP_PKEY_CTX_free(ctx);
        rb_jump_tag(state);
    }
    if (EVP_PKEY_derive(ctx, (unsigned char *)RSTRING_PTR(str), &keylen) <= 0) {
        EVP_PKEY_CTX_free(ctx);
        ossl_raise(ePKeyError, "EVP_PKEY_derive");
    }
    EVP_PKEY_CTX_free(ctx);
    rb_str_set_len(str, keylen);
    return str;
}

#encrypt(data[, options]) ⇒ String

Performs a public key encryption operation using pkey.

See #decrypt for the reverse operation.

Added in version 3.0. See also the man page EVP_PKEY_encrypt(3).

data

A String to be encrypted.

options

A Hash that contains algorithm specific control operations to OpenSSL. See OpenSSL’s man page EVP_PKEY_CTX_ctrl_str(3) for details.

Example:

pkey = OpenSSL::PKey.generate_key("RSA", rsa_keygen_bits: 2048)
data = "secret data"
encrypted = pkey.encrypt(data, rsa_padding_mode: "oaep")
decrypted = pkey.decrypt(data, rsa_padding_mode: "oaep")
p decrypted #=> "secret data"

Returns:

  • (String)


1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
# File 'ext/openssl/ossl_pkey.c', line 1538

static VALUE
ossl_pkey_encrypt(int argc, VALUE *argv, VALUE self)
{
    EVP_PKEY *pkey;
    EVP_PKEY_CTX *ctx;
    VALUE data, options, str;
    size_t outlen;
    int state;

    GetPKey(self, pkey);
    rb_scan_args(argc, argv, "11", &data, &options);
    StringValue(data);

    ctx = EVP_PKEY_CTX_new(pkey, /* engine */NULL);
    if (!ctx)
        ossl_raise(ePKeyError, "EVP_PKEY_CTX_new");
    if (EVP_PKEY_encrypt_init(ctx) <= 0) {
        EVP_PKEY_CTX_free(ctx);
        ossl_raise(ePKeyError, "EVP_PKEY_encrypt_init");
    }
    if (!NIL_P(options)) {
        pkey_ctx_apply_options(ctx, options, &state);
        if (state) {
            EVP_PKEY_CTX_free(ctx);
            rb_jump_tag(state);
        }
    }
    if (EVP_PKEY_encrypt(ctx, NULL, &outlen,
                         (unsigned char *)RSTRING_PTR(data),
                         RSTRING_LEN(data)) <= 0) {
        EVP_PKEY_CTX_free(ctx);
        ossl_raise(ePKeyError, "EVP_PKEY_encrypt");
    }
    if (outlen > LONG_MAX) {
        EVP_PKEY_CTX_free(ctx);
        rb_raise(ePKeyError, "encrypted data would be too large");
    }
    str = ossl_str_new(NULL, (long)outlen, &state);
    if (state) {
        EVP_PKEY_CTX_free(ctx);
        rb_jump_tag(state);
    }
    if (EVP_PKEY_encrypt(ctx, (unsigned char *)RSTRING_PTR(str), &outlen,
                         (unsigned char *)RSTRING_PTR(data),
                         RSTRING_LEN(data)) <= 0) {
        EVP_PKEY_CTX_free(ctx);
        ossl_raise(ePKeyError, "EVP_PKEY_encrypt");
    }
    EVP_PKEY_CTX_free(ctx);
    rb_str_set_len(str, outlen);
    return str;
}

#initialize_copy(other) ⇒ Object

:nodoc:



620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
# File 'ext/openssl/ossl_pkey.c', line 620

static VALUE
ossl_pkey_initialize_copy(VALUE self, VALUE other)
{
    EVP_PKEY *pkey, *pkey_other;

    TypedData_Get_Struct(self, EVP_PKEY, &ossl_evp_pkey_type, pkey);
    TypedData_Get_Struct(other, EVP_PKEY, &ossl_evp_pkey_type, pkey_other);
    if (pkey)
        rb_raise(rb_eTypeError, "pkey already initialized");
    if (pkey_other) {
        pkey = EVP_PKEY_dup(pkey_other);
        if (!pkey)
            ossl_raise(ePKeyError, "EVP_PKEY_dup");
        RTYPEDDATA_DATA(self) = pkey;
    }
    return self;
}

#inspectString

Returns a string describing the PKey object.

Returns:

  • (String)


753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
# File 'ext/openssl/ossl_pkey.c', line 753

static VALUE
ossl_pkey_inspect(VALUE self)
{
    EVP_PKEY *pkey;

    GetPKey(self, pkey);
    VALUE str = rb_sprintf("#<%"PRIsVALUE":%p",
                           rb_obj_class(self), (void *)self);
    int nid = EVP_PKEY_id(pkey);
#ifdef OSSL_USE_PROVIDER
    if (nid != EVP_PKEY_KEYMGMT)
#endif
    rb_str_catf(str, " oid=%s", OBJ_nid2sn(nid));
#ifdef OSSL_USE_PROVIDER
    rb_str_catf(str, " type_name=%s", EVP_PKEY_get0_type_name(pkey));
    const OSSL_PROVIDER *prov = EVP_PKEY_get0_provider(pkey);
    if (prov)
        rb_str_catf(str, " provider=%s", OSSL_PROVIDER_get0_name(prov));
#endif
    rb_str_catf(str, ">");
    return str;
}

#oidString

Returns the short name of the OID associated with pkey.

Returns:

  • (String)


732
733
734
735
736
737
738
739
740
741
742
743
744
745
# File 'ext/openssl/ossl_pkey.c', line 732

static VALUE
ossl_pkey_oid(VALUE self)
{
    EVP_PKEY *pkey;
    int nid;

    GetPKey(self, pkey);
    nid = EVP_PKEY_id(pkey);
#ifdef OSSL_USE_PROVIDER
    if (nid == EVP_PKEY_KEYMGMT)
        ossl_raise(ePKeyError, "EVP_PKEY_id");
#endif
    return rb_str_new_cstr(OBJ_nid2sn(nid));
}

#private_to_derString #private_to_der(cipher, password) ⇒ String

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.

Overloads:

  • #private_to_derString

    Returns:

    • (String)
  • #private_to_der(cipher, password) ⇒ String

    Returns:

    • (String)


897
898
899
900
901
# File 'ext/openssl/ossl_pkey.c', line 897

static VALUE
ossl_pkey_private_to_der(int argc, VALUE *argv, VALUE self)
{
    return do_pkcs8_export(argc, argv, self, 1);
}

#private_to_pemString #private_to_pem(cipher, password) ⇒ String

Serializes the private key to PEM-encoded PKCS #8 format. See #private_to_der for more details.

An unencrypted PEM-encoded key will look like:

-----BEGIN PRIVATE KEY-----
[...]
-----END PRIVATE KEY-----

An encrypted PEM-encoded key will look like:

-----BEGIN ENCRYPTED PRIVATE KEY-----
[...]
-----END ENCRYPTED PRIVATE KEY-----

Overloads:

  • #private_to_pemString

    Returns:

    • (String)
  • #private_to_pem(cipher, password) ⇒ String

    Returns:

    • (String)


923
924
925
926
927
# File 'ext/openssl/ossl_pkey.c', line 923

static VALUE
ossl_pkey_private_to_pem(int argc, VALUE *argv, VALUE self)
{
    return do_pkcs8_export(argc, argv, self, 0);
}

#public_to_derString

Serializes the public key to DER-encoded X.509 SubjectPublicKeyInfo format.

Returns:

  • (String)


988
989
990
991
992
# File 'ext/openssl/ossl_pkey.c', line 988

static VALUE
ossl_pkey_public_to_der(VALUE self)
{
    return ossl_pkey_export_spki(self, 1);
}

#public_to_pemString

Serializes the public key to PEM-encoded X.509 SubjectPublicKeyInfo format.

A PEM-encoded key will look like:

-----BEGIN PUBLIC KEY-----
[...]
-----END PUBLIC KEY-----

Returns:

  • (String)


1006
1007
1008
1009
1010
# File 'ext/openssl/ossl_pkey.c', line 1006

static VALUE
ossl_pkey_public_to_pem(VALUE self)
{
    return ossl_pkey_export_spki(self, 0);
}

#raw_private_keyString

See the OpenSSL documentation for EVP_PKEY_get_raw_private_key()

Returns:

  • (String)


936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
# File 'ext/openssl/ossl_pkey.c', line 936

static VALUE
ossl_pkey_raw_private_key(VALUE self)
{
    EVP_PKEY *pkey;
    VALUE str;
    size_t len;

    GetPKey(self, pkey);
    if (EVP_PKEY_get_raw_private_key(pkey, NULL, &len) != 1)
        ossl_raise(ePKeyError, "EVP_PKEY_get_raw_private_key");
    str = rb_str_new(NULL, len);

    if (EVP_PKEY_get_raw_private_key(pkey, (unsigned char *)RSTRING_PTR(str), &len) != 1)
        ossl_raise(ePKeyError, "EVP_PKEY_get_raw_private_key");

    rb_str_set_len(str, len);

    return str;
}

#raw_public_keyString

See the OpenSSL documentation for EVP_PKEY_get_raw_public_key()

Returns:

  • (String)


1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
# File 'ext/openssl/ossl_pkey.c', line 1019

static VALUE
ossl_pkey_raw_public_key(VALUE self)
{
    EVP_PKEY *pkey;
    VALUE str;
    size_t len;

    GetPKey(self, pkey);
    if (EVP_PKEY_get_raw_public_key(pkey, NULL, &len) != 1)
        ossl_raise(ePKeyError, "EVP_PKEY_get_raw_public_key");
    str = rb_str_new(NULL, len);

    if (EVP_PKEY_get_raw_public_key(pkey, (unsigned char *)RSTRING_PTR(str), &len) != 1)
        ossl_raise(ePKeyError, "EVP_PKEY_get_raw_public_key");

    rb_str_set_len(str, len);

    return str;
}

#sign(digest, data[, options]) ⇒ String

Hashes and signs the data using a message digest algorithm digest and a private key pkey.

See #verify for the verification operation.

See also the man page EVP_DigestSign(3).

digest

A String that represents the message digest algorithm name, or nil if the PKey type requires no digest algorithm. For backwards compatibility, this can be an instance of OpenSSL::Digest. Its state will not affect the signature.

data

A String. The data to be hashed and signed.

options

A Hash that contains algorithm specific control operations to OpenSSL. See OpenSSL’s man page EVP_PKEY_CTX_ctrl_str(3) for details. options parameter was added in version 3.0.

Example:

data = "Sign me!"
pkey = OpenSSL::PKey.generate_key("RSA", rsa_keygen_bits: 2048)
signopts = { rsa_padding_mode: "pss" }
signature = pkey.sign("SHA256", data, signopts)

# Creates a copy of the RSA key pkey, but without the private components
pub_key = pkey.public_key
puts pub_key.verify("SHA256", signature, data, signopts) # => true

Returns:

  • (String)


1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
# File 'ext/openssl/ossl_pkey.c', line 1110

static VALUE
ossl_pkey_sign(int argc, VALUE *argv, VALUE self)
{
    EVP_PKEY *pkey;
    VALUE digest, data, options, sig, md_holder;
    const EVP_MD *md = NULL;
    EVP_MD_CTX *ctx;
    EVP_PKEY_CTX *pctx;
    size_t siglen;
    int state;

    pkey = GetPrivPKeyPtr(self);
    rb_scan_args(argc, argv, "21", &digest, &data, &options);
    if (!NIL_P(digest))
        md = ossl_evp_md_fetch(digest, &md_holder);
    StringValue(data);

    ctx = EVP_MD_CTX_new();
    if (!ctx)
        ossl_raise(ePKeyError, "EVP_MD_CTX_new");
    if (EVP_DigestSignInit(ctx, &pctx, md, /* engine */NULL, pkey) < 1) {
        EVP_MD_CTX_free(ctx);
        ossl_raise(ePKeyError, "EVP_DigestSignInit");
    }
    if (!NIL_P(options)) {
        pkey_ctx_apply_options(pctx, options, &state);
        if (state) {
            EVP_MD_CTX_free(ctx);
            rb_jump_tag(state);
        }
    }
    if (EVP_DigestSign(ctx, NULL, &siglen, (unsigned char *)RSTRING_PTR(data),
                       RSTRING_LEN(data)) < 1) {
        EVP_MD_CTX_free(ctx);
        ossl_raise(ePKeyError, "EVP_DigestSign");
    }
    if (siglen > LONG_MAX) {
        EVP_MD_CTX_free(ctx);
        rb_raise(ePKeyError, "signature would be too large");
    }
    sig = ossl_str_new(NULL, (long)siglen, &state);
    if (state) {
        EVP_MD_CTX_free(ctx);
        rb_jump_tag(state);
    }
    if (EVP_DigestSign(ctx, (unsigned char *)RSTRING_PTR(sig), &siglen,
                       (unsigned char *)RSTRING_PTR(data),
                       RSTRING_LEN(data)) < 1) {
        EVP_MD_CTX_free(ctx);
        ossl_raise(ePKeyError, "EVP_DigestSign");
    }
    EVP_MD_CTX_free(ctx);
    rb_str_set_len(sig, siglen);
    return sig;
}

#sign_raw(digest, data[, options]) ⇒ String

Signs data using a private key pkey. Unlike #sign, data will not be hashed by digest automatically.

See #verify_raw for the verification operation.

Added in version 3.0. See also the man page EVP_PKEY_sign(3).

digest

A String that represents the message digest algorithm name, or nil if the PKey type requires no digest algorithm. Although this method will not hash data with it, this parameter may still be required depending on the signature algorithm.

data

A String. The data to be signed.

options

A Hash that contains algorithm specific control operations to OpenSSL. See OpenSSL’s man page EVP_PKEY_CTX_ctrl_str(3) for details.

Example:

data = "Sign me!"
hash = OpenSSL::Digest.digest("SHA256", data)
pkey = OpenSSL::PKey.generate_key("RSA", rsa_keygen_bits: 2048)
signopts = { rsa_padding_mode: "pss" }
signature = pkey.sign_raw("SHA256", hash, signopts)

# Creates a copy of the RSA key pkey, but without the private components
pub_key = pkey.public_key
puts pub_key.verify_raw("SHA256", signature, hash, signopts) # => true

Returns:

  • (String)


1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
# File 'ext/openssl/ossl_pkey.c', line 1268

static VALUE
ossl_pkey_sign_raw(int argc, VALUE *argv, VALUE self)
{
    EVP_PKEY *pkey;
    VALUE digest, data, options, sig, md_holder;
    const EVP_MD *md = NULL;
    EVP_PKEY_CTX *ctx;
    size_t outlen;
    int state;

    GetPKey(self, pkey);
    rb_scan_args(argc, argv, "21", &digest, &data, &options);
    if (!NIL_P(digest))
        md = ossl_evp_md_fetch(digest, &md_holder);
    StringValue(data);

    ctx = EVP_PKEY_CTX_new(pkey, /* engine */NULL);
    if (!ctx)
        ossl_raise(ePKeyError, "EVP_PKEY_CTX_new");
    if (EVP_PKEY_sign_init(ctx) <= 0) {
        EVP_PKEY_CTX_free(ctx);
        ossl_raise(ePKeyError, "EVP_PKEY_sign_init");
    }
    if (md && EVP_PKEY_CTX_set_signature_md(ctx, md) <= 0) {
        EVP_PKEY_CTX_free(ctx);
        ossl_raise(ePKeyError, "EVP_PKEY_CTX_set_signature_md");
    }
    if (!NIL_P(options)) {
        pkey_ctx_apply_options(ctx, options, &state);
        if (state) {
            EVP_PKEY_CTX_free(ctx);
            rb_jump_tag(state);
        }
    }
    if (EVP_PKEY_sign(ctx, NULL, &outlen, (unsigned char *)RSTRING_PTR(data),
                      RSTRING_LEN(data)) <= 0) {
        EVP_PKEY_CTX_free(ctx);
        ossl_raise(ePKeyError, "EVP_PKEY_sign");
    }
    if (outlen > LONG_MAX) {
        EVP_PKEY_CTX_free(ctx);
        rb_raise(ePKeyError, "signature would be too large");
    }
    sig = ossl_str_new(NULL, (long)outlen, &state);
    if (state) {
        EVP_PKEY_CTX_free(ctx);
        rb_jump_tag(state);
    }
    if (EVP_PKEY_sign(ctx, (unsigned char *)RSTRING_PTR(sig), &outlen,
                      (unsigned char *)RSTRING_PTR(data),
                      RSTRING_LEN(data)) <= 0) {
        EVP_PKEY_CTX_free(ctx);
        ossl_raise(ePKeyError, "EVP_PKEY_sign");
    }
    EVP_PKEY_CTX_free(ctx);
    rb_str_set_len(sig, outlen);
    return sig;
}

#to_textString

Dumps key parameters, public key, and private key components contained in the key into a human-readable text.

This is intended for debugging purpose.

See also the man page EVP_PKEY_print_private(3).

Returns:

  • (String)


787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
# File 'ext/openssl/ossl_pkey.c', line 787

static VALUE
ossl_pkey_to_text(VALUE self)
{
    EVP_PKEY *pkey;
    BIO *bio;

    GetPKey(self, pkey);
    if (!(bio = BIO_new(BIO_s_mem())))
        ossl_raise(ePKeyError, "BIO_new");

    if (EVP_PKEY_print_private(bio, pkey, 0, NULL) == 1)
        goto out;
    OSSL_BIO_reset(bio);
    if (EVP_PKEY_print_public(bio, pkey, 0, NULL) == 1)
        goto out;
    OSSL_BIO_reset(bio);
    if (EVP_PKEY_print_params(bio, pkey, 0, NULL) == 1)
        goto out;

    BIO_free(bio);
    ossl_raise(ePKeyError, "EVP_PKEY_print_params");

  out:
    return ossl_membio2str(bio);
}

#verify(digest, signature, data[, options]) ⇒ Boolean

Verifies the signature for the data using a message digest algorithm digest and a public key pkey.

Returns true if the signature is successfully verified, false otherwise. The caller must check the return value.

See #sign for the signing operation and an example.

See also the man page EVP_DigestVerify(3).

digest

See #sign.

signature

A String containing the signature to be verified.

data

See #sign.

options

See #sign. options parameter was added in version 3.0.

Returns:

  • (Boolean)


1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
# File 'ext/openssl/ossl_pkey.c', line 1189

static VALUE
ossl_pkey_verify(int argc, VALUE *argv, VALUE self)
{
    EVP_PKEY *pkey;
    VALUE digest, sig, data, options, md_holder;
    const EVP_MD *md = NULL;
    EVP_MD_CTX *ctx;
    EVP_PKEY_CTX *pctx;
    int state, ret;

    GetPKey(self, pkey);
    rb_scan_args(argc, argv, "31", &digest, &sig, &data, &options);
    ossl_pkey_check_public_key(pkey);
    if (!NIL_P(digest))
        md = ossl_evp_md_fetch(digest, &md_holder);
    StringValue(sig);
    StringValue(data);

    ctx = EVP_MD_CTX_new();
    if (!ctx)
        ossl_raise(ePKeyError, "EVP_MD_CTX_new");
    if (EVP_DigestVerifyInit(ctx, &pctx, md, /* engine */NULL, pkey) < 1) {
        EVP_MD_CTX_free(ctx);
        ossl_raise(ePKeyError, "EVP_DigestVerifyInit");
    }
    if (!NIL_P(options)) {
        pkey_ctx_apply_options(pctx, options, &state);
        if (state) {
            EVP_MD_CTX_free(ctx);
            rb_jump_tag(state);
        }
    }
    ret = EVP_DigestVerify(ctx, (unsigned char *)RSTRING_PTR(sig),
                           RSTRING_LEN(sig), (unsigned char *)RSTRING_PTR(data),
                           RSTRING_LEN(data));
    EVP_MD_CTX_free(ctx);
    if (ret < 0)
        ossl_raise(ePKeyError, "EVP_DigestVerify");
    if (ret)
        return Qtrue;
    else {
        ossl_clear_error();
        return Qfalse;
    }
}

#verify_raw(digest, signature, data[, options]) ⇒ Boolean

Verifies the signature for the data using a public key pkey. Unlike #verify, this method will not hash data with digest automatically.

Returns true if the signature is successfully verified, false otherwise. The caller must check the return value.

See #sign_raw for the signing operation and an example code.

Added in version 3.0. See also the man page EVP_PKEY_verify(3).

signature

A String containing the signature to be verified.

Returns:

  • (Boolean)


1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
# File 'ext/openssl/ossl_pkey.c', line 1344

static VALUE
ossl_pkey_verify_raw(int argc, VALUE *argv, VALUE self)
{
    EVP_PKEY *pkey;
    VALUE digest, sig, data, options, md_holder;
    const EVP_MD *md = NULL;
    EVP_PKEY_CTX *ctx;
    int state, ret;

    GetPKey(self, pkey);
    rb_scan_args(argc, argv, "31", &digest, &sig, &data, &options);
    ossl_pkey_check_public_key(pkey);
    if (!NIL_P(digest))
        md = ossl_evp_md_fetch(digest, &md_holder);
    StringValue(sig);
    StringValue(data);

    ctx = EVP_PKEY_CTX_new(pkey, /* engine */NULL);
    if (!ctx)
        ossl_raise(ePKeyError, "EVP_PKEY_CTX_new");
    if (EVP_PKEY_verify_init(ctx) <= 0) {
        EVP_PKEY_CTX_free(ctx);
        ossl_raise(ePKeyError, "EVP_PKEY_verify_init");
    }
    if (md && EVP_PKEY_CTX_set_signature_md(ctx, md) <= 0) {
        EVP_PKEY_CTX_free(ctx);
        ossl_raise(ePKeyError, "EVP_PKEY_CTX_set_signature_md");
    }
    if (!NIL_P(options)) {
        pkey_ctx_apply_options(ctx, options, &state);
        if (state) {
            EVP_PKEY_CTX_free(ctx);
            rb_jump_tag(state);
        }
    }
    ret = EVP_PKEY_verify(ctx, (unsigned char *)RSTRING_PTR(sig),
                          RSTRING_LEN(sig),
                          (unsigned char *)RSTRING_PTR(data),
                          RSTRING_LEN(data));
    EVP_PKEY_CTX_free(ctx);
    if (ret < 0)
        ossl_raise(ePKeyError, "EVP_PKEY_verify");

    if (ret)
        return Qtrue;
    else {
        ossl_clear_error();
        return Qfalse;
    }
}

#verify_recover(digest, signature[, options]) ⇒ String

Recovers the signed data from signature using a public key pkey. Not all signature algorithms support this operation.

Added in version 3.0. See also the man page EVP_PKEY_verify_recover(3).

signature

A String containing the signature to be verified.

Returns:

  • (String)


1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
# File 'ext/openssl/ossl_pkey.c', line 1407

static VALUE
ossl_pkey_verify_recover(int argc, VALUE *argv, VALUE self)
{
    EVP_PKEY *pkey;
    VALUE digest, sig, options, out, md_holder;
    const EVP_MD *md = NULL;
    EVP_PKEY_CTX *ctx;
    int state;
    size_t outlen;

    GetPKey(self, pkey);
    rb_scan_args(argc, argv, "21", &digest, &sig, &options);
    ossl_pkey_check_public_key(pkey);
    if (!NIL_P(digest))
        md = ossl_evp_md_fetch(digest, &md_holder);
    StringValue(sig);

    ctx = EVP_PKEY_CTX_new(pkey, /* engine */NULL);
    if (!ctx)
        ossl_raise(ePKeyError, "EVP_PKEY_CTX_new");
    if (EVP_PKEY_verify_recover_init(ctx) <= 0) {
        EVP_PKEY_CTX_free(ctx);
        ossl_raise(ePKeyError, "EVP_PKEY_verify_recover_init");
    }
    if (md && EVP_PKEY_CTX_set_signature_md(ctx, md) <= 0) {
        EVP_PKEY_CTX_free(ctx);
        ossl_raise(ePKeyError, "EVP_PKEY_CTX_set_signature_md");
    }
    if (!NIL_P(options)) {
        pkey_ctx_apply_options(ctx, options, &state);
        if (state) {
            EVP_PKEY_CTX_free(ctx);
            rb_jump_tag(state);
        }
    }
    if (EVP_PKEY_verify_recover(ctx, NULL, &outlen,
                                (unsigned char *)RSTRING_PTR(sig),
                                RSTRING_LEN(sig)) <= 0) {
        EVP_PKEY_CTX_free(ctx);
        ossl_raise(ePKeyError, "EVP_PKEY_verify_recover");
    }
    out = ossl_str_new(NULL, (long)outlen, &state);
    if (state) {
        EVP_PKEY_CTX_free(ctx);
        rb_jump_tag(state);
    }
    if (EVP_PKEY_verify_recover(ctx, (unsigned char *)RSTRING_PTR(out), &outlen,
                                (unsigned char *)RSTRING_PTR(sig),
                                RSTRING_LEN(sig)) <= 0) {
        EVP_PKEY_CTX_free(ctx);
        ossl_raise(ePKeyError, "EVP_PKEY_verify_recover");
    }
    EVP_PKEY_CTX_free(ctx);
    rb_str_set_len(out, outlen);
    return out;
}