.TH public_key 3erl "public_key 1.13.3.2" "Ericsson AB" "Erlang Module Definition" .SH NAME public_key \- API module for public-key infrastructure. .SH DESCRIPTION .LP Provides functions to handle public-key infrastructure, for details see public_key(7)\&. .SH "COMMON RECORDS AND ASN.1 TYPES" .LP .RS -4 .B Note: .RE 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\&. .LP Use the following include directive to get access to the records and constant macros described here and in the User\&'s Guide: .LP .nf -include_lib("public_key/include/public_key.hrl"). .fi .SH DATA TYPES .nf \fBoid()\fR\& = tuple() .br .fi .RS .LP Object identifier, a tuple of integers as generated by the \fIASN\&.1\fR\& compiler\&. .RE .nf \fBkey_oid_name()\fR\& = .br rsaEncryption | \&'id-RSASSA-PSS\&' | \&'id-ecPublicKey\&' | .br \&'id-Ed25519\&' | \&'id-Ed448\&' | \&'id-dsa\&' .br .fi .RS .LP Macro names for key object identifiers used by prefixing with ? .RE .nf \fBder_encoded()\fR\& = binary() .br .fi .RS .RE .nf \fBpki_asn1_type()\fR\& = .br \&'Certificate\&' | \&'RSAPrivateKey\&' | \&'RSAPublicKey\&' | .br \&'SubjectPublicKeyInfo\&' | \&'DSAPrivateKey\&' | \&'DHParameter\&' | .br \&'PrivateKeyInfo\&' | \&'CertificationRequest\&' | \&'ContentInfo\&' | .br \&'CertificateList\&' | \&'ECPrivateKey\&' | \&'OneAsymmetricKey\&' | .br \&'EcpkParameters\&' .br .fi .RS .RE .nf \fBasn1_type()\fR\& = atom() .br .fi .RS .LP ASN\&.1 type present in the Public Key applications ASN\&.1 specifications\&. .RE .nf \fBpem_entry()\fR\& = .br {pki_asn1_type(), .br der_or_encrypted_der(), .br not_encrypted | cipher_info()} .br .fi .nf \fBder_or_encrypted_der()\fR\& = binary() .br .fi .nf \fBcipher_info()\fR\& = {cipher(), cipher_info_params()} .br .fi .nf \fBcipher()\fR\& = string() .br .fi .nf \fBsalt()\fR\& = binary() .br .fi .nf \fBcipher_info_params()\fR\& = .br salt() | .br {#\&'PBEParameter\&'{}, digest_type()} | .br #\&'PBES2-params\&'{} .br .fi .RS .LP .nf Cipher = "RC2-CBC" | "DES-CBC" | "DES-EDE3-CBC" .fi .LP \fISalt\fR\& could be generated with \fIcrypto:strong_rand_bytes(8)\fR\&\&. .RE .nf \fBpublic_key()\fR\& = .br rsa_public_key() | .br rsa_pss_public_key() | .br dsa_public_key() | .br ec_public_key() | .br ed_public_key() .br .fi .nf \fBrsa_public_key()\fR\& = #\&'RSAPublicKey\&'{} .br .fi .nf \fBdss_public_key()\fR\& = integer() .br .fi .nf \fBrsa_pss_public_key()\fR\& = .br {rsa_pss_public_key(), #\&'RSASSA-PSS-params\&'{}} .br .fi .nf \fBdsa_public_key()\fR\& = {dss_public_key(), #\&'Dss-Parms\&'{}} .br .fi .nf \fBec_public_key()\fR\& = {#\&'ECPoint\&'{}, ecpk_parameters_api()} .br .fi .nf \fBpublic_key_params()\fR\& = .br \&'NULL\&' | .br #\&'RSASSA-PSS-params\&'{} | .br {namedCurve, oid()} | .br #\&'ECParameters\&'{} | .br #\&'Dss-Parms\&'{} .br .fi .nf \fBecpk_parameters()\fR\& = .br {ecParameters, #\&'ECParameters\&'{}} | .br {namedCurve, Oid :: tuple()} .br .fi .nf \fBecpk_parameters_api()\fR\& = .br ecpk_parameters() | .br #\&'ECParameters\&'{} | .br {namedCurve, Name :: crypto:ec_named_curve()} .br .fi .nf \fBpublic_key_info()\fR\& = .br {key_oid_name(), .br rsa_public_key() | #\&'ECPoint\&'{} | dss_public_key(), .br public_key_params()} .br .fi .RS .RE .nf \fBed_public_key()\fR\& = {#\&'ECPoint\&'{}, ed_params()} .br .fi .RS .RE .nf \fBed_params()\fR\& = {namedCurve, ed_oid_name()} .br .fi .nf \fBprivate_key()\fR\& = .br rsa_private_key() | .br rsa_pss_private_key() | .br dsa_private_key() | .br ec_private_key() | .br ed_private_key() .br .fi .nf \fBrsa_private_key()\fR\& = #\&'RSAPrivateKey\&'{} .br .fi .nf \fBrsa_pss_private_key()\fR\& = .br {#\&'RSAPrivateKey\&'{}, #\&'RSASSA-PSS-params\&'{}} .br .fi .nf \fBdsa_private_key()\fR\& = #\&'DSAPrivateKey\&'{} .br .fi .nf \fBec_private_key()\fR\& = #\&'ECPrivateKey\&'{} .br .fi .RS .RE .nf \fBed_private_key()\fR\& = #\&'ECPrivateKey\&'{parameters = ed_params()} .br .fi .RS .RE .nf \fBed_oid_name()\fR\& = \&'id-Ed25519\&' | \&'id-Ed448\&' .br .fi .RS .LP Macro names for object identifiers for EDDSA curves used by prefixing with ? .RE .nf \fBkey_params()\fR\& = .br #\&'DHParameter\&'{} | .br {namedCurve, oid()} | .br #\&'ECParameters\&'{} | .br {rsa, Size :: integer(), PubExp :: integer()} .br .fi .RS .RE .nf \fBdigest_type()\fR\& = .br none | sha1 | .br crypto:rsa_digest_type() | .br crypto:dss_digest_type() | .br crypto:ecdsa_digest_type() .br .fi .RS .RE .nf \fBissuer_name()\fR\& = {rdnSequence, [[#\&'AttributeTypeAndValue\&'{}]]} .br .fi .RS .RE .nf \fBreferenceIDs()\fR\& = [referenceID()] .br .fi .RS .RE .nf \fBreferenceID()\fR\& = .br {uri_id | dns_id | ip | srv_id | atom() | oid(), string()} | .br {ip, inet:ip_address() | string()} .br .fi .RS .RE .nf \fBcert_id()\fR\& = {SerialNr :: integer(), issuer_name()} .br .fi .RS .RE .nf \fBcert()\fR\& = der_cert() | otp_cert() .br .fi .RS .RE .nf \fBotp_cert()\fR\& = #\&'OTPCertificate\&'{} .br .fi .RS .RE .nf \fBder_cert()\fR\& = der_encoded() .br .fi .RS .RE .nf \fBcombined_cert()\fR\& = .br #cert{der = public_key:der_encoded(), .br otp = #\&'OTPCertificate\&'{}} .br .fi .RS .RE .nf \fBbad_cert_reason()\fR\& = .br cert_expired | invalid_issuer | invalid_signature | .br name_not_permitted | missing_basic_constraint | .br invalid_key_usage | .br {revoked, crl_reason()} | .br atom() .br .fi .RS .RE .nf \fBcrl_reason()\fR\& = .br unspecified | keyCompromise | cACompromise | .br affiliationChanged | superseded | cessationOfOperation | .br certificateHold | privilegeWithdrawn | aACompromise .br .fi .RS .RE .nf \fBchain_opts()\fR\& = .br #{chain_end() := [cert_opt()], .br intermediates => [[cert_opt()]]} .br .fi .RS .RE .nf \fBchain_end()\fR\& = root | peer .br .fi .RS .RE .nf \fBcert_opt()\fR\& = .br {digest, public_key:digest_type()} | .br {key, public_key:key_params() | public_key:private_key()} | .br {validity, .br {From :: erlang:timestamp(), To :: erlang:timestamp()}} | .br {extensions, [#\&'Extension\&'{}]} .br .fi .RS .RE .nf \fBtest_root_cert()\fR\& = .br #{cert := der_encoded(), key := public_key:private_key()} .br .fi .RS .RE .nf \fBtest_config()\fR\& = .br #{server_config := [conf_opt()], .br client_config := [conf_opt()]} .br .fi .RS .RE .nf \fBconf_opt()\fR\& = .br {cert, public_key:der_encoded()} | .br {key, public_key:private_key()} | .br {cacerts, [public_key:der_encoded()]} .br .fi .RS .RE .SH EXPORTS .LP .nf .B cacerts_clear() -> boolean() .br .fi .br .RS .LP Clears any loaded CA certificates, returns true if any was loaded\&. .RE .LP .nf .B cacerts_get() -> [combined_cert()] .br .fi .br .RS .LP Returns the trusted CA certificates if any are loaded, otherwise uses cacerts_load/0 to load them\&. The function fails if no \fIcacerts\fR\& could be loaded\&. .RE .LP .nf .B cacerts_load() -> ok | {error, Reason :: term()} .br .fi .br .RS .LP Loads the OS supplied trusted CA certificates\&. .RE .LP .nf .B cacerts_load(File :: file:filename_all()) -> .B ok | {error, Reason :: term()} .br .fi .br .RS .LP Loads the trusted CA certificates from a file\&. .RE .LP .nf .B compute_key(OthersECDHkey, MyECDHkey) -> SharedSecret .br .fi .br .RS .LP Types: .RS 3 OthersECDHkey = #\&'ECPoint\&'{} .br MyECDHkey = #\&'ECPrivateKey\&'{} .br SharedSecret = binary() .br .RE .RE .RS .LP Computes shared secret\&. .RE .LP .nf .B compute_key(OthersDHkey, MyDHkey, DHparms) -> SharedSecret .br .fi .br .RS .LP Types: .RS 3 OthersDHkey = crypto:dh_public() .br MyDHkey = crypto:dh_private() .br DHparms = #\&'DHParameter\&'{} .br SharedSecret = binary() .br .RE .RE .RS .LP Computes shared secret\&. .RE .LP .nf .B decrypt_private(CipherText, Key) -> PlainText .br .fi .br .nf .B decrypt_private(CipherText, Key, Options) -> PlainText .br .fi .br .RS .LP Types: .RS 3 CipherText = binary() .br Key = rsa_private_key() .br Options = crypto:pk_encrypt_decrypt_opts() .br PlainText = binary() .br .RE .RE .RS .LP Public-key decryption using the private key\&. See also crypto:private_decrypt/4 .RE .LP .nf .B decrypt_public(CipherText, Key) -> PlainText .br .fi .br .nf .B decrypt_public(CipherText, Key, Options) -> PlainText .br .fi .br .RS .LP Types: .RS 3 CipherText = binary() .br Key = rsa_public_key() .br Options = crypto:pk_encrypt_decrypt_opts() .br PlainText = binary() .br .RE .RE .RS .LP Public-key decryption using the public key\&. See also crypto:public_decrypt/4 .RE .LP .nf .B der_decode(Asn1Type, Der) -> Entity .br .fi .br .RS .LP Types: .RS 3 Asn1Type = asn1_type() .br Der = der_encoded() .br Entity = term() .br .RE .RE .RS .LP Decodes a public-key ASN\&.1 DER encoded entity\&. .RE .LP .nf .B der_encode(Asn1Type, Entity) -> Der .br .fi .br .RS .LP Types: .RS 3 Asn1Type = asn1_type() .br Entity = term() .br Der = binary() .br .RE .RE .RS .LP Encodes a public-key entity with ASN\&.1 DER encoding\&. .RE .LP .nf .B dh_gex_group(MinSize, SuggestedSize, MaxSize, Groups) -> .B {ok, {Size, Group}} | {error, term()} .br .fi .br .RS .LP Types: .RS 3 MinSize = SuggestedSize = MaxSize = integer() >= 1 .br Groups = undefined | [{Size, [Group]}] .br Size = integer() >= 1 .br Group = {G, P} .br G = P = integer() >= 1 .br .RE .RE .RS .LP Selects a group for Diffie-Hellman key exchange with the key size in the range \fIMinSize\&.\&.\&.MaxSize\fR\& and as close to \fISuggestedSize\fR\& as possible\&. If \fIGroups == undefined\fR\& a default set will be used, otherwise the group is selected from \fIGroups\fR\&\&. .LP First a size, as close as possible to SuggestedSize, is selected\&. Then one group with that key size is randomly selected from the specified set of groups\&. If no size within the limits of \fIMinSize\fR\& and \fIMaxSize\fR\& is available, \fI{error,no_group_found}\fR\& is returned\&. .LP The default set of groups is listed in \fIlib/public_key/priv/moduli\fR\&\&. This file may be regenerated like this: .LP .nf $> cd $ERL_TOP/lib/public_key/priv/ $> generate ---- wait until all background jobs has finished. It may take several days ! $> cat moduli-* > moduli $> cd ..; make .fi .RE .LP .nf .B encrypt_private(PlainText, Key) -> CipherText .br .fi .br .nf .B encrypt_private(PlainText, Key, Options) -> CipherText .br .fi .br .RS .LP Types: .RS 3 PlainText = binary() .br Key = rsa_private_key() .br Options = crypto:pk_encrypt_decrypt_opts() .br CipherText = binary() .br .RE .RE .RS .LP Public-key encryption using the private key\&. See also crypto:private_encrypt/4\&. .RE .LP .nf .B encrypt_public(PlainText, Key) -> CipherText .br .fi .br .nf .B encrypt_public(PlainText, Key, Options) -> CipherText .br .fi .br .RS .LP Types: .RS 3 PlainText = binary() .br Key = rsa_public_key() .br Options = crypto:pk_encrypt_decrypt_opts() .br CipherText = binary() .br .RE .RE .RS .LP Public-key encryption using the public key\&. See also crypto:public_encrypt/4\&. .RE .LP .nf .B generate_key(Params :: DHparams | ECparams | RSAparams) -> .B DHkeys | ECkey | RSAkey .br .fi .br .RS .LP Types: .RS 3 DHparams = #\&'DHParameter\&'{} .br DHkeys = {PublicDH :: binary(), PrivateDH :: binary()} .br ECparams = ecpk_parameters_api() .br ECkey = #\&'ECPrivateKey\&'{} .br RSAparams = {rsa, Size, PubExp} .br Size = PubExp = integer() >= 1 .br RSAkey = #\&'RSAPrivateKey\&'{} .br .RE .RE .RS .LP Generates a new key pair\&. Note that except for Diffie-Hellman the public key is included in the private key structure\&. See also crypto:generate_key/2 .RE .LP .nf .B pem_decode(PemBin :: binary()) -> [pem_entry()] .br .fi .br .RS .LP Decodes PEM binary data and returns entries as ASN\&.1 DER encoded entities\&. .LP Example \fI{ok, PemBin} = file:read_file("cert\&.pem")\&. PemEntries = public_key:pem_decode(PemBin)\&. \fR\& .RE .LP .nf .B pem_encode(PemEntries :: [pem_entry()]) -> binary() .br .fi .br .RS .LP Creates a PEM binary\&. .RE .LP .nf .B pem_entry_decode(PemEntry) -> term() .br .fi .br .nf .B pem_entry_decode(PemEntry, Password) -> term() .br .fi .br .RS .LP Types: .RS 3 PemEntry = pem_entry() .br Password = iodata() | fun(() -> iodata()) .br .RE .RE .RS .LP Decodes a PEM entry\&. \fIpem_decode/1\fR\& returns a list of PEM entries\&. Notice that if the PEM entry is of type \&'SubjectPublickeyInfo\&', it is further decoded to an \fIrsa_public_key()\fR\& or \fIdsa_public_key()\fR\&\&. .LP Password can be either an octet string or function which returns same type\&. .RE .LP .nf .B pem_entry_encode(Asn1Type, Entity) -> pem_entry() .br .fi .br .nf .B pem_entry_encode(Asn1Type, Entity, InfoPwd) -> pem_entry() .br .fi .br .RS .LP Types: .RS 3 Asn1Type = pki_asn1_type() .br Entity = term() .br InfoPwd = {CipherInfo, Password} .br CipherInfo = cipher_info() .br Password = iodata() .br .RE .RE .RS .LP Creates a PEM entry that can be feed to \fIpem_encode/1\fR\&\&. .LP If \fIAsn1Type\fR\& is \fI\&'SubjectPublicKeyInfo\&'\fR\&, \fIEntity\fR\& must be either an \fIrsa_public_key()\fR\&, \fIdsa_public_key()\fR\& or an \fIec_public_key()\fR\& and this function creates the appropriate \fI\&'SubjectPublicKeyInfo\&'\fR\& entry\&. .RE .LP .nf .B pkix_decode_cert(Cert, Type) -> #\&'Certificate\&'{} | otp_cert() .br .fi .br .RS .LP Types: .RS 3 Cert = der_cert() .br Type = plain | otp .br .RE .RE .RS .LP Decodes an ASN\&.1 DER-encoded PKIX certificate\&. Option \fIotp\fR\& uses the customized ASN\&.1 specification OTP-PKIX\&.asn1 for decoding and also recursively decode most of the standard parts\&. .RE .LP .nf .B pkix_encode(Asn1Type, Entity, Type) -> Der .br .fi .br .RS .LP Types: .RS 3 Asn1Type = asn1_type() .br Entity = term() .br Type = otp | plain .br Der = der_encoded() .br .RE .RE .RS .LP 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 \fIotp\fR\& format, whereas for the plain format this function directly calls \fIder_encode/2\fR\&\&. .LP .RS -4 .B Note: .RE Subtle ASN-1 encoding errors in certificates may be worked around when decoding, this may have the affect that the encoding a certificate back to DER may generate different bytes then the supplied original\&. .RE .LP .nf .B pkix_is_issuer(CertorCRL, IssuerCert) -> boolean() .br .fi .br .RS .LP Types: .RS 3 CertorCRL = cert() | #\&'CertificateList\&'{} .br IssuerCert = cert() .br .RE .RE .RS .LP Checks if \fIIssuerCert\fR\& issued \fICert\fR\&\&. .RE .LP .nf .B pkix_is_fixed_dh_cert(Cert) -> boolean() .br .fi .br .RS .LP Types: .RS 3 Cert = cert() .br .RE .RE .RS .LP Checks if a certificate is a fixed Diffie-Hellman certificate\&. .RE .LP .nf .B pkix_is_self_signed(Cert) -> boolean() .br .fi .br .RS .LP Types: .RS 3 Cert = cert() .br .RE .RE .RS .LP Checks if a certificate is self-signed\&. .RE .LP .nf .B pkix_issuer_id(Cert, IssuedBy) -> .B {ok, ID :: cert_id()} | {error, Reason} .br .fi .br .RS .LP Types: .RS 3 Cert = cert() .br IssuedBy = self | other .br Reason = term() .br .RE .RE .RS .LP Returns the x509 certificate issuer id, if it can be determined\&. .RE .LP .nf .B pkix_normalize_name(Issuer) -> Normalized .br .fi .br .RS .LP Types: .RS 3 Issuer = issuer_name() | der_encoded() .br Normalized = issuer_name() .br .RE .RE .RS .LP Normalizes an issuer name so that it can be easily compared to another issuer name\&. .RE .LP .nf .B pkix_path_validation(Cert, CertChain, Options) -> .B {ok, {PublicKeyInfo, PolicyTree}} | .B {error, .B {bad_cert, Reason :: bad_cert_reason()}} .br .fi .br .RS .LP Types: .RS 3 Cert = cert() | atom() .br CertChain = [cert() | combined_cert()] .br Options = .br [{max_path_length, integer()} | .br {verify_fun, {function(), term()}}] .br PublicKeyInfo = public_key_info() .br PolicyTree = list() .br .RE .RE .RS .LP 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 \fIverify_fun\fR\&\&. The optional policy tree check is currently not implemented but an empty place holder list is returned instead\&. .LP Available options: .RS 2 .TP 2 .B {verify_fun, {fun(), InitialUserState::term()}: The fun must be defined as: .LP .nf 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()}. .fi .RS 2 .LP If the verify callback fun returns \fI{fail, Reason}\fR\&, the verification process is immediately stopped\&. If the verify callback fun returns \fI{valid, UserState}\fR\&, the verification process is continued\&. This can be used to accept specific path validation errors, such as \fIselfsigned_peer\fR\&, as well as verifying application-specific extensions\&. If called with an extension unknown to the user application, the return value \fI{unknown, UserState}\fR\& is to be used\&. .RE .LP .RS -4 .B Warning: .RE Note that user defined custom \fIverify_fun\fR\& may alter original path validation error (e\&.g \fIselfsigned_peer\fR\&)\&. Use with caution\&. .TP 2 .B {max_path_length, integer()}: The \fImax_path_length\fR\& is the maximum number of non-self-issued intermediate certificates that can follow the peer certificate in a valid certification path\&. So, if \fImax_path_length\fR\& 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\&. .RE .LP Explanations of reasons for a bad certificate: .RS 2 .TP 2 .B cert_expired: Certificate is no longer valid as its expiration date has passed\&. .TP 2 .B invalid_issuer: Certificate issuer name does not match the name of the issuer certificate in the chain\&. .TP 2 .B invalid_signature: Certificate was not signed by its issuer certificate in the chain\&. .TP 2 .B name_not_permitted: Invalid Subject Alternative Name extension\&. .TP 2 .B missing_basic_constraint: Certificate, required to have the basic constraints extension, does not have a basic constraints extension\&. .TP 2 .B invalid_key_usage: Certificate key is used in an invalid way according to the key-usage extension\&. .TP 2 .B {revoked, crl_reason()}: Certificate has been revoked\&. .TP 2 .B atom(): Application-specific error reason that is to be checked by the \fIverify_fun\fR\&\&. .RE .RE .LP .nf .B pkix_crl_issuer(CRL) -> Issuer .br .fi .br .RS .LP Types: .RS 3 CRL = der_encoded() | #\&'CertificateList\&'{} .br Issuer = issuer_name() .br .RE .RE .RS .LP Returns the issuer of the \fICRL\fR\&\&. .RE .LP .nf .B pkix_crls_validate(OTPcertificate, DPandCRLs, Options) -> .B CRLstatus .br .fi .br .RS .LP Types: .RS 3 OTPcertificate = #\&'OTPCertificate\&'{} .br DPandCRLs = [DPandCRL] .br DPandCRL = {DP, {DerCRL, CRL}} .br DP = #\&'DistributionPoint\&'{} .br DerCRL = der_encoded() .br CRL = #\&'CertificateList\&'{} .br Options = [{atom(), term()}] .br CRLstatus = valid | {bad_cert, BadCertReason} .br BadCertReason = .br revocation_status_undetermined | .br {revocation_status_undetermined, Reason :: term()} | .br {revoked, crl_reason()} .br .RE .RE .RS .LP Performs CRL validation\&. It is intended to be called from the verify fun of pkix_path_validation/3 \&. .LP Available options: .RS 2 .TP 2 .B {update_crl, fun()}: The fun has the following type specification: .LP .nf fun(#'DistributionPoint'{}, #'CertificateList'{}) -> #'CertificateList'{} .fi .RS 2 .LP 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: .RE .LP .nf fun(_DP, CRL) -> CRL end .fi .TP 2 .B {issuer_fun, fun()}: The fun has the following type specification: .LP .nf fun(#'DistributionPoint'{}, #'CertificateList'{}, {rdnSequence,[#'AttributeTypeAndValue'{}]}, term()) -> {ok, #'OTPCertificate'{}, [der_encoded]} .fi .RS 2 .LP The fun returns the root certificate and certificate chain that has signed the CRL\&. .RE .LP .nf fun(DP, CRL, Issuer, UserState) -> {ok, RootCert, CertChain} .fi .TP 2 .B {undetermined_details, boolean()}: Defaults to false\&. When revocation status cannot be determined, and this option is set to true, details of why no CRLs where accepted are included in the return value\&. .RE .RE .LP .nf .B pkix_crl_verify(CRL, Cert) -> boolean() .br .fi .br .RS .LP Types: .RS 3 CRL = der_encoded() | #\&'CertificateList\&'{} .br Cert = cert() .br .RE .RE .RS .LP Verify that \fICert\fR\& is the \fICRL\fR\& signer\&. .RE .LP .nf .B pkix_dist_point(Cert) -> DistPoint .br .fi .br .RS .LP Types: .RS 3 Cert = cert() .br DistPoint = #\&'DistributionPoint\&'{} .br .RE .RE .RS .LP Creates a distribution point for CRLs issued by the same issuer as \fICert\fR\&\&. Can be used as input to pkix_crls_validate/3 .RE .LP .nf .B pkix_dist_points(Cert) -> DistPoints .br .fi .br .RS .LP Types: .RS 3 Cert = cert() .br DistPoints = [#\&'DistributionPoint\&'{}] .br .RE .RE .RS .LP Extracts distribution points from the certificates extensions\&. .RE .LP .nf .B pkix_hash_type(HashOid :: oid()) -> .B DigestType :: .B md5 | crypto:sha1() | crypto:sha2() .br .fi .br .RS .LP Translates OID to Erlang digest type .RE .LP .nf .B pkix_match_dist_point(CRL, DistPoint) -> boolean() .br .fi .br .RS .LP Types: .RS 3 CRL = der_encoded() | #\&'CertificateList\&'{} .br DistPoint = #\&'DistributionPoint\&'{} .br .RE .RE .RS .LP Checks whether the given distribution point matches the Issuing Distribution Point of the CRL, as described in RFC 5280\&. If the CRL doesn\&'t have an Issuing Distribution Point extension, the distribution point always matches\&. .RE .LP .nf .B pkix_sign(Cert, Key) -> Der .br .fi .br .RS .LP Types: .RS 3 Cert = #\&'OTPTBSCertificate\&'{} .br Key = private_key() .br Der = der_encoded() .br .RE .RE .RS .LP Signs an \&'OTPTBSCertificate\&'\&. Returns the corresponding DER-encoded certificate\&. .RE .LP .nf .B pkix_sign_types(AlgorithmId) -> {DigestType, SignatureType} .br .fi .br .RS .LP Types: .RS 3 AlgorithmId = oid() .br DigestType = crypto:rsa_digest_type() | none .br SignatureType = rsa | dsa | ecdsa | eddsa .br .RE .RE .RS .LP Translates signature algorithm OID to Erlang digest and signature types\&. .LP The \fIAlgorithmId\fR\& is the signature OID from a certificate or a certificate revocation list\&. .RE .LP .nf .B pkix_test_data(ChainConf) -> TestConf .br .fi .br .RS .LP Types: .RS 3 ChainConf = .br #{server_chain := chain_opts(), client_chain := chain_opts()} | .br chain_opts() .br TestConf = test_config() | [conf_opt()] .br .RE .RE .RS .LP Creates certificate configuration(s) consisting of certificate and its private key plus CA certificate bundle, for a client and a server, intended to facilitate automated testing of applications using X509-certificates, often through SSL/TLS\&. The test data can be used when you have control over both the client and the server in a test scenario\&. .LP When this function is called with a map containing client and server chain specifications; it generates both a client and a server certificate chain where the \fIcacerts\fR\& returned for the server contains the root cert the server should trust and the intermediate certificates the server should present to connecting clients\&. The root cert the server should trust is the one used as root of the client certificate chain\&. Vice versa applies to the \fIcacerts\fR\& returned for the client\&. The root cert(s) can either be pre-generated with pkix_test_root_cert/2 , or if options are specified; it is (they are) generated\&. .LP When this function is called with a list of certificate options; it generates a configuration with just one node certificate where \fIcacerts\fR\& contains the root cert and the intermediate certs that should be presented to a peer\&. In this case the same root cert must be used for all peers\&. This is useful in for example an Erlang distributed cluster where any node, towards another node, acts either as a server or as a client depending on who connects to whom\&. The generated certificate contains a subject altname, which is not needed in a client certificate, but makes the certificate useful for both roles\&. .LP Explanation of the options used to customize certificates in the generated chains: .RS 2 .TP 2 .B {digest, digest_type()}: Hash algorithm to be used for signing the certificate together with the key option\&. Defaults to sha that is sha1\&. .TP 2 .B {key, key_params() | private_key()}: Parameters to be used to call public_key:generate_key/1, to generate a key, or an existing key\&. Defaults to generating an ECDSA key\&. Note this could fail if Erlang/OTP is compiled with a very old cryptolib\&. .TP 2 .B {validity, {From::erlang:timestamp(), To::erlang:timestamp()}} : The validity period of the certificate\&. .TP 2 .B {extensions, [#\&'Extension\&'{}]}: Extensions to include in the certificate\&. .RS 2 .LP Default extensions included in CA certificates if not otherwise specified are: .RE .LP .nf [#'Extension'{extnID = ?'id-ce-keyUsage', extnValue = [keyCertSign, cRLSign], critical = false}, #'Extension'{extnID = ?'id-ce-basicConstraints', extnValue = #'BasicConstraints'{cA = true}, critical = true}] .fi .RS 2 .LP Default extensions included in the server peer cert if not otherwise specified are: .RE .LP .nf [#'Extension'{extnID = ?'id-ce-keyUsage', extnValue = [digitalSignature, keyAgreement], critical = false}, #'Extension'{extnID = ?'id-ce-subjectAltName', extnValue = [{dNSName, Hostname}], critical = false}] .fi .RS 2 .LP Hostname is the result of calling net_adm:localhost() in the Erlang node where this function is called\&. .RE .RE .LP .RS -4 .B Note: .RE Note that the generated certificates and keys does not provide a formally correct PKIX-trust-chain and they cannot be used to achieve real security\&. This function is provided for testing purposes only\&. .RE .LP .nf .B pkix_test_root_cert(Name, Options) -> RootCert .br .fi .br .RS .LP Types: .RS 3 Name = string() .br Options = [cert_opt()] .br RootCert = test_root_cert() .br .RE .RE .RS .LP Generates a root certificate that can be used in multiple calls to pkix_test_data/1 when you want the same root certificate for several generated certificates\&. .RE .LP .nf .B pkix_subject_id(Cert) -> ID .br .fi .br .RS .LP Types: .RS 3 Cert = cert() .br ID = cert_id() .br .RE .RE .RS .LP Returns the X509 certificate subject id\&. .RE .LP .nf .B pkix_verify(Cert, Key) -> boolean() .br .fi .br .RS .LP Types: .RS 3 Cert = der_cert() .br Key = public_key() .br .RE .RE .RS .LP Verifies PKIX x\&.509 certificate signature\&. .RE .LP .nf .B pkix_verify_hostname(Cert, ReferenceIDs) -> boolean() .br .fi .br .nf .B pkix_verify_hostname(Cert, ReferenceIDs, Options) -> boolean() .br .fi .br .RS .LP Types: .RS 3 Cert = cert() .br ReferenceIDs = referenceIDs() .br Options = [{match_fun | fail_callback | fqdn_fun, function()}] .br .RE .RE .RS .LP This function checks that the \fIPresented Identifier\fR\& (e\&.g hostname) in a peer certificate is in agreement with at least one of the \fIReference Identifier\fR\& that the client expects to be connected to\&. The function is intended to be added as an extra client check of the peer certificate when performing public_key:pkix_path_validation/3 .LP See RFC 6125 for detailed information about hostname verification\&. The User\&'s Guide and code examples describes this function more detailed\&. .LP The option funs are described here: .RS 2 .TP 2 .B \fImatch_fun\fR\&: .LP .nf fun(ReferenceId::ReferenceId() | FQDN::string(), PresentedId::{dNSName,string()} | {uniformResourceIdentifier,string() | {iPAddress,list(byte())} | {OtherId::atom()|oid(),term()}}) .fi This function replaces the default host name matching rules\&. The fun should return a boolean to tell if the Reference ID and Presented ID matches or not\&. The match fun can also return a third value, value, the atom \fIdefault\fR\&, if the default matching rules shall apply\&. This makes it possible to augment the tests with a special case: .LP .nf fun(....) -> true; % My special case (_, _) -> default % all others falls back to the inherit tests end .fi .br See pkix_verify_hostname_match_fun/1 for a function that takes a protocol name as argument and returns a \fIfun/2\fR\& suitable for this option and Re-defining the match operation in the User\&'s Guide for an example\&. .LP .RS -4 .B Note: .RE Reference Id values given as binaries will be converted to strings, and ip references may be given in string format that is "10\&.0\&.1\&.1" or "1234::5678:9012" as well as on the format inet:ip_address() .TP 2 .B \fIfail_callback\fR\&: If a matching fails, there could be circumstances when the certificate should be accepted anyway\&. Think for example of a web browser where you choose to accept an outdated certificate\&. This option enables implementation of such an exception but for hostnames\&. This \fIfun/1\fR\& is called when no \fIReferenceID\fR\& matches\&. The return value of the fun (a \fIboolean()\fR\&) decides the outcome\&. If \fItrue\fR\& the the certificate is accepted otherwise it is rejected\&. See "Pinning" a Certificate in the User\&'s Guide\&. .TP 2 .B \fIfqdn_fun\fR\&: This option augments the host name extraction from URIs and other Reference IDs\&. It could for example be a very special URI that is not standardised\&. The fun takes a Reference ID as argument and returns one of: .RS 2 .TP 2 * the hostname .LP .TP 2 * the atom \fIdefault\fR\&: the default host name extract function will be used .LP .TP 2 * the atom \fIundefined\fR\&: a host name could not be extracted\&. The pkix_verify_hostname/3 will return \fIfalse\fR\&\&. .LP .RE .br For an example, see Hostname extraction in the User\&'s Guide\&. .RE .RE .LP .nf .B pkix_verify_hostname_match_fun(Protocol) -> Result .br .fi .br .RS .LP Types: .RS 3 Protocol = https .br Result = function() .br .RE .RE .RS .LP The return value of calling this function is intended to be used in the \fImatch_fun\fR\& option in pkix_verify_hostname/3\&. .LP The returned fun augments the verify hostname matching according to the specific rules for the protocol in the argument\&. .LP .RS -4 .B Note: .RE Currently supported https fun will allow wildcard certificate matching as specified by the HTTP standard\&. Note that for instance LDAP have a different set of wildcard matching rules\&. If you do not want to allow wildcard certificates (recommended from a security perspective) or otherwise customize the hostname match the default match function used by ssl application will be sufficient\&. .RE .LP .nf .B sign(Msg, DigestType, Key) -> Signature .br .fi .br .nf .B sign(Msg, DigestType, Key, Options) -> Signature .br .fi .br .RS .LP Types: .RS 3 Msg = binary() | {digest, binary()} .br DigestType = digest_type() .br Key = private_key() .br Options = crypto:pk_sign_verify_opts() .br Signature = binary() .br .RE .RE .RS .LP Creates a digital signature\&. .LP The \fIMsg\fR\& is either the binary "plain text" data to be signed or it is the hashed value of "plain text", that is, the digest\&. .RE .LP .nf .B verify(Msg, DigestType, Signature, Key) -> boolean() .br .fi .br .nf .B verify(Msg, DigestType, Signature, Key, Options) -> boolean() .br .fi .br .RS .LP Types: .RS 3 Msg = binary() | {digest, binary()} .br DigestType = digest_type() .br Signature = binary() .br Key = public_key() .br Options = crypto:pk_sign_verify_opts() .br .RE .RE .RS .LP Verifies a digital signature\&. .LP The \fIMsg\fR\& is either the binary "plain text" data or it is the hashed value of "plain text", that is, the digest\&. .RE .LP .nf .B short_name_hash(Name) -> string() .br .fi .br .RS .LP Types: .RS 3 Name = issuer_name() .br .RE .RE .RS .LP Generates a short hash of an issuer name\&. The hash is returned as a string containing eight hexadecimal digits\&. .LP The return value of this function is the same as the result of the commands \fIopenssl crl -hash\fR\& and \fIopenssl x509 -issuer_hash\fR\&, when passed the issuer name of a CRL or a certificate, respectively\&. This hash is used by the \fIc_rehash\fR\& tool to maintain a directory of symlinks to CRL files, in order to facilitate looking up a CRL by its issuer name\&. .RE