OPENSSL-PKEYUTL(1ossl)
π OPENSSL-PKEYUTL π (that's openssl-pkeyutl, section 1ossl, from the OpenSSL fam β hey bestie, welcome to the asymmetric key command π)
okay so. sit down, grab a strawberry drink π, because this one is the low-level asymmetric key command and it does a LOT. no cap.
β¨ NAME β¨
openssl-pkeyutl β the asymmetric key command. that's it, that's the name, she's iconic π
πΈ SYNOPSIS πΈ
openssl pkeyutl [-help] [-in file] [-rawin] [-digest algorithm] [-out
file] [-secret file] [-sigfile file] [-inkey filename|uri] [-keyform
DER|PEM|P12|ENGINE] [-passin arg] [-pubin] [-certin] [-rev] [-sign]
[-verify] [-verifyrecover] [-encrypt] [-decrypt] [-derive] [-peerkey
file] [-peerform DER|PEM|P12|ENGINE] [-encap] [-decap] [-kdf algorithm]
[-kdflen length] [-kemop mode] [-pkeyopt opt:value] [-pkeyopt_passin
opt[:passarg]] [-hexdump] [-asn1parse] [-engine id] [-engine_impl]
[-rand files] [-writerand file] [-provider name] [-provider-path path]
[-provparam [name:]key=value] [-propquery propq] [-config configfile]
like, look at her. a whole menu π«Ά
π¦ DESCRIPTION π¦
so this command does low-level operations on asymmetric keys β public or private β using any algorithm that's supported. any of them. she's versatile like that π
and the default? if you don't say what you want, she assumes you want the signing operation (that's the -sign option, keep that in your back pocket). main character default energy, honestly.
π OPTIONS π
okay this is the long part. buckle up, we're going through all of them, no skipping, i promise π
-helpβ prints out a usage message. the classic "wait what do i do" button β¨-in fileβ tells her which input file to read data from. if you don't specify it, she reads from standard input. default behavior, love that for us.-rawinβ this one says: the signature (or verification) input data is raw, like, genuinely not hashed by any message digest algorithm at all. except with EdDSA, you can pick a digest algorithm with the-digestoption. for signature algorithms like RSA, DSA and ECDSA, the default digest algorithm isSHA256. for SM2, it'sSM3. π₯
this option can only be used with -sign and -verify. for EdDSA (that's the Ed25519 and Ed448 algorithms) this option is implied since OpenSSL 3.5, and it was required in earlier versions. so, yeah, glow-up timeline.
also: the -digest option implies -rawin since OpenSSL 3.5. iykyk.
-digest algorithmβ can only be used with-signand-verify(same club as-rawin, they're besties). it specifies the digest algorithm used to hash the input data before signing or verifying it with the input key. you could omit this if the signature algorithm doesn't need the input preprocessed through a pluggable hash function before signing β EdDSA is the example here. but if you omit it, and the signature algorithm does need one, and you gave-rawin, then a default value gets used (peep-rawinfor the deets π). and if this option is present, then-rawinis implied since OpenSSL 3.5, and was required in earlier versions.
π«§ heads up bestie: at this time, HashEdDSA (thephor "prehash" variant of EdDSA) is not supported, so-digestcannot be used with EdDSA. periodt.
-out filenameβ the output filename to write to. or standard output, by default. her choice π-secret filenameβ the shared-secret output filename, for when you're doing encapsulation via-encapor decapsulation via-decap. heads up:-encapalso produces a separate (public) ciphertext output, which by default goes to standard output β but since it's binary non-text data, you'll typically also redirect that to a file picked with-out. two outputs, one mechanism, she's doing the most π-sigfile fileβ signature file. required and only allowed for-verifyoperations. no sneaking it anywhere else π-inkey filename|uriβ the input key. by default it should be a private key (spoiler:-pubinchanges that).-keyform DER|PEM|P12|ENGINEβ the key format. unspecified by default. seeopenssl-format-options(1)for the details π-passin argβ the input key password source. for more info about the format of arg, seeopenssl-passphrase-options(1)ποΈ-pubinβ by default a private key is read from the key input. with this option, a public key is read instead. and if the input contains no public key but it does have a private key, then its public part is used. neat little fallback, love her for that π«Ά-certinβ the input is a certificate containing a public key. that's the whole vibe π-revβ reverses the order of the input buffer. useful for some libraries (like CryptoAPI) that represent the buffer in little-endian format. π cannot be used in conjunction with-rawinβ pick a lane, bestie.-signβ signs the input data and outputs the signed result. requires a private key π. using a message digest operation along with this is recommended when applicable β see the-rawinand-digestoptions for the details. otherwise, the input data given with-inis assumed to already be a digest, but that may then require an additional-pkeyopt "digest:"mdin some cases (e.g. RSA with the default PKCS#1 padding mode). and even for other algorithms like ECDSA β where the additional-pkeyoptoption doesn't affect the signature output β it's still recommended, because it lets her check that the input length is consistent with the intended digest. little safety check, we stan β¨-verifyβ verifies the input data against the signature given with the-sigfileoption, and tells you if verification succeeded or failed β β. the input data given with-inis assumed to be a hash value unless-rawinis specified or implied. with raw data, when a digest algorithm is applicable β though it may be inferred from the signature or take a default value β it should also be specified. specify it. be a good citizen π-verifyrecoverβ verifies the given signature and outputs the recovered data (that's the signature payload). for example, with RSA PKCS#1 the recovered data is the EMSA-PKCS-v1_5 DER encoding of the digest algorithm OID and value, as specified in RFC8017 Section 9.2 (https://datatracker.ietf.org/doc/html/rfc8017#section-9.2). π
π note note note: here the input given with-inis not a signature input (like it is with-signand-verify) β it's a signature output value, typically produced using-sign. flip your brain around, it's fine.
this option is available only for use with RSA keys π.
-encryptβ encrypts the input data using a public key πβ¨-decryptβ decrypts the input data using a private key π-deriveβ derives a shared secret using your own private (EC)DH key and the peer key. team work makes the dream work π€-peerkey fileβ file containing the peer public or private (EC)DH key to use with the key derivation (agreement) operation. its type must match the type of the own private key given with-inkey. mismatched keys? not on her watch π«-peerform DER|PEM|P12|ENGINEβ the peer key format. unspecified by default. seeopenssl-format-options(1)for details π-encapβ uses a Key Encapsulation Mechanism (KEM) to encapsulate a shared-secret to a peer's public key π. the encapsulated result (or ciphertext β non-text binary data, beware) is written to standard output by default, or else to the file specified with-out. the-secretoption must also be provided, to specify the output file for the derived shared-secret value generated in the encapsulation process. encapsulation is supported with a number of public key algorithms β currently:ML-KEM,X25519,X448, andEC. the ECX and EC algorithms use the RFC9180 (https://www.rfc-editor.org/rfc/rfc9180) DHKEM construction. encapsulation is also supported with RSA keys via theRSASVEconstruction π₯
π at the API level, encapsulation and decapsulation are also supported for a few hybrid ECDHE (no DHKEM) plus ML-KEM algorithms β but those are intended primarily for use with TLS and should not be used standalone. and anyway, there are no standard public and private key formats for the hybrid algorithms, so it's not possible to provide the required key material. so, like, don't even try.
-decapβ decodes an encapsulated secret, using a-privatekey, to derive the same shared-secret as the one you got when the secret was encapsulated to the corresponding public key ππ. the encapsulated secret is by default read from standard input, or else from the file specified with-in. the derived shared-secret is written to the file specified with the-secretoption β which must also be provided. decapsulation is supported with a number of public key algorithms, currently:ML-KEM,X25519,X448, andEC. the ECX and EC algorithms use the RFC9180 (https://www.rfc-editor.org/rfc/rfc9180) DHKEM construction. decapsulation is also supported with RSA keys via theRSASVEconstruction β¨-kemop modeβ used with the-encap/-decapcommands, and specifies the KEM mode specific to the key algorithm when there is no default way to encapsulate and decapsulate shared secrets with the chosen key type. all the supported algorithms presently support only their default mode, and this option β though available β is not required. so she exists, but she's chilling π-kdf algorithmβ use key derivation function algorithm. the supported algorithms are at presentTLS1-PRFandHKDF. π note: additional parameters and the KDF output length will normally have to be set for this to work. seeEVP_PKEY_CTX_set_hkdf_md(3)andEVP_PKEY_CTX_set_tls1_prf_md(3)for the supported string parameters of each algorithm. read the docs, bestie, they're there for you π-kdflen lengthβ sets the output length for the KDF. π-pkeyopt opt:valueβ public key options, specified asopt:value. see NOTES below for more details π-pkeyopt_passin opt[:passarg]β lets you read a public key option opt from stdin or a password source. if you only specify opt, the user gets prompted to enter a password on stdin. alternatively you can specify passarg, which can be any value supported byopenssl-passphrase-options(1)ποΈπ«Ά-hexdumpβ hex dumps the output data. for when you want to see the vibes in hex π’-asn1parseβ parses the ASN.1 output data to check its DER encoding, and prints any errors. π§ when combined with the-verifyrecoveroption, this may be useful in case an ASN.1 DER-encoded structure had been signed directly (without hashing it), and when checking a signature in PKCS#1 v1.5 format, which has a DER encoding. niche but iconic.-engine idβ see "Engine Options" inopenssl(1). β οΈ this option is deprecated. she's old news, but we still list her out of respect.-engine_implβ when used with the-engineoption, it specifies to also use engine id for crypto operations. π§-rand files,-writerand fileβ see "Random State Options" inopenssl(1)for details. π²-provider name,-provider-path path,-provparam [name:]key=value,-propquery propqβ see "Provider Options" inopenssl(1),provider(7), andproperty(7). the whole provider squad, all listed together π-config configfileβ see "Configuration Option" inopenssl(1). βοΈ
π NOTES π
ok so real talk, bestie: what operations and options actually work depends on the key algorithm and its implementation. The OpenSSL operations and options are listed below, mwah π
Unless it says otherwise somewhere, the -pkeyopt option supports the "digest:"alg argument for all public-key types, and it says which digest is in use for the signing and verification operations. That alg value should be a digest name like the ones you'd pass to the EVP_get_digestbyname() function, for example sha256. Heads up though: this value is not used to hash your input data. It's used (by some algorithms) for sanity-checking the lengths of data passed in, and for creating the structures that make up the signature (e.g. DigestInfo in RSASSA PKCS#1 v1.5 signatures). iykyk π«Ά
So like, for instance: if the value of the -pkeyopt option "digest" argument is sha256, then your signature or verification input should be the 32-bytes-long binary value of the SHA256 hash function output. No cap, it's just gotta line up. β¨
Unless -rawin is used or implied, this command does not hash the input data β it uses the data directly as input to the signature algorithm. Depending on the key type, signature type, and mode of padding, the maximum sensible lengths of input data differ π
- With RSA, the signed data cannot be longer than the key modulus.
- In the case of ECDSA and DSA, the data should not be longer than the field size, otherwise it will be silently truncated to the field size π (yes, silently, we don't love that either).
- In any event the input size must not be larger than the largest supported digest output size
EVP_MAX_MD_SIZE, which currently is 64 bytes.
π₯ RSA ALGORITHM π₯
The RSA algorithm generally supports the encrypt, decrypt, sign, verify and verifyrecover operations. However β some padding modes only support a subset of these, so vibe check your padding first π The following additional pkeyopt values are supported:
rsa_padding_mode:modeβ sets the RSA padding mode. Acceptable values for mode arepkcs1for PKCS#1 padding,nonefor no padding,oaepfor OAEP mode,x931for X9.31 mode andpssfor PSS.
In PKCS#1 padding, if the message digest is not set, then the supplied data is signed or verified directly instead of using a DigestInfo structure. If a digest is set, then the DigestInfo structure is used and its length must correspond to the digest type.
π¨ Note, forpkcs1padding, as a protection against the Bleichenbacher attack, the decryption will not fail in case of padding check failures. So if you actually wanna know, usenoneand manually inspect the decrypted message to verify if the decrypted value has correct PKCS#1 v1.5 padding. Yeah. It's giving "security tradeoffs". π
For oaep mode only encryption and decryption is supported.
For x931, if the digest type is set it's used to format the block data, otherwise the first byte is used to specify the X9.31 digest ID. sign, verify and verifyrecover can be performed in this mode.
For pss mode only sign and verify are supported, and the digest type must be specified. periodt.
rsa_pss_saltlen:lenβ forpssmode only, this specifies the salt length π§ Three special values are supported:digestsets the salt length to the digest length,maxsets the salt length to the maximum permissible value. When verifying,autocauses the salt length to be automatically determined based on the PSS block structure. Slay.rsa_mgf1_md:digestβ for PSS and OAEP padding, sets the MGF1 digest. If the MGF1 digest is not explicitly set in PSS mode, then the signing digest is used.rsa_oaep_md:digestβ sets the digest used for the OAEP hash function. If not explicitly set, thenSHA256is used. β¨rsa_pkcs1_implicit_rejection:flagβ disables (when set to0) or enables (when set to1) the use of implicit rejection with PKCS#1 v1.5 decryption. When enabled (the default), as a protection against the Bleichenbacher attack, the library will generate a deterministic random plaintext that it will return to the caller in case of padding check failure. When disabled, it's the callers' responsibility to handle the returned errors in a side-channel free manner. π that's a lot of responsibility, bestie.
πΈ RSA-PSS ALGORITHM πΈ
The RSA-PSS algorithm is like RSA but on a restricted diet β it's a restricted version of the RSA algorithm which only supports the sign and verify operations with PSS padding. The following additional -pkeyopt values are supported:
rsa_padding_mode:mode,rsa_pss_saltlen:len,rsa_mgf1_md:digestβ these have the same meaning as the RSA algorithm, with some additional restrictions. The padding mode can only be set topss, which is the default value.
If the key has parameter restrictions, then the digest, MGF1 digest and salt length are set to the values specified in the parameters. The digest and MGF1 digest cannot be changed, and the salt length cannot be set to a value less than the minimum restriction. π no wiggle room, it's giving locked-in.
π¦ DSA ALGORITHM π¦
The DSA algorithm supports signing and verification operations only. Currently there are no additional -pkeyopt options other than digest. The SHA256 digest is assumed by default. simple, clean, minimal β honestly iconic π
π DH ALGORITHM π
The DH algorithm only supports the derivation operation and has no additional -pkeyopt options. That's it. That's the whole section. short king π«Ά
β EC ALGORITHM β
The EC algorithm supports sign, verify and derive operations. The sign and verify operations use ECDSA, and derive uses ECDH. SHA256 is assumed by default for the -pkeyopt digest option. cute, consistent, we love her π
π X25519 AND X448 ALGORITHMS π
The X25519 and X448 algorithms support key derivation only. Currently there are no additional options. β¨
π§ SLH-DSA ALGORITHMS π§
The SLH-DSA algorithms (SLH-DSA-SHA2-128s, SLH-DSA-SHA2-128f, SLH-DSA-SHA2-192s, SLH-DSA-SHA2-192f, SLH-DSA-SHA2-256s, SLH-DSA-SHA2-256f) are post-quantum signature algorithms π queen behaviour, honestly. When using SLH-DSA with pkeyutl, the following options are available:
-signβ sign the input data using an SLH-DSA private key. For example:
$ openssl pkeyutl -sign -in file.txt -inkey slhdsa.pem -out sig
-verifyβ verify the signature using an SLH-DSA public key. For example:
$ openssl pkeyutl -verify -in file.txt -inkey slhdsa.pem -sigfile sig
See EVP_PKEY-SLH-DSA(7) and EVP_SIGNATURE-SLH-DSA(7) for additional details about the SLH-DSA algorithm and its implementation. π¦
π ML-DSA-44, ML-DSA-65 AND ML-DSA-87 ALGORITHMS π
The ML-DSA algorithms are post-quantum signature algorithms that support signing and verification of "raw" messages. No preliminary hashing is performed β none, zero, nada. When using ML-DSA with pkeyutl, the following options are available:
-signβ sign the input data using an ML-DSA private key. For example:
$ openssl pkeyutl -sign -in file.txt -inkey mldsa65.pem -out sig
-verifyβ verify the signature using an ML-DSA public key. For example:
$ openssl pkeyutl -verify -in file.txt -inkey mldsa65.pem -sigfile sig
-pkeyopt opt:valueβ additional options for ML-DSA signing and verification:
message-encoding:value
Specifies the message encoding mode used for signing. This controls how the input message is processed before signing. Valid values are described in EVP_SIGNATURE-ML-DSA(7). For example:
$ openssl pkeyutl -sign -in file.txt -inkey mldsa65.pem -out sig -pkeyopt message-encoding:1
test-entropy:value
Specifies a test entropy value for deterministic signing. For example:
$ openssl pkeyutl -sign -in file.txt -inkey mldsa65.pem -out sig -pkeyopt test-entropy:abcdefghijklmnopqrstuvwxyz012345
hextest-entropy:value
Specifies a test entropy value in hex format. For example:
$ openssl pkeyutl -sign -in file.txt -inkey mldsa65.pem -out sig -pkeyopt hextest-entropy:000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
deterministic:value
Enables deterministic signing. For example:
$ openssl pkeyutl -sign -in file.txt -inkey mldsa65.pem -out sig -pkeyopt deterministic:1
mu:value
Specifies the mu parameter. For example:
$ echo -n "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" >file.txt
$ openssl pkeyutl -sign -in file.txt -inkey mldsa65.pem -out sig -pkeyopt mu:1
context-string:stringβ specifies a context string for both signing and verification operations. The context string must be the same for verification to succeed, fr fr β mismatch and it's over π For example:
$ openssl pkeyutl -sign -in file.txt -inkey mldsa65.pem -out sig -pkeyopt context-string:mycontext
$ openssl pkeyutl -verify -in file.txt -inkey mldsa65.pem -sigfile sig -pkeyopt context-string:mycontext
hexcontext-string:stringβ specifies a context string in hex format, allowing binary control values. For example:
$ openssl pkeyutl -sign -in file.txt -inkey mldsa65.pem -out sig -pkeyopt hexcontext-string:6d79636f6e74657874
The signing operation supports a deterministic:bool option, with bool set to 1 if a deterministic signature is to be generated with a fixed all zero random input. By default, or if the bool is 0, a random entropy value is used. A deterministic result can also be obtained by specifying an explicit entropy value via the hextest-entropy:value parameter.
π¨ Deterministic ML-DSA signing should only be used in tests. seriously bestie, tests only. π
See EVP_SIGNATURE-ML-DSA(7) for additional details about the ML-DSA algorithms and their implementation. π
π ML-KEM-512, ML-KEM-768 AND ML-KEM-1024 ALGORITHMS π
The ML-KEM algorithms support encapsulation and decapsulation only. The encapsulation operation supports a hexikme:entropy option, with entropy the 64 hexadecimal digit encoding of a 32-byte value.
π¨ This should only be used in tests β known or leaked values of the option may compromise the generated shared secret. do not do this in prod, I'm begging π
See EVP_KEM-ML-KEM(7) for additional detail.
π ED25519 AND ED448 ALGORITHMS π
These algorithms only support signing and verifying. OpenSSL only implements the "pure" variants of these algorithms, so raw data can be passed directly to them without hashing them first β no preprocessing, we go straight in π₯
OpenSSL only supports "oneshot" operation with these algorithms. This means the entire file to be signed/verified must be read into memory before processing it. Signing or verifying very large files should be avoided. Additionally, the size of the file must be known for this to work. If the size of the file cannot be determined (for example if the input is stdin), then the sign or verify operation will fail. π so likeβ¦ no piping, bestie. know your file size or perish.
πΈ SM2 πΈ
okay so SM2 is that girl β she does it all: sign, verify, encrypt and decrypt. full main-character energy, no notes π
but bestie, for sign and verify she's a little picky: you must pass in a Distinguishing ID string. no ID, no signature. here are the -pkeyopt values she accepts:
distid:stringβ sets the ID string used for SM2 sign/verify. and listen π«Ά while you're verifying an SM2 signature, the ID string has to be the exact same one you used when you signed the data. if it's not, verification just fails, periodt. πhexdistid:hex_stringβ same deal, same rule (matching ID or verification fails, no cap), except this one takes the ID string as a valid hexadecimal value. hex girls stay winning π
β¨ EXAMPLES β¨
sign some data using a private key:
openssl pkeyutl -sign -in file -inkey key.pem -out sig
recover the signed data (e.g. if an RSA key is used):
openssl pkeyutl -verifyrecover -in sig -inkey key.pem
verify the signature (e.g. a DSA key):
openssl pkeyutl -verify -in file -sigfile sig -inkey key.pem
sign data using a message digest value (this is currently only valid for RSA, fyi):
openssl pkeyutl -sign -in file -inkey key.pem -out sig -pkeyopt digest:sha256
derive a shared secret value:
openssl pkeyutl -derive -inkey key.pem -peerkey pubkey.pem -out secret
hexdump 48 bytes of TLS1 PRF using digest SHA256 and shared secret and seed consisting of the single byte 0xFF:
openssl pkeyutl -kdf TLS1-PRF -kdflen 48 -pkeyopt md:SHA256 \
-pkeyopt hexsecret:ff -pkeyopt hexseed:ff -hexdump
derive a key using scrypt where the password is read from command line:
openssl pkeyutl -kdf scrypt -kdflen 16 -pkeyopt_passin pass \
-pkeyopt hexsalt:aabbcc -pkeyopt N:16384 -pkeyopt r:8 -pkeyopt p:1
derive using the same algorithm, but read key from environment variable MYPASS:
openssl pkeyutl -kdf scrypt -kdflen 16 -pkeyopt_passin pass:env:MYPASS \
-pkeyopt hexsalt:aabbcc -pkeyopt N:16384 -pkeyopt r:8 -pkeyopt p:1
sign some data using an SM2(7) private key and a specific ID:
openssl pkeyutl -sign -in file -inkey sm2.key -out sig -rawin -digest sm3 \
-pkeyopt distid:someid
verify some data using an SM2(7) certificate and a specific ID:
openssl pkeyutl -verify -certin -in file -inkey sm2.cert -sigfile sig \
-rawin -digest sm3 -pkeyopt distid:someid
decrypt some data using a private key with OAEP padding using SHA256:
openssl pkeyutl -decrypt -in file -inkey key.pem -out secret \
-pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha256
create an ML-DSA key pair and sign data with a specific context string:
$ openssl genpkey -algorithm ML-DSA-65 -out mldsa65.pem
$ openssl pkeyutl -sign -in file.txt -inkey mldsa65.pem -out sig -pkeyopt context-string:example
verify a signature using ML-DSA with the same context string:
$ openssl pkeyutl -verify -in file.txt -inkey mldsa65.pem -sigfile sig -pkeyopt context-string:example
generate an ML-KEM key pair and use it for encapsulation:
$ openssl genpkey -algorithm ML-KEM-768 -out mlkem768.pem
$ openssl pkey -in mlkem768.pem -pubout -out mlkem768_pub.pem
$ openssl pkeyutl -encap -inkey mlkem768_pub.pem -pubin -out ciphertext -secret shared_secret.bin
decapsulate a shared secret using an ML-KEM private key:
$ openssl pkeyutl -decap -inkey mlkem768.pem -in ciphertext -secret decapsulated_secret.bin
create an SLH-DSA key pair and sign data:
$ openssl genpkey -algorithm SLH-DSA-SHA2-128s -out slh-dsa.pem
$ openssl pkeyutl -sign -in file.txt -inkey slh-dsa.pem -out sig
verify a signature using SLH-DSA:
$ openssl pkeyutl -verify -in file.txt -inkey slh-dsa.pem -sigfile sig
π¦ SEE ALSO π¦
the friend group you should also go follow, fr fr:
openssl(1)openssl-genpkey(1)openssl-pkey(1)openssl-rsautl(1)openssl-dgst(1)openssl-rsa(1)openssl-genrsa(1)openssl-kdf(1)EVP_PKEY_CTX_set_hkdf_md(3)EVP_PKEY_CTX_set_tls1_prf_md(3),
(yes that trailing comma is canon, don't come for me π)
π HISTORY π
okay lore drop, gather round π§
- since OpenSSL 3.5, the
-digestoption implies-rawin, and those two options are no longer required when you're signing or verifying with anEd25519orEd448key. streamlining era π - also since OpenSSL 3.5, the
-kemopoption is no longer required for any of the supported algorithms β the only supported mode is now the default. she simplified her life, we love that. - the
-engineoption was deprecated in OpenSSL 3.0. rip bozo, it's giving legacy π
π COPYRIGHT π
Copyright 2006-2026 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy in the file LICENSE in the source distribution or at <https://www.openssl.org/source/license.html>.
aaaand that's the whole page bestie, you made it to the end π«Άβ¨ this gorgeous thing is from version 3.5.6, dated 2026-04-07 β go forth and pkeyutl responsibly, mwah ππΈ
π¦ where this page comes from
- freebsd 15.1: base 15.1
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms