public_key(3)

NAME
public_key - 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'

        | 'CertificateList'

        | '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'{} | #'CertificateList'{}
        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_encoded() | 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_encoded()]
            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_private_key() | dsa_private_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 | ecdsa

    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() | ec_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.