On this page:
pk-spec?
pk-impl?
get-pk
pk-can-sign?
pk-can-encrypt?
pk-can-key-agree?
pk-has-parameters?
5.1 PK Keys and Parameters
pk-key?
private-key?
public-only-key?
pk-parameters?
pk-key->parameters
pk-security-strength
public-key=?
pk-key->public-only-key
generate-pk-parameters
generate-private-key
5.2 PK Signatures
pk-sign
pk-verify
digest/  sign
digest/  verify
pk-sign-digest
pk-verify-digest
5.3 PK Encryption
pk-encrypt
pk-decrypt
5.4 PK Key Agreement
pk-derive-secret
5.5 PK External Representations
pk-key->datum
datum->pk-key
pk-parameters->datum
datum->pk-parameters
5.6 PKCS #8 Encrypted Private Keys
pkcs8-encrypt/  pbkdf2-hmac
pkcs8-encrypt/  scrypt
pkcs8-decrypt-bytes
pkcs8-decrypt-key
Bibliography

5 Public-Key Cryptography🔗ℹ

Public-key (PK) cryptography covers operations such as signing, encryption, and key agreement between parties that do not start with any shared secrets. Instead of shared secrets, each party possesses a keypair consisting of a secret private key and a non-secret public key. Not all PK cryptosystems support all PK operations (for example, DSA only supports signing, not encryption or key agreement), and some PK implementations may support a subset of a PK cryptosystem’s potential operations.

procedure

(pk-spec? v)  boolean?

  v : any/c
Returns #t if v is a PK cryptosystem specifier, #f otherwise.

A PK cryptosystem specifies the information represented by the public and private keys and the algorithms that operate on that information. The following PK systems are supported:

  • 'rsa RSA keys with RSAES-* encryption and RSASSA-* signing [PKCS1].

  • 'dsa DSA keys with DSA signing [FIPS186-4].

  • 'dh Diffie-Hellman key agreement using modular integer exponentiation [RFC2631, SP800-56A].

  • 'ec Elliptic curve keys with ECDSA signing and ECDH key agreement [SEC1, FIPS186-5, SP800-56A]. Only named curves are supported, and different implementations support different sets of curves.

  • 'eddsa Specialized elliptic curve keys with EdDSA signing, specifically Ed25519 and Ed448 [RFC8032, FIPS186-5]. Not compatible with 'ec keys and operations.

  • 'ecx Specialized elliptic curve keys with ECDH key agreement, specifically X25519 and X448 [RFC7748]. Not compatible with 'ec keys and operations.

Use factory-print-info to see supported systems and named elliptic curves.

Changed in version 1.1 of package crypto-lib: Added 'eddsa and 'ecx.

procedure

(pk-impl? v)  boolean?

  v : any/c
Returns #t if v is a PK cryptosystem implementation, #f otherwise.

procedure

(get-pk pki factories)  (or/c pk-impl? #f)

  pki : pk-spec?
  factories : (or/c crypto-factory? (listof crypto-factory?))
Returns an implementation of PK system pki from the given factories, or #f if no factory in factories implements pki.

procedure

(pk-can-sign? pk)  boolean?

  pk : (or/c pk-impl? pk-key?)

procedure

(pk-can-encrypt? pk)  boolean?

  pk : (or/c pk-impl? pk-key?)

procedure

(pk-can-key-agree? pk)  boolean?

  pk : (or/c pk-impl? pk-key?)
Indicates whether the cryptosystem implementation pk (or the implementation corresponding to pk, if pk is a key) supports signing, encryption, and key agreement, respectively.

Note that the functions only report the capabilities of the cryptosystem implementation, regardless of the limitations of pk if pk is a key. For example, (pk-can-sign? pk) would return true when pk is an RSA public-only key, even though signing requires a private key.

procedure

(pk-has-parameters? pk)  boolean?

  pk : (or/c pk-impl? pk-key?)
Returns #f if the PK cryptosystem represented by pk uses key parameters, #f otherwise. See PK Keys and Parameters for more information.

5.1 PK Keys and Parameters🔗ℹ

A PK keypair consists of public key component and private key components. A public key is a key that contains the public key components. In this library, a private key contains both private and public components, so it can also be used wherever a public key is required. That is, every private key is also a public key. This library uses the term “public-only key” to refer to a public key that is not a private key.

In some PK cryptosystems, the public components are further divided into key-specific values and shared “parameters.” For example, elliptic curve (EC) keys only interoperate if they use the “curve” (comprising a modulus, a polynomial equation, and a generator point). That is, EC keys have one parameter, the curve, in addition to the key-specific public value, a point on that curve. Keys only interoperate if they have the same parameter values. The following key types have parameters: 'dsa, 'dh, 'ec, 'eddsa, and 'ecx. The 'rsa system does not; the bit-length of an RSA public modulus is not a parameter.

procedure

(pk-key? v)  boolean?

  v : any/c
Returns #t if v is a public key or a private key, #f otherwise. Since all PK keys contain the public key components, pk-key? is a predicate for public keys.

procedure

(private-key? v)  boolean?

  v : any/c
Returns #t if v is a private key.

procedure

(public-only-key? v)  boolean?

  v : any/c
Returns #t if v is a public key but not a private key, #f otherwise.

Equivalent to (and (pk-key? v) (not (private-key? v))).

procedure

(pk-parameters? v)  boolean?

  v : any/c
Returns #t if v is a value representing PK key parameters for some cryptosystem, #f otherwise.

procedure

(pk-key->parameters pk)  (or/c pk-parameters? #f)

  pk : pk-key?
Returns a value representing the key parameters of pk, or #f if pk’s cryptosystem does not use key parameters.

procedure

(pk-security-strength pk)  (or/c #f security-strength/c)

  pk : (or/c pk-key? pk-parameters?)
Returns the security strength rating for the given PK key or parameters. If pk does not support strength calculation, #f is returned.

Added in version 1.8 of package crypto-lib.

procedure

(public-key=? pk1 pk2 ...)  boolean?

  pk1 : pk-key?
  pk2 : pk-key?
Returns #t if the public key components of pk1 and pk2 are equal, #f otherwise. One use of this function is to check whether a private key matches some public-only key.

procedure

(pk-key->public-only-key pk)  public-only-key?

  pk : pk-key?
Returns a public-only key pub-pk such that (public-key=? pk pub-pk). If pk is already a public-only key, the function may simply return pk.

procedure

(generate-pk-parameters pki    
  [paramgen-config])  pk-parameters?
  pki : (or/c pk-spec? pk-impl?)
  paramgen-config : (listof (list/c symbol? any/c)) = '()
Generate PK parameter values for the cryptosystem of pki using the given configuration options. The default values of optional configuration arguments are implementation-dependent.

The acceptable configuration values depend on pki.
  • The following configuration values are recognized for DSA ('dsa):
    • (list 'nbits nbits) Optional. Generate a prime modulus of size nbits. Examples include 1024 and 2048.

  • The following configuration values are recognized for DH ('dh):
    • (list 'nbits nbits) Optional. Generate a prime modulus of size nbits. Examples include 1024 and 2048.

    • (list 'generator generator) Optional. Use the given generator; must be either 2 or 5.

  • The following configuration values are recognized for EC ('ec):
    • (list 'curve curve-name) Required. Use the standard curve named curve-name, which must be a symbol or string. Examples include "NIST P-256" and 'secp192r1. Use factory-print-info to show available curves. (No additional values are generated; the result is a parameters object representing the curve.)

  • The following configuration values are recognized for EdDSA ('eddsa):
    • (list 'curve curve-sym) Required. Generate a key for the given curve. The curve-sym must be 'ed25519 or 'ed448. (No additional values are generated; the result is a parameters object representing the curve.)

  • The following configuration values are recognized for 'ecx:
    • (list 'curve curve-sym) Required. Generate a key for the given curve. The curve-sym must be 'x25519 or 'x448. (No additional values are generated; the result is a parameters object representing the curve.)

Changed in version 1.1 of package crypto-lib: Added 'eddsa and 'ecx options.

procedure

(generate-private-key pki [keygen-config])  private-key?

  pki : (or/c pk-spec? pk-impl? pk-parameters?)
  keygen-config : (listof (list/c symbol? any/c)) = '()
Generate a private key from the given PK implementation or PK parameters. The default values of optional configuration arguments are implementation dependent.

The accepted configuration arguments depend on pki:
  • If pki is a PK parameters object (pk-parameters?), then keygen-config must be empty.

  • The following configuration values are recognized for RSA ('rsa):
    • (list 'nbits nbits) Optional. Generate a modulus of size nbits. A typical value for nbits is 2048.

  • If pki is a PK specifier (pk-spec?) or PK implementation (pk-impl?), then the same configuration arguments are supported as for generate-pk-parameters. This is equivalent to (generate-private-key (generate-pk-parameters pki keygen-config) '()).

5.2 PK Signatures🔗ℹ

In PK signing, the sender uses their own private key to sign a message, and any other party can verify the sender’s signature using the sender’s public key.

With RSA, DSA, and ECDSA, only short messages can be signed directly (limits are generally proportional to the size of the keys), so a typical process is to compute a digest of the message and sign the digest. The message and digest signature are sent together, possibly with additional data.

With EdDSA, messages are signed directly. (The signing process computes a message digest internally.)

procedure

(pk-sign pk msg [#:pad padding #:digest dspec])  bytes?

  pk : private-key?
  msg : bytes?
  padding : (or/c #f 'pkcs1-v1.5 'pss 'pss*) = #f
  dspec : (or/c digest-spec? 'none #f) = #f
Returns the signature using the private key pk of the message msg.

If pk is an RSA private key, then padding must be one of the following:
  • 'pkcs1-v1.5 or #f use PKCS#1-v1.5 padding

  • 'pss use PSS padding with a salt length equal to (digest-size dspec)

  • 'pss* sign using PSS padding with a salt length equal to (digest-size dspec), but infer the salt length when verifying

For all other cryptosystems, padding must be #f.

If pk is an RSA private key, then dspec must be the name of a digest algorithm, and msg should be a digest computed with dspec (in particular, the length of msg must be the output size of dspec). The resulting signature depends on the identity of the digest algorithm. Different RSA implementations may support different digest algorithms.

If pk is a DSA or EC private key, the signature does not depend on the digest algorithm; the dspec should be omitted. (For backwards compatibility, the dspec argument is accepted, but it has no effect other than checking the length of msg.)

If pk is a EdDSA private key, then dspec must be #f or 'none (both values mean the same thing). The message may be of any length, and the EdDSA signature is computed. Future versions of this library may accept other values of dspec and compute HashEdDSA signatures (eg, Ed25519ph) in reponse.

Added in version 1.1 of package crypto-lib.

procedure

(pk-verify pk    
  msg    
  sig    
  [#:digest dspec    
  #:pad padding])  boolean?
  pk : pk-key?
  msg : bytes?
  sig : bytes?
  dspec : (or/c digest-spec? #f 'none) = #f
  padding : (or/c #f 'pkcs1-v1.5 'pss) = #f
Returns #t if pk verifies that sig is a valid signature of the message msg, or #f if the signature is invalid.

The dspec and padding arguments have the same meanings as for pk-sign.

Added in version 1.1 of package crypto-lib.

procedure

(digest/sign pk di input [#:pad padding])  bytes?

  pk : private-key?
  di : (or/c digest-spec? digest-impl?)
  input : input/c
  padding : (or/c #f 'pkcs1-v1.5 'pss) = #f

procedure

(digest/verify pk di input sig [#:pad padding])  boolean?

  pk : pk-key?
  di : (or/c digest-spec? digest-impl?)
  input : input/c
  sig : bytes?
  padding : (or/c #f 'pkcs1-v1.5 'pss) = #f
Computes or verifies signature of the di message digest of input; equivalent to calling digest then pk-sign-digest or pk-verify-digest, respectively.

Do not use these functions with EdDSA keys; use pk-sign and pk-verify directly on the messages. (This library currently does not support pre-hashing EdDSA variants, eg Ed25519ph.)

procedure

(pk-sign-digest pk di dgst [#:pad padding])  bytes?

  pk : private-key?
  di : (or/c digest-spec? digest-impl?)
  dgst : bytes?
  padding : (or/c #f 'pkcs1-v1.5 'pss 'pss*) = #f

procedure

(pk-verify-digest pk    
  di    
  dgst    
  sig    
  [#:pad padding])  boolean?
  pk : pk-key?
  di : (or/c digest-spec? digest-impl?)
  dgst : bytes?
  sig : bytes?
  padding : (or/c #f 'pkcs1-v1.5 'pss) = #f
Equivalent to (pk-sign pk dgst #:digest di #:pad padding) and (pk-verify pk dgst sig #:digest di #:pad padding), respectively.

5.3 PK Encryption🔗ℹ

In PK encryption, the sender uses the public key of the intended receiver to encrypt a message; the receiver decrypts the message with the receiver’s own private key. Only short messages can be directly encrypted using PK cryptosystems (limits are generally proportional to the size of the PK keys), so a typical approach is to encrypt the message using a symmetric cipher with a randomly-generated key (sometimes called the bulk encryption key) and encrypt that key using PK cryptography. The symmetric-key-encrypted message and PK-encrypted symmetric key are sent together, perhaps with additional data such as a MAC. PK encryption is supported by the RSA cryptosystem.

procedure

(pk-encrypt pk msg [#:pad padding])  bytes?

  pk : pk-key?
  msg : bytes?
  padding : (or/c #f 'pkcs1-v1.5 'oaep) = #f

procedure

(pk-decrypt pk msg [#:pad padding])  bytes?

  pk : private-key?
  msg : bytes?
  padding : (or/c #f 'pkcs1-v1.5 'oaep) = #f
Encrypt or decrypt, respectively, the message msg using PK key pk.

If pk is an RSA key, then padding choses between PKCS#1-v1.5 padding and OAEP padding [PKCS1]. If padding is #f, then an implementation-dependent mode is chosen. For all other cryptosystems, padding must be #f.

If msg is too large to encrypt using pk, then an exception is raised.

5.4 PK Key Agreement🔗ℹ

In PK key agreement (sometimes called key exchange or Diffie-Hellman) two parties derive a shared secret by exchanging public keys. Each party can compute the secret from their own private key and the other’s public key, but it is believed infeasible for an observer to compute the secret from the two public keys alone. PK secret derivation is supported by the 'dh, 'ec, and 'ecx cryptosystems.

procedure

(pk-derive-secret pk peer-pk)  bytes?

  pk : private-key?
  peer-pk : (or/c pk-key? bytes?)
Returns the shared secret derived from the private key pk and the public key peer-pk. If peer-pk is a PK key, it must be a key compatible with pk (same algorithm and same parameters); otherwise an exception is raised. If peer-pk is a bytestring, an exception is raised if it cannot be interpreted as raw public key data.

Note that the derived secret is a deterministic function of the private keys: if two parties perform secret derivation twice, they will produce the same secret both times. In addition, the secret is not uniformly distributed. For these reasons, the derived secret should not be used directly as a key; instead, it should be used to generate key material using a key-derivation function (see kdf).

5.5 PK External Representations🔗ℹ

This section describes serialization of public and private keys in various formats. See also PKCS #8 Encrypted Private Keys.

procedure

(pk-key->datum pk fmt)  printable/c

  pk : pk-key?
  fmt : symbol?
Returns a datum representing the key pk, where the encoding is selected by fmt. Unless noted below, the result is a bytestring (bytes?). The following fmt options are supported:

  • 'SubjectPublicKeyInfo DER-encoded SubjectPublicKeyInfo [PKIX] representation of the public part of pk. All key types are supported, and an identifier for the key type is embedded in the encoding [PKIX-AlgId, PKIX-EdC].

  • 'PrivateKeyInfo DER-encoded PrivateKeyInfo [PKCS8] or OneAsymmetricKey [AKP] representation of pk, which must be a private key. All key types are supported, and an identifier for the key type is embedded in the encoding.

    OneAsymmetricKey is essentially PrivateKeyInfo v2; it adds an optional field for the public key. The OneAsymmetricKey (v2) format is automatically used when necessary; otherwise, the PrivateKeyInfo (v1) format is used when the private key format already includes the public components.

  • 'OneAsymmetricKey Alias for 'PrivateKeyInfo.

  • 'RSAPrivateKey DER-encoded RSAPrivateKey [PKCS1] representation of pk, which must be an RSA private key.

  • 'age/v1-private String encoded in the age-encryption (v1) format, representing an X25519 private key. The string is Bech32-encoded and has 74 characters beginning with AGE-SECRET-KEY-1.

  • 'age/v1-public String encoded in the age-encryption (v1) format, representing an X25519 public key. The string is Bech32-encoded and has 62 characters beginning with age1.

  • 'openssh-public A string containing an OpenSSH-format public key. The string starts with a tag such as ssh-rsa or ssh-ed25519, then contains the key data encoded in Base64. Only RSA, Ed25519, and Ed448 public keys are currently supported.

  • 'rkt-private An S-expression of one of the following forms:

    • (list 'rsa 'private 0 n e d p q dp dq qInv)

    • (list 'dsa 'private p q g y d)

    • (list 'dh 'private p g q j seed pgen y x)

    • (list 'dh 'private p g y x)

    • (list 'ec 'private curve-oid q-bytes d)

    • (list 'eddsa 'private curve-sym q-bytes d-bytes)

    • (list 'ecx 'private curve-sym q-bytes d-bytes)

  • 'rkt-public An S-expression of one of the following forms:

    • (list 'rsa 'public n e)

    • (list 'dsa 'public p q g y)

    • (list 'dh 'private p g q j seed pgen y)

    • (list 'dh 'public p g y)

    • (list 'ec 'public curve-oid q-bytes)

    • (list 'eddsa 'public curve-sym q-bytes)

    • (list 'ecx 'public curve-sym q-bytes)

More formats may be added in future versions of this library.

Changed in version 1.1 of package crypto-lib: Added 'OneAsymmetricKey, 'rkt-private, and 'rkt-public formats.
Changed in version 1.9: Added 'age/v1-public, 'age/v1-private, and 'openssh-public formats.
Changed in version 2.0: Added the longer DH variants of 'rkt-public and 'rkt-private encodings.
Changed in version 2.0: Previously, SubjectPublicKeyInfo encoding of DH keys used the PKCS #3 identifier and parameters [PKCS3] for compatibility with old versions of OpenSSL.

procedure

(datum->pk-key datum fmt [sources])  pk-key?

  datum : any/c
  fmt : symbol?
  sources : 
(or/c pk-impl? crypto-factory?
      (listof (or/c pk-impl? crypto-factory?)))
   = (crypto-factories)
Parses datum and returns a PK key associated with an implementation from sources. If no implementation in sources supports the decoded key, an exception is raised.

See pk-key->datum for information about the fmt argument.

Changed in version 2.0 of package crypto-lib: Generalized sources argument from factories to allow PK implementations also.

procedure

(pk-parameters->datum pkp fmt)  printable/c

  pkp : pk-parameters?
  fmt : symbol?
Returns a datum representing the PK parameters pkp, where the encoding is selected by fmt. Unless noted below, the result is a bytestring (bytes?). The following fmt options are supported:

  • 'AlgorithmIdentifier DER-encoded AlgorithmIdentifier [PKIX] representation of pkp. All key parameter types are supported, and an identifier for the key parameter type is embedded in the encoding.

  • 'DSAParameters DER-encoded Dss-Parms [PKIX-AlgId] for DSA parameters.

  • 'DomainParameters DER-encoded DomainParameters [PKIX-AlgId] for DH parameters.

  • 'DHParameter DER-encoded DHParameter [PKCS3] for DH parameters. (This format contains insufficient information for parameter validation.)

  • 'EcpkParameters DER-encoded EcpkParameters [PKIX-AlgId] (called ECDomainParameters in [SEC1]) for EC parameters.

  • 'rkt-params An S-expression of one of the following forms:

    • (list 'dsa 'params p q g)

    • (list 'dh 'params p g q j seed pgen)

    • (list 'dh 'params p g)

    • (list 'ec 'params curve-oid)

    • (list 'eddsa 'params curve-sym)

    • (list 'ecx 'params curve-sym)

More formats may be added in future versions of this library.

Changed in version 1.1 of package crypto-lib: Added 'rkt-params support.
Changed in version 2.0: Added the longer DH variants of the 'rkt-params encoding.
Changed in version 2.0: Previously, AlgorithmIdentifier encoding of DH keys used the PKCS #3 identifier and parameters [PKCS3] for compatibility with old versions of OpenSSL.

procedure

(datum->pk-parameters datum fmt [sources])  pk-parameters?

  datum : any/c
  fmt : symbol?
  sources : 
(or/c pk-impl? crypto-factory?
      (listof (or/c pk-impl? crypto-factory?)))
   = (crypto-factories)
Parses datum and returns a PK parameters value associated with an implementation in sources. If no implementation is found that supports the decoded parameters, an exception is raised.

5.6 PKCS #8 Encrypted Private Keys🔗ℹ

Added in version 1.5 of package crypto-lib.

procedure

(pkcs8-encrypt/pbkdf2-hmac password    
  pk    
  [#:digest digest-spec    
  #:iterations iterations    
  #:cipher cipher-spec    
  #:key-size key-size])  bytes?
  password : bytes?
  pk : (or/c private-key? bytes?)
  digest-spec : digest-spec? = 'sha512
  iterations : exact-positive-integer? = (expt 2 16)
  cipher-spec : cipher-spec? = '(aes cbc)
  key-size : exact-positive-integer?
   = (cipher-default-key-size cipher-spec)

procedure

(pkcs8-encrypt/scrypt password    
  pk    
  [#:N N    
  #:r r    
  #:p p    
  #:cipher cipher-spec    
  #:key-size key-size])  bytes?
  password : bytes?
  pk : (or/c private-key? bytes?)
  N : exact-positive-integer? = (expt 2 14)
  r : exact-positive-integer? = 8
  p : exact-positive-integer? = 1
  cipher-spec : cipher-spec? = '(aes cbc)
  key-size : exact-positive-integer?
   = (cipher-default-key-size cipher-spec)
Produce a DER-encoded EncryptedPrivateKeyInfo [PKCS8] containing the private key pk encrypted with a key derived from password. If pk is a private key object (private-key?), it is converted to a byte string using OneAsymmetricKey format. If pk is a byte string, it should be a OneAsymmetricKey or PrivateKeyInfo encoding, but the structure of the byte string is not inspected.

See pbkdf2-hmac for the meaning of the iterations argument, and see scrypt for the meanings of the N, r, and p arguments.

The following values of cipher-spec are currently supported: '(aes cbc), '(des-ede3 cbc), '(aes gcm), and '(chacha20-poly1305 stream).

The following values of digest-spec are currently supported: 'sha1, 'sha224, 'sha256, 'sha384, and 'sha512.

Compatibility with OpenSSL 1.1.0 has been tested with '(aes cbc) and '(des-ede3 cbc).

procedure

(pkcs8-decrypt-bytes password p8-epki)  bytes?

  password : bytes?
  p8-epki : bytes?
Decrypts the DER-encoded EncryptedPrivateKeyInfo p8-epki using password and returns the unencrypted private key as a byte string. The structure of the decrypted byte string is not inspected.

If the wrong password is given, then an exception will probably be raised, but for non-AEAD ciphers (such as AES-CBC), there is a possibility that the decryption will succeed and return nonsense.

procedure

(pkcs8-decrypt-key password p8-epki)  private-key?

  password : bytes?
  p8-epki : bytes?
Decrypts the DER-encodedEncryptedPrivateKeyInfo p8-epki using password and parses the unencrypted private key as OneAsymmetricKey.

Equivalent to the following:

(datum->pk-key (pkcs8-decrypt-bytes password p8-epki) 'OneAsymmetricKey)

Bibliography🔗ℹ

[AKP] “RFC 5958: Asymmetric Key Packages.” https://tools.ietf.org/html/rfc5958
[FIPS186-4] “Digital Signature Standard.” https://csrc.nist.gov/pubs/fips/186-4/final
[FIPS186-5] “Digital Signature Standard.” https://csrc.nist.gov/pubs/fips/186-5/final
[PKCS1] “PKCS #1: RSA Cryptography, version 2.2.” https://tools.ietf.org/html/rfc8017
[PKCS3] “PKCS #3: Diffie-Hellman Key-Agreement Standard.”
[PKCS8] “PKCS #8: Private-Key Information Syntax Specification, version 1.2.” https://tools.ietf.org/html/rfc5208
[PKIX] “RFC 5280: Internet X.509 Public Key Infrastructure: Certificate and CRL Profile.” https://tools.ietf.org/html/rfc5280
[PKIX-AlgId] “RFC 3279: Algorithms and Identifiers for the Internet X.509 Public Key Infrastructure Certificate and Certificate Revocation List (CRL) Profile.” https://tools.ietf.org/html/rfc3279
[PKIX-EdC] “RFC 8410: Algorithm Identifiers for Ed25519, Ed448, X25519 and X448 for use in the Internet X.509 Public Key Infrastructure.” https://tools.ietf.org/html/rfc8410
[RFC2631] “RFC 2631: Diffie-Hellman Key Agreement Method.” https://tools.ietf.org/html/rfc2631
[RFC7468] “Textual Encodings of PKIX, PKCS, and CMS Structures.” https://tools.ietf.org/html/rfc7468
[RFC7748] “Elliptic Curves for Security.” https://tools.ietf.org/html/rfc7748
[RFC8032] “Edwards-Curve Digital Signature Algorithm (EdDSA).” https://tools.ietf.org/html/rfc8032
[SEC1] “SEC 1: Elliptic Curve Cryptography.” http://www.secg.org/sec1-v2.pdf