aboutsummaryrefslogtreecommitdiffstats
path: root/lib/public_key/doc/src/public_key.xml
diff options
context:
space:
mode:
Diffstat (limited to 'lib/public_key/doc/src/public_key.xml')
-rw-r--r--lib/public_key/doc/src/public_key.xml737
1 files changed, 478 insertions, 259 deletions
diff --git a/lib/public_key/doc/src/public_key.xml b/lib/public_key/doc/src/public_key.xml
index bce6d58682..385604677c 100644
--- a/lib/public_key/doc/src/public_key.xml
+++ b/lib/public_key/doc/src/public_key.xml
@@ -1,24 +1,25 @@
-<?xml version="1.0" encoding="iso-8859-1" ?>
+<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE erlref SYSTEM "erlref.dtd">
<erlref>
<header>
<copyright>
<year>2008</year>
- <year>2013</year>
+ <year>2015</year>
<holder>Ericsson AB, All Rights Reserved</holder>
</copyright>
<legalnotice>
- The contents of this file are subject to the Erlang Public License,
- Version 1.1, (the "License"); you may not use this file except in
- compliance with the License. You should have received a copy of the
- Erlang Public License along with this software. If not, it can be
- retrieved online at http://www.erlang.org/.
-
- Software distributed under the License is distributed on an "AS IS"
- basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
- the License for the specific language governing rights and limitations
- under the License.
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
The Initial Developer of the Original Code is Ericsson AB.
</legalnotice>
@@ -31,97 +32,142 @@
<rev></rev>
</header>
<module>public_key</module>
- <modulesummary> API module for public key infrastructure.</modulesummary>
+ <modulesummary>API module for public-key infrastructure.</modulesummary>
<description>
- <p>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.
+ <p>Provides functions to handle public-key infrastructure,
+ for details see
+ <seealso marker="public_key_app">public_key(6)</seealso>.
</p>
</description>
<section>
- <title>public_key</title>
-
- <list type="bulleted">
- <item>public_key requires the crypto and asn1 applications, the latter since R16 (hopefully the runtime dependency on asn1 will
- be removed again in the future).</item>
-
- <item>Supports <url href="http://www.ietf.org/rfc/rfc5280.txt">RFC 5280 </url> -
- Internet X.509 Public Key Infrastructure Certificate and Certificate Revocation List (CRL) Profile </item>
- <item>Supports <url href="http://www.rsa.com/rsalabs/node.asp?id=2125"> PKCS-1 </url> - RSA Cryptography Standard </item>
- <item>Supports <url href="http://csrc.nist.gov/publications/fips/fips186-3/fips_186-3.pdf"> DSS</url>- Digital Signature Standard (DSA - Digital Signature Algorithm)</item>
- <item>Supports <url href="http://www.rsa.com/rsalabs/node.asp?id=2126"> PKCS-3 </url> - Diffie-Hellman Key Agreement Standard </item>
- <item>Supports <url href="http://www.rsa.com/rsalabs/node.asp?id=2127"> PKCS-5</url> - Password-Based Cryptography Standard </item>
- <item>Supports <url href="http://www.rsa.com/rsalabs/node.asp?id=2130"> PKCS-8</url> - Private-Key Information Syntax Standard</item>
- <item>Supports <url href="http://www.rsa.com/rsalabs/node.asp?id=2132"> PKCS-10</url> - Certification Request Syntax Standard</item>
- </list>
- </section>
-
- <section>
- <title>COMMON DATA TYPES </title>
+ <title>DATA TYPES</title>
- <note><p>All records used in this manual
+ <note><p>All records used in this Reference Manual
<!-- except #policy_tree_node{} -->
are generated from ASN.1 specifications
and are documented in the User's Guide. See <seealso
- marker="public_key_records">Public key records</seealso> and <seealso
- marker="cert_records">X.509 Certificate records</seealso>.
+ marker="public_key_records">Public-key Records</seealso>.
</p></note>
<p>Use the following include directive to get access to the
- records and constant macros described here and in the User's Guide.</p>
+ records and constant macros described here and in the User's Guide:</p>
- <code> -include_lib("public_key/include/public_key.hrl"). </code>
+ <code> -include_lib("public_key/include/public_key.hrl").</code>
- <p><em>Data Types </em></p>
-
- <p><code>oid() - a tuple of integers as generated by the ASN1 compiler.</code></p>
+ <p>The following data types are used in the functions for <c>public_key</c>:</p>
- <p><code>boolean() = true | false</code></p>
+ <taglist>
+ <tag><c>oid()</c></tag>
+ <item><p>Object identifier, a tuple of integers as generated by the <c>ASN.1</c> compiler.</p></item>
- <p><code>string() = [bytes()]</code></p>
+ <tag><c>boolean() =</c></tag>
+ <item><p><c>true | false</c></p></item>
+
+ <tag><c>string() =</c></tag>
+ <item><p><c>[bytes()]</c></p></item>
+
+ <tag><c>der_encoded() =</c></tag>
+ <item><p><c>binary()</c></p></item>
+
+ <tag><c>pki_asn1_type() =</c></tag>
+ <item>
+ <p><c>'Certificate'</c></p>
+ <p><c>| 'RSAPrivateKey'</c></p>
+ <p><c>| 'RSAPublicKey'</c></p>
+ <p><c>| 'DSAPrivateKey'</c></p>
+ <p><c>| 'DSAPublicKey'</c></p>
+ <p><c>| 'DHParameter'</c></p>
+ <p><c>| 'SubjectPublicKeyInfo'</c></p>
+ <p><c>| 'PrivateKeyInfo'</c></p>
+ <p><c>| 'CertificationRequest'</c></p>
+ <p><c>| 'CertificateList'</c></p>
+ <p><c>| 'ECPrivateKey'</c></p>
+ <p><c>| 'EcpkParameters'</c></p>
+ </item>
+
+ <tag><c>pem_entry () =</c></tag>
+ <item><p><c>{pki_asn1_type(), binary(), %% DER or encrypted DER</c></p>
+ <p><c> not_encrypted | cipher_info()}</c></p></item>
+
+ <tag><c>cipher_info() = </c></tag>
+ <item><p><c>{"RC2-CBC" | "DES-CBC" | "DES-EDE3-CBC", crypto:strong_rand_bytes(8)</c></p>
+ <p><c>| {#'PBEParameter{}, digest_type()} | #'PBES2-params'{}}</c></p>
+ </item>
+
+ <tag><c>public_key() =</c></tag>
+ <item><p><c>rsa_public_key() | dsa_public_key() | ec_public_key()</c></p></item>
+
+ <tag><c>private_key() =</c></tag>
+ <item><p><c>rsa_private_key() | dsa_private_key() | ec_private_key()</c></p></item>
- <p><code>der_encoded() = binary()</code></p>
-
- <p><code>pki_asn1_type() = 'Certificate' | 'RSAPrivateKey'| 'RSAPublicKey' |
- 'DSAPrivateKey' | 'DSAPublicKey' | 'DHParameter' | 'SubjectPublicKeyInfo' |
- 'PrivateKeyInfo' | 'CertificationRequest' | 'ECPrivateKey'|
- 'EcpkParameters'</code></p>
-
- <p><code>pem_entry () = {pki_asn1_type(), binary(), %% DER or encrypted DER
- not_encrypted | cipher_info()} </code></p>
+ <tag><c>rsa_public_key() =</c></tag>
+ <item><p><c>#'RSAPublicKey'{}</c></p></item>
- <p><code>cipher_info() = {"RC2-CBC | "DES-CBC" | "DES-EDE3-CBC", crypto:rand_bytes(8)} |
- 'PBES2-params'} </code></p>
-
- <p><code>rsa_public_key() = #'RSAPublicKey'{}</code></p>
+ <tag><c>rsa_private_key() =</c></tag>
+ <item><p><c>#'RSAPrivateKey'{}</c></p></item>
- <p><code>rsa_private_key() = #'RSAPrivateKey'{} </code></p>
+ <tag><c>dsa_public_key() =</c></tag>
+ <item><p><c>{integer(), #'Dss-Parms'{}}</c></p></item>
- <p><code>dsa_public_key() = {integer(), #'Dss-Parms'{}} </code></p>
+ <tag><c>dsa_private_key() =</c></tag>
+ <item><p><c>#'DSAPrivateKey'{}</c></p></item>
- <p><code>dsa_private_key() = #'DSAPrivateKey'{}</code></p>
+ <tag><c>ec_public_key()</c></tag>
+ <item><p>= <c>{#'ECPoint'{}, #'ECParameters'{} | {namedCurve, oid()}}</c></p></item>
- <p><code>ec_public_key() = {#'ECPoint'{}, #'EcpkParameters'{} | {namedCurve, oid()}} </code></p>
-
- <p><code>ec_private_key() = #'ECPrivateKey'{}</code></p>
+ <tag><c>ec_private_key() =</c></tag>
+ <item><p><c>#'ECPrivateKey'{}</c></p></item>
- <p><code> public_crypt_options() = [{rsa_pad, rsa_padding()}]. </code></p>
+ <tag><c>public_crypt_options() =</c></tag>
+ <item><p><c>[{rsa_pad, rsa_padding()}]</c></p></item>
- <p><code> rsa_padding() = 'rsa_pkcs1_padding' | 'rsa_pkcs1_oaep_padding'
- | 'rsa_no_padding'</code></p>
-
- <p><code> rsa_digest_type() = 'md5' | 'sha' | 'sha224' | 'sha256' | 'sha384' | 'sha512' </code></p>
+ <tag><c>rsa_padding() =</c></tag>
+ <item>
+ <p><c>'rsa_pkcs1_padding'</c></p>
+ <p><c>| 'rsa_pkcs1_oaep_padding'</c></p>
+ <p><c>| 'rsa_no_padding'</c></p>
+ </item>
- <p><code> dss_digest_type() = 'sha' </code></p>
+ <tag><c>digest_type() = </c></tag>
+ <item><p>Union of <c>rsa_digest_type()</c>, <c>dss_digest_type()</c>,
+ and <c>ecdsa_digest_type()</c>.</p></item>
- <p><code> ecdsa_digest_type() = 'sha'| 'sha224' | 'sha256' | 'sha384' | 'sha512' </code></p>
+ <tag><c>rsa_digest_type() = </c></tag>
+ <item><p><c>'md5' | 'sha' | 'sha224' | 'sha256' | 'sha384' | 'sha512'</c></p></item>
- <p><code> crl_reason() = unspecified | keyCompromise | cACompromise | affiliationChanged | superseded | cessationOfOperation | certificateHold | privilegeWithdrawn | aACompromise
- </code></p>
+ <tag><c>dss_digest_type() = </c></tag>
+ <item><p><c>'sha'</c></p></item>
- <p><code> ssh_file() = openssh_public_key | rfc4716_public_key |
- known_hosts | auth_keys </code></p>
+ <tag><c>ecdsa_digest_type() = </c></tag>
+ <item><p><c>'sha'| 'sha224' | 'sha256' | 'sha384' | 'sha512'</c></p></item>
+
+ <tag><c>crl_reason() = </c></tag>
+ <item>
+ <p><c>unspecified</c></p>
+ <p><c>| keyCompromise</c></p>
+ <p><c>| cACompromise</c></p>
+ <p><c>| affiliationChanged</c></p>
+ <p><c>| superseded</c></p>
+ <p><c>| cessationOfOperation</c></p>
+ <p><c>| certificateHold</c></p>
+ <p><c>| privilegeWithdrawn</c></p>
+ <p><c>| aACompromise</c></p>
+ </item>
+
+ <tag><c>issuer_name() =</c></tag>
+ <item><p><c>{rdnSequence,[#'AttributeTypeAndValue'{}]}</c></p>
+ </item>
+
+ <tag><c>ssh_file() =</c></tag>
+ <item>
+ <p><c>openssh_public_key</c></p>
+ <p><c>| rfc4716_public_key</c></p>
+ <p><c>| known_hosts</c></p>
+ <p><c>| auth_keys</c></p>
+ </item>
+ </taglist>
+
<!-- <p><code>policy_tree() = [Root, Children]</code></p> -->
@@ -129,12 +175,12 @@
<!-- <p><code>Children = [] | policy_tree()</code></p> -->
-<!-- <p> The policy_tree_node record has the following fields:</p> -->
+<!-- <p>The <c>policy_tree_node</c> record has the following fields:</p> -->
<!-- <taglist> -->
<!-- <tag>valid_policy</tag> -->
-<!-- <item> Is a single policy OID representing a -->
+<!-- <item>A single policy OID representing a -->
<!-- valid policy for the path of length x.</item> -->
<!-- <tag>qualifier_set</tag> -->
@@ -142,13 +188,13 @@
<!-- with the valid policy in certificate x.</item> -->
<!-- <tag>critically_indicator</tag> -->
-<!-- <item>The critically_indicator indicates whether the -->
+<!-- <item>Indicates whether the -->
<!-- certificate policy extension in certificate x was marked as -->
-<!-- critical. </item> -->
+<!-- critical.</item> -->
<!-- <tag>expected_policy_set</tag> -->
-<!-- <item>The expected_policy_set contains one or more policy OIDs -->
-<!-- that would satisfy this policy in the certificate x+1. </item> -->
+<!-- <item>Contains one or more policy OIDs -->
+<!-- that would satisfy this policy in the certificate x+1.</item> -->
<!-- </taglist> -->
</section>
@@ -157,27 +203,27 @@
<func>
<name>compute_key(OthersKey, MyKey)-></name>
<name>compute_key(OthersKey, MyKey, Params)-></name>
- <fsummary> Compute shared secret</fsummary>
+ <fsummary>Computes shared secret.</fsummary>
<type>
<v>OthersKey = #'ECPoint'{} | binary(), MyKey = #'ECPrivateKey'{} | binary()</v>
<v>Params = #'DHParameter'{}</v>
</type>
<desc>
- <p> Compute shared secret </p>
+ <p>Computes shared secret.</p>
</desc>
</func>
<func>
<name>decrypt_private(CipherText, Key) -> binary()</name>
<name>decrypt_private(CipherText, Key, Options) -> binary()</name>
- <fsummary>Public key decryption.</fsummary>
+ <fsummary>Public-key decryption.</fsummary>
<type>
<v>CipherText = binary()</v>
<v>Key = rsa_private_key()</v>
<v>Options = public_crypt_options()</v>
</type>
<desc>
- <p>Public key decryption using the private key. See also <seealso
+ <p>Public-key decryption using the private key. See also <seealso
marker="crypto:crypto#private_decrypt/4">crypto:private_decrypt/4</seealso></p>
</desc>
</func>
@@ -185,156 +231,188 @@
<func>
<name>decrypt_public(CipherText, Key) - > binary()</name>
<name>decrypt_public(CipherText, Key, Options) - > binary()</name>
- <fsummary></fsummary>
+ <fsummary>Public-key decryption.</fsummary>
<type>
<v>CipherText = binary()</v>
<v>Key = rsa_public_key()</v>
<v>Options = public_crypt_options()</v>
</type>
<desc>
- <p> Public key decryption using the public key. See also <seealso
+ <p>Public-key decryption using the public key. See also <seealso
marker="crypto:crypto#public_decrypt/4">crypto:public_decrypt/4</seealso></p>
</desc>
</func>
<func>
<name>der_decode(Asn1type, Der) -> term()</name>
- <fsummary> Decodes a public key ASN.1 DER encoded entity.</fsummary>
+ <fsummary>Decodes a public-key ASN.1 DER encoded entity.</fsummary>
<type>
<v>Asn1Type = atom()</v>
- <d> ASN.1 type present in the public_key applications
- asn1 specifications.</d>
+ <d>ASN.1 type present in the Public Key applications
+ ASN.1 specifications.</d>
<v>Der = der_encoded()</v>
</type>
<desc>
- <p> Decodes a public key ASN.1 DER encoded entity.</p>
+ <p>Decodes a public-key ASN.1 DER encoded entity.</p>
</desc>
</func>
<func>
<name>der_encode(Asn1Type, Entity) -> der_encoded()</name>
- <fsummary> Encodes a public key entity with asn1 DER encoding.</fsummary>
+ <fsummary>Encodes a public-key entity with ASN.1 DER encoding.</fsummary>
<type>
<v>Asn1Type = atom()</v>
- <d> Asn1 type present in the public_key applications
+ <d>ASN.1 type present in the Public Key applications
ASN.1 specifications.</d>
<v>Entity = term()</v>
- <d>The erlang representation of <c>Asn1Type</c></d>
+ <d>Erlang representation of <c>Asn1Type</c></d>
</type>
<desc>
- <p> Encodes a public key entity with ASN.1 DER encoding.</p>
+ <p>Encodes a public-key entity with ASN.1 DER encoding.</p>
</desc>
</func>
<func>
+ <name>dh_gex_group(MinSize, SuggestedSize, MaxSize, Groups) -> {ok, {Size,Group}} | {error,Error}</name>
+ <fsummary>Selects a group for Diffie-Hellman key exchange</fsummary>
+ <type>
+ <v>MinSize = positive_integer()</v>
+ <v>SuggestedSize = positive_integer()</v>
+ <v>MaxSize = positive_integer()</v>
+ <v>Groups = undefined | [{Size,[{G,P}]}]</v>
+ <v>Size = positive_integer()</v>
+ <v>Group = {G,P}</v>
+ <v>G = positive_integer()</v>
+ <v>P = positive_integer()</v>
+ </type>
+ <desc>
+ <p>Selects a group for Diffie-Hellman key exchange with the key size in the range <c>MinSize...MaxSize</c>
+ and as close to <c>SuggestedSize</c> as possible. If <c>Groups == undefined</c> a default set will be
+ used, otherwise the group is selected from <c>Groups</c>.</p>
+ <p>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 <c>MinSize</c>
+ and <c>MaxSize</c> is available, <c>{error,no_group_found}</c> is returned.</p>
+ <p>The default set of groups is listed in <c>lib/public_key/priv/moduli</c>. This file may be regenerated like this:</p>
+ <pre>
+ $> 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
+ </pre>
+ </desc>
+ </func>
+
+ <func>
+ <name>encrypt_private(PlainText, Key) -> binary()</name>
+ <fsummary>Public-key encryption using the private key.</fsummary>
+ <type>
+ <v>PlainText = binary()</v>
+ <v>Key = rsa_private_key()</v>
+ </type>
+ <desc>
+ <p>Public-key encryption using the private key.
+ See also <seealso
+ marker="crypto:crypto#private_encrypt/4">crypto:private_encrypt/4</seealso>.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name>encrypt_public(PlainText, Key) -> binary()</name>
+ <fsummary>Public-key encryption using the public key.</fsummary>
+ <type>
+ <v>PlainText = binary()</v>
+ <v>Key = rsa_public_key()</v>
+ </type>
+ <desc>
+ <p>Public-key encryption using the public key. See also <seealso
+ marker="crypto:crypto#public_encrypt/4">crypto:public_encrypt/4</seealso>.</p>
+ </desc>
+ </func>
+
+ <func>
<name>generate_key(Params) -> {Public::binary(), Private::binary()} | #'ECPrivateKey'{} </name>
- <fsummary>Generates a new keypair</fsummary>
+ <fsummary>Generates a new keypair.</fsummary>
<type>
- <v> Params = #'DHParameter'{} | {namedCurve, oid()} | #'ECParameters'{} </v>
+ <v>Params = #'DHParameter'{} | {namedCurve, oid()} | #'ECParameters'{}</v>
</type>
<desc>
- <p>Generates a new keypair</p>
+ <p>Generates a new keypair.</p>
</desc>
</func>
<func>
<name>pem_decode(PemBin) -> [pem_entry()]</name>
- <fsummary>Decode PEM binary data and return
- entries as ASN.1 DER encoded entities. </fsummary>
+ <fsummary>Decodes PEM binary data and returns
+ entries as ASN.1 DER encoded entities.</fsummary>
<type>
<v>PemBin = binary()</v>
<d>Example {ok, PemBin} = file:read_file("cert.pem").</d>
</type>
<desc>
- <p>Decode PEM binary data and return
+ <p>Decodes PEM binary data and returns
entries as ASN.1 DER encoded entities.</p>
</desc>
</func>
<func>
<name>pem_encode(PemEntries) -> binary()</name>
- <fsummary>Creates a PEM binary</fsummary>
+ <fsummary>Creates a PEM binary.</fsummary>
<type>
<v> PemEntries = [pem_entry()] </v>
</type>
<desc>
- <p>Creates a PEM binary</p>
+ <p>Creates a PEM binary.</p>
</desc>
</func>
<func>
<name>pem_entry_decode(PemEntry) -> term()</name>
<name>pem_entry_decode(PemEntry, Password) -> term()</name>
- <fsummary>Decodes a pem entry.</fsummary>
+ <fsummary>Decodes a PEM entry.</fsummary>
<type>
- <v> PemEntry = pem_entry() </v>
- <v> Password = string() </v>
+ <v>PemEntry = pem_entry()</v>
+ <v>Password = string()</v>
</type>
<desc>
- <p>Decodes a PEM entry. pem_decode/1 returns a list of PEM
- entries. Note that if the PEM entry is of type
- 'SubjectPublickeyInfo' it will be further decoded to an
- rsa_public_key() or dsa_public_key().</p>
+ <p>Decodes a PEM entry. <c>pem_decode/1</c> returns a list of PEM
+ entries. Notice that if the PEM entry is of type
+ 'SubjectPublickeyInfo', it is further decoded to an
+ <c>rsa_public_key()</c> or <c>dsa_public_key()</c>.</p>
</desc>
</func>
<func>
<name>pem_entry_encode(Asn1Type, Entity) -> pem_entry()</name>
<name>pem_entry_encode(Asn1Type, Entity, {CipherInfo, Password}) -> pem_entry()</name>
- <fsummary> Creates a PEM entry that can be fed to pem_encode/1.</fsummary>
+ <fsummary>Creates a PEM entry that can be fed to <c>pem_encode/1</c>.</fsummary>
<type>
<v>Asn1Type = pki_asn1_type()</v>
<v>Entity = term()</v>
- <d>The Erlang representation of
- <c>Asn1Type</c>. If <c>Asn1Type</c> is 'SubjectPublicKeyInfo'
- then <c>Entity</c> must be either an rsa_public_key() or a
- dsa_public_key() and this function will create the appropriate
+ <d>Erlang representation of
+ <c>Asn1Type</c>. If <c>Asn1Type</c> is 'SubjectPublicKeyInfo',
+ <c>Entity</c> must be either an <c>rsa_public_key()</c>,
+ <c>dsa_public_key()</c> or an <c>ec_public_key()</c>
+ and this function creates the appropriate
'SubjectPublicKeyInfo' entry.
</d>
<v>CipherInfo = cipher_info()</v>
<v>Password = string()</v>
- </type>
+ </type>
<desc>
- <p> Creates a PEM entry that can be feed to pem_encode/1.</p>
+ <p>Creates a PEM entry that can be feed to <c>pem_encode/1</c>.</p>
</desc>
</func>
-
- <func>
- <name>encrypt_private(PlainText, Key) -> binary()</name>
- <fsummary> Public key encryption using the private key.</fsummary>
- <type>
- <v>PlainText = binary()</v>
- <v>Key = rsa_private_key()</v>
- </type>
- <desc>
- <p> Public key encryption using the private key.
- See also <seealso
- marker="crypto:crypto#private_encrypt/4">crypto:private_encrypt/4</seealso></p>
- </desc>
- </func>
-
- <func>
- <name>encrypt_public(PlainText, Key) -> binary()</name>
- <fsummary> Public key encryption using the public key.</fsummary>
- <type>
- <v>PlainText = binary()</v>
- <v>Key = rsa_public_key()</v>
- </type>
- <desc>
- <p> Public key encryption using the public key. See also <seealso
- marker="crypto:crypto#public_encrypt/4">crypto:public_encrypt/4</seealso></p>
- </desc>
- </func>
<func>
<name>pkix_decode_cert(Cert, otp|plain) -> #'Certificate'{} | #'OTPCertificate'{}</name>
- <fsummary> Decodes an ASN.1 DER encoded PKIX x509 certificate.</fsummary>
+ <fsummary>Decodes an ASN.1 DER-encoded PKIX x509 certificate.</fsummary>
<type>
<v>Cert = der_encoded()</v>
</type>
<desc>
- <p>Decodes an ASN.1 DER encoded PKIX certificate. The otp option
- will use the customized ASN.1 specification OTP-PKIX.asn1 for
+ <p>Decodes an ASN.1 DER-encoded PKIX certificate. Option <c>otp</c>
+ uses the customized ASN.1 specification OTP-PKIX.asn1 for
decoding and also recursively decode most of the standard
parts.</p>
</desc>
@@ -346,262 +424,383 @@
certificate.</fsummary>
<type>
<v>Asn1Type = atom()</v>
- <d>The ASN.1 type can be 'Certificate', 'OTPCertificate' or a subtype of either .</d>
+ <d>The ASN.1 type can be 'Certificate', 'OTPCertificate' or a subtype of either.</d>
<v>Entity = #'Certificate'{} | #'OTPCertificate'{} | a valid subtype</v>
</type>
<desc>
<p>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 will directly call der_encode/2. </p>
+ that are decoded/created in the <c>otp</c> format, whereas for the plain format this
+ function directly calls <c>der_encode/2</c>.</p>
</desc>
</func>
<func>
<name>pkix_is_issuer(Cert, IssuerCert) -> boolean()</name>
- <fsummary> Checks if <c>IssuerCert</c> issued <c>Cert</c> </fsummary>
+ <fsummary>Checks if <c>IssuerCert</c> issued <c>Cert</c>.</fsummary>
<type>
- <v>Cert = der_encode() | #'OTPCertificate'{}</v>
- <v>IssuerCert = der_encode() | #'OTPCertificate'{}</v>
+ <v>Cert = der_encoded() | #'OTPCertificate'{} | #'CertificateList'{}</v>
+ <v>IssuerCert = der_encoded() | #'OTPCertificate'{}</v>
</type>
<desc>
- <p> Checks if <c>IssuerCert</c> issued <c>Cert</c> </p>
+ <p>Checks if <c>IssuerCert</c> issued <c>Cert</c>.</p>
</desc>
</func>
<func>
<name>pkix_is_fixed_dh_cert(Cert) -> boolean()</name>
- <fsummary> Checks if a Certificate is a fixed Diffie-Hellman Cert.</fsummary>
+ <fsummary>Checks if a certificate is a fixed Diffie-Hellman certificate.</fsummary>
<type>
- <v>Cert = der_encode() | #'OTPCertificate'{}</v>
+ <v>Cert = der_encoded() | #'OTPCertificate'{}</v>
</type>
<desc>
- <p> Checks if a Certificate is a fixed Diffie-Hellman Cert.</p>
+ <p>Checks if a certificate is a fixed Diffie-Hellman certificate.</p>
</desc>
</func>
<func>
<name>pkix_is_self_signed(Cert) -> boolean()</name>
- <fsummary> Checks if a Certificate is self signed.</fsummary>
+ <fsummary>Checks if a certificate is self-signed.</fsummary>
<type>
- <v>Cert = der_encode() | #'OTPCertificate'{}</v>
+ <v>Cert = der_encoded() | #'OTPCertificate'{}</v>
</type>
<desc>
- <p> Checks if a Certificate is self signed.</p>
+ <p>Checks if a certificate is self-signed.</p>
</desc>
</func>
<func>
<name>pkix_issuer_id(Cert, IssuedBy) -> {ok, IssuerID} | {error, Reason}</name>
- <fsummary> Returns the issuer id.</fsummary>
+ <fsummary>Returns the issuer id.</fsummary>
<type>
- <v>Cert = der_encode() | #'OTPCertificate'{}</v>
+ <v>Cert = der_encoded() | #'OTPCertificate'{}</v>
<v>IssuedBy = self | other</v>
- <v>IssuerID = {integer(), {rdnSequence, [#'AttributeTypeAndValue'{}]}}</v>
+ <v>IssuerID = {integer(), issuer_name()}</v>
<d>The issuer id consists of the serial number and the issuers name.</d>
<v>Reason = term()</v>
- </type>
- <desc>
- <p> Returns the issuer id.</p>
- </desc>
+ </type>
+ <desc>
+ <p>Returns the issuer id.</p>
+ </desc>
</func>
-
+
+
<func>
<name>pkix_normalize_name(Issuer) -> Normalized</name>
- <fsummary>Normalizes a issuer name so that it can be easily
- compared to another issuer name. </fsummary>
+ <fsummary>Normalizes an issuer name so that it can be easily
+ compared to another issuer name.</fsummary>
<type>
- <v>Issuer = {rdnSequence,[#'AttributeTypeAndValue'{}]}</v>
- <v>Normalized = {rdnSequence, [#'AttributeTypeAndValue'{}]}</v>
+ <v>Issuer = issuer_name()</v>
+ <v>Normalized = issuer_name()</v>
</type>
<desc>
- <p>Normalizes a issuer name so that it can be easily
+ <p>Normalizes an issuer name so that it can be easily
compared to another issuer name.</p>
</desc>
</func>
<func>
<name>pkix_path_validation(TrustedCert, CertChain, Options) -> {ok, {PublicKeyInfo, PolicyTree}} | {error, {bad_cert, Reason}} </name>
- <fsummary> Performs a basic path validation according to RFC 5280.</fsummary>
+ <fsummary>Performs a basic path validation according to RFC 5280.</fsummary>
<type>
- <v> TrustedCert = #'OTPCertificate'{} | der_encode() | unknown_ca | selfsigned_peer </v>
- <d>Normally a trusted certificate but it can also be one of the path validation
- errors <c>unknown_ca </c> or <c>selfsigned_peer </c> that can be discovered while
- constructing the input to this function and that should be run through the <c>verify_fun</c>.</d>
- <v> CertChain = [der_encode()]</v>
- <d>A list of DER encoded certificates in trust order ending with the peer certificate.</d>
- <v> Options = proplists:proplists()</v>
+ <v>TrustedCert = #'OTPCertificate'{} | der_encoded() | atom()</v>
+ <d>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 <c>verify_fun</c>.
+ Examples are <c>unknown_ca</c> and <c>selfsigned_peer.</c>
+ </d>
+ <v>CertChain = [der_encoded()]</v>
+ <d>A list of DER-encoded certificates in trust order ending with the peer certificate.</d>
+ <v>Options = proplists:proplist()</v>
<v>PublicKeyInfo = {?'rsaEncryption' | ?'id-dsa',
rsa_public_key() | integer(), 'NULL' | 'Dss-Parms'{}}</v>
- <v> PolicyTree = term() </v>
- <d>At the moment this will always be an empty list as Policies are not currently supported</d>
- <v> Reason = cert_expired | invalid_issuer | invalid_signature | unknown_ca |
- selfsigned_peer | name_not_permitted | missing_basic_constraint | invalid_key_usage | crl_reason()
+ <v>PolicyTree = term()</v>
+ <d>At the moment this is always an empty list as policies are not currently supported.</d>
+ <v>Reason = cert_expired | invalid_issuer | invalid_signature | name_not_permitted |
+ missing_basic_constraint | invalid_key_usage | {revoked, crl_reason()} | atom()
</v>
</type>
<desc>
<p>
Performs a basic path validation according to
<url href="http://www.ietf.org/rfc/rfc5280.txt">RFC 5280.</url>
- However CRL validation is done separately by <seealso
- marker="public_key#pkix_crls_validate-3">pkix_crls_validate/3 </seealso> and should be called
- from the supplied <c>verify_fun</c>
+ However, CRL validation is done separately by <seealso
+ marker="#pkix_crls_validate-3">pkix_crls_validate/3 </seealso> and is to be called
+ from the supplied <c>verify_fun</c>.
</p>
- <taglist>
- <p> Available options are: </p>
+ <p>Available options:</p>
+ <taglist>
<tag>{verify_fun, fun()}</tag>
<item>
- <p>The fun should be defined as:</p>
+ <p>The fun must be defined as:</p>
<code>
-fun(OtpCert :: #'OTPCertificate'{}, Event :: {bad_cert, Reason :: atom()} |
- {extension, #'Extension'{}},
+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()}.
+ {valid, UserState :: term()} |
+ {valid_peer, UserState :: term()} |
+ {fail, Reason :: term()} |
+ {unknown, UserState :: term()}.
</code>
- <p>If the verify callback fun returns {fail, Reason}, the
+ <p>If the verify callback fun returns <c>{fail, Reason}</c>, 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 <c>selfsigned_peer</c> as well as
- verifying application specific extensions. If called with an
- extension unknown to the user application the return value
- {unknown, UserState} should be used.</p>
+ callback fun returns <c>{valid, UserState}</c>, the verification
+ process is continued. This can be used to accept specific path
+ validation errors, such as <c>selfsigned_peer</c>, as well as
+ verifying application-specific extensions. If called with an
+ extension unknown to the user application, the return value
+ <c>{unknown, UserState}</c> is to be used.</p>
</item>
<tag>{max_path_length, integer()}</tag>
<item>
The <c>max_path_length</c> is the maximum number of non-self-issued
- intermediate certificates that may follow the peer certificate
- in a valid certification path. So if <c>max_path_length</c> is 0 the PEER must
- be signed by the trusted ROOT-CA directly, if 1 the path can
- be PEER, CA, ROOT-CA, if it is 2 PEER, CA, CA, ROOT-CA and so
- on.
+ intermediate certificates that can follow the peer certificate
+ in a valid certification path. So, if <c>max_path_length</c> 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.
</item>
</taglist>
+
+ <p>Possible reasons for a bad certificate: </p>
+ <taglist>
+ <tag>cert_expired</tag>
+ <item><p>Certificate is no longer valid as its expiration date has passed.</p></item>
+
+ <tag>invalid_issuer</tag>
+ <item><p>Certificate issuer name does not match the name of the issuer certificate in the chain.</p></item>
+
+ <tag>invalid_signature</tag>
+ <item><p>Certificate was not signed by its issuer certificate in the chain.</p></item>
+
+ <tag>name_not_permitted</tag>
+ <item><p>Invalid Subject Alternative Name extension.</p></item>
+
+ <tag>missing_basic_constraint</tag>
+ <item><p>Certificate, required to have the basic constraints extension, does not have
+ a basic constraints extension.</p></item>
+
+ <tag>invalid_key_usage</tag>
+ <item><p>Certificate key is used in an invalid way according to the key-usage extension.</p></item>
+
+ <tag>{revoked, crl_reason()}</tag>
+ <item><p>Certificate has been revoked.</p></item>
+
+ <tag>atom()</tag>
+ <item><p>Application-specific error reason that is to be checked by the <c>verify_fun</c>.</p></item>
+ </taglist>
+
</desc>
</func>
+ <func>
+ <name>pkix_crl_issuer(CRL) -> issuer_name()</name>
+ <fsummary>Returns the issuer of the <c>CRL</c>.</fsummary>
+ <type>
+ <v>CRL = der_encoded() | #'CertificateList'{} </v>
+ </type>
+ <desc>
+ <p>Returns the issuer of the <c>CRL</c>.</p>
+ </desc>
+ </func>
+
<func>
<name>pkix_crls_validate(OTPCertificate, DPAndCRLs, Options) -> CRLStatus()</name>
- <fsummary> Performs CRL validation.</fsummary>
+ <fsummary>Performs CRL validation.</fsummary>
<type>
- <v> OTPCertificate = #'OTPCertificate'{}</v>
- <v> DPAndCRLs = [{DP::#'DistributionPoint'{} ,CRL::#'CertificateList'{}}] </v>
- <v> Options = proplists:proplists()</v>
- <v> CRLStatus() = valid | {bad_cert, revocation_status_undetermined} |
+ <v>OTPCertificate = #'OTPCertificate'{}</v>
+ <v>DPAndCRLs = [{DP::#'DistributionPoint'{}, {DerCRL::der_encoded(), CRL::#'CertificateList'{}}}] </v>
+ <v>Options = proplists:proplist()</v>
+ <v>CRLStatus() = valid | {bad_cert, revocation_status_undetermined} |
{bad_cert, {revoked, crl_reason()}}</v>
</type>
<desc>
- <p> Performs CRL validation. It is intended to be called from
- the verify fun of <seealso marker="public_key#pkix_path_validation-3"> pkix_path_validation/3
- </seealso></p>
+ <p>Performs CRL validation. It is intended to be called from
+ the verify fun of <seealso marker="#pkix_path_validation-3"> pkix_path_validation/3
+ </seealso>.</p>
+
+ <p>Available options:</p>
+
<taglist>
- <p> Available options are: </p>
+
<tag>{update_crl, fun()}</tag>
<item>
- <p>The fun has the following type spec:</p>
+ <p>The fun has the following type specification:</p>
- <code> fun(#'DistributionPoint'{}, #'CertificateList'{}) -> #'CertificateList'{}</code>
+ <code> fun(#'DistributionPoint'{}, #'CertificateList'{}) ->
+ #'CertificateList'{}</code>
- <p>The fun should use the information in the distribution point to acesses
- the lates possible version of the CRL. If this fun is not specified
- public_key will use the default implementation:
+ <p>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:
</p>
<code> fun(_DP, CRL) -> CRL end</code>
</item>
+
+ <tag>{issuer_fun, fun()}</tag>
+ <item>
+ <p>The fun has the following type specification:</p>
+
+ <code>
+fun(#'DistributionPoint'{}, #'CertificateList'{},
+ {rdnSequence,[#'AttributeTypeAndValue'{}]}, term()) ->
+ {ok, #'OTPCertificate'{}, [der_encoded]}</code>
+
+ <p>The fun returns the root certificate and certificate chain
+ that has signed the CRL.
+ </p>
+ <code> fun(DP, CRL, Issuer, UserState) -> {ok, RootCert, CertChain}</code>
+ </item>
</taglist>
</desc>
</func>
+
+ <func>
+ <name>pkix_crl_verify(CRL, Cert) -> boolean()</name>
+ <fsummary> Verify that <c>Cert</c> is the <c> CRL</c> signer. </fsummary>
+ <type>
+ <v>CRL = der_encoded() | #'CertificateList'{} </v>
+ <v>Cert = der_encoded() | #'OTPCertificate'{} </v>
+ </type>
+ <desc>
+ <p>Verify that <c>Cert</c> is the <c>CRL</c> signer.</p>
+ </desc>
+ </func>
+ <func>
+ <name>pkix_dist_point(Cert) -> DistPoint</name>
+ <fsummary>Creates a distribution point for CRLs issued by the same issuer as <c>Cert</c>.</fsummary>
+ <type>
+ <v> Cert = der_encoded() | #'OTPCertificate'{} </v>
+ <v> DistPoint = #'DistributionPoint'{}</v>
+ </type>
+ <desc>
+ <p>Creates a distribution point for CRLs issued by the same issuer as <c>Cert</c>.
+ Can be used as input to <seealso
+ marker="#pkix_crls_validate-3">pkix_crls_validate/3 </seealso>
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name>pkix_dist_points(Cert) -> DistPoints</name>
+ <fsummary> Extracts distribution points from the certificates extensions.</fsummary>
+ <type>
+ <v> Cert = der_encoded() | #'OTPCertificate'{} </v>
+ <v> DistPoints = [#'DistributionPoint'{}]</v>
+ </type>
+ <desc>
+ <p> Extracts distribution points from the certificates extensions.</p>
+ </desc>
+ </func>
+
<func>
- <name>pkix_sign(#'OTPTBSCertificate'{}, Key) -> der_encode()</name>
+ <name>pkix_match_dist_point(CRL, DistPoint) -> boolean()</name>
+ <fsummary>Checks whether the given distribution point matches the
+ Issuing Distribution Point of the CRL.</fsummary>
+
+ <type>
+ <v>CRL = der_encoded() | #'CertificateList'{} </v>
+ <v>DistPoint = #'DistributionPoint'{}</v>
+ </type>
+ <desc>
+ <p>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.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name>pkix_sign(#'OTPTBSCertificate'{}, Key) -> der_encoded()</name>
<fsummary>Signs certificate.</fsummary>
<type>
- <v>Key = rsa_public_key() | dsa_public_key()</v>
+ <v>Key = rsa_private_key() | dsa_private_key()</v>
</type>
<desc>
- <p>Signs a 'OTPTBSCertificate'. Returns the corresponding
- der encoded certificate.</p>
+ <p>Signs an 'OTPTBSCertificate'. Returns the corresponding
+ DER-encoded certificate.</p>
</desc>
</func>
<func>
<name>pkix_sign_types(AlgorithmId) -> {DigestType, SignatureType}</name>
- <fsummary>Translates signature algorithm oid to erlang digest and signature algorithm types.</fsummary>
+ <fsummary>Translates signature algorithm OID to Erlang digest and signature algorithm types.</fsummary>
<type>
<v>AlgorithmId = oid()</v>
- <d>Signature oid from a certificate or a certificate revocation list</d>
- <v>DigestType = rsa_digest_type() | dss_digest_type() </v>
- <v>SignatureType = rsa | dsa</v>
+ <d>Signature OID from a certificate or a certificate revocation list.</d>
+ <v>DigestType = rsa_digest_type() | dss_digest_type()</v>
+ <v>SignatureType = rsa | dsa | ecdsa</v>
</type>
<desc>
- <p>Translates signature algorithm oid to erlang digest and signature types.
+ <p>Translates signature algorithm OID to Erlang digest and signature types.
</p>
</desc>
</func>
<func>
<name>pkix_verify(Cert, Key) -> boolean()</name>
- <fsummary> Verify pkix x.509 certificate signature.</fsummary>
+ <fsummary>Verifies PKIX x.509 certificate signature.</fsummary>
<type>
- <v>Cert = der_encode()</v>
- <v>Key = rsa_public_key() | dsa_public_key()</v>
+ <v>Cert = der_encoded()</v>
+ <v>Key = rsa_public_key() | dsa_public_key() | ec_public_key()</v>
</type>
<desc>
- <p> Verify PKIX x.509 certificate signature.</p>
+ <p>Verifies PKIX x.509 certificate signature.</p>
</desc>
</func>
<func>
<name>sign(Msg, DigestType, Key) -> binary()</name>
- <fsummary> Create digital signature.</fsummary>
+ <fsummary>Creates a digital signature.</fsummary>
<type>
<v>Msg = binary() | {digest,binary()}</v>
- <d>The msg is either the binary "plain text" data to be
- signed or it is the hashed value of "plain text" i.e. the
+ <d>The <c>Msg</c> is either the binary "plain text" data to be
+ signed or it is the hashed value of "plain text", that is, the
digest.</d>
<v>DigestType = rsa_digest_type() | dss_digest_type() | ecdsa_digest_type()</v>
<v>Key = rsa_private_key() | dsa_private_key() | ec_private_key()</v>
</type>
<desc>
- <p> Creates a digital signature.</p>
+ <p>Creates a digital signature.</p>
</desc>
</func>
<func>
<name>ssh_decode(SshBin, Type) -> [{public_key(), Attributes::list()}]</name>
- <fsummary>Decodes a ssh file-binary. </fsummary>
+ <fsummary>Decodes an SSH file-binary.</fsummary>
<type>
<v>SshBin = binary()</v>
- <d>Example {ok, SshBin} = file:read_file("known_hosts").</d>
- <v> Type = public_key | ssh_file()</v>
- <d>If <c>Type</c> is <c>public_key</c> the binary may be either
- a rfc4716 public key or a openssh public key.</d>
+ <d>Example <c>{ok, SshBin} = file:read_file("known_hosts")</c>.</d>
+ <v>Type = public_key | ssh_file()</v>
+ <d>If <c>Type</c> is <c>public_key</c> the binary can be either
+ an RFC4716 public key or an OpenSSH public key.</d>
</type>
<desc>
- <p> Decodes a ssh file-binary. In the case of know_hosts or
- auth_keys the binary may include one or more lines of the
+ <p>Decodes an SSH file-binary. In the case of <c>known_hosts</c> or
+ <c>auth_keys</c>, 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.
</p>
<taglist>
- <tag>rfc4716 attributes - see RFC 4716</tag>
- <item>{headers, [{string(), utf8_string()}]}</item>
- <tag>auth_key attributes - see man sshd </tag>
+ <tag>RFC4716 attributes - see RFC 4716.</tag>
+ <item><p>{headers, [{string(), utf8_string()}]}</p></item>
+ <tag>auth_key attributes - see manual page for sshd.</tag>
<item>{comment, string()}</item>
<item>{options, [string()]}</item>
- <item>{bits, integer()} - In ssh version 1 files</item>
- <tag>known_host attributes - see man sshd</tag>
+ <item><p>{bits, integer()} - In SSH version 1 files.</p></item>
+ <tag>known_host attributes - see manual page for sshd.</tag>
<item>{hostnames, [string()]}</item>
<item>{comment, string()}</item>
- <item>{bits, integer()} - In ssh version 1 files</item>
+ <item><p>{bits, integer()} - In SSH version 1 files.</p></item>
</taglist>
</desc>
@@ -609,16 +808,16 @@ fun(OtpCert :: #'OTPCertificate'{}, Event :: {bad_cert, Reason :: atom()} |
<func>
<name>ssh_encode([{Key, Attributes}], Type) -> binary()</name>
- <fsummary> Encodes a list of ssh file entries to a binary.</fsummary>
+ <fsummary>Encodes a list of SSH file entries to a binary.</fsummary>
<type>
<v>Key = public_key()</v>
<v>Attributes = list()</v>
<v>Type = ssh_file()</v>
</type>
<desc>
- <p>Encodes a list of ssh file entries (public keys and attributes) to a binary. Possible
- attributes depends on the file type, see <seealso
- marker="#ssh_decode-2"> ssh_decode/2 </seealso></p>
+ <p>Encodes a list of SSH file entries (public keys and attributes) to a binary. Possible
+ attributes depend on the file type, see <seealso
+ marker="#ssh_decode-2"> ssh_decode/2 </seealso>.</p>
</desc>
</func>
@@ -627,17 +826,37 @@ fun(OtpCert :: #'OTPCertificate'{}, Event :: {bad_cert, Reason :: atom()} |
<fsummary>Verifies a digital signature.</fsummary>
<type>
<v>Msg = binary() | {digest,binary()}</v>
- <d>The msg is either the binary "plain text" data
- or it is the hashed value of "plain text" i.e. the digest.</d>
+ <d>The <c>Msg</c> is either the binary "plain text" data
+ or it is the hashed value of "plain text", that is, the digest.</d>
<v>DigestType = rsa_digest_type() | dss_digest_type() | ecdsa_digest_type()</v>
<v>Signature = binary()</v>
<v>Key = rsa_public_key() | dsa_public_key() | ec_public_key()</v>
</type>
<desc>
- <p>Verifies a digital signature</p>
+ <p>Verifies a digital signature.</p>
</desc>
</func>
-
+
+ <func>
+ <name>short_name_hash(Name) -> string()</name>
+ <fsummary>Generates a short hash of an issuer name.</fsummary>
+ <type>
+ <v>Name = issuer_name()</v>
+ </type>
+ <desc>
+ <p>Generates a short hash of an issuer name. The hash is
+ returned as a string containing eight hexadecimal digits.</p>
+
+ <p>The return value of this function is the same as the result
+ of the commands <c>openssl crl -hash</c> and
+ <c>openssl x509 -issuer_hash</c>, when passed the issuer name of
+ a CRL or a certificate, respectively. This hash is used by the
+ <c>c_rehash</c> tool to maintain a directory of symlinks to CRL
+ files, in order to facilitate looking up a CRL by its issuer
+ name.</p>
+ </desc>
+ </func>
+
</funcs>
</erlref>