Sophie

Sophie

distrib > Fedora > 17 > i386 > media > updates > by-pkgid > 675c8c8167236dfcf8d66da674f931e8 > files > 1220

erlang-doc-R15B-03.3.fc17.noarch.rpm

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html xmlns:fn="http://www.w3.org/2005/02/xpath-functions">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<link rel="stylesheet" href="../../../../doc/otp_doc.css" type="text/css">
<title>Erlang -- Using the public_key API</title>
</head>
<body bgcolor="white" text="#000000" link="#0000ff" vlink="#ff00ff" alink="#ff0000"><div id="container">
<script id="js" type="text/javascript" language="JavaScript" src="../../../../doc/js/flipmenu/flipmenu.js"></script><script id="js2" type="text/javascript" src="../../../../doc/js/erlresolvelinks.js"></script><script language="JavaScript" type="text/javascript">
            <!--
              function getWinHeight() {
                var myHeight = 0;
                if( typeof( window.innerHeight ) == 'number' ) {
                  //Non-IE
                  myHeight = window.innerHeight;
                } else if( document.documentElement && ( document.documentElement.clientWidth ||
                                                         document.documentElement.clientHeight ) ) {
                  //IE 6+ in 'standards compliant mode'
                  myHeight = document.documentElement.clientHeight;
                } else if( document.body && ( document.body.clientWidth || document.body.clientHeight ) ) {
                  //IE 4 compatible
                  myHeight = document.body.clientHeight;
                }
                return myHeight;
              }

              function setscrollpos() {
                var objf=document.getElementById('loadscrollpos');
                 document.getElementById("leftnav").scrollTop = objf.offsetTop - getWinHeight()/2;
              }

              function addEvent(obj, evType, fn){
                if (obj.addEventListener){
                obj.addEventListener(evType, fn, true);
                return true;
              } else if (obj.attachEvent){
                var r = obj.attachEvent("on"+evType, fn);
                return r;
              } else {
                return false;
              }
             }

             addEvent(window, 'load', setscrollpos);

             //--></script><div id="leftnav"><div class="innertube">
<img alt="Erlang logo" src="../../../../doc/erlang-logo.png"><br><small><a href="users_guide.html">User's Guide</a><br><a href="index.html">Reference Manual</a><br><a href="release_notes.html">Release Notes</a><br><a href="../pdf/public_key-0.17.pdf">PDF</a><br><a href="../../../../doc/index.html">Top</a></small><p><strong>public_key</strong><br><strong>User's Guide</strong><br><small>Version 0.17</small></p>
<br><a href="javascript:openAllFlips()">Expand All</a><br><a href="javascript:closeAllFlips()">Contract All</a><p><small><strong>Chapters</strong></small></p>
<ul class="flipMenu" imagepath="../../../../doc/js/flipmenu">
<li id="no" title="Introduction" expanded="false">Introduction<ul>
<li><a href="introduction.html">
              Top of chapter
            </a></li>
<li title="Purpose"><a href="introduction.html#id56658">Purpose</a></li>
<li title="Prerequisites"><a href="introduction.html#id62235">Prerequisites</a></li>
<li title="Performance tips"><a href="introduction.html#id56630">Performance tips</a></li>
</ul>
</li>
<li id="no" title="Public key records" expanded="false">Public key records<ul>
<li><a href="public_key_records.html">
              Top of chapter
            </a></li>
<li title="RSA as defined by the PKCS-1 standard and RFC 3447."><a href="public_key_records.html#id60524">RSA as defined by the PKCS-1 standard and RFC 3447.</a></li>
<li title="DSA as defined by Digital Signature Standard (NIST FIPS PUB 186-2)
    "><a href="public_key_records.html#id60554">DSA as defined by Digital Signature Standard (NIST FIPS PUB 186-2)
    </a></li>
</ul>
</li>
<li id="no" title="Certificate records" expanded="false">Certificate records<ul>
<li><a href="cert_records.html">
              Top of chapter
            </a></li>
<li title="Common Data Types"><a href="cert_records.html#id61390">Common Data Types</a></li>
<li title=" PKIX Certificates"><a href="cert_records.html#id61050"> PKIX Certificates</a></li>
<li title="Standard certificate extensions"><a href="cert_records.html#id62358">Standard certificate extensions</a></li>
<li title="Private Internet Extensions"><a href="cert_records.html#id62027">Private Internet Extensions</a></li>
<li title=" CRL and CRL Extensions Profile"><a href="cert_records.html#id62112"> CRL and CRL Extensions Profile</a></li>
</ul>
</li>
<li id="loadscrollpos" title="Using the public_key API" expanded="true">Using the public_key API<ul>
<li><a href="using_public_key.html">
              Top of chapter
            </a></li>
<li title="General information"><a href="using_public_key.html#id60775">General information</a></li>
<li title="PEM files"><a href="using_public_key.html#id60793">PEM files</a></li>
<li title="RSA public key cryptography "><a href="using_public_key.html#id63884">RSA public key cryptography </a></li>
<li title="Digital signatures"><a href="using_public_key.html#id63919">Digital signatures</a></li>
<li title="SSH files"><a href="using_public_key.html#id63952">SSH files</a></li>
</ul>
</li>
</ul>
</div></div>
<div id="content">
<div class="innertube">
<h1>4 Using the public_key API</h1>
  

  <h3><a name="id60775">4.1 
        General information</a></h3>
    

    <p> This chapter is dedicated to showing some
    examples of how to use the public_key API. Keys and certificates
    used in the following sections are generated only for the purpose
    of testing the public key application.</p>

    <p>Note that some shell printouts, in the following examples,
    have been abbreviated for increased readability.</p>
    
  
    
  <h3><a name="id60793">4.2 
        PEM files</a></h3>
    
    <p> Pulic key data (keys, certificates etc) may be stored in PEM format. PEM files
    comes from the Private Enhanced Mail Internet standard and has a
    structure that looks like this:</p>

    <div class="example"><pre>&lt;text&gt;
	-----BEGIN &lt;SOMETHING&gt;-----
	&lt;Attribute&gt; : &lt;Value&gt;
	&lt;Base64 encoded DER data&gt;
	-----END &lt;SOMETHING&gt;-----
	&lt;text&gt;</pre></div>

    <p>A file can contain several BEGIN/END blocks. Text lines between
    blocks are ignored.  Attributes, if present, are currently ignored except
    for <span class="code">Proc-Type</span> and <span class="code">DEK-Info</span> that are used when the DER data is
    encrypted.</p>

    <h4>DSA private key</h4>
      
      
      <p>Note file handling is not done by the public_key application. </p>
      <div class="example"><pre>1&gt; {ok, PemBin} = file:read_file("dsa.pem").
{ok,&lt;&lt;"-----BEGIN DSA PRIVATE KEY-----\nMIIBuw"...&gt;&gt;}</pre></div>
      
      <p>This PEM file only has one entry a private DSA key.</p>
      <div class="example"><pre>2&gt; [DSAEntry] =  public_key:pem_decode(PemBin).
[{'DSAPrivateKey',&lt;&lt;48,130,1,187,2,1,0,2,129,129,0,183,
                    179,230,217,37,99,144,157,21,228,204,
		    162,207,61,246,...&gt;&gt;,
		    not_encrypted}]</pre></div>
      
      <div class="example"><pre>3&gt; Key = public_key:pem_entry_decode(DSAEntry).
#'DSAPrivateKey'{version = 0,
                 p = 12900045185019966618...6593,
                 q = 1216700114794736143432235288305776850295620488937,
                 g = 10442040227452349332...47213,
                 y = 87256807980030509074...403143,
                 x = 510968529856012146351317363807366575075645839654}</pre></div>
    

    <h4>RSA private key encrypted with a password.</h4>
      
      
      <div class="example"><pre>1&gt; {ok, PemBin} = file:read_file("rsa.pem").
{ok,&lt;&lt;"Bag Attribut"...&gt;&gt;}</pre></div>

    <p>This PEM file only has one entry a private RSA key.</p>
    <div class="example"><pre>2&gt;[RSAEntry] = public_key:pem_decode(PemBin).
[{'RSAPrivateKey',&lt;&lt;224,108,117,203,152,40,15,77,128,126,
                    221,195,154,249,85,208,202,251,109,
                    119,120,57,29,89,19,9,...&gt;&gt;,
                  {"DES-EDE3-CBC",&lt;&lt;"kÙeø¼pµL"&gt;&gt;}}]

    </pre></div>

    <p>In this example the password is "abcd1234".</p>
    <div class="example"><pre>3&gt; Key = public_key:pem_entry_decode(RSAEntry, "abcd1234").
    #'RSAPrivateKey'{version = 'two-prime',
                 modulus = 1112355156729921663373...2737107,
                 publicExponent = 65537,
                 privateExponent = 58064406231183...2239766033,
                 prime1 = 11034766614656598484098...7326883017,
                 prime2 = 10080459293561036618240...77738643771,
                 exponent1 = 77928819327425934607...22152984217,
                 exponent2 = 36287623121853605733...20588523793,
                 coefficient = 924840412626098444...41820968343,
                 otherPrimeInfos = asn1_NOVALUE}</pre></div>
    
  
  <h4>X509 Certificates</h4>
    
    
      <div class="example"><pre>1&gt; {ok, PemBin} = file:read_file("cacerts.pem").
{ok,&lt;&lt;"-----BEGIN CERTIFICATE-----\nMIIC7jCCAl"...&gt;&gt;}</pre></div>

      <p>This file includes two certificates</p>
      <div class="example"><pre>2&gt; [CertEntry1, CertEntry2] = public_key:pem_decode(PemBin).
[{'Certificate',&lt;&lt;48,130,2,238,48,130,2,87,160,3,2,1,2,2,
                  9,0,230,145,97,214,191,2,120,150,48,13,
                  ...&gt;&gt;,
                not_encrypted},
 {'Certificate',&lt;&lt;48,130,3,200,48,130,3,49,160,3,2,1,2,2,1,
                  1,48,13,6,9,42,134,72,134,247,...&gt;&gt;&gt;,
                not_encrypted}]</pre></div>
      
      <p>Certificates may of course be decoded as usual ... </p>
      <div class="example"><pre>2&gt; Cert = public_key:pem_entry_decode(CertEntry1).
#'Certificate'{
    tbsCertificate =
        #'TBSCertificate'{
            version = v3,serialNumber = 16614168075301976214,
            signature =
                #'AlgorithmIdentifier'{
                    algorithm = {1,2,840,113549,1,1,5},
                    parameters = &lt;&lt;5,0&gt;&gt;},
            issuer =
                {rdnSequence,
                    [[#'AttributeTypeAndValue'{
                          type = {2,5,4,3},
                          value = &lt;&lt;19,8,101,114,108,97,110,103,67,65&gt;&gt;}],
                     [#'AttributeTypeAndValue'{
                          type = {2,5,4,11},
                          value = &lt;&lt;19,10,69,114,108,97,110,103,32,79,84,80&gt;&gt;}],
                     [#'AttributeTypeAndValue'{
                          type = {2,5,4,10},
                          value = &lt;&lt;19,11,69,114,105,99,115,115,111,110,32,65,66&gt;&gt;}],
                     [#'AttributeTypeAndValue'{
                          type = {2,5,4,7},
                          value = &lt;&lt;19,9,83,116,111,99,107,104,111,108,109&gt;&gt;}],
                     [#'AttributeTypeAndValue'{
                          type = {2,5,4,6},
                          value = &lt;&lt;19,2,83,69&gt;&gt;}],
                     [#'AttributeTypeAndValue'{
                          type = {1,2,840,113549,1,9,1},
                          value = &lt;&lt;22,22,112,101,116,101,114,64,101,114,...&gt;&gt;}]]},
            validity =
                #'Validity'{
                    notBefore = {utcTime,"080109082929Z"},
                    notAfter = {utcTime,"080208082929Z"}},
            subject =
                {rdnSequence,
                    [[#'AttributeTypeAndValue'{
                          type = {2,5,4,3},
                          value = &lt;&lt;19,8,101,114,108,97,110,103,67,65&gt;&gt;}],
                     [#'AttributeTypeAndValue'{
                          type = {2,5,4,11},
                          value = &lt;&lt;19,10,69,114,108,97,110,103,32,79,84,80&gt;&gt;}],
                     [#'AttributeTypeAndValue'{
                          type = {2,5,4,10},
                          value = &lt;&lt;19,11,69,114,105,99,115,115,111,110,32,...&gt;&gt;}],
                     [#'AttributeTypeAndValue'{
                          type = {2,5,4,7},
                          value = &lt;&lt;19,9,83,116,111,99,107,104,111,108,...&gt;&gt;}],
                     [#'AttributeTypeAndValue'{
                          type = {2,5,4,6},
                          value = &lt;&lt;19,2,83,69&gt;&gt;}],
                     [#'AttributeTypeAndValue'{
                          type = {1,2,840,113549,1,9,1},
                          value = &lt;&lt;22,22,112,101,116,101,114,64,...&gt;&gt;}]]},
            subjectPublicKeyInfo =
                #'SubjectPublicKeyInfo'{
                    algorithm =
                        #'AlgorithmIdentifier'{
                            algorithm = {1,2,840,113549,1,1,1},
                            parameters = &lt;&lt;5,0&gt;&gt;},
                    subjectPublicKey =
                        {0,&lt;&lt;48,129,137,2,129,129,0,203,209,187,77,73,231,90,...&gt;&gt;}},
            issuerUniqueID = asn1_NOVALUE,
            subjectUniqueID = asn1_NOVALUE,
            extensions =
                [#'Extension'{
                     extnID = {2,5,29,19},
                     critical = true,
                     extnValue = [48,3,1,1,255]},
                 #'Extension'{
                     extnID = {2,5,29,15},
                     critical = false,
                     extnValue = [3,2,1,6]},
                 #'Extension'{
                     extnID = {2,5,29,14},
                     critical = false,
                     extnValue = [4,20,27,217,65,152,6,30,142|...]},
                 #'Extension'{
                     extnID = {2,5,29,17},
                     critical = false,
                     extnValue = [48,24,129,22,112,101,116,101|...]}]},
    signatureAlgorithm =
        #'AlgorithmIdentifier'{
            algorithm = {1,2,840,113549,1,1,5},
            parameters = &lt;&lt;5,0&gt;&gt;},
    signature =
        {0,
         &lt;&lt;163,186,7,163,216,152,63,47,154,234,139,73,154,96,120,
           165,2,52,196,195,109,167,192,...&gt;&gt;}}
</pre></div>

      <p> Parts of certificates can be decoded with
      public_key:der_decode/2 using that parts ASN.1 type.
      Although application specific certificate
      extension requires application specific ASN.1 decode/encode-functions.
      Example, the first value of the rdnSequence above is of ASN.1 type
      'X520CommonName'. ({2,5,4,3} = ?id-at-commonName)</p>
      
      <div class="example"><pre>public_key:der_decode('X520CommonName', &lt;&lt;19,8,101,114,108,97,110,103,67,65&gt;&gt;).
{printableString,"erlangCA"}</pre></div>

      <p>... but certificates can also be decode using the pkix_decode_cert/2 that
      can customize and recursively decode standard parts of a certificate.</p>
      <div class="example"><pre>3&gt;{_, DerCert, _} = CertEntry1.</pre></div>
      <div class="example"><pre>4&gt; public_key:pkix_decode_cert(DerCert, otp).
#'OTPCertificate'{
    tbsCertificate =
        #'OTPTBSCertificate'{
            version = v3,serialNumber = 16614168075301976214,
            signature =
                #'SignatureAlgorithm'{
                    algorithm = {1,2,840,113549,1,1,5},
                    parameters = 'NULL'},
            issuer =
                {rdnSequence,
                    [[#'AttributeTypeAndValue'{
                          type = {2,5,4,3},
                          value = {printableString,"erlangCA"}}],
                     [#'AttributeTypeAndValue'{
                          type = {2,5,4,11},
                          value = {printableString,"Erlang OTP"}}],
                     [#'AttributeTypeAndValue'{
                          type = {2,5,4,10},
                          value = {printableString,"Ericsson AB"}}],
                     [#'AttributeTypeAndValue'{
                          type = {2,5,4,7},
                          value = {printableString,"Stockholm"}}],
                     [#'AttributeTypeAndValue'{type = {2,5,4,6},value = "SE"}],
                     [#'AttributeTypeAndValue'{
                          type = {1,2,840,113549,1,9,1},
                          value = "peter@erix.ericsson.se"}]]},
            validity =
                #'Validity'{
                    notBefore = {utcTime,"080109082929Z"},
                    notAfter = {utcTime,"080208082929Z"}},
            subject =
                {rdnSequence,
                    [[#'AttributeTypeAndValue'{
                          type = {2,5,4,3},
                          value = {printableString,"erlangCA"}}],
                     [#'AttributeTypeAndValue'{
                          type = {2,5,4,11},
                          value = {printableString,"Erlang OTP"}}],
                     [#'AttributeTypeAndValue'{
                          type = {2,5,4,10},
                          value = {printableString,"Ericsson AB"}}],
                     [#'AttributeTypeAndValue'{
                          type = {2,5,4,7},
                          value = {printableString,"Stockholm"}}],
                     [#'AttributeTypeAndValue'{type = {2,5,4,6},value = "SE"}],
                     [#'AttributeTypeAndValue'{
                          type = {1,2,840,113549,1,9,1},
                          value = "peter@erix.ericsson.se"}]]},
            subjectPublicKeyInfo =
                #'OTPSubjectPublicKeyInfo'{
                    algorithm =
                        #'PublicKeyAlgorithm'{
                            algorithm = {1,2,840,113549,1,1,1},
                            parameters = 'NULL'},
                    subjectPublicKey =
                        #'RSAPublicKey'{
                            modulus =
                                1431267547247997...37419,
                            publicExponent = 65537}},
            issuerUniqueID = asn1_NOVALUE,
            subjectUniqueID = asn1_NOVALUE,
            extensions =
                [#'Extension'{
                     extnID = {2,5,29,19},
                     critical = true,
                     extnValue =
                         #'BasicConstraints'{
                             cA = true,pathLenConstraint = asn1_NOVALUE}},
                 #'Extension'{
                     extnID = {2,5,29,15},
                     critical = false,
                     extnValue = [keyCertSign,cRLSign]},
                 #'Extension'{
                     extnID = {2,5,29,14},
                     critical = false,
                     extnValue = [27,217,65,152,6,30,142,132,245|...]},
                 #'Extension'{
                     extnID = {2,5,29,17},
                     critical = false,
                     extnValue = [{rfc822Name,"peter@erix.ericsson.se"}]}]},
    signatureAlgorithm =
        #'SignatureAlgorithm'{
            algorithm = {1,2,840,113549,1,1,5},
            parameters = 'NULL'},
    signature =
        {0,
         &lt;&lt;163,186,7,163,216,152,63,47,154,234,139,73,154,96,120,
           165,2,52,196,195,109,167,192,...&gt;&gt;}}
</pre></div>

      <p>This call is equivalent to public_key:pem_entry_decode(CertEntry1)</p>
      <div class="example"><pre>5&gt; public_key:pkix_decode_cert(DerCert, plain).
#'Certificate'{ ...}
</pre></div>
  

  <h4>Encoding public key data to PEM format</h4>
    

    <p>If you have public key data and and want to create a PEM file
    you can do that by calling the functions
    public_key:pem_entry_encode/2 and pem_encode/1 and then saving the
    result to a file. For example assume you have PubKey =
    'RSAPublicKey'{} then you can create a PEM-"RSA PUBLIC KEY" file
    (ASN.1 type 'RSAPublicKey') or a PEM-"PUBLIC KEY" file
    ('SubjectPublicKeyInfo' ASN.1 type).</p>

    <p> The second element of the PEM-entry will be the ASN.1 DER encoded
    key data.</p>

    <div class="example"><pre>1&gt; PemEntry = public_key:pem_entry_encode('RSAPublicKey', RSAPubKey).
{'RSAPublicKey', &lt;&lt;48,72,...&gt;&gt;, not_encrypted}

2&gt; PemBin = public_key:pem_encode([PemEntry]).
&lt;&lt;"-----BEGIN RSA PUBLIC KEY-----\nMEgC...&gt;&gt;

3&gt; file:write_file("rsa_pub_key.pem", PemBin).
ok</pre></div>

    <p> or </p>

    <div class="example"><pre>1&gt; PemBin = public_key:pem_entry_encode('SubjectPublicKeyInfo', RSAPubKey).
{'SubjectPublicKeyInfo', &lt;&lt;48,92...&gt;&gt;, not_encrypted}

2&gt; PemBin = public_key:pem_encode([PemEntry]).
&lt;&lt;"-----BEGIN PUBLIC KEY-----\nMFw...&gt;&gt;

3&gt; file:write_file("pub_key.pem", PemBin).
ok</pre></div>

  


<h3><a name="id63884">4.3 
        RSA public key cryptography </a></h3>
      
       <p> Suppose you have PrivateKey = #'RSAPrivateKey{}' and the
       plaintext Msg = binary() and the corresponding public key
       PublicKey = #'RSAPublicKey'{} then you can do the following.
       Note that you normally will only do one of the encrypt or
       decrypt operations and the peer will do the other.
       </p>

       <p>Encrypt with the private key </p>
       <div class="example"><pre>RsaEncrypted = public_key:encrypt_private(Msg, PrivateKey),
Msg = public_key:decrypt_public(RsaEncrypted, PublicKey),</pre></div>

       <p>Encrypt with the public key </p>
       <div class="example"><pre>RsaEncrypted = public_key:encrypt_public(Msg, PublicKey),
Msg = public_key:decrypt_private(RsaEncrypted, PrivateKey),</pre></div>
  

  <h3><a name="id63919">4.4 
        Digital signatures</a></h3>
    

    <p> Suppose you have PrivateKey = #'RSAPrivateKey{}'or
    #'DSAPrivateKey'{} and the plaintext Msg = binary() and the
    corresponding public key PublicKey = #'RSAPublicKey'{} or
    {integer(), #'DssParams'{}} then you can do the following.  Note
    that you normally will only do one of the sign or verify operations
    and the peer will do the other. </p>

    <div class="example"><pre>Signature = public_key:sign(Msg, sha, PrivateKey),
true = public_key:verify(Msg, sha, Signature, PublicKey),</pre></div>

    <p>It might be appropriate to calculate the message digest before
    calling sign or verify and then you can use the none as second
    argument.</p>

    <div class="example"><pre>Digest = crypto:sha(Msg),
Signature = public_key:sign(Digest, none, PrivateKey),
true = public_key:verify(Digest, none, Signature, PublicKey),
    </pre></div>
    
  
  
  <h3><a name="id63952">4.5 
        SSH files</a></h3>
    
    
    <p>SSH typically uses PEM files for private keys but has its
    own file format for storing public keys. The erlang public_key
    application can be used to parse the content of SSH public key files.</p>

    <h4> RFC 4716 SSH public key files </h4>
   

    <p>RFC 4716 SSH files looks confusingly like PEM files,
       but there are some differences.</p>
      <div class="example"><pre>1&gt; {ok, SshBin} = file:read_file("ssh2_rsa_pub").
{ok, &lt;&lt;"---- BEGIN SSH2 PUBLIC KEY ----\nAAAA"...&gt;&gt;}</pre></div>

    <p>This is equivalent to calling public_key:ssh_decode(SshBin, rfc4716_public_key).
    </p>
      <div class="example"><pre>2&gt; public_key:ssh_decode(SshBin, public_key).
[{#'RSAPublicKey'{modulus = 794430685...91663,
                  publicExponent = 35}, []}]
</pre></div>

 

 <h4> Openssh public key format </h4>
   
      <div class="example"><pre>1&gt; {ok, SshBin} = file:read_file("openssh_dsa_pub").
{ok,&lt;&lt;"ssh-dss AAAAB3Nza"...&gt;&gt;}</pre></div>

    <p>This is equivalent to calling public_key:ssh_decode(SshBin, openssh_public_key).
    </p>
    <div class="example"><pre>2&gt;  public_key:ssh_decode(SshBin, public_key).
[{{15642692...694280725,
   #'Dss-Parms'{p = 17291273936...696123221,
                q = 1255626590179665817295475654204371833735706001853,
                g = 10454211196...480338645}},
  [{comment,"dhopson@VMUbuntu-DSH"}]}]
</pre></div>
 

 <h4> Known hosts - openssh format</h4>
   

      <div class="example"><pre>1&gt; {ok, SshBin} = file:read_file("known_hosts").
{ok,&lt;&lt;"hostname.domain.com,192.168.0.1 ssh-rsa AAAAB...&gt;&gt;}</pre></div>

    <p>Returns a list of public keys and their related attributes
    each pair of key and attributes corresponds to one entry in
    the known hosts file.</p>
    
    <div class="example"><pre>2&gt;  public_key:ssh_decode(SshBin, known_hosts).
[{#'RSAPublicKey'{modulus = 1498979460408...72721699,
                  publicExponent = 35},
  [{hostnames,["hostname.domain.com","192.168.0.1"]}]},
 {#'RSAPublicKey'{modulus = 14989794604088...2721699,
                  publicExponent = 35},
  [{comment,"foo@bar.com"},
   {hostnames,["|1|BWO5qDxk/cFH0wa05JLdHn+j6xQ=|rXQvIxh5cDD3C43k5DPDamawVNA="]}]}]
</pre></div>
  

  <h4> Authorized keys - openssh format</h4>
    

    <div class="example"><pre>1&gt; {ok, SshBin} = file:read_file("auth_keys").
{ok, &lt;&lt;"command=\"dump /home\",no-pty,no-port-forwarding ssh-rsa AAA...&gt;&gt;}</pre></div>

    <p>Returns a list of public keys and their related attributes
    each pair of key and attributes corresponds to one entry in
    the authorized key file.</p>

    <div class="example"><pre>2&gt; public_key:ssh_decode(SshBin, auth_keys).
[{#'RSAPublicKey'{modulus = 794430685...691663,
                  publicExponent = 35},
  [{comment,"dhopson@VMUbuntu-DSH"},
   {options,["command=\"dump/home\"","no-pty",
             "no-port-forwarding"]}]},
 {{1564269258491...607694280725,
   #'Dss-Parms'{p = 17291273936185...763696123221,
                q = 1255626590179665817295475654204371833735706001853,
                g = 10454211195705...60511039590076780999046480338645}},
  [{comment,"dhopson@VMUbuntu-DSH"}]}]
</pre></div>
    

    <h4> Creating an SSH file from public key data </h4>
      

      <p>If you got a public key <span class="code">PubKey</span> and a related list of
      attributes <span class="code">Attributes</span> as returned
      by ssh_decode/2 you can create a new ssh file for example</p>
      <div class="example"><pre>N&gt; SshBin = public_key:ssh_encode([{PubKey, Attributes}], openssh_public_key),
&lt;&lt;"ssh-rsa "...&gt;&gt;
N+1&gt; file:write_file("id_rsa.pub", SshBin).
ok</pre></div>
    
  
</div>
<div class="footer">
<hr>
<p>Copyright © 2008-2012 Ericsson AB, All Rights Reserved</p>
</div>
</div>
</div></body>
</html>