Erlang -- public_key

User's Guide
Reference Manual
Release Notes
PDF
Top

public_key
Reference Manual
Version 1.0

Expand All
Contract All

Table of Contents

- public_key
  - Top of manual page
  - compute_key/2
  - compute_key/3
  - decrypt_private/2
  - decrypt_private/3
  - decrypt_public/2
  - decrypt_public/3
  - der_decode/2
  - der_encode/2
  - encrypt_private/2
  - encrypt_public/2
  - generate_key/1
  - pem_decode/1
  - pem_encode/1
  - pem_entry_decode/1
  - pem_entry_decode/2
  - pem_entry_encode/2
  - pem_entry_encode/3
  - pkix_decode_cert/2
  - pkix_encode/3
  - pkix_is_issuer/2
  - pkix_is_fixed_dh_cert/1
  - pkix_is_self_signed/1
  - pkix_issuer_id/2
  - pkix_normalize_name/1
  - pkix_path_validation/3
  - pkix_crl_issuer/1
  - pkix_crls_validate/3
  - pkix_crl_verify/2
  - pkix_dist_point/1
  - pkix_dist_points/1
  - pkix_sign/2
  - pkix_sign_types/1
  - pkix_verify/2
  - sign/3
  - ssh_decode/2
  - ssh_encode/2
  - verify/4

# public_key

### MODULE

public_key

### MODULE SUMMARY

API module for public-key infrastructure.

### DESCRIPTION

This module provides functions to handle public-key infrastructure. It can encode/decode different file formats (PEM, OpenSSH), sign and verify digital signatures, and validate certificate paths and certificate revocation lists.

### public_key

- Public Key requires the Crypto and ASN1 applications, the latter as OTP R16 (hopefully the runtime dependency on ASN1 will be removed again in the future).
- Supports RFC 5280 - Internet X.509 Public-Key Infrastructure Certificate and Certificate Revocation List (CRL) Profile
- Supports PKCS-1 - RSA Cryptography Standard
- Supports DSS - Digital Signature Standard (DSA - Digital Signature Algorithm)
- Supports PKCS-3 - Diffie-Hellman Key Agreement Standard
- Supports PKCS-5 - Password-Based Cryptography Standard
- Supports PKCS-8 - Private-Key Information Syntax Standard
- Supports PKCS-10 - Certification Request Syntax Standard

### DATA TYPES

Note

All records used in this Reference Manual are generated from ASN.1 specifications and are documented in the User's Guide. See Public-key Records.

Use the following include directive to get access to the records and constant macros described here and in the User's Guide:

     -include_lib("public_key/include/public_key.hrl").

The following data types are used in the functions for public_key:

oid()

  Object identifier, a tuple of integers as generated by the ASN.1 compiler.

boolean() =

  true | false

string() =

  [bytes()]

der_encoded() =

  binary()

pki_asn1_type() =

  'Certificate'

  | 'RSAPrivateKey'

  | 'RSAPublicKey'

  | 'DSAPrivateKey'

  | 'DSAPublicKey'

  | 'DHParameter'

  | 'SubjectPublicKeyInfo'

  | 'PrivateKeyInfo'

  | 'CertificationRequest'

  | 'ECPrivateKey'

  | 'EcpkParameters'

pem_entry () =

  {pki_asn1_type(), binary(), %% DER or encrypted DER not_encrypted

  | cipher_info()}

cipher_info() =

  {"RC2-CBC" | "DES-CBC" | "DES-EDE3-CBC", crypto:rand_bytes(8)

  | {#'PBEParameter{}, digest_type()} | #'PBES2-params'{}}

public_key() =

  rsa_public_key() | dsa_public_key() | ec_public_key()

private_key() =

  rsa_private_key() | dsa_private_key() | ec_private_key()

rsa_public_key() =

  #'RSAPublicKey'{}

rsa_private_key() =

  #'RSAPrivateKey'{}

dsa_public_key() =

  {integer(), #'Dss-Parms'{}}

dsa_private_key() =

  #'DSAPrivateKey'{}

ec_public_key()

  = {#'ECPoint'{}, #'EcpkParameters'{} | {namedCurve, oid()}}

ec_private_key() =

  #'ECPrivateKey'{}

public_crypt_options() =

  [{rsa_pad, rsa_padding()}]

rsa_padding() =

  'rsa_pkcs1_padding'

  | 'rsa_pkcs1_oaep_padding'

  | 'rsa_no_padding'

digest_type() =

  Union of rsa_digest_type(), dss_digest_type(), and ecdsa_digest_type().

rsa_digest_type() =

  'md5' | 'sha' | 'sha224' | 'sha256' | 'sha384' | 'sha512'

dss_digest_type() =

  'sha'

ecdsa_digest_type() =

  'sha'| 'sha224' | 'sha256' | 'sha384' | 'sha512'

crl_reason() =

  unspecified

  | keyCompromise

  | cACompromise

  | affiliationChanged

  | superseded

  | cessationOfOperation

  | certificateHold

  | privilegeWithdrawn

  | aACompromise

issuer_name() =

  {rdnSequence,[#'AttributeTypeAndValue'{}]}

ssh_file() =

  openssh_public_key

  | rfc4716_public_key

  | known_hosts

  | auth_keys

### EXPORTS

compute_key(OthersKey, MyKey)->
compute_key(OthersKey, MyKey, Params)->

Types:

OthersKey = #'ECPoint'{} | binary(), MyKey = #'ECPrivateKey'{} | binary()
Params = #'DHParameter'{}

Computes shared secret.

decrypt_private(CipherText, Key) -> binary()
decrypt_private(CipherText, Key, Options) -> binary()

Types:

CipherText = binary()
Key = rsa_private_key()
Options = public_crypt_options()

Public-key decryption using the private key. See also crypto:private_decrypt/4

decrypt_public(CipherText, Key) - > binary()
decrypt_public(CipherText, Key, Options) - > binary()

Types:

CipherText = binary()
Key = rsa_public_key()
Options = public_crypt_options()

Public-key decryption using the public key. See also crypto:public_decrypt/4

der_decode(Asn1type, Der) -> term()

Types:

Asn1Type = atom()
ASN.1 type present in the Public Key applications ASN.1 specifications.
Der = der_encoded()

Decodes a public-key ASN.1 DER encoded entity.

der_encode(Asn1Type, Entity) -> der_encoded()

Types:

Asn1Type = atom()
ASN.1 type present in the Public Key applications ASN.1 specifications.
Entity = term()
Erlang representation of Asn1Type

Encodes a public-key entity with ASN.1 DER encoding.

encrypt_private(PlainText, Key) -> binary()

Types:

PlainText = binary()
Key = rsa_private_key()

Public-key encryption using the private key. See also crypto:private_encrypt/4.

encrypt_public(PlainText, Key) -> binary()

Types:

PlainText = binary()
Key = rsa_public_key()

Public-key encryption using the public key. See also crypto:public_encrypt/4.

generate_key(Params) -> {Public::binary(), Private::binary()} | #'ECPrivateKey'{}

Types:

Params = #'DHParameter'{} | {namedCurve, oid()} | #'ECParameters'{}

Generates a new keypair.

pem_decode(PemBin) -> [pem_entry()]

Types:

PemBin = binary()
Example {ok, PemBin} = file:read_file("cert.pem").

Decodes PEM binary data and returns entries as ASN.1 DER encoded entities.

pem_encode(PemEntries) -> binary()

Types:

PemEntries = [pem_entry()]

Creates a PEM binary.

pem_entry_decode(PemEntry) -> term()
pem_entry_decode(PemEntry, Password) -> term()

Types:

PemEntry = pem_entry()
Password = string()

Decodes a PEM entry. pem_decode/1 returns a list of PEM entries. Notice that if the PEM entry is of type 'SubjectPublickeyInfo', it is further decoded to an rsa_public_key() or dsa_public_key().

pem_entry_encode(Asn1Type, Entity) -> pem_entry()
pem_entry_encode(Asn1Type, Entity, {CipherInfo, Password}) -> pem_entry()

Types:

Asn1Type = pki_asn1_type()
Entity = term()
Erlang representation of Asn1Type. If Asn1Type is 'SubjectPublicKeyInfo', Entity must be either an rsa_public_key() or a dsa_public_key() and this function creates the appropriate 'SubjectPublicKeyInfo' entry.
CipherInfo = cipher_info()
Password = string()

Creates a PEM entry that can be feed to pem_encode/1.

pkix_decode_cert(Cert, otp|plain) -> #'Certificate'{} | #'OTPCertificate'{}

Types:

Cert = der_encoded()

Decodes an ASN.1 DER-encoded PKIX certificate. Option otp uses the customized ASN.1 specification OTP-PKIX.asn1 for decoding and also recursively decode most of the standard parts.

pkix_encode(Asn1Type, Entity, otp | plain) -> der_encoded()

Types:

Asn1Type = atom()
The ASN.1 type can be 'Certificate', 'OTPCertificate' or a subtype of either.
Entity = #'Certificate'{} | #'OTPCertificate'{} | a valid subtype

DER encodes a PKIX x509 certificate or part of such a certificate. This function must be used for encoding certificates or parts of certificates that are decoded/created in the otp format, whereas for the plain format this function directly calls der_encode/2.

pkix_is_issuer(Cert, IssuerCert) -> boolean()

Types:

Cert = der_encoded() | #'OTPCertificate'{}
IssuerCert = der_encoded() | #'OTPCertificate'{}

Checks if IssuerCert issued Cert.

pkix_is_fixed_dh_cert(Cert) -> boolean()

Types:

Cert = der_encoded() | #'OTPCertificate'{}

Checks if a certificate is a fixed Diffie-Hellman certificate.

pkix_is_self_signed(Cert) -> boolean()

Types:

Cert = der_encoded() | #'OTPCertificate'{}

Checks if a certificate is self-signed.

pkix_issuer_id(Cert, IssuedBy) -> {ok, IssuerID} | {error, Reason}

Types:

Cert = der_encoded() | #'OTPCertificate'{}
IssuedBy = self | other
IssuerID = {integer(), issuer_name()}
The issuer id consists of the serial number and the issuers name.
Reason = term()

Returns the issuer id.

pkix_normalize_name(Issuer) -> Normalized

Types:

Issuer = issuer_name()
Normalized = issuer_name()

Normalizes an issuer name so that it can be easily compared to another issuer name.

pkix_path_validation(TrustedCert, CertChain, Options) -> {ok, {PublicKeyInfo, PolicyTree}} | {error, {bad_cert, Reason}}

Types:

TrustedCert = #'OTPCertificate'{} | der_encode() | atom()
Normally a trusted certificate, but it can also be a path-validation error that can be discovered while constructing the input to this function and that is to be run through the verify_fun. Examples are unknown_ca and selfsigned_peer.
CertChain = [der_encode()]
A list of DER-encoded certificates in trust order ending with the peer certificate.
Options = proplists:proplist()
PublicKeyInfo = {?'rsaEncryption' | ?'id-dsa', rsa_public_key() | integer(), 'NULL' | 'Dss-Parms'{}}
PolicyTree = term()
At the moment this is always an empty list as policies are not currently supported.
Reason = cert_expired | invalid_issuer | invalid_signature | name_not_permitted | missing_basic_constraint | invalid_key_usage | {revoked, crl_reason()} | atom()

Performs a basic path validation according to RFC 5280. However, CRL validation is done separately by pkix_crls_validate/3 and is to be called from the supplied verify_fun.

Available options:

{verify_fun, fun()}

  The fun must be defined as:

      fun(OtpCert :: #'OTPCertificate'{},
          Event :: {bad_cert, Reason :: atom() | {revoked, atom()}} |
                   {extension, #'Extension'{}},
          InitialUserState :: term()) ->
      	{valid, UserState :: term()} |
      	{valid_peer, UserState :: term()} |
      	{fail, Reason :: term()} |
      	{unknown, UserState :: term()}.

  If the verify callback fun returns {fail, Reason}, the verification process is immediately stopped. If the verify callback fun returns {valid, UserState}, the verification process is continued. This can be used to accept specific path validation errors, such as selfsigned_peer, as well as verifying application-specific extensions. If called with an extension unknown to the user application, the return value {unknown, UserState} is to be used.

{max_path_length, integer()}
  The max_path_length is the maximum number of non-self-issued intermediate certificates that can follow the peer certificate in a valid certification path. So, if max_path_length is 0, the PEER must be signed by the trusted ROOT-CA directly, if it is 1, the path can be PEER, CA, ROOT-CA, if it is 2, the path can be PEER, CA, CA, ROOT-CA, and so on.

Possible reasons for a bad certificate:

cert_expired

  Certificate is no longer valid as its expiration date has passed.

invalid_issuer

  Certificate issuer name does not match the name of the issuer certificate in the chain.

invalid_signature

  Certificate was not signed by its issuer certificate in the chain.

name_not_permitted

  Invalid Subject Alternative Name extension.

missing_basic_constraint

  Certificate, required to have the basic constraints extension, does not have a basic constraints extension.

invalid_key_usage

  Certificate key is used in an invalid way according to the key-usage extension.

{revoked, crl_reason()}

  Certificate has been revoked.

atom()

  Application-specific error reason that is to be checked by the verify_fun.

pkix_crl_issuer(CRL) -> issuer_name()

Types:

CRL = der_encoded() | #'CertificateList'{}

Returns the issuer of the CRL.

pkix_crls_validate(OTPCertificate, DPAndCRLs, Options) -> CRLStatus()

Types:

OTPCertificate = #'OTPCertificate'{}
DPAndCRLs = [{DP::#'DistributionPoint'{}, {DerCRL::der_encoded(), CRL::#'CertificateList'{}}}]
Options = proplists:proplist()
CRLStatus() = valid | {bad_cert, revocation_status_undetermined} | {bad_cert, {revoked, crl_reason()}}

Performs CRL validation. It is intended to be called from the verify fun of pkix_path_validation/3 .

Available options:

{update_crl, fun()}

  The fun has the following type specification:

       fun(#'DistributionPoint'{}, #'CertificateList'{}) ->
              #'CertificateList'{}

  The fun uses the information in the distribution point to access the latest possible version of the CRL. If this fun is not specified, Public Key uses the default implementation:

       fun(_DP, CRL) -> CRL end

{issuer_fun, fun()}

  The fun has the following type specification:

      fun(#'DistributionPoint'{}, #'CertificateList'{},
          {rdnSequence,[#'AttributeTypeAndValue'{}]}, term()) ->
      	{ok, #'OTPCertificate'{}, [der_encoded]}

  The fun returns the root certificate and certificate chain that has signed the CRL.

       fun(DP, CRL, Issuer, UserState) -> {ok, RootCert, CertChain}

pkix_crl_verify(CRL, Cert) -> boolean()

Types:

CRL = der_encoded() | #'CertificateList'{}
Cert = der_encoded() | #'OTPCertificate'{}

Verify that Cert is the CRL signer.

pkix_dist_point(Cert) -> DistPoint

Types:

Cert = der_encoded() | #'OTPCertificate'{}
DistPoint = #'DistributionPoint'{}

Creates a distribution point for CRLs issued by the same issuer as Cert. Can be used as input to pkix_crls_validate/3

pkix_dist_points(Cert) -> DistPoints

Types:

Cert = der_encoded() | #'OTPCertificate'{}
DistPoints = [#'DistributionPoint'{}]

Extracts distribution points from the certificates extensions.

pkix_sign(#'OTPTBSCertificate'{}, Key) -> der_encoded()

Types:

Key = rsa_public_key() | dsa_public_key()

Signs an 'OTPTBSCertificate'. Returns the corresponding DER-encoded certificate.

pkix_sign_types(AlgorithmId) -> {DigestType, SignatureType}

Types:

AlgorithmId = oid()
Signature OID from a certificate or a certificate revocation list.
DigestType = rsa_digest_type() | dss_digest_type()
SignatureType = rsa | dsa

Translates signature algorithm OID to Erlang digest and signature types.

pkix_verify(Cert, Key) -> boolean()

Types:

Cert = der_encoded()
Key = rsa_public_key() | dsa_public_key()

Verifies PKIX x.509 certificate signature.

sign(Msg, DigestType, Key) -> binary()

Types:

Msg = binary() | {digest,binary()}
The Msg is either the binary "plain text" data to be signed or it is the hashed value of "plain text", that is, the digest.
DigestType = rsa_digest_type() | dss_digest_type() | ecdsa_digest_type()
Key = rsa_private_key() | dsa_private_key() | ec_private_key()

Creates a digital signature.

ssh_decode(SshBin, Type) -> [{public_key(), Attributes::list()}]

Types:

SshBin = binary()
Example {ok, SshBin} = file:read_file("known_hosts").
Type = public_key | ssh_file()
If Type is public_key the binary can be either an RFC4716 public key or an OpenSSH public key.

Decodes an SSH file-binary. In the case of know_hosts or auth_keys, the binary can include one or more lines of the file. Returns a list of public keys and their attributes, possible attribute values depends on the file type represented by the binary.

RFC4716 attributes - see RFC 4716.

  {headers, [{string(), utf8_string()}]}

auth_key attributes - see manual page for sshd.
  {comment, string()}
  {options, [string()]}

  {bits, integer()} - In SSH version 1 files.

known_host attributes - see manual page for sshd.
  {hostnames, [string()]}
  {comment, string()}

  {bits, integer()} - In SSH version 1 files.

ssh_encode([{Key, Attributes}], Type) -> binary()

Types:

Key = public_key()
Attributes = list()
Type = ssh_file()

Encodes a list of SSH file entries (public keys and attributes) to a binary. Possible attributes depend on the file type, see ssh_decode/2 .

verify(Msg, DigestType, Signature, Key) -> boolean()

Types:

Msg = binary() | {digest,binary()}
The Msg is either the binary "plain text" data or it is the hashed value of "plain text", that is, the digest.
DigestType = rsa_digest_type() | dss_digest_type() | ecdsa_digest_type()
Signature = binary()
Key = rsa_public_key() | dsa_public_key() | ec_public_key()

Veryfies a digital signature.