查看源码 public_key (public_key v1.17)
公钥基础设施的 API 模块。
提供处理公钥基础设施的功能,详情请参阅public_key 应用程序。
注意
本参考手册中使用的所有记录均由 ASN.1 规范生成,并在用户指南中记录。请参阅公钥记录。
使用以下 include 指令来访问此处和用户指南中描述的记录和常量宏
-include_lib("public_key/include/public_key.hrl").
摘要
类型:密钥
可以与自定义私钥一起提供,指定一个密钥函数,以提供该函数理解的其他选项。
DSA 算法的 ASN.1 定义的私钥格式。
DSA 算法的 ASN.1 定义的公钥格式。
DSS 算法(DSA 密钥的一部分)的 ASN.1 定义的公钥格式。
ECDSA 算法的 ASN.1 定义的私钥格式。
ECDSA 算法的 ASN.1 定义的公钥格式。
EDDSA 算法的 ASN.1 定义的私钥格式,可能的 oids:?'id-Ed25519' | ?'id-Ed448'
EDDSA 算法的 ASN.1 定义的公钥格式,可能的 oids:?'id-Ed25519' | ?'id-Ed448'
公钥算法的 ASN.1 定义的参数。
支持的私钥
支持的公钥
纯 RSA 算法或自定义函数的 ASN.1 定义的私钥格式。
RSSASSA-PSS 算法或自定义函数的 ASN.1 定义的私钥格式。
RSSASSA-PSS 算法的 ASN.1 定义的公钥格式。
纯 RSA 算法的 ASN.1 定义的公钥格式。
类型:PEM 文件
可能的 Ciphers
是 "RC2-CBC" | "DES-CBC" | "DES-EDE3-CBC" Salt
可以使用 crypto:strong_rand_bytes(8)
生成。
可以在 PEM 文件中找到的 ASN.1 类型,可以由 public_key 应用程序解码。
类型:证书
证书被证书路径验证拒绝的原因。
编码或解码的证书。
证书由其序列号和颁发者名称标识。
可用于同时提供 DER 编码格式和 OTP 解码格式的证书的记录。
证书的颁发者部分的值。
证书策略信息。
证书公钥的信息。
类型:证书吊销
根据 RFC 5280 定义的证书被吊销的原因。
PEM API
解码 PEM 二进制数据,并将条目作为 ASN.1 DER 编码的实体返回。
创建 PEM 二进制数据。
解码 PEM 条目。pem_decode/1
返回 PEM 条目列表。请注意,如果 PEM 条目的类型为“SubjectPublickeyInfo”,它将进一步解码为 rsa_public_key/0
或 dsa_public_key/0
。
创建可馈送到 pem_encode/1
的 PEM 条目。
密钥 API
选择一个 Diffie-Hellman 密钥交换的组,其密钥大小在 MinSize...MaxSize
范围内,并尽可能接近 SuggestedSize
。如果 Groups == undefined
,将使用默认集,否则从 Groups
中选择组。
生成一个新的密钥对。请注意,除了 Diffie-Hellman 之外,公钥包含在私钥结构中。另请参阅 crypto:generate_key/2
证书 API
清除所有已加载的 CA 证书,如果加载了任何证书,则返回 true。
如果加载了受信任的 CA 证书,则返回它们,否则使用 cacerts_load/0
加载它们。如果无法加载 cacerts
,则该函数会失败。
加载操作系统提供的受信任的 CA 证书。
从文件中加载受信任的 CA 证书。
解码 ASN.1 DER 编码的 PKIX 证书。
DER 编码 PKIX x509 证书或此类证书的一部分。
将 OID 转换为 Erlang 摘要类型
检查证书是否为固定 Diffie-Hellman 证书。
检查 IssuerCert
是否颁发了 Cert
。
检查证书是否为自签名证书。
返回 x509 证书颁发者 ID(如果可以确定)。
规范化颁发者名称,以便可以轻松地将其与另一个颁发者名称进行比较。
根据 RFC 5280 执行基本路径验证。
将签名算法 OID 转换为 Erlang 摘要和签名类型。
返回 X509 证书主题 ID。
此函数检查对等证书中的呈现标识符(例如主机名)是否与客户端期望连接的至少一个引用标识符一致。
调用此函数的返回值旨在用于 pkix_verify_hostname/3
中的 match_fun
选项。
证书吊销 API
返回 CRL
的颁发者。
验证 Cert
是否为 CRL
签名者。
执行 CRL 验证。它旨在从 pkix_path_validation/3 的 verify 函数中调用。
为与 Cert
的颁发者相同的颁发者颁发的 CRL 创建一个分发点。可以用作 pkix_crls_validate/3
的输入
从证书扩展中提取分发点。
检查给定的分发点是否与 CRL 的颁发分发点匹配,如 RFC 5280 中所述。
根据 RFC 6960 执行 OCSP 响应验证。当 OCSP 响应成功验证时,返回 {'ok', Details},否则返回 {error, {bad_cert, Reason}}。
生成颁发者名称的短哈希值。哈希值以包含八位十六进制数字的字符串形式返回。
测试数据 API
创建证书配置,包括证书及其私钥加上 CA 证书包,用于客户端和服务器,旨在促进使用 X509 证书的应用程序的自动化测试,通常通过 SSL/TLS。当您在测试场景中可以控制客户端和服务器时,可以使用测试数据。
生成一个根证书,当您希望为多个生成的证书使用相同的根证书时,可以在多次调用 pkix_test_data/1
中使用。
旧版 RSA 加密 API
使用私钥进行公钥解密。另请参阅 crypto:private_decrypt/4
使用公钥进行公钥解密。另请参阅 crypto:public_decrypt/4
使用私钥进行公钥加密。
使用公钥进行公钥加密。另请参阅 crypto:public_encrypt/4
。
类型:通用
-type asn1_type() :: atom().
公钥应用程序 ASN.1 规范中存在的 ASN.1 类型。
-type der_encoded() :: binary().
ASN.1 DER 编码实体。
-type digest_type() :: crypto:sha2() | crypto:sha1() | md5 | none.
用于创建消息摘要的哈希函数
-type oid() :: tuple().
对象标识符,是由 ASN.1
编译器生成的整数元组。
类型:密钥
-type custom_key_opts() :: [term()].
可以与自定义私钥一起提供,指定一个密钥函数,以提供该函数理解的其他选项。
-type dsa_private_key() :: #'DSAPrivateKey'{version :: term(), p :: term(), q :: term(), g :: term(), y :: term(), x :: term()}.
DSA 算法的 ASN.1 定义的私钥格式。
-type dsa_public_key() :: {dss_public_key(), #'Dss-Parms'{p :: term(), q :: term(), g :: term()}}.
DSA 算法的 ASN.1 定义的公钥格式。
-type dss_public_key() :: pos_integer().
DSS 算法(DSA 密钥的一部分)的 ASN.1 定义的公钥格式。
-type ecdsa_private_key() :: #'ECPrivateKey'{version :: term(), privateKey :: term(), parameters :: term(), publicKey :: term(), attributes :: term()}.
ECDSA 算法的 ASN.1 定义的私钥格式。
-type ecdsa_public_key() :: {#'ECPoint'{point :: term()}, {namedCurve, oid()} | #'ECParameters'{version :: term(), fieldID :: term(), curve :: term(), base :: term(), order :: term(), cofactor :: term()}}.
ECDSA 算法的 ASN.1 定义的公钥格式。
-type eddsa_private_key() :: #'ECPrivateKey'{parameters :: {namedCurve, oid()}, version :: term(), privateKey :: term(), publicKey :: term(), attributes :: term()}.
EDDSA 算法的 ASN.1 定义的私钥格式,可能的 oids:?'id-Ed25519' | ?'id-Ed448'
EDDSA 算法的 ASN.1 定义的公钥格式,可能的 oids:?'id-Ed25519' | ?'id-Ed448'
-type key_params() :: 'NULL' | #'RSASSA-PSS-params'{hashAlgorithm :: term(), maskGenAlgorithm :: term(), saltLength :: term(), trailerField :: term()} | {namedCurve, oid()} | #'ECParameters'{version :: term(), fieldID :: term(), curve :: term(), base :: term(), order :: term(), cofactor :: term()} | #'Dss-Parms'{p :: term(), q :: term(), g :: term()}.
公钥算法的 ASN.1 定义的参数。
-type private_key() :: rsa_private_key() | rsa_pss_private_key() | dsa_private_key() | ecdsa_private_key() | eddsa_private_key() | #{algorithm := eddsa | rsa_pss_pss | ecdsa | rsa | dsa, sign_fun => fun()}.
支持的私钥
-type public_key() :: rsa_public_key() | rsa_pss_public_key() | dsa_public_key() | ecdsa_public_key() | eddsa_public_key().
支持的公钥
-type rsa_private_key() :: #'RSAPrivateKey'{version :: term(), modulus :: term(), publicExponent :: term(), privateExponent :: term(), prime1 :: term(), prime2 :: term(), exponent1 :: term(), exponent2 :: term(), coefficient :: term(), otherPrimeInfos :: term()} | #{algorithm := rsa, encrypt_fun => fun()}.
纯 RSA 算法或自定义函数的 ASN.1 定义的私钥格式。
-type rsa_pss_private_key() :: {#'RSAPrivateKey'{version :: term(), modulus :: term(), publicExponent :: term(), privateExponent :: term(), prime1 :: term(), prime2 :: term(), exponent1 :: term(), exponent2 :: term(), coefficient :: term(), otherPrimeInfos :: term()}, #'RSASSA-PSS-params'{hashAlgorithm :: term(), maskGenAlgorithm :: term(), saltLength :: term(), trailerField :: term()}}.
RSSASSA-PSS 算法或自定义函数的 ASN.1 定义的私钥格式。
-type rsa_pss_public_key() :: {rsa_public_key(), #'RSASSA-PSS-params'{hashAlgorithm :: term(), maskGenAlgorithm :: term(), saltLength :: term(), trailerField :: term()}}.
RSSASSA-PSS 算法的 ASN.1 定义的公钥格式。
纯 RSA 算法的 ASN.1 定义的公钥格式。
类型:PEM 文件
-type pem_entry() :: {pki_asn1_type(), DerOrDerEncrypted :: binary(), not_encrypted | {Cipher :: iodata(), Salt :: binary() | {#'PBEParameter'{salt :: term(), iterationCount :: term()}, digest_type()} | #'PBES2-params'{keyDerivationFunc :: term(), encryptionScheme :: term()}}}.
可能的 Ciphers
是 "RC2-CBC" | "DES-CBC" | "DES-EDE3-CBC" Salt
可以使用 crypto:strong_rand_bytes(8)
生成。
-type pki_asn1_type() ::
'Certificate' | 'RSAPrivateKey' | 'RSAPublicKey' | 'SubjectPublicKeyInfo' | 'DSAPrivateKey' |
'DHParameter' | 'PrivateKeyInfo' | 'CertificationRequest' | 'ContentInfo' |
'CertificateList' | 'ECPrivateKey' | 'OneAsymmetricKey' | 'EcpkParameters'.
可以在 PEM 文件中找到的 ASN.1 类型,可以由 public_key 应用程序解码。
类型:证书
-type bad_cert_reason() :: cert_expired | invalid_issuer | invalid_signature | name_not_permitted | missing_basic_constraint | invalid_key_usage | duplicate_cert_in_path | {key_usage_mismatch, term()} | {policy_requirement_not_met, term()} | {invalid_policy_mapping, term()} | {revoked, crl_reason()} | invalid_validity_dates | {revocation_status_undetermined, term()} | atom().
证书被证书路径验证拒绝的原因。
-type cert() :: der_encoded() | #'OTPCertificate'{tbsCertificate :: term(), signatureAlgorithm :: term(), signature :: term()}.
编码或解码的证书。
-type cert_id() :: {SerialNr :: integer(), issuer_name()}.
证书由其序列号和颁发者名称标识。
-type combined_cert() :: #cert{der :: public_key:der_encoded(), otp :: #'OTPCertificate'{tbsCertificate :: term(), signatureAlgorithm :: term(), signature :: term()}}.
可用于同时提供 DER 编码格式和 OTP 解码格式的证书的记录。
这种结构可以避免由于宽松的解码规则而可能出现的转换和问题。
-type issuer_name() :: {rdnSequence, [[#'AttributeTypeAndValue'{type :: term(), value :: term()}]]}.
证书的颁发者部分的值。
-type policy_node() :: #{valid_policy := oid(), qualifier_set := [#'UserNotice'{noticeRef :: term(), explicitText :: term()} | {uri, string()}], expected_policy_set := [oid()]}.
证书策略信息。
-type public_key_info() :: {oid(), rsa_public_key() | #'ECPoint'{point :: term()} | dss_public_key(), key_params()}.
证书公钥的信息。
可能的 oids:?'rsaEncryption' | ?'id-RSASSA-PSS' | ?'id-ecPublicKey' | ?'id-Ed25519' | ?'id-Ed448' | ?'id-dsa'
类型:证书吊销
类型:测试数据
-type cert_opt() :: {digest, digest_type()} | {key, {namedCurve, oid()} | #'ECParameters'{version :: term(), fieldID :: term(), curve :: term(), base :: term(), order :: term(), cofactor :: term()} | {rsa, Size :: pos_integer(), Prime :: pos_integer()} | private_key()} | {validity, {From :: erlang:timestamp(), To :: erlang:timestamp()}} | {extensions, [#'Extension'{extnID :: term(), critical :: term(), extnValue :: term()}]}.
自定义生成的测试证书的选项
-type chain_opts() :: #{root := [cert_opt()], intermediates => [[cert_opt()]], peer := [cert_opt()]}.
证书测试链的不同部分的证书自定义选项。
-type conf_opt() :: {cert, der_encoded()} | {key, private_key()} | {cacerts, [der_encoded()]}.
生成的证书测试链的配置选项。
PEM API
解码 PEM 二进制数据,并将条目作为 ASN.1 DER 编码的实体返回。
示例 {ok, PemBin} = file:read_file("cert.pem"). PemEntries = public_key:pem_decode(PemBin).
创建 PEM 二进制数据。
-spec pem_entry_decode(PemEntry, Password) -> term() when PemEntry :: pem_entry(), Password :: iodata() | fun(() -> iodata()).
解码 PEM 条目。pem_decode/1
返回 PEM 条目列表。请注意,如果 PEM 条目的类型为“SubjectPublickeyInfo”,它将进一步解码为 rsa_public_key/0
或 dsa_public_key/0
。
密码可以是八位字节字符串或返回相同类型的函数。
-spec pem_entry_encode(Asn1Type, Entity) -> pem_entry() when Asn1Type :: pki_asn1_type(), Entity :: term().
等同于 pem_entry_encode/3
。
-spec pem_entry_encode(Asn1Type, Entity, InfoPwd) -> pem_entry() when Asn1Type :: pki_asn1_type(), Entity :: term(), InfoPwd :: {CipherInfo, Password}, CipherInfo :: {Cipher :: iodata(), Salt :: binary() | {#'PBEParameter'{salt :: term(), iterationCount :: term()}, digest_type()} | #'PBES2-params'{keyDerivationFunc :: term(), encryptionScheme :: term()}}, Password :: iodata().
创建可馈送到 pem_encode/1
的 PEM 条目。
如果 Asn1Type
是 'SubjectPublicKeyInfo'
,则 Entity
必须是 rsa_public_key/0
、dsa_public_key/0
或 ecdsa_public_key/0
,此函数将创建相应的 'SubjectPublicKeyInfo'
条目。
密钥 API
-spec compute_key(OthersECDHkey, MyECDHkey) -> SharedSecret when OthersECDHkey :: #'ECPoint'{point :: term()}, MyECDHkey :: #'ECPrivateKey'{version :: term(), privateKey :: term(), parameters :: term(), publicKey :: term(), attributes :: term()}, SharedSecret :: binary().
计算共享密钥。
-spec compute_key(OthersDHkey, MyDHkey, DHparms) -> SharedSecret when OthersDHkey :: crypto:dh_public(), MyDHkey :: crypto:dh_private(), DHparms :: #'DHParameter'{prime :: term(), base :: term(), privateValueLength :: term()}, SharedSecret :: binary().
计算共享密钥。
-spec dh_gex_group(MinSize, SuggestedSize, MaxSize, Groups) -> {ok, {Size, Group}} | {error, term()} when MinSize :: pos_integer(), SuggestedSize :: pos_integer(), MaxSize :: pos_integer(), Groups :: undefined | [{Size, [Group]}], Size :: pos_integer(), Group :: {G, P}, G :: pos_integer(), P :: pos_integer().
选择一个 Diffie-Hellman 密钥交换的组,其密钥大小在 MinSize...MaxSize
范围内,并尽可能接近 SuggestedSize
。如果 Groups == undefined
,将使用默认集,否则从 Groups
中选择组。
首先选择一个大小,尽可能接近 SuggestedSize。然后从指定的组集中随机选择一个具有该密钥大小的组。如果在 MinSize
和 MaxSize
限制范围内没有可用的大小,则返回 {error,no_group_found}
。
默认的组集在 lib/public_key/priv/moduli
中列出。可以像这样重新生成此文件
$> 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
-spec generate_key(DHparams | ECparams | RSAparams) -> DHkeys | ECkey | RSAkey when DHparams :: #'DHParameter'{prime :: term(), base :: term(), privateValueLength :: term()}, DHkeys :: {PublicDH :: binary(), PrivateDH :: binary()}, ECparams :: {namedCurve, oid() | atom()} | #'ECParameters'{version :: term(), fieldID :: term(), curve :: term(), base :: term(), order :: term(), cofactor :: term()}, ECkey :: #'ECPrivateKey'{version :: term(), privateKey :: term(), parameters :: term(), publicKey :: term(), attributes :: term()}, RSAparams :: {rsa, Size, PubExp}, Size :: pos_integer(), PubExp :: pos_integer(), RSAkey :: #'RSAPrivateKey'{version :: term(), modulus :: term(), publicExponent :: term(), privateExponent :: term(), prime1 :: term(), prime2 :: term(), exponent1 :: term(), exponent2 :: term(), coefficient :: term(), otherPrimeInfos :: term()}.
生成一个新的密钥对。请注意,除了 Diffie-Hellman 之外,公钥包含在私钥结构中。另请参阅 crypto:generate_key/2
签名/验证 API
-spec pkix_sign(Cert, Key) -> Der when Cert :: #'OTPTBSCertificate'{version :: term(), serialNumber :: term(), signature :: term(), issuer :: term(), validity :: term(), subject :: term(), subjectPublicKeyInfo :: term(), issuerUniqueID :: term(), subjectUniqueID :: term(), extensions :: term()}, Key :: private_key(), Der :: der_encoded().
签署一个 'OTPTBSCertificate'。返回相应的 DER 编码的证书。
-spec pkix_verify(Cert, Key) -> boolean() when Cert :: der_encoded(), Key :: public_key().
验证 PKIX x.509 证书签名。
-spec sign(Msg, DigestType, Key) -> Signature when Msg :: binary() | {digest, binary()}, DigestType :: digest_type(), Key :: private_key(), Signature :: binary().
-spec sign(Msg, DigestType, Key, Options) -> Signature when Msg :: binary() | {digest, binary()}, DigestType :: digest_type(), Key :: private_key(), Options :: crypto:pk_sign_verify_opts() | custom_key_opts(), Signature :: binary().
创建数字签名。
Msg
是要签名的二进制“纯文本”数据,或者是“纯文本”的哈希值,即摘要。密钥除了是标准密钥外,还可以是指定密钥算法和应处理签名的函数的映射。这可以用于使用例如硬件安全模块 (HSM) 或可信平台模块 (TPM) 进行自定义签名。
-spec verify(Msg, DigestType, Signature, Key) -> boolean() when Msg :: binary() | {digest, binary()}, DigestType :: digest_type(), Signature :: binary(), Key :: public_key().
-spec verify(Msg, DigestType, Signature, Key, Options) -> boolean() when Msg :: binary() | {digest, binary()}, DigestType :: digest_type(), Signature :: binary(), Key :: public_key(), Options :: crypto:pk_sign_verify_opts().
验证数字签名。
Msg
是二进制“纯文本”数据,或者是“纯文本”的哈希值,即摘要。
证书 API
-spec cacerts_clear() -> boolean().
清除所有已加载的 CA 证书,如果加载了任何证书,则返回 true。
-spec cacerts_get() -> [combined_cert()].
如果加载了受信任的 CA 证书,则返回它们,否则使用 cacerts_load/0
加载它们。如果无法加载 cacerts
,则该函数会失败。
-spec cacerts_load() -> ok | {error, Reason :: term()}.
加载操作系统提供的受信任的 CA 证书。
可以通过使用备用证书的位置设置 public_key
应用程序的 cacerts_path
环境变量来覆盖此设置。您可以通过命令行将其设置为
erl -public_key cacerts_path '"/path/to/certs.pem"'
谨慎使用。您有责任确保运行的系统可以信任此备用路径中找到的证书。
-spec cacerts_load(File :: file:filename_all()) -> ok | {error, Reason :: term()}.
从文件中加载受信任的 CA 证书。
-spec pkix_decode_cert(Cert, Type) -> #'Certificate'{tbsCertificate :: term(), signatureAlgorithm :: term(), signature :: term()} | #'OTPCertificate'{tbsCertificate :: term(), signatureAlgorithm :: term(), signature :: term()} when Cert :: der_encoded(), Type :: plain | otp.
解码 ASN.1 DER 编码的 PKIX 证书。
选项 otp
使用自定义的 ASN.1 规范 OTP-PKIX.asn1 进行解码,并且还递归解码大多数标准部分。
-spec pkix_encode(Asn1Type, Entity, Type) -> Der when Asn1Type :: asn1_type(), Entity :: term(), Type :: otp | plain, Der :: der_encoded().
DER 编码 PKIX x509 证书或此类证书的一部分。
此函数必须用于编码以 otp
格式解码/创建的证书或证书部分,而对于纯格式,此函数直接调用 der_encode/2
。
注意
在解码时,可以解决证书中细微的 ASN-1 编码错误,这可能会影响将证书编码回 DER 时可能生成与提供的原始字节不同的字节。
-spec pkix_hash_type(HashOid :: oid()) -> DigestType :: md5 | crypto:sha1() | crypto:sha2().
将 OID 转换为 Erlang 摘要类型
检查证书是否为固定 Diffie-Hellman 证书。
-spec pkix_is_issuer(CertorCRL, IssuerCert) -> boolean() when CertorCRL :: cert() | #'CertificateList'{tbsCertList :: term(), signatureAlgorithm :: term(), signature :: term()}, IssuerCert :: cert().
检查 IssuerCert
是否颁发了 Cert
。
检查证书是否为自签名证书。
-spec pkix_issuer_id(Cert, IssuedBy) -> {ok, ID :: cert_id()} | {error, Reason} when Cert :: cert(), IssuedBy :: self | other, Reason :: term().
返回 x509 证书颁发者 ID(如果可以确定)。
-spec pkix_normalize_name(Issuer) -> Normalized when Issuer :: issuer_name() | der_encoded(), Normalized :: issuer_name().
规范化颁发者名称,以便可以轻松地将其与另一个颁发者名称进行比较。
-spec pkix_path_validation(Cert, CertChain, Options) -> {ok, {PublicKeyInfo, ConstrainedPolicyNodes}} | {error, {bad_cert, Reason :: bad_cert_reason()}} when Cert :: cert() | combined_cert() | atom(), CertChain :: [cert() | combined_cert()], Options :: [{max_path_length, integer()} | {verify_fun, {fun(), term()}}], PublicKeyInfo :: public_key_info(), ConstrainedPolicyNodes :: [policy_node()].
根据 RFC 5280 执行基本路径验证。
但是,CRL 验证由 pkix_crls_validate/3 单独完成,并且应从提供的 verify_fun
中调用。策略树检查是在 OTP-26.2 中添加的,如果证书包含策略,则将返回具有潜在限定符的约束策略集,这些值源自作为路径验证算法一部分创建的策略树。约束集可以仅由证书颁发机构约束,也可以由用户在向此函数提供 policy_set
选项时约束。限定符传达有关有效策略的信息,旨在为最终用户提供信息。
可用选项
{verify_fun, {fun(), UserState::term()} - 该函数必须定义为
fun(OtpCert :: #'OTPCertificate'{}, Event :: {bad_cert, Reason :: bad_cert_reason() | {revoked, atom()}} | {extension, #'Extension'{}}, UserState :: term()) -> {valid, UserState :: term()} | {valid_peer, UserState :: term()} | {fail, Reason :: term()} | {unknown, UserState :: term()}.
或者定义为
fun(OtpCert :: #'OTPCertificate'{}, DerCert :: der_encoded(), Event :: {bad_cert, Reason :: bad_cert_reason() | {revoked, atom()}} | {extension, #'Extension'{}}, UserState :: term()) -> {valid, UserState :: term()} | {valid_peer, UserState :: term()} | {fail, Reason :: term()} | {unknown, UserState :: term()}.
如果回调需要 DER 编码版本,则验证回调可以有 3 个或 4 个参数。
如果验证回调函数返回
{fail, Reason}
,则验证过程立即停止。如果验证回调函数返回{valid, UserState}
,则验证过程继续。这可以用于接受特定的路径验证错误,例如selfsigned_peer
,以及验证应用程序特定的扩展。如果调用时使用了用户应用程序未知的扩展,则应使用返回值{unknown, UserState}
。注意
如果您需要证书的 DER 编码版本,并且拥有 OTP 解码版本,则将其重新编码可能会因常见的不规范编码器的解决方法而导致错误结果。因此,建议使用
Cert
和CertChain
参数调用pkix_path_validation
,格式为der_encoded() | #cert{}
和[der_encoded() | #cert{}]
。另请注意,路径验证本身需要证书的编码版本和解码版本。警告
请注意,用户自定义的
verify_fun
可能会更改原始路径验证错误(例如selfsigned_peer
)。请谨慎使用。{max_path_length, integer()} -
max_path_length
是有效证书路径中,在对等证书之后可以跟随的最大非自签中间证书数量。因此,如果max_path_length
为 0,则 PEER 必须由受信任的 ROOT-CA 直接签名;如果为 1,则路径可以是 PEER、CA、ROOT-CA;如果为 2,则路径可以是 PEER、CA、CA、ROOT-CA,依此类推。{policy_set, [oid()]}(自 OTP 26.2 起)
将接受的策略集合,默认为特殊值[?anyPolicy]
,它将接受所有策略。{explicit_policy, boolean()}(自 OTP 26.2 起)
显式要求路径中的每个证书都必须包含policy_set
中的至少一个证书策略。{inhibit_policy_mapping, boolean()}(自 OTP 26.2 起)
阻止策略映射到其他策略。{inhibit_any_policy, boolean()}(自 OTP 26.2 起)
阻止接受特殊策略?anyPolicy
。
证书无效的原因解释
cert_expired - 证书已过期,因为其到期日期已过。
invalid_issuer - 证书颁发者名称与链中颁发者证书的名称不匹配。
invalid_signature - 证书不是由链中的颁发者证书签名的。
name_not_permitted - 无效的主题备用名称扩展。
missing_basic_constraint - 需要具有基本约束扩展的证书没有基本约束扩展。
invalid_key_usage - 根据密钥用途扩展,证书密钥以无效方式使用。
{revoked, crl_reason()} - 证书已被吊销。
invalid_validity_dates - X.509 证书的有效期部分包含不符合 RFC 的无效日期格式。
atom() - 应用程序特定的错误原因,将由
verify_fun
检查。
-spec pkix_sign_types(AlgorithmId) -> {DigestType, SignatureType} when AlgorithmId :: oid(), DigestType :: digest_type(), SignatureType :: rsa | dsa | ecdsa | eddsa.
将签名算法 OID 转换为 Erlang 摘要和签名类型。
AlgorithmId
是证书或证书吊销列表中的签名 OID。
返回 X509 证书主题 ID。
-spec pkix_verify_hostname(Cert, ReferenceIDs, Options) -> boolean() when Cert :: cert(), ReferenceIDs :: [{uri_id | dns_id | ip | srv_id | atom() | oid(), string()} | {ip, inet:ip_address() | string()}], Options :: [{match_fun | fail_callback | fqdn_fun, fun()}].
此函数检查对等证书中的呈现标识符(例如主机名)是否与客户端期望连接的至少一个引用标识符一致。
该函数旨在作为执行 public_key:pkix_path_validation/3 时对等证书的额外客户端检查添加。
有关主机名验证的详细信息,请参阅 RFC 6125。 用户指南 和 代码示例 更详细地描述了此函数。
此处描述了选项函数
match_fun
fun(ReferenceId::ReferenceId() | FQDN::string(), PresentedId::{dNSName,string()} | {uniformResourceIdentifier,string() | {iPAddress,list(byte())} | {OtherId::atom()|oid(),term()}})
此函数替换默认主机名匹配规则。该函数应返回一个布尔值,以指示参考 ID 和呈现 ID 是否匹配。匹配函数还可以返回第三个值,值,即原子
default
,如果应应用默认匹配规则。这使得可以使用特殊情况来增强测试。fun(....) -> true; % My special case (_, _) -> default % all others falls back to the inherit tests end
有关获取协议名称作为参数并返回适用于此选项的
fun/2
的函数,请参阅pkix_verify_hostname_match_fun/1
,有关示例,请参阅用户指南中的重新定义匹配操作。注意
以二进制形式给出的参考 ID 值将转换为字符串,并且 IP 参考可以以字符串格式给出,例如“10.0.1.1”或“1234::5678:9012”,以及
inet:ip_address/0
格式。fail_callback
- 如果匹配失败,则在某些情况下仍应接受证书。例如,考虑一个 Web 浏览器,您可以选择接受过期的证书。此选项允许实现此类例外情况,但针对主机名。当没有ReferenceID
匹配时,将调用此fun/1
。该函数的返回值(boolean/0
)决定结果。如果true
,则接受证书,否则拒绝证书。请参阅用户指南中的“固定”证书。fqdn_fun
- 此选项增强了从 URI 和其他参考 ID 中提取主机名的能力。例如,它可能是一个非常特殊的非标准化 URI。该函数以参考 ID 作为参数,并返回以下之一:- 主机名
- 原子
default
:将使用默认的主机名提取函数 - 原子
undefined
:无法提取主机名。pkix_verify_hostname/3 将返回false
。
有关示例,请参阅用户指南中的主机名提取。
-spec pkix_verify_hostname_match_fun(Protocol) -> Result when Protocol :: https, Result :: fun().
调用此函数的返回值旨在用于 pkix_verify_hostname/3
中的 match_fun
选项。
根据参数中协议的特定规则,返回的函数会增强主机名匹配。
注意
当前支持的 https 函数将允许按照 HTTP 标准指定的通配符证书匹配。请注意,例如,LDAP 有一组不同的通配符匹配规则。如果您不想允许通配符证书(从安全角度来看建议这样做)或以其他方式自定义主机名匹配,则 ssl 应用程序使用的默认匹配函数就足够了。
证书吊销 API
-spec pkix_crl_issuer(CRL) -> Issuer when CRL :: der_encoded() | #'CertificateList'{tbsCertList :: term(), signatureAlgorithm :: term(), signature :: term()}, Issuer :: issuer_name().
返回 CRL
的颁发者。
-spec pkix_crl_verify(CRL, Cert) -> boolean() when CRL :: der_encoded() | #'CertificateList'{tbsCertList :: term(), signatureAlgorithm :: term(), signature :: term()}, Cert :: cert().
验证 Cert
是否为 CRL
签名者。
-spec pkix_crls_validate(OTPcertificate, DPandCRLs, Options) -> CRLstatus when OTPcertificate :: #'OTPCertificate'{tbsCertificate :: term(), signatureAlgorithm :: term(), signature :: term()}, DPandCRLs :: [DPandCRL], DPandCRL :: {DP, {DerCRL, CRL}}, DP :: #'DistributionPoint'{distributionPoint :: term(), reasons :: term(), cRLIssuer :: term()}, DerCRL :: der_encoded(), CRL :: #'CertificateList'{tbsCertList :: term(), signatureAlgorithm :: term(), signature :: term()}, Options :: [{atom(), term()}], CRLstatus :: valid | {bad_cert, BadCertReason}, BadCertReason :: revocation_status_undetermined | {revocation_status_undetermined, Reason :: term()} | {revoked, crl_reason()}.
执行 CRL 验证。它旨在从 pkix_path_validation/3 的 verify 函数中调用。
可用选项
{update_crl, fun()} - 该函数具有以下类型规范:
fun(#'DistributionPoint'{}, #'CertificateList'{}) -> #'CertificateList'{}
该函数使用分配点中的信息来访问最新版本的 CRL。如果未指定此函数,则 Public Key 使用默认实现。
fun(_DP, CRL) -> CRL end
{issuer_fun, {fun(), UserState::term()}} - 该函数具有以下类型规范:
fun(#'DistributionPoint'{}, #'CertificateList'{}, {rdnSequence,[#'AttributeTypeAndValue'{}]}, UserState::term()) -> {ok, #'OTPCertificate'{}, [der_encoded]}
该函数返回签署 CRL 的根证书和证书链。
fun(DP, CRL, Issuer, UserState) -> {ok, RootCert, CertChain}
{undetermined_details, boolean()} - 默认为 false。当无法确定吊销状态时,如果将此选项设置为 true,则返回值中将包含未接受任何 CRL 的原因的详细信息。
-spec pkix_dist_point(Cert) -> DistPoint when Cert :: cert(), DistPoint :: #'DistributionPoint'{distributionPoint :: term(), reasons :: term(), cRLIssuer :: term()}.
为与 Cert
的颁发者相同的颁发者颁发的 CRL 创建一个分发点。可以用作 pkix_crls_validate/3
的输入
-spec pkix_dist_points(Cert) -> DistPoints when Cert :: cert(), DistPoints :: [#'DistributionPoint'{distributionPoint :: term(), reasons :: term(), cRLIssuer :: term()}].
从证书扩展中提取分发点。
-spec pkix_match_dist_point(CRL, DistPoint) -> boolean() when CRL :: der_encoded() | #'CertificateList'{tbsCertList :: term(), signatureAlgorithm :: term(), signature :: term()}, DistPoint :: #'DistributionPoint'{distributionPoint :: term(), reasons :: term(), cRLIssuer :: term()}.
检查给定的分发点是否与 CRL 的颁发分发点匹配,如 RFC 5280 中所述。
如果 CRL 没有颁发分配点扩展,则分配点始终匹配。
-spec pkix_ocsp_validate(Cert, IssuerCert, OcspRespDer, NonceExt, Options) -> {ok, Details} | {error, {bad_cert, Reason}} when Cert :: cert(), IssuerCert :: cert(), OcspRespDer :: der_encoded(), NonceExt :: undefined | binary(), Options :: [{is_trusted_responder_fun, fun((combined_cert()) -> boolean)}], Details :: list(), Reason :: bad_cert_reason().
根据 RFC 6960 执行 OCSP 响应验证。当 OCSP 响应成功验证时,返回 {'ok', Details},否则返回 {error, {bad_cert, Reason}}。
可用选项
{is_trusted_responder_fun, fun()} - 该函数具有以下类型规范:
fun(#cert{}) -> boolean()
如果参数中的证书受信任,则该函数返回
true
。如果未指定此函数,则 Public Key 使用默认实现。fun(_) -> false end
注意
可以在没有 nonce 值的情况下提供 OCSP 响应 - 即使客户端请求了 nonce 值。在这种情况下,{missing, ocsp_nonce} 将在 Details 列表中返回。
-spec short_name_hash(Name) -> string() when Name :: issuer_name().
生成颁发者名称的短哈希值。哈希值以包含八位十六进制数字的字符串形式返回。
此函数的返回值与命令 openssl crl -hash
和 openssl x509 -issuer_hash
的结果相同,分别传递 CRL 或证书的颁发者名称时。此哈希由 c_rehash
工具使用,以维护指向 CRL 文件的符号链接目录,以便于按其颁发者名称查找 CRL。
ASN.1 编码 API
测试数据 API
-spec pkix_test_data(ChainConf) -> TestConf when ChainConf :: #{server_chain := chain_opts(), client_chain := chain_opts()} | chain_opts(), TestConf :: #{server_config := [conf_opt()], client_config := [conf_opt()]} | [conf_opt()].
创建证书配置,包括证书及其私钥加上 CA 证书包,用于客户端和服务器,旨在促进使用 X509 证书的应用程序的自动化测试,通常通过 SSL/TLS。当您在测试场景中可以控制客户端和服务器时,可以使用测试数据。
当使用包含客户端和服务器链规范的映射调用此函数时,它会生成客户端和服务器证书链。其中,返回给服务器的 cacerts
包含服务器应信任的根证书以及服务器应呈现给连接客户端的中间证书。服务器应信任的根证书是客户端证书链的根证书。反之亦然适用于返回给客户端的 cacerts
。根证书可以使用 pkix_test_root_cert/2 预先生成,或者如果指定了选项,则会生成根证书。
当使用证书选项列表调用此函数时,它会生成一个配置,其中只有一个节点证书,其中 cacerts
包含根证书和应该呈现给对等方的中间证书。在这种情况下,所有对等方都必须使用相同的根证书。这在例如 Erlang 分布式集群中很有用,其中任何节点相对于另一个节点,都根据谁连接到谁而充当服务器或客户端。生成的证书包含一个主体备用名称,这不是客户端证书所必需的,但使该证书可用于两种角色。
用于自定义生成的链中证书的选项说明
{digest, digest_type()} - 用于签署证书以及密钥选项的哈希算法。默认为 sha,即 sha1。
{key, ec_params()| {rsa, Size:pos_integer(), Prime::pos_integer()} | private_key()} - 用于调用 public_key:generate_key/1 生成密钥的参数,或者现有密钥。默认为生成 ECDSA 密钥。请注意,如果 Erlang/OTP 是用非常旧的 cryptolib 编译的,则可能会失败。
{validity, {From::erlang:timestamp(), To::erlang:timestamp()}} - 证书的有效期。
{extensions, [#'Extension'{}]} - 要包含在证书中的扩展。
如果未另行指定,则 CA 证书中包含的默认扩展为
[#'Extension'{extnID = ?'id-ce-keyUsage', extnValue = [keyCertSign, cRLSign], critical = false}, #'Extension'{extnID = ?'id-ce-basicConstraints', extnValue = #'BasicConstraints'{cA = true}, critical = true}]
如果未另行指定,则服务器对等证书中包含的默认扩展为
[#'Extension'{extnID = ?'id-ce-keyUsage', extnValue = [digitalSignature, keyAgreement], critical = false}, #'Extension'{extnID = ?'id-ce-subjectAltName', extnValue = [{dNSName, Hostname}], critical = false}]
主机名是在调用此函数的 Erlang 节点中调用 net_adm:localhost() 的结果。
注意
请注意,生成的证书和密钥不提供正式正确的 PKIX 信任链,它们不能用于实现真正的安全性。此功能仅供测试使用。
-spec pkix_test_root_cert(Name, Options) -> RootCertAndKey when Name :: string(), Options :: [cert_opt()], RootCertAndKey :: #{cert := der_encoded(), key := private_key()}.
生成一个根证书,当您希望为多个生成的证书使用相同的根证书时,可以在多次调用 pkix_test_data/1
中使用。
传统 RSA 加密 API
-spec decrypt_private(CipherText, Key) -> PlainText when CipherText :: binary(), Key :: rsa_private_key(), PlainText :: binary().
-spec decrypt_private(CipherText, Key, Options) -> PlainText when CipherText :: binary(), Key :: rsa_private_key(), Options :: crypto:pk_encrypt_decrypt_opts(), PlainText :: binary().
使用私钥进行公钥解密。另请参阅 crypto:private_decrypt/4
警告
这是一个遗留函数,出于安全原因,请勿将其与 rsa_pkcs1_padding 一起使用。
-spec decrypt_public(CipherText, Key) -> PlainText when CipherText :: binary(), Key :: rsa_public_key(), PlainText :: binary().
-spec decrypt_public(CipherText, Key, Options) -> PlainText when CipherText :: binary(), Key :: rsa_public_key(), Options :: crypto:pk_encrypt_decrypt_opts(), PlainText :: binary().
使用公钥进行公钥解密。另请参阅 crypto:public_decrypt/4
警告
这是一个遗留函数,出于安全原因,请勿将其与 rsa_pkcs1_padding 一起使用。对于数字签名,建议使用
verify/4
和sign/3
。
-spec encrypt_private(PlainText, Key) -> CipherText when PlainText :: binary(), Key :: rsa_private_key(), CipherText :: binary().
-spec encrypt_private(PlainText, Key, Options) -> CipherText when PlainText :: binary(), Key :: rsa_private_key(), Options :: crypto:pk_encrypt_decrypt_opts() | custom_key_opts(), CipherText :: binary().
使用私钥进行公钥加密。
另请参阅 crypto:private_encrypt/4
。密钥除了标准的 RSA 密钥外,还可以是指定密钥算法 rsa
和用于处理加密操作的函数的映射。这可用于通过例如硬件安全模块(HSM)或可信平台模块(TPM)自定义加密操作。
警告
这是一个遗留函数,出于安全原因,请勿将其与 rsa_pkcs1_padding 一起使用。对于数字签名,建议使用
sign/3
和verify/4
。
-spec encrypt_public(PlainText, Key) -> CipherText when PlainText :: binary(), Key :: rsa_public_key(), CipherText :: binary().
-spec encrypt_public(PlainText, Key, Options) -> CipherText when PlainText :: binary(), Key :: rsa_public_key(), Options :: crypto:pk_encrypt_decrypt_opts(), CipherText :: binary().
使用公钥进行公钥加密。另请参阅 crypto:public_encrypt/4
。
警告
这是一个遗留函数,出于安全原因,请勿将其与 rsa_pkcs1_padding 一起使用。