diff options
author | Ng Pheng Siong <ngps@netmemetic.com> | 2003-06-22 16:41:19 +0000 |
---|---|---|
committer | Ng Pheng Siong <ngps@netmemetic.com> | 2003-06-22 16:41:19 +0000 |
commit | c0a9ac01395c395fb9c6198fb05980e8b5c108e4 (patch) | |
tree | 0670860e972d2fe22c2762ddb06d46e0638f5613 /doc | |
parent | 93d1049a42830e1d3c1303a460bc1e2a9a0a765b (diff) | |
download | m2crypto-c0a9ac01395c395fb9c6198fb05980e8b5c108e4.tar.gz |
*** empty log message ***
git-svn-id: http://svn.osafoundation.org/m2crypto/trunk@172 2715db39-9adf-0310-9c64-84f055769b4b
Diffstat (limited to 'doc')
-rw-r--r-- | doc/DOCU | 51 | ||||
-rw-r--r-- | doc/INSTALL.html | 237 | ||||
-rw-r--r-- | doc/README.html | 101 | ||||
-rw-r--r-- | doc/default.css | 174 | ||||
-rw-r--r-- | doc/howto.ca.docbook | 456 | ||||
-rw-r--r-- | doc/howto.ca.html | 891 | ||||
-rw-r--r-- | doc/howto.https.docbook | 248 | ||||
-rw-r--r-- | doc/howto.smime.docbook | 962 | ||||
-rw-r--r-- | doc/howto.smime.html | 1570 | ||||
-rw-r--r-- | doc/m2_blurb.docbook | 10 |
10 files changed, 4700 insertions, 0 deletions
diff --git a/doc/DOCU b/doc/DOCU new file mode 100644 index 0000000..a854d82 --- /dev/null +++ b/doc/DOCU @@ -0,0 +1,51 @@ +======================== + M2Crypto Documentation +======================== + +:Author: Ng Pheng Siong +:Id: $Id: DOCU,v 1.1 2003/06/22 16:41:18 ngps Exp $ + + +2003-06-22 +------------ + +DocBook wasn't to my taste, and I stopped soon after. + +I didn't start again, until recently. ;-) + +I now write in ReStructuredText. I use Zope as the content management +system, which has the advantage of automatic HTML rendering. Not +having to run the Jade command line shown below (or the +ReStructuredText equivalent) to generate HTML is like getting rid of +the "compile/link" step in the "edit-compile/link-run" +cycle. Productivity goes up! + +Of course, nobody in his right mind uses Zope's TTW interface to do +serious editing. I use Emacs/ange-ftp. + +I envisage some kind of ReportLab-based magic to generate PDF output +easily from within Zope. + + +15 Dec 2001 +------------- + +Here begins documentation. + +A year ago, I started writing documentation in Structured Text, but didn't +get very far. + +I'm currently writing in DocBook. I use the following to process the +DocBook files: + +- DocBook 4.1 +- Modular DSSSL stylesheets 1.64 +- Jade 1.2.1 +- SP 1.3.4 +- ISO 8879-1986 character entity sets. (I don't really know how these are used.) + +I invoke Jade thusly:: + + jade -V nochunks -t sgml -d /.../html/docbook.dsl file.docbook > file.html + + diff --git a/doc/INSTALL.html b/doc/INSTALL.html new file mode 100644 index 0000000..9d2c8e1 --- /dev/null +++ b/doc/INSTALL.html @@ -0,0 +1,237 @@ +<?xml version="1.0" encoding="utf-8" ?> +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> +<head> +<base href="https://localhost:9443/home/m2/INSTALL/" /> + +<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> +<meta name="generator" content="Docutils 0.2.8: http://docutils.sourceforge.net/" /> +<title>Installing M2Crypto 0.11</title> +<meta name="author" content="Ng Pheng Siong" /> +<meta name="date" content="2003-06-22" /> +<link rel="stylesheet" href="default.css" type="text/css" /> +</head> +<body> +<div class="document" id="installing-m2crypto-0-11"> +<h1 class="title">Installing M2Crypto 0.11</h1> +<table class="docinfo" frame="void" rules="none"> +<col class="docinfo-name" /> +<col class="docinfo-content" /> +<tbody valign="top"> +<tr><th class="docinfo-name">Author:</th> +<td>Ng Pheng Siong</td></tr> +<tr class="field"><th class="docinfo-name">Id:</th><td class="field-body">INSTALL,v 1.6 2003/06/22 16:28:47 ngps Exp</td> +</tr> +<tr><th class="docinfo-name">Date:</th> +<td>2003-06-22</td></tr> +<tr class="field"><th class="docinfo-name">Web-Site:</th><td class="field-body"><a class="reference" href="http://www.post1.com/home/ngps/m2">http://www.post1.com/home/ngps/m2</a></td> +</tr> +</tbody> +</table> +<div class="contents topic" id="contents"> +<p class="topic-title"><a name="contents">Contents</a></p> +<ul class="simple"> +<li><a class="reference" href="#pre-requisites" id="id1" name="id1">Pre-requisites</a></li> +<li><a class="reference" href="#preparation" id="id2" name="id2">Preparation</a></li> +<li><a class="reference" href="#installing-on-un-x" id="id3" name="id3">Installing on Un*x</a></li> +<li><a class="reference" href="#installing-on-windows" id="id4" name="id4">Installing on Windows</a><ul> +<li><a class="reference" href="#msvc" id="id5" name="id5">MSVC++</a></li> +<li><a class="reference" href="#bc" id="id6" name="id6">BC++</a></li> +<li><a class="reference" href="#mingw32" id="id7" name="id7">mingw32</a></li> +<li><a class="reference" href="#openssl-dlls" id="id8" name="id8">OpenSSL DLLs</a></li> +<li><a class="reference" href="#installing" id="id9" name="id9">Installing</a></li> +</ul> +</li> +<li><a class="reference" href="#building-on-mac-os-x" id="id10" name="id10">Building on Mac OS X</a></li> +</ul> +</div> +<div class="section" id="pre-requisites"> +<h1><a class="toc-backref" href="#id1" name="pre-requisites">Pre-requisites</a></h1> +<p>The following software packages are pre-requisites:</p> +<ul class="simple"> +<li><strong>Python 2.1 or 2.2</strong></li> +<li><strong>OpenSSL 0.9.7 or later</strong></li> +<li><strong>SWIG 1.3.17</strong></li> +</ul> +<div class="note"> +<p class="admonition-title">Note</p> +<ul class="simple"> +<li>Earlier versions of Python may or may not work.</li> +<li>This release is incompatible with OpenSSL versions prior to 0.9.7.</li> +<li>Earlier versions of SWIG may not work.</li> +</ul> +</div> +<p>This distribution is tested with OpenSSL 0.9.7a.</p> +</div> +<div class="section" id="preparation"> +<h1><a class="toc-backref" href="#id2" name="preparation">Preparation</a></h1> +<ol class="arabic"> +<li><p class="first">Read Sebastien Sauvage's webpage:</p> +<blockquote> +<p><a class="reference" href="http://sebsauvage.net/python/mingw.html">http://sebsauvage.net/python/mingw.html</a></p> +</blockquote> +</li> +<li><p class="first">(<strong>This step applies to both Windows and Un*x platforms</strong>). Tweak +Distutils per the above webpage. The following differs slightly from +Sebastien's instructions:</p> +<blockquote> +<ul> +<li><p class="first">Locate build_ext.py in your Python directory. On my Win98 +Python 2.2 installation it is <tt class="literal"><span class="pre">c:\pkg\py22\lib\distutils\command\build_ext.py</span></tt>.</p> +</li> +<li><p class="first">Change the 2 following lines:</p> +<pre class="literal-block"> +#new_sources.append(base + target_ext) # old +new_sources.append(base + '_wrap' + target_ext) # new + +#swig_cmd = [swig, "-python", "-dnone", "-ISWIG"] # old +swig_cmd = [swig, "-python", "-ISWIG"] # new +</pre> +</li> +</ul> +</blockquote> +</li> +</ol> +</div> +<div class="section" id="installing-on-un-x"> +<h1><a class="toc-backref" href="#id3" name="installing-on-un-x">Installing on Un*x</a></h1> +<pre class="literal-block"> +$ unzip m2crypto-0.11.zip +$ cd m2crypto-0.11 +$ python setup.py build +# python setup.py install +$ cd tests +$ python alltests.py +</pre> +<p>Also see the examples in <tt class="literal"><span class="pre">m2crypto-0.11/demo</span></tt>.</p> +</div> +<div class="section" id="installing-on-windows"> +<h1><a class="toc-backref" href="#id4" name="installing-on-windows">Installing on Windows</a></h1> +<div class="note"> +<p class="admonition-title">Note</p> +This section is from M2Crypto 0.10. These instructions +should continue to work for this release.</div> +<p>I have built and tested this distribution with the following:</p> +<ul class="simple"> +<li>MSVC++ 6.0</li> +<li>BC++ 5.5 free compiler suite</li> +<li>Bloodshed Dev-C++ version 4; Mingw compiler 2.95.2-1</li> +</ul> +<p>Before building from source, you need to install OpenSSL's include files, +import libraries and DLLs.</p> +<p>Here is the relevant section from setup.py:</p> +<pre class="literal-block"> +if os.name == 'nt': + openssl_dir = 'c:\\pkg\\openssl' + include_dirs = [my_inc, openssl_dir + '/include'] + library_dirs = [openssl_dir + '\\lib'] + libraries = ['ssleay32', 'libeay32'] + #libraries = ['ssleay32_bc', 'libeay32_bc'] +</pre> +<p>By convention, I place OpenSSL include files in <tt class="literal"><span class="pre">c:\pkg\openssl\include</span></tt>, and +the import libraries in <tt class="literal"><span class="pre">c:\pkg\openssl\lib</span></tt>.</p> +<div class="section" id="msvc"> +<h2><a class="toc-backref" href="#id5" name="msvc">MSVC++</a></h2> +<p>For MSVC++, the import libraries, as built by OpenSSL, are named <tt class="literal"><span class="pre">libeay32.lib</span></tt> +and <tt class="literal"><span class="pre">ssleay32.lib</span></tt>.</p> +</div> +<div class="section" id="bc"> +<h2><a class="toc-backref" href="#id6" name="bc">BC++</a></h2> +<p>For BC++ these files are created from the MSVC++-built ones using the +tool <tt class="literal"><span class="pre">coff2omf.exe</span></tt>. I call them <tt class="literal"><span class="pre">libeay32_bc.lib</span></tt> and +<tt class="literal"><span class="pre">ssleay32_bc.lib</span></tt>, respectively.</p> +<p>You'll also need Python's import library, e.g., <tt class="literal"><span class="pre">python22.lib</span></tt>, to +be the BC++-compatible version; i.e., create <tt class="literal"><span class="pre">python22_bc.lib</span></tt> from +<tt class="literal"><span class="pre">python22.lib</span></tt>, save a copy of <tt class="literal"><span class="pre">python22.lib</span></tt> (as <tt class="literal"><span class="pre">python22_vc.lib</span></tt>, +say), then rename <tt class="literal"><span class="pre">python22_bc.lib</span></tt> to <tt class="literal"><span class="pre">python22.lib</span></tt>.</p> +</div> +<div class="section" id="mingw32"> +<h2><a class="toc-backref" href="#id7" name="mingw32">mingw32</a></h2> +<p>For mingw32, the import libraries are named <tt class="literal"><span class="pre">libeay32.a</span></tt> and +<tt class="literal"><span class="pre">libssl32.a</span></tt>. To keep <tt class="literal"><span class="pre">setup.py</span></tt> simple, rename these to +<tt class="literal"><span class="pre">liblibeay32.a</span></tt> and <tt class="literal"><span class="pre">libssleay32.a</span></tt>, respectively, when you +install them into <tt class="literal"><span class="pre">c:\pkg\openssl\lib</span></tt>. If you do not wish to do +this, then modify <tt class="literal"><span class="pre">setup.py</span></tt> directly to change the <em>libraries</em> line in +the section quoted above.</p> +<p>You'll also need to create <tt class="literal"><span class="pre">libpython22.a</span></tt>.</p> +</div> +<div class="section" id="openssl-dlls"> +<h2><a class="toc-backref" href="#id8" name="openssl-dlls">OpenSSL DLLs</a></h2> +<p>With MSVC++, the OpenSSL DLLs, as built, are named <tt class="literal"><span class="pre">libeay32.dll</span></tt> +and <tt class="literal"><span class="pre">ssleay32.dll</span></tt>. With mingw32, the DLLs are named +<tt class="literal"><span class="pre">libeay32.dll</span></tt> and <tt class="literal"><span class="pre">libssl32.dll</span></tt>. Install these somewhere on +your PATH; by convention, I place them in <tt class="literal"><span class="pre">c:\bin</span></tt>, together with +<tt class="literal"><span class="pre">openssl.exe</span></tt>. It is best to make <tt class="literal"><span class="pre">ssleay32.dll</span></tt> and +<tt class="literal"><span class="pre">libssl32.dll</span></tt> copies of each other.</p> +</div> +<div class="section" id="installing"> +<h2><a class="toc-backref" href="#id9" name="installing">Installing</a></h2> +<p>Now you are ready to build M2Crypto. Do one of the following:</p> +<pre class="literal-block"> +python setup.py build +python setup.py build -cbcpp +python setup.py build -cmingw32 +</pre> +<p>Then,</p> +<pre class="literal-block"> +python setup.py install +cd tests +python alltests.py +</pre> +</div> +</div> +<div class="section" id="building-on-mac-os-x"> +<h1><a class="toc-backref" href="#id10" name="building-on-mac-os-x">Building on Mac OS X</a></h1> +<div class="note"> +<p class="admonition-title">Note</p> +This section has been left as is since it was originally +created. It is possibly outdated now. Updates are welcome.</div> +<p>Richard Jones has kindly contributed a makefile for Mac OS X. It is included +here as Makefile.osx. I have not tested it myself.</p> +<p>Follow these steps:</p> +<ol class="arabic"> +<li><p class="first"><tt class="literal"><span class="pre">cd</span> <span class="pre">swig</span></tt></p> +</li> +<li><p class="first">Fix paths in <tt class="literal"><span class="pre">Makefile.osx</span></tt>.</p> +</li> +<li><p class="first">One of:</p> +<blockquote> +<ul class="simple"> +<li>Python 2.1: make -f Makefile.osx</li> +<li>Python 2.0: dunno, give it a go...</li> +<li>Python 1.5.2: dunno, give it a go...</li> +</ul> +</blockquote> +</li> +<li><p class="first"><tt class="literal"><span class="pre">cd</span> <span class="pre">..</span></tt></p> +</li> +<li><p class="first">Install the directory <tt class="literal"><span class="pre">M2Crypto</span></tt> into a directory on the PYTHONPATH.</p> +</li> +<li><p class="first">If you have PyUnit installed:</p> +<pre class="literal-block"> +cd tests, python alltests.py +</pre> +</li> +<li><p class="first"><tt class="literal"><span class="pre">cd</span> <span class="pre">..</span></tt></p> +</li> +<li><p class="first"><tt class="literal"><span class="pre">cd</span> <span class="pre">demo</span></tt></p> +</li> +<li><p class="first">Try out the various test programs.</p> +</li> +</ol> +<p>Here are Richard's instructions on building OpenSSL 0.9.6 on OS X:</p> +<pre class="literal-block"> +> That and one needs to install openssl-0.9.6. But that's a whole other +> story. In short: +> 1. ./Configure OpenBSD +> 2. edit root Makefile to change "gcc" to "cc" +> 3. edit Makefile in apps and test to change the libraries to: +> LIBCRYPTO=../libcrypto.a +> LIBSSL=../libssl.a +> +> and you're there. +</pre> +</div> +</div> +</body> +</html> diff --git a/doc/README.html b/doc/README.html new file mode 100644 index 0000000..fa8c4ec --- /dev/null +++ b/doc/README.html @@ -0,0 +1,101 @@ +<?xml version="1.0" encoding="utf-8" ?> +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> +<head> +<base href="https://localhost:9443/home/m2/README/" /> + +<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> +<meta name="generator" content="Docutils 0.2.8: http://docutils.sourceforge.net/" /> +<title>M2Crypto 0.11</title> +<meta name="author" content="Ng Pheng Siong" /> +<meta name="date" content="2003-06-22" /> +<link rel="stylesheet" href="default.css" type="text/css" /> +</head> +<body> +<div class="document" id="m2crypto-0-11"> +<h1 class="title">M2Crypto 0.11</h1> +<table class="docinfo" frame="void" rules="none"> +<col class="docinfo-name" /> +<col class="docinfo-content" /> +<tbody valign="top"> +<tr><th class="docinfo-name">Author:</th> +<td>Ng Pheng Siong</td></tr> +<tr class="field"><th class="docinfo-name">Id:</th><td class="field-body">README,v 1.4 2003/06/22 16:28:47 ngps Exp</td> +</tr> +<tr><th class="docinfo-name">Date:</th> +<td>2003-06-22</td></tr> +<tr class="field"><th class="docinfo-name">Web-Site:</th><td class="field-body"><a class="reference" href="http://www.post1.com/home/ngps/m2">http://www.post1.com/home/ngps/m2</a></td> +</tr> +</tbody> +</table> +<div class="section" id="m2crypto-python-openssl-swig"> +<h1><a name="m2crypto-python-openssl-swig">M2Crypto = Python + OpenSSL + SWIG</a></h1> +<p>M2 stands for "me, too!" <a class="footnote-reference" href="#id5" id="id1" name="id1"><sup>1</sup></a></p> +<p>M2Crypto comes with the following:</p> +<ul class="simple"> +<li><strong>DH</strong>, <strong>RSA</strong>, <strong>DSA</strong>, <strong>symmetric ciphers</strong> including <strong>AES</strong>, +<strong>message digests</strong>, <strong>HMACs</strong>.</li> +<li><strong>SSL functionality</strong> to implement clients and servers.</li> +<li><strong>Example SSL client and server programs</strong>, which are variously +<strong>threading</strong>, <strong>forking</strong> or based on <strong>non-blocking socket IO</strong>.</li> +<li><strong>HTTPS</strong> extensions to Python's HTTP functionality.</li> +<li>Unforgeable HMAC'ing <strong>AuthCookies</strong> for <strong>web session management</strong>.</li> +<li><strong>XML-RPC over SSL</strong>.</li> +<li><strong>S/MIME v2</strong>.</li> +<li><strong>FTP/TLS</strong> client and server.</li> +<li><strong>ZServerSSL</strong>: A <strong>HTTPS server for Zope</strong>.</li> +<li><strong>ZSmime</strong>: A <strong>Zope</strong> server plug-in to generate <strong>S/MIME</strong> messages.</li> +</ul> +<p>M2Crypto is released under a very liberal BSD-style licence. See +LICENCE for details.</p> +<p>This release requires Python 2.1, 2.2, OpenSSL 0.9.6 or later, and +SWIG 1.3.17. Earlier versions of Python may or may not work. You are +recommended to use the current version of OpenSSL. Earlier versions of +SWIG may not work.</p> +<p>To install, see the file INSTALL.</p> +<p>Note these caveats:</p> +<ul class="simple"> +<li>Possible memory leaks, because some objects need to be freed on the +Python side and other objects on the C side, and these may change +between OpenSSL versions. (Multiple free's lead to crashes very +quickly, so these should be relatively rare.)</li> +<li>No memory locking/clearing for keys, passphrases, etc.</li> +<li>PRNG may not be CS <a class="footnote-reference" href="#id6" id="id2" name="id2"><sup>2</sup></a> nor CS <a class="footnote-reference" href="#id7" id="id3" name="id3"><sup>3</sup></a>.</li> +<li>AFAIK, Python and OpenSSL have not been subjected to the full +attention of the Bugtraq crowd. M2Crypto's handling of active hostile +input is probably suspect. <a class="footnote-reference" href="#id8" id="id4" name="id4"><sup>4</sup></a></li> +</ul> +<p>Have fun! Your feedback is welcome.</p> +<table class="footnote" frame="void" id="id5" rules="none"> +<colgroup><col class="label" /><col /></colgroup> +<tbody valign="top"> +<tr><td class="label"><a class="fn-backref" href="#id1" name="id5">[1]</a></td><td>Similar software are Marc-Andre Lemburg's mxCrypto, and two earlier +Python interfaces to the SSL portion of SSLeay/OpenSSL. Since M2Crypto, +yet more OpenSSL wrappers and non-OpenSSL crypto toolkits for +Python have appeared.</td></tr> +</tbody> +</table> +<table class="footnote" frame="void" id="id6" rules="none"> +<colgroup><col class="label" /><col /></colgroup> +<tbody valign="top"> +<tr><td class="label"><a class="fn-backref" href="#id2" name="id6">[2]</a></td><td>Continuous seeding.</td></tr> +</tbody> +</table> +<table class="footnote" frame="void" id="id7" rules="none"> +<colgroup><col class="label" /><col /></colgroup> +<tbody valign="top"> +<tr><td class="label"><a class="fn-backref" href="#id3" name="id7">[3]</a></td><td>Cryptographically strong.</td></tr> +</tbody> +</table> +<table class="footnote" frame="void" id="id8" rules="none"> +<colgroup><col class="label" /><col /></colgroup> +<tbody valign="top"> +<tr><td class="label"><a class="fn-backref" href="#id4" name="id8">[4]</a></td><td>In recent years, there have been reported vulnerabilities +in some versions of OpenSSL and attacks against the SSL protocol +itself.</td></tr> +</tbody> +</table> +</div> +</div> +</body> +</html> diff --git a/doc/default.css b/doc/default.css new file mode 100644 index 0000000..0024748 --- /dev/null +++ b/doc/default.css @@ -0,0 +1,174 @@ +/* +:Author: David Goodger +:Contact: goodger@users.sourceforge.net +:date: $Date: 2003/06/22 16:41:18 $ +:version: $Revision: 1.1 $ +:copyright: This stylesheet has been placed in the public domain. + +Default cascading style sheet for the HTML output of Docutils. +*/ + +a.footnote-reference { + font-size: smaller } + +a.target { + color: blue } + +a.toc-backref { + text-decoration: none ; + color: black } + +dd { + margin-bottom: 0.5em } + +div.abstract { + margin: 2em 5em } + +div.abstract p.topic-title { + font-weight: bold ; + text-align: center } + +div.attention, div.caution, div.danger, div.error, div.hint, +div.important, div.note, div.tip, div.warning { + margin: 2em ; + border: medium outset ; + padding: 1em } + +div.attention p.admonition-title, div.caution p.admonition-title, +div.danger p.admonition-title, div.error p.admonition-title, +div.warning p.admonition-title { + color: red ; + font-weight: bold ; + font-family: sans-serif } + +div.hint p.admonition-title, div.important p.admonition-title, +div.note p.admonition-title, div.tip p.admonition-title { + font-weight: bold ; + font-family: sans-serif } + +div.dedication { + margin: 2em 5em ; + text-align: center ; + font-style: italic } + +div.dedication p.topic-title { + font-weight: bold ; + font-style: normal } + +div.figure { + margin-left: 2em } + +div.footer, div.header { + font-size: smaller } + +div.system-messages { + margin: 5em } + +div.system-messages h1 { + color: red } + +div.system-message { + border: medium outset ; + padding: 1em } + +div.system-message p.system-message-title { + color: red ; + font-weight: bold } + +div.topic { + margin: 2em } + +h1.title { + text-align: center } + +h2.subtitle { + text-align: center } + +hr { + width: 75% } + +ol.simple, ul.simple { + margin-bottom: 1em } + +ol.arabic { + list-style: decimal } + +ol.loweralpha { + list-style: lower-alpha } + +ol.upperalpha { + list-style: upper-alpha } + +ol.lowerroman { + list-style: lower-roman } + +ol.upperroman { + list-style: upper-roman } + +p.caption { + font-style: italic } + +p.credits { + font-style: italic ; + font-size: smaller } + +p.first { + margin-top: 0 } + +p.label { + white-space: nowrap } + +p.topic-title { + font-weight: bold } + +pre.literal-block, pre.doctest-block { + margin-left: 2em ; + margin-right: 2em ; + background-color: #eeeeee } + +span.classifier { + font-family: sans-serif ; + font-style: oblique } + +span.classifier-delimiter { + font-family: sans-serif ; + font-weight: bold } + +span.field-argument { + font-style: italic } + +span.interpreted { + font-family: sans-serif } + +span.option-argument { + font-style: italic } + +span.problematic { + color: red } + +table { + margin-top: 0.5em ; + margin-bottom: 0.5em } + +table.citation { + border-left: solid thin gray ; + padding-left: 0.5ex } + +table.docinfo { + margin: 2em 4em } + +table.footnote { + border-left: solid thin black ; + padding-left: 0.5ex } + +td, th { + padding-left: 0.5em ; + padding-right: 0.5em ; + vertical-align: baseline } + +td.docinfo-name { + font-weight: bold ; + text-align: right } + +td.field-name { + font-weight: bold } diff --git a/doc/howto.ca.docbook b/doc/howto.ca.docbook new file mode 100644 index 0000000..5d08e92 --- /dev/null +++ b/doc/howto.ca.docbook @@ -0,0 +1,456 @@ +<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook V4.1//EN"> + +<article> + <articleinfo> + <title>HOWTO: Creating your own CA with OpenSSL</title> + + <author> + <firstname>Pheng Siong</firstname> + <surname>Ng</surname> + <affiliation> + <address><email>ngps@netmemetic.com</email></address> + </affiliation> + </author> + + <copyright> + <year>2000</year> + <year>2001</year> + <holder>Ng Pheng Siong.</holder> + </copyright> + + <revhistory> + <revision> + <revnumber>$Revision: 1.1 $</revnumber> + <date>$Date: 2003/06/22 16:41:18 $</date> + </revision> + </revhistory> + </articleinfo> + + <sect1 id="introduction"> + <title>Introduction</title> + <para>This is a HOWTO on creating your own <emphasis>certification + authority</emphasis> (<emphasis>CA</emphasis>) with OpenSSL. + </para> + + <para>I last created a CA about a year ago, when I began work on <ulink + url="http://www.post1.com/home/ngps/m2">M2Crypto</ulink> and needed + certificates for the SSL bits. I accepted the tools' default settings + then, e.g., certificate validity of 365 days; this meant that my + certificates, including my CA's certificate, have now expired. + </para> + + <para>Since I am using these certificates for M2Crypto's demonstration + programs (and I have forgotten the passphrase to the CA's private key), + I decided to discard the old CA and start afresh. I also decided to + document the process, hence this HOWTO. + </para> + </sect1> + + <sect1 id="procedure"> + <title>The Procedure</title> + <para>I use <filename>CA.pl</filename>, a Perl program written by + Steve Henson and bundled with OpenSSL. + </para> + + <para>The following are the steps to create a CA: + </para> + + <procedure> + <step> + <para>Choose a directory to do your CA work. All commands are executed + within this directory. Let's call the directory <filename>demo</filename>. + </para> + </step> + + <step> + <para>Copy <filename>CA.pl</filename> and <filename>openssl.cnf</filename> + into <filename>demo</filename>. + </para> + </step> + + <step> + <para>Apply the following patch to <filename>CA.pl</filename>, which + allows it to generate a CA certificate with a validity period of 1095 days, + i.e., 3 years: + </para> + + <programlisting> + --- CA.pl.org Sat Mar 31 12:40:13 2001 + +++ CA.pl Sat Mar 31 12:41:15 2001 + @@ -97,7 +97,7 @@ + } else { + print "Making CA certificate ...\n"; + system ("$REQ -new -x509 -keyout " . + - "${CATOP}/private/$CAKEY -out ${CATOP}/$CACERT $DAYS"); + + "${CATOP}/private/$CAKEY -out ${CATOP}/$CACERT -days 1095"); + $RET=$?; + } + } + </programlisting> + </step> + + <step> + <para>Create a new CA like this: + </para> + + <screen> + <userinput> +./CA.pl -newca + </userinput> + A certificate filename (or enter to create) <userinput><replaceable><enter></replaceable></userinput> + + Making CA certificate ... + Using configuration from openssl.cnf + Generating a 1024 bit RSA private key + ............++++++ + ......................++++++ + writing new private key to './demoCA/private/cakey.pem' + Enter PEM pass phrase: <userinput><replaceable><secret passphrase here></replaceable></userinput> + Verifying password - Enter PEM pass phrase: <userinput><replaceable><secret passphrase again></replaceable></userinput> + ----- + You are about to be asked to enter information that will be incorporated + into your certificate request. + What you are about to enter is what is called a Distinguished Name or a DN. + There are quite a few fields but you can leave some blank + For some fields there will be a default value, + If you enter '.', the field will be left blank. + ----- + Country Name (2 letter code) [AU]:<userinput><replaceable>SG</replaceable></userinput> + State or Province Name (full name) [Some-State]:<userinput><replaceable>.</replaceable></userinput> + Locality Name (eg, city) []:<userinput><replaceable>.</replaceable></userinput>. + Organization Name (eg, company) [Internet Widgits Pty Ltd]:<userinput><replaceable>DemoCA</replaceable></userinput> + Organizational Unit Name (eg, section) []:<userinput><replaceable>.</replaceable></userinput> + Common Name (eg, YOUR name) []:<userinput><replaceable>DemoCA Certificate Master</replaceable></userinput> + Email Address []:<userinput><replaceable>certmaster@democa.dom</replaceable></userinput> + </screen> + + <para>This creates a new CA in the directory <filename>demoCA</filename>. + The CA's self-signed certificate is in + <filename>demoCA/cacert.pem</filename> and its RSA key pair is in + <filename>demoCA/private/cakey.pem</filename>. + </para> + + <para><filename>demoCA/private/cakey.pem</filename> looks like this: + </para> + + <screen> + <userinput> +cat demoCA/private/cakey.pem + </userinput> + -----BEGIN RSA PRIVATE KEY----- + Proc-Type: 4,ENCRYPTED + DEK-Info: DES-EDE3-CBC,19973A9DBBB601BA + + eOq9WFScNiI4/UWEUaSnGTKpJv2JYuMD3HwQox2Q3Cd4zGqVjJ6gF3exa5126cKf + X/bMVnwbPpuFZPiAIvaLyCjT6pYeXTBbSzs7/GQnvEOv+nYnDUFWi0Qm92qLk0uy + pFi/M1aWheN3vir2ZlAw+DW0bOOZhj8tC7Co7lMYb0YE271b6/YRPZCwQ3GXAHUJ + +aMYxlUDrK45aCUa/1CZDzTgk7h9cDgx2QJSIvYMYytCfI3zsuZMJS8/4OXLL0bI + lKmAc1dwB3DqGJt5XK4WJesiNfdxeCNEgAcYtEAgYZTPIApU+kTgTCIxJl2nMW7j + ax+Q1z7g+4MpgG20WD633D4z4dTlDdz+dnLi0rvuvxiwt+dUhrqiML1tyi+Z6EBH + jU4/cLBWev3rYfrlp4x8J9mDte0YKOk3t0wQOHqRetTsIfdtjnFp/Hu3qDmTCWjD + z/g7PPoO/bg/B877J9WBPbL/1hXXFYo88M+2aGlPOgDcFdiOqbLb2DCscohMbbVr + A4mgiy2kwWfIE73qiyV7yyG8FlRvr1iib+jbT3LTGf743utYAAs7HNGuOUObhoyt + jYvBD7ACn35P5YX7KTqvqErwdijxYCaNBCnvmRtmYSaNw9Kv1UJTxc5Vx7YLwIPk + E9KyBgKI7vPOjWBZ27+zOvNycmv1ciNtpALAw4bWtXnhCDVTHaVDy34OkheMzNCg + 2cjcBFzOkMIjcI03KbTQXOFIQGlsTWXGzkNf/zBQ+KksT1MCj+zBXSCvlDASMckg + kef21pGgUqPF14gKGfWX3sV4bjc1vbrRwq6zlG3nMuYqR5MtJJY9eQ== + -----END RSA PRIVATE KEY----- + </screen> + </step> + + <step> + <para>Next, generate a certificate request. + </para> + + <screen> + <userinput> +./CA.pl -newreq + </userinput> + Using configuration from openssl.cnf + Generating a 1024 bit RSA private key + ..........++++++ + ..............++++++ + writing new private key to 'newreq.pem' + Enter PEM pass phrase: <userinput><replaceable><another secret passphrase here></replaceable></userinput> + Verifying password - Enter PEM pass phrase: <userinput><replaceable><another secret passphrase again></replaceable></userinput> + ----- + You are about to be asked to enter information that will be incorporated + into your certificate request. + What you are about to enter is what is called a Distinguished Name or a DN. + There are quite a few fields but you can leave some blank + For some fields there will be a default value, + If you enter '.', the field will be left blank. + ----- + Country Name (2 letter code) [AU]:<userinput><replaceable>SG</replaceable></userinput> + State or Province Name (full name) [Some-State]:.<userinput><replaceable>.</replaceable></userinput> + Locality Name (eg, city) []:<userinput><replaceable>.</replaceable></userinput> + Organization Name (eg, company) [Internet Widgits Pty Ltd]:<userinput><replaceable>M2Crypto</replaceable></userinput> + Organizational Unit Name (eg, section) []:<userinput><replaceable>.</replaceable></userinput> + Common Name (eg, YOUR name) []:<userinput><replaceable>localhost</replaceable></userinput> + Email Address []:<userinput><replaceable>admin@server.example.dom</replaceable></userinput> + + Please enter the following 'extra' attributes + to be sent with your certificate request + A challenge password []:<userinput><replaceable><enter></replaceable></userinput> + An optional company name []:<userinput><replaceable><enter></replaceable></userinput> + Request (and private key) is in newreq.pem + </screen> + + <para>The certificate request and private key in <filename>newreq.pem</filename> looks like this: + </para> + + <screen> + <userinput> +cat newreq.pem + </userinput> + -----BEGIN RSA PRIVATE KEY----- + Proc-Type: 4,ENCRYPTED + DEK-Info: DES-EDE3-CBC,41B2874DF3D02DD4 + + mg611EoVkLEooSTv+qTM0Ddmm/M1jE/Jy5RD/sc3LSMhuGu9xc26OgsTJmkQuIAh + J/B4lAw8G59VTG6DykeEtrG0rUBx4bggc7PKbFuiN423YjJODWcHvVgnPOzXMQt+ + lY4tPl5+217MRHyx2NsWGrpkQNdu3GeSPOVMl3jeQiaXupONbwQ7rj42+X/VtAJP + W4D1NNwu8aGCPyShsEXHc/fI1WDpphYWke97pOjIZVQESFZOPty5HjIYZux4U+td + W81xODtq2ecJXc8fn2Wpa9y5VD1LT7oJksOuL1+Z04OVaeUe4x0swM17HlBm2kVt + fe/C/L6kN27MwZhE331VjtTjSGl4/gknqQDbLOtqT06f3OISsDJETm2itllyhgzv + C6Fi3N03rGFmKectijC+tws5k+P+HRG6sai33usk8xPokJqA+HYSWPz1XVlpRmv4 + kdjQOdST7ovU62mOTgf3ARcduPPwuzTfxOlYONe5NioO1APVHBrInQwcpLkpOTQR + vI4roIN+b75/nihUWGUJn/nbbBa2Yl0N5Gs1Tyiy9Z+CcRT2TfWKBBFlEUIFl7Mb + J9fTV3DI+k+akbR4il1NkQ8EcSmCr3WpA0I9n0EHI7ZVpVaHxc0sqaPFl8YGdFHq + 1Qk53C/w6+qPpDzT3yKFmG2LZytAAM1czvb6RbNRJJP2ZrpBwn/h99sUTo/yPfxY + nueYmFJDm0uVNtG0icXGNUfSfnjKNTtHPAgyKGetRIC3kgJz/bo2w7EI6iEjBAzK + l5TRm4x6ZJxwuXXMiJCehMMd8TC8ybwWO4AO19B3ebFFeTVsUgxSGA== + -----END RSA PRIVATE KEY----- + -----BEGIN CERTIFICATE REQUEST----- + MIIBnTCCAQYCAQAwXTELMAkGA1UEBhMCU0cxETAPBgNVBAoTCE0yQ3J5cHRvMRIw + EAYDVQQDEwlsb2NhbGhvc3QxJzAlBgkqhkiG9w0BCQEWGGFkbWluQHNlcnZlci5l + eGFtcGxlLmRvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAr1nYY1Qrll1r + uB/FqlCRrr5nvupdIN+3wF7q915tvEQoc74bnu6b8IbbGRMhzdzmvQ4SzFfVEAuM + MuTHeybPq5th7YDrTNizKKxOBnqE2KYuX9X22A1Kh49soJJFg6kPb9MUgiZBiMlv + tb7K3CHfgw5WagWnLl8Lb+ccvKZZl+8CAwEAAaAAMA0GCSqGSIb3DQEBBAUAA4GB + AHpoRp5YS55CZpy+wdigQEwjL/wSluvo+WjtpvP0YoBMJu4VMKeZi405R7o8oEwi + PdlrrliKNknFmHKIaCKTLRcU59ScA6ADEIWUzqmUzP5Cs6jrSRo3NKfg1bd09D1K + 9rsQkRc9Urv9mRBIsredGnYECNeRaK5R1yzpOowninXC + -----END CERTIFICATE REQUEST----- + </screen> + + <para>Decoding the certificate request gives the following: + </para> + + <screen> + <userinput> +openssl req -text -noout < newreq.pem + </userinput> + Using configuration from /usr/local/pkg/openssl/openssl.cnf + Certificate Request: + Data: + Version: 0 (0x0) + Subject: C=SG, O=M2Crypto, CN=localhost/Email=admin@server.example.dom + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:af:59:d8:63:54:2b:96:5d:6b:b8:1f:c5:aa:50: + 91:ae:be:67:be:ea:5d:20:df:b7:c0:5e:ea:f7:5e: + 6d:bc:44:28:73:be:1b:9e:ee:9b:f0:86:db:19:13: + 21:cd:dc:e6:bd:0e:12:cc:57:d5:10:0b:8c:32:e4: + c7:7b:26:cf:ab:9b:61:ed:80:eb:4c:d8:b3:28:ac: + 4e:06:7a:84:d8:a6:2e:5f:d5:f6:d8:0d:4a:87:8f: + 6c:a0:92:45:83:a9:0f:6f:d3:14:82:26:41:88:c9: + 6f:b5:be:ca:dc:21:df:83:0e:56:6a:05:a7:2e:5f: + 0b:6f:e7:1c:bc:a6:59:97:ef + Exponent: 65537 (0x10001) + Attributes: + a0:00 + Signature Algorithm: md5WithRSAEncryption + 7a:68:46:9e:58:4b:9e:42:66:9c:be:c1:d8:a0:40:4c:23:2f: + fc:12:96:eb:e8:f9:68:ed:a6:f3:f4:62:80:4c:26:ee:15:30: + a7:99:8b:8d:39:47:ba:3c:a0:4c:22:3d:d9:6b:ae:58:8a:36: + 49:c5:98:72:88:68:22:93:2d:17:14:e7:d4:9c:03:a0:03:10: + 85:94:ce:a9:94:cc:fe:42:b3:a8:eb:49:1a:37:34:a7:e0:d5: + b7:74:f4:3d:4a:f6:bb:10:91:17:3d:52:bb:fd:99:10:48:b2: + b7:9d:1a:76:04:08:d7:91:68:ae:51:d7:2c:e9:3a:8c:27:8a: + 75:c2 + </screen> + </step> + + <step> + <para>Now, sign the certificate request: + </para> + + <screen> + <userinput> +./CA.pl -sign + </userinput> + Using configuration from openssl.cnf + Enter PEM pass phrase: <userinput><replaceable><CA's passphrase></replaceable></userinput> + Check that the request matches the signature + Signature ok + The Subjects Distinguished Name is as follows + countryName :PRINTABLE:'SG' + organizationName :PRINTABLE:'M2Crypto' + commonName :PRINTABLE:'localhost' + emailAddress :IA5STRING:'admin@server.example.dom' + Certificate is to be certified until Mar 31 02:57:30 2002 GMT (365 days) + Sign the certificate? [y/n]:<userinput><replaceable>y</replaceable></userinput> + + + 1 out of 1 certificate requests certified, commit? [y/n]<userinput><replaceable>y</replaceable></userinput> + Write out database with 1 new entries + Data Base Updated + Signed certificate is in newcert.pem + </screen> + + <para><filename>newcert.pem</filename> looks like this: + </para> + + <screen> + <userinput> +cat newcert.pem + </userinput> + Certificate: + Data: + Version: 3 (0x2) + Serial Number: 1 (0x1) + Signature Algorithm: md5WithRSAEncryption + Issuer: C=SG, O=DemoCA, CN=DemoCA Certificate Master/Email=certmaster@democa.dom + Validity + Not Before: Mar 31 02:57:30 2001 GMT + Not After : Mar 31 02:57:30 2002 GMT + Subject: C=SG, O=M2Crypto, CN=localhost/Email=admin@server.example.dom + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:af:59:d8:63:54:2b:96:5d:6b:b8:1f:c5:aa:50: + 91:ae:be:67:be:ea:5d:20:df:b7:c0:5e:ea:f7:5e: + 6d:bc:44:28:73:be:1b:9e:ee:9b:f0:86:db:19:13: + 21:cd:dc:e6:bd:0e:12:cc:57:d5:10:0b:8c:32:e4: + c7:7b:26:cf:ab:9b:61:ed:80:eb:4c:d8:b3:28:ac: + 4e:06:7a:84:d8:a6:2e:5f:d5:f6:d8:0d:4a:87:8f: + 6c:a0:92:45:83:a9:0f:6f:d3:14:82:26:41:88:c9: + 6f:b5:be:ca:dc:21:df:83:0e:56:6a:05:a7:2e:5f: + 0b:6f:e7:1c:bc:a6:59:97:ef + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: + Certificate: + Data: + Version: 3 (0x2) + Serial Number: 1 (0x1) + Signature Algorithm: md5WithRSAEncryption + Issuer: C=SG, O=DemoCA, CN=DemoCA Certificate Master/Email=certmaster@democa.dom + Validity + Not Before: Mar 31 02:57:30 2001 GMT + Not After : Mar 31 02:57:30 2002 GMT + Subject: C=SG, O=M2Crypto, CN=localhost/Email=admin@server.example.dom + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:af:59:d8:63:54:2b:96:5d:6b:b8:1f:c5:aa:50: + 91:ae:be:67:be:ea:5d:20:df:b7:c0:5e:ea:f7:5e: + 6d:bc:44:28:73:be:1b:9e:ee:9b:f0:86:db:19:13: + 21:cd:dc:e6:bd:0e:12:cc:57:d5:10:0b:8c:32:e4: + c7:7b:26:cf:ab:9b:61:ed:80:eb:4c:d8:b3:28:ac: + 4e:06:7a:84:d8:a6:2e:5f:d5:f6:d8:0d:4a:87:8f: + 6c:a0:92:45:83:a9:0f:6f:d3:14:82:26:41:88:c9: + 6f:b5:be:ca:dc:21:df:83:0e:56:6a:05:a7:2e:5f: + 0b:6f:e7:1c:bc:a6:59:97:ef + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: + CA:FALSE + Netscape Comment: + OpenSSL Generated Certificate + X509v3 Subject Key Identifier: + B3:D6:89:88:2F:B1:15:40:EC:0A:C0:30:35:3A:B7:DA:72:73:1B:4D + X509v3 Authority Key Identifier: + keyid:F9:6A:A6:34:97:6B:BC:BB:5A:17:0D:19:FC:62:21:0B:00:B5:0E:29 + DirName:/C=SG/O=DemoCA/CN=DemoCA Certificate Master/Email=certmaster@democa.dom + serial:00 + + Signature Algorithm: md5WithRSAEncryption + </screen> + </step> + + <step> + <para>In certain situations, e.g., where your certificate and + private key are to be used in an unattended SSL server, you may wish to + not encrypt the private key, i.e., leave the key in the clear. This + decision should be governed by your site's security policy and threat + model, of course. + </para> + + <screen> + <userinput> +openssl rsa < newreq.pem > newkey.pem + </userinput> + read RSA key + Enter PEM pass phrase:<userinput><replaceable><secret passphrase here></replaceable></userinput> + writing RSA key + </screen> + + <para><filename>newkey.pem</filename> looks like this: + </para> + + <screen> + <userinput> +cat newkey.pem + </userinput> + -----BEGIN RSA PRIVATE KEY----- + MIICXgIBAAKBgQCvWdhjVCuWXWu4H8WqUJGuvme+6l0g37fAXur3Xm28RChzvhue + 7pvwhtsZEyHN3Oa9DhLMV9UQC4wy5Md7Js+rm2HtgOtM2LMorE4GeoTYpi5f1fbY + DUqHj2ygkkWDqQ9v0xSCJkGIyW+1vsrcId+DDlZqBacuXwtv5xy8plmX7wIDAQAB + AoGAbAkU8w3W1Qu15Hle1bJSL7GMReoreqeblOBmMAZz4by0l6sXZXJpjWXo86f/ + +dASMYTMPC4ZTYtv06N07AFbjL+kDfqDMTfzQkYMHp1LAq1Ihbq1rHWSBH5n3ekq + KiY8JKpv8DR5Po1iKaXJFuDByGDENJwYbSRSpSK3P+vkWWECQQDkEUE/ZPqqqZkQ + 2iWRPAsCbEID8SAraQl3DdCLYs/GgARfmmj4yUHEwkys9Jo1H8k4BdxugmaUwNi5 + YQ/CVzrXAkEAxNO80ArbGxPUmr11GHG/bGBYj1DUBkHZSc7dgxZdtUCLGNxQnNsg + Iwq3n6j1sUzS3UW6abQ8bivYNOUcMKJAqQJBANQxFaLU4b/NQaODQ3aoBZpAfP9L + 5eFdvbet+7zjt2r5CpikgkwOfAmDuXEltx/8LevY0CllW+nErx9zJgVrwUsCQQCu + 76H5JiznPBDSF2FjgHWqVVdgyW4owY3mU739LHvNBLicN/RN9VPy0Suy8/CqzKT9 + lWPBXzf2k3FuUdNkRlFBAkEAmpXoybuiFR2S5Bma/ax96lVs0/VihhfC1zZP/X/F + Br77+h9dIul+2DnyOl50zu0Sdzst1/7ay4JSDHyiBCMGSQ== + -----END RSA PRIVATE KEY----- + </screen> + </step> + </procedure> + + <para>That's it! The certificate, <filename>newcert.pem</filename>, and + the private key - <filename>newreq.pem</filename> (encrypted) or + <filename>newkey.pem</filename> (unencrypted) - are now ready to be used. + You may wish to rename the files to more intuitive names. + </para> + + <para>You should also keep the CA's certificate <filename>demo/cacert.pem + </filename> handy for use when developing and deploying SSL or S/MIME + applications. + </para> + </sect1> + + <sect1 id="conclusion"> + <title>Conclusion</title> + + <para>We've walked through the basic steps in the creation of a CA and + certificates using the tools that come with OpenSSL. We did not cover more + advanced topics such as constraining a certificate to be SSL-only or + S/MIME-only. + </para> + + <para>There exist several HOWTOs similar to this one on the net. This one + is written specifically to facilitate discussions in my other HOWTOs + on developing SSL and S/MIME applications in + <ulink url="http://www.python.org">Python</ulink> using + <ulink url="http://www.post1.com/home/ngps/m2">M2Crypto</ulink>. + </para> + </sect1> + + <sect1 id="id-kludge"> + <title></title> + <para> + <literal>$Id: howto.ca.docbook,v 1.1 2003/06/22 16:41:18 ngps Exp $</literal> + </para> + </sect1> +</article> + diff --git a/doc/howto.ca.html b/doc/howto.ca.html new file mode 100644 index 0000000..d517c1e --- /dev/null +++ b/doc/howto.ca.html @@ -0,0 +1,891 @@ +<HTML +><HEAD +><TITLE +>HOWTO: Creating your own CA with OpenSSL</TITLE +><META +NAME="GENERATOR" +CONTENT="Modular DocBook HTML Stylesheet Version 1.64 +"></HEAD +><BODY +CLASS="ARTICLE" +BGCOLOR="#FFFFFF" +TEXT="#000000" +LINK="#0000FF" +VLINK="#840084" +ALINK="#0000FF" +><DIV +CLASS="ARTICLE" +><DIV +CLASS="TITLEPAGE" +><H1 +CLASS="TITLE" +><A +NAME="AEN2" +>HOWTO: Creating your own CA with OpenSSL</A +></H1 +><H3 +CLASS="AUTHOR" +><A +NAME="AEN4" +>Pheng Siong Ng</A +></H3 +><DIV +CLASS="AFFILIATION" +><DIV +CLASS="ADDRESS" +><P +CLASS="ADDRESS" +>ngps@post1.com</P +></DIV +></DIV +><P +CLASS="COPYRIGHT" +>Copyright © 2000, 2001 by Ng Pheng Siong.</P +><DIV +CLASS="REVHISTORY" +><TABLE +WIDTH="100%" +BORDER="0" +><TR +><TH +ALIGN="LEFT" +VALIGN="TOP" +COLSPAN="3" +><B +>Revision History</B +></TH +></TR +><TR +><TD +ALIGN="LEFT" +>Revision $Revision: 1.1 $</TD +><TD +ALIGN="LEFT" +>$Date: 2003/06/22 16:41:18 $</TD +><TD +ALIGN="LEFT" +></TD +></TR +><TR +><TD +ALIGN="LEFT" +COLSPAN="3" +></TD +></TR +></TABLE +></DIV +><HR></DIV +><DIV +CLASS="SECT1" +><HR><H1 +CLASS="SECT1" +><A +NAME="INTRODUCTION" +>Introduction</A +></H1 +><P +>This is a HOWTO on creating your own <I +CLASS="EMPHASIS" +>certification + authority</I +> (<I +CLASS="EMPHASIS" +>CA</I +>) with OpenSSL. + </P +><P +>I last created a CA about a year ago, when I began work on <A +HREF="http://www.post1.com/home/ngps/m2" +TARGET="_top" +>M2Crypto</A +> and needed + certificates for the SSL bits. I accepted the tools' default settings + then, e.g., certificate validity of 365 days; this meant that my + certificates, including my CA's certificate, have now expired. + </P +><P +>Since I am using these certificates for M2Crypto's demonstration + programs (and I have forgotten the passphrase to the CA's private key), + I decided to discard the old CA and start afresh. I also decided to + document the process, hence this HOWTO. + </P +></DIV +><DIV +CLASS="SECT1" +><HR><H1 +CLASS="SECT1" +><A +NAME="PROCEDURE" +>The Procedure</A +></H1 +><P +>I use <TT +CLASS="FILENAME" +>CA.pl</TT +>, a Perl program written by + Steve Hanson and bundled with OpenSSL. + </P +><P +>The following are the steps to create a CA: + </P +><DIV +CLASS="PROCEDURE" +><OL +TYPE="1" +><LI +><P +>Choose a directory to do your CA work. All commands are executed + within this directory. Let's call the directory <TT +CLASS="FILENAME" +>demo</TT +>. + </P +></LI +><LI +><P +>Copy <TT +CLASS="FILENAME" +>CA.pl</TT +> and <TT +CLASS="FILENAME" +>openssl.cnf</TT +> + into <TT +CLASS="FILENAME" +>demo</TT +>. + </P +></LI +><LI +><P +>Apply the following patch to <TT +CLASS="FILENAME" +>CA.pl</TT +>, which + allows it to generate a CA certificate with a validity period of 1095 days, + i.e., 3 years: + </P +><PRE +CLASS="PROGRAMLISTING" +> --- CA.pl.org Sat Mar 31 12:40:13 2001 + +++ CA.pl Sat Mar 31 12:41:15 2001 + @@ -97,7 +97,7 @@ + } else { + print "Making CA certificate ...\n"; + system ("$REQ -new -x509 -keyout " . + - "${CATOP}/private/$CAKEY -out ${CATOP}/$CACERT $DAYS"); + + "${CATOP}/private/$CAKEY -out ${CATOP}/$CACERT -days 1095"); + $RET=$?; + } + } + </PRE +></LI +><LI +><P +>Create a new CA like this: + </P +><PRE +CLASS="SCREEN" +> <TT +CLASS="USERINPUT" +><B +>./CA.pl -newca + </B +></TT +> + A certificate filename (or enter to create) <TT +CLASS="USERINPUT" +><B +><TT +CLASS="REPLACEABLE" +><I +><enter></I +></TT +></B +></TT +> + + Making CA certificate ... + Using configuration from openssl.cnf + Generating a 1024 bit RSA private key + ............++++++ + ......................++++++ + writing new private key to './demoCA/private/cakey.pem' + Enter PEM pass phrase: <TT +CLASS="USERINPUT" +><B +><TT +CLASS="REPLACEABLE" +><I +><secret passphrase here></I +></TT +></B +></TT +> + Verifying password - Enter PEM pass phrase: <TT +CLASS="USERINPUT" +><B +><TT +CLASS="REPLACEABLE" +><I +><secret passphrase again></I +></TT +></B +></TT +> + ----- + You are about to be asked to enter information that will be incorporated + into your certificate request. + What you are about to enter is what is called a Distinguished Name or a DN. + There are quite a few fields but you can leave some blank + For some fields there will be a default value, + If you enter '.', the field will be left blank. + ----- + Country Name (2 letter code) [AU]:<TT +CLASS="USERINPUT" +><B +><TT +CLASS="REPLACEABLE" +><I +>SG</I +></TT +></B +></TT +> + State or Province Name (full name) [Some-State]:<TT +CLASS="USERINPUT" +><B +><TT +CLASS="REPLACEABLE" +><I +>.</I +></TT +></B +></TT +> + Locality Name (eg, city) []:<TT +CLASS="USERINPUT" +><B +><TT +CLASS="REPLACEABLE" +><I +>.</I +></TT +></B +></TT +>. + Organization Name (eg, company) [Internet Widgits Pty Ltd]:<TT +CLASS="USERINPUT" +><B +><TT +CLASS="REPLACEABLE" +><I +>DemoCA</I +></TT +></B +></TT +> + Organizational Unit Name (eg, section) []:<TT +CLASS="USERINPUT" +><B +><TT +CLASS="REPLACEABLE" +><I +>.</I +></TT +></B +></TT +> + Common Name (eg, YOUR name) []:<TT +CLASS="USERINPUT" +><B +><TT +CLASS="REPLACEABLE" +><I +>DemoCA Certificate Master</I +></TT +></B +></TT +> + Email Address []:<TT +CLASS="USERINPUT" +><B +><TT +CLASS="REPLACEABLE" +><I +>certmaster@democa.dom</I +></TT +></B +></TT +> + </PRE +><P +>This creates a new CA in the directory <TT +CLASS="FILENAME" +>demoCA</TT +>. + The CA's self-signed certificate is in + <TT +CLASS="FILENAME" +>demoCA/cacert.pem</TT +> and its RSA key pair is in + <TT +CLASS="FILENAME" +>demoCA/private/cakey.pem</TT +>. + </P +><P +><TT +CLASS="FILENAME" +>demoCA/private/cakey.pem</TT +> looks like this: + </P +><PRE +CLASS="SCREEN" +> <TT +CLASS="USERINPUT" +><B +>cat demoCA/private/cakey.pem + </B +></TT +> + -----BEGIN RSA PRIVATE KEY----- + Proc-Type: 4,ENCRYPTED + DEK-Info: DES-EDE3-CBC,19973A9DBBB601BA + + eOq9WFScNiI4/UWEUaSnGTKpJv2JYuMD3HwQox2Q3Cd4zGqVjJ6gF3exa5126cKf + X/bMVnwbPpuFZPiAIvaLyCjT6pYeXTBbSzs7/GQnvEOv+nYnDUFWi0Qm92qLk0uy + pFi/M1aWheN3vir2ZlAw+DW0bOOZhj8tC7Co7lMYb0YE271b6/YRPZCwQ3GXAHUJ + +aMYxlUDrK45aCUa/1CZDzTgk7h9cDgx2QJSIvYMYytCfI3zsuZMJS8/4OXLL0bI + lKmAc1dwB3DqGJt5XK4WJesiNfdxeCNEgAcYtEAgYZTPIApU+kTgTCIxJl2nMW7j + ax+Q1z7g+4MpgG20WD633D4z4dTlDdz+dnLi0rvuvxiwt+dUhrqiML1tyi+Z6EBH + jU4/cLBWev3rYfrlp4x8J9mDte0YKOk3t0wQOHqRetTsIfdtjnFp/Hu3qDmTCWjD + z/g7PPoO/bg/B877J9WBPbL/1hXXFYo88M+2aGlPOgDcFdiOqbLb2DCscohMbbVr + A4mgiy2kwWfIE73qiyV7yyG8FlRvr1iib+jbT3LTGf743utYAAs7HNGuOUObhoyt + jYvBD7ACn35P5YX7KTqvqErwdijxYCaNBCnvmRtmYSaNw9Kv1UJTxc5Vx7YLwIPk + E9KyBgKI7vPOjWBZ27+zOvNycmv1ciNtpALAw4bWtXnhCDVTHaVDy34OkheMzNCg + 2cjcBFzOkMIjcI03KbTQXOFIQGlsTWXGzkNf/zBQ+KksT1MCj+zBXSCvlDASMckg + kef21pGgUqPF14gKGfWX3sV4bjc1vbrRwq6zlG3nMuYqR5MtJJY9eQ== + -----END RSA PRIVATE KEY----- + </PRE +></LI +><LI +><P +>Next, generate a certificate request. + </P +><PRE +CLASS="SCREEN" +> <TT +CLASS="USERINPUT" +><B +>./CA.pl -newreq + </B +></TT +> + Using configuration from openssl.cnf + Generating a 1024 bit RSA private key + ..........++++++ + ..............++++++ + writing new private key to 'newreq.pem' + Enter PEM pass phrase: <TT +CLASS="USERINPUT" +><B +><TT +CLASS="REPLACEABLE" +><I +><another secret passphrase here></I +></TT +></B +></TT +> + Verifying password - Enter PEM pass phrase: <TT +CLASS="USERINPUT" +><B +><TT +CLASS="REPLACEABLE" +><I +><another secret passphrase again></I +></TT +></B +></TT +> + ----- + You are about to be asked to enter information that will be incorporated + into your certificate request. + What you are about to enter is what is called a Distinguished Name or a DN. + There are quite a few fields but you can leave some blank + For some fields there will be a default value, + If you enter '.', the field will be left blank. + ----- + Country Name (2 letter code) [AU]:<TT +CLASS="USERINPUT" +><B +><TT +CLASS="REPLACEABLE" +><I +>SG</I +></TT +></B +></TT +> + State or Province Name (full name) [Some-State]:.<TT +CLASS="USERINPUT" +><B +><TT +CLASS="REPLACEABLE" +><I +>.</I +></TT +></B +></TT +> + Locality Name (eg, city) []:<TT +CLASS="USERINPUT" +><B +><TT +CLASS="REPLACEABLE" +><I +>.</I +></TT +></B +></TT +> + Organization Name (eg, company) [Internet Widgits Pty Ltd]:<TT +CLASS="USERINPUT" +><B +><TT +CLASS="REPLACEABLE" +><I +>M2Crypto</I +></TT +></B +></TT +> + Organizational Unit Name (eg, section) []:<TT +CLASS="USERINPUT" +><B +><TT +CLASS="REPLACEABLE" +><I +>.</I +></TT +></B +></TT +> + Common Name (eg, YOUR name) []:<TT +CLASS="USERINPUT" +><B +><TT +CLASS="REPLACEABLE" +><I +>localhost</I +></TT +></B +></TT +> + Email Address []:<TT +CLASS="USERINPUT" +><B +><TT +CLASS="REPLACEABLE" +><I +>admin@server.example.dom</I +></TT +></B +></TT +> + + Please enter the following 'extra' attributes + to be sent with your certificate request + A challenge password []:<TT +CLASS="USERINPUT" +><B +><TT +CLASS="REPLACEABLE" +><I +><enter></I +></TT +></B +></TT +> + An optional company name []:<TT +CLASS="USERINPUT" +><B +><TT +CLASS="REPLACEABLE" +><I +><enter></I +></TT +></B +></TT +> + Request (and private key) is in newreq.pem + </PRE +><P +>The certificate request and private key in <TT +CLASS="FILENAME" +>newreq.pem</TT +> looks like this: + </P +><PRE +CLASS="SCREEN" +> <TT +CLASS="USERINPUT" +><B +>cat newreq.pem + </B +></TT +> + -----BEGIN RSA PRIVATE KEY----- + Proc-Type: 4,ENCRYPTED + DEK-Info: DES-EDE3-CBC,41B2874DF3D02DD4 + + mg611EoVkLEooSTv+qTM0Ddmm/M1jE/Jy5RD/sc3LSMhuGu9xc26OgsTJmkQuIAh + J/B4lAw8G59VTG6DykeEtrG0rUBx4bggc7PKbFuiN423YjJODWcHvVgnPOzXMQt+ + lY4tPl5+217MRHyx2NsWGrpkQNdu3GeSPOVMl3jeQiaXupONbwQ7rj42+X/VtAJP + W4D1NNwu8aGCPyShsEXHc/fI1WDpphYWke97pOjIZVQESFZOPty5HjIYZux4U+td + W81xODtq2ecJXc8fn2Wpa9y5VD1LT7oJksOuL1+Z04OVaeUe4x0swM17HlBm2kVt + fe/C/L6kN27MwZhE331VjtTjSGl4/gknqQDbLOtqT06f3OISsDJETm2itllyhgzv + C6Fi3N03rGFmKectijC+tws5k+P+HRG6sai33usk8xPokJqA+HYSWPz1XVlpRmv4 + kdjQOdST7ovU62mOTgf3ARcduPPwuzTfxOlYONe5NioO1APVHBrInQwcpLkpOTQR + vI4roIN+b75/nihUWGUJn/nbbBa2Yl0N5Gs1Tyiy9Z+CcRT2TfWKBBFlEUIFl7Mb + J9fTV3DI+k+akbR4il1NkQ8EcSmCr3WpA0I9n0EHI7ZVpVaHxc0sqaPFl8YGdFHq + 1Qk53C/w6+qPpDzT3yKFmG2LZytAAM1czvb6RbNRJJP2ZrpBwn/h99sUTo/yPfxY + nueYmFJDm0uVNtG0icXGNUfSfnjKNTtHPAgyKGetRIC3kgJz/bo2w7EI6iEjBAzK + l5TRm4x6ZJxwuXXMiJCehMMd8TC8ybwWO4AO19B3ebFFeTVsUgxSGA== + -----END RSA PRIVATE KEY----- + -----BEGIN CERTIFICATE REQUEST----- + MIIBnTCCAQYCAQAwXTELMAkGA1UEBhMCU0cxETAPBgNVBAoTCE0yQ3J5cHRvMRIw + EAYDVQQDEwlsb2NhbGhvc3QxJzAlBgkqhkiG9w0BCQEWGGFkbWluQHNlcnZlci5l + eGFtcGxlLmRvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAr1nYY1Qrll1r + uB/FqlCRrr5nvupdIN+3wF7q915tvEQoc74bnu6b8IbbGRMhzdzmvQ4SzFfVEAuM + MuTHeybPq5th7YDrTNizKKxOBnqE2KYuX9X22A1Kh49soJJFg6kPb9MUgiZBiMlv + tb7K3CHfgw5WagWnLl8Lb+ccvKZZl+8CAwEAAaAAMA0GCSqGSIb3DQEBBAUAA4GB + AHpoRp5YS55CZpy+wdigQEwjL/wSluvo+WjtpvP0YoBMJu4VMKeZi405R7o8oEwi + PdlrrliKNknFmHKIaCKTLRcU59ScA6ADEIWUzqmUzP5Cs6jrSRo3NKfg1bd09D1K + 9rsQkRc9Urv9mRBIsredGnYECNeRaK5R1yzpOowninXC + -----END CERTIFICATE REQUEST----- + </PRE +><P +>Decoding the certificate request gives the following: + </P +><PRE +CLASS="SCREEN" +> <TT +CLASS="USERINPUT" +><B +>openssl req -text -noout < newreq.pem + </B +></TT +> + Using configuration from /usr/local/pkg/openssl/openssl.cnf + Certificate Request: + Data: + Version: 0 (0x0) + Subject: C=SG, O=M2Crypto, CN=localhost/Email=admin@server.example.dom + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:af:59:d8:63:54:2b:96:5d:6b:b8:1f:c5:aa:50: + 91:ae:be:67:be:ea:5d:20:df:b7:c0:5e:ea:f7:5e: + 6d:bc:44:28:73:be:1b:9e:ee:9b:f0:86:db:19:13: + 21:cd:dc:e6:bd:0e:12:cc:57:d5:10:0b:8c:32:e4: + c7:7b:26:cf:ab:9b:61:ed:80:eb:4c:d8:b3:28:ac: + 4e:06:7a:84:d8:a6:2e:5f:d5:f6:d8:0d:4a:87:8f: + 6c:a0:92:45:83:a9:0f:6f:d3:14:82:26:41:88:c9: + 6f:b5:be:ca:dc:21:df:83:0e:56:6a:05:a7:2e:5f: + 0b:6f:e7:1c:bc:a6:59:97:ef + Exponent: 65537 (0x10001) + Attributes: + a0:00 + Signature Algorithm: md5WithRSAEncryption + 7a:68:46:9e:58:4b:9e:42:66:9c:be:c1:d8:a0:40:4c:23:2f: + fc:12:96:eb:e8:f9:68:ed:a6:f3:f4:62:80:4c:26:ee:15:30: + a7:99:8b:8d:39:47:ba:3c:a0:4c:22:3d:d9:6b:ae:58:8a:36: + 49:c5:98:72:88:68:22:93:2d:17:14:e7:d4:9c:03:a0:03:10: + 85:94:ce:a9:94:cc:fe:42:b3:a8:eb:49:1a:37:34:a7:e0:d5: + b7:74:f4:3d:4a:f6:bb:10:91:17:3d:52:bb:fd:99:10:48:b2: + b7:9d:1a:76:04:08:d7:91:68:ae:51:d7:2c:e9:3a:8c:27:8a: + 75:c2 + </PRE +></LI +><LI +><P +>Now, sign the certificate request: + </P +><PRE +CLASS="SCREEN" +> <TT +CLASS="USERINPUT" +><B +>./CA.pl -sign + </B +></TT +> + Using configuration from openssl.cnf + Enter PEM pass phrase: <TT +CLASS="USERINPUT" +><B +><TT +CLASS="REPLACEABLE" +><I +><CA's passphrase></I +></TT +></B +></TT +> + Check that the request matches the signature + Signature ok + The Subjects Distinguished Name is as follows + countryName :PRINTABLE:'SG' + organizationName :PRINTABLE:'M2Crypto' + commonName :PRINTABLE:'localhost' + emailAddress :IA5STRING:'admin@server.example.dom' + Certificate is to be certified until Mar 31 02:57:30 2002 GMT (365 days) + Sign the certificate? [y/n]:<TT +CLASS="USERINPUT" +><B +><TT +CLASS="REPLACEABLE" +><I +>y</I +></TT +></B +></TT +> + + + 1 out of 1 certificate requests certified, commit? [y/n]<TT +CLASS="USERINPUT" +><B +><TT +CLASS="REPLACEABLE" +><I +>y</I +></TT +></B +></TT +> + Write out database with 1 new entries + Data Base Updated + Signed certificate is in newcert.pem + </PRE +><P +><TT +CLASS="FILENAME" +>newcert.pem</TT +> looks like this: + </P +><PRE +CLASS="SCREEN" +> <TT +CLASS="USERINPUT" +><B +>cat newcert.pem + </B +></TT +> + Certificate: + Data: + Version: 3 (0x2) + Serial Number: 1 (0x1) + Signature Algorithm: md5WithRSAEncryption + Issuer: C=SG, O=DemoCA, CN=DemoCA Certificate Master/Email=certmaster@democa.dom + Validity + Not Before: Mar 31 02:57:30 2001 GMT + Not After : Mar 31 02:57:30 2002 GMT + Subject: C=SG, O=M2Crypto, CN=localhost/Email=admin@server.example.dom + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:af:59:d8:63:54:2b:96:5d:6b:b8:1f:c5:aa:50: + 91:ae:be:67:be:ea:5d:20:df:b7:c0:5e:ea:f7:5e: + 6d:bc:44:28:73:be:1b:9e:ee:9b:f0:86:db:19:13: + 21:cd:dc:e6:bd:0e:12:cc:57:d5:10:0b:8c:32:e4: + c7:7b:26:cf:ab:9b:61:ed:80:eb:4c:d8:b3:28:ac: + 4e:06:7a:84:d8:a6:2e:5f:d5:f6:d8:0d:4a:87:8f: + 6c:a0:92:45:83:a9:0f:6f:d3:14:82:26:41:88:c9: + 6f:b5:be:ca:dc:21:df:83:0e:56:6a:05:a7:2e:5f: + 0b:6f:e7:1c:bc:a6:59:97:ef + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: + Certificate: + Data: + Version: 3 (0x2) + Serial Number: 1 (0x1) + Signature Algorithm: md5WithRSAEncryption + Issuer: C=SG, O=DemoCA, CN=DemoCA Certificate Master/Email=certmaster@democa.dom + Validity + Not Before: Mar 31 02:57:30 2001 GMT + Not After : Mar 31 02:57:30 2002 GMT + Subject: C=SG, O=M2Crypto, CN=localhost/Email=admin@server.example.dom + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:af:59:d8:63:54:2b:96:5d:6b:b8:1f:c5:aa:50: + 91:ae:be:67:be:ea:5d:20:df:b7:c0:5e:ea:f7:5e: + 6d:bc:44:28:73:be:1b:9e:ee:9b:f0:86:db:19:13: + 21:cd:dc:e6:bd:0e:12:cc:57:d5:10:0b:8c:32:e4: + c7:7b:26:cf:ab:9b:61:ed:80:eb:4c:d8:b3:28:ac: + 4e:06:7a:84:d8:a6:2e:5f:d5:f6:d8:0d:4a:87:8f: + 6c:a0:92:45:83:a9:0f:6f:d3:14:82:26:41:88:c9: + 6f:b5:be:ca:dc:21:df:83:0e:56:6a:05:a7:2e:5f: + 0b:6f:e7:1c:bc:a6:59:97:ef + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: + CA:FALSE + Netscape Comment: + OpenSSL Generated Certificate + X509v3 Subject Key Identifier: + B3:D6:89:88:2F:B1:15:40:EC:0A:C0:30:35:3A:B7:DA:72:73:1B:4D + X509v3 Authority Key Identifier: + keyid:F9:6A:A6:34:97:6B:BC:BB:5A:17:0D:19:FC:62:21:0B:00:B5:0E:29 + DirName:/C=SG/O=DemoCA/CN=DemoCA Certificate Master/Email=certmaster@democa.dom + serial:00 + + Signature Algorithm: md5WithRSAEncryption + </PRE +></LI +><LI +><P +>In certain situations, e.g., where your certificate and + private key are to be used in an unattended SSL server, you may wish to + not encrypt the private key, i.e., leave the key in the clear. This + decision should be governed by your site's security policy and threat + model, of course. + </P +><PRE +CLASS="SCREEN" +> <TT +CLASS="USERINPUT" +><B +>openssl rsa < newreq.pem > newkey.pem + </B +></TT +> + read RSA key + Enter PEM pass phrase:<TT +CLASS="USERINPUT" +><B +><TT +CLASS="REPLACEABLE" +><I +><secret passphrase here></I +></TT +></B +></TT +> + writing RSA key + </PRE +><P +><TT +CLASS="FILENAME" +>newkey.pem</TT +> looks like this: + </P +><PRE +CLASS="SCREEN" +> <TT +CLASS="USERINPUT" +><B +>cat newkey.pem + </B +></TT +> + -----BEGIN RSA PRIVATE KEY----- + MIICXgIBAAKBgQCvWdhjVCuWXWu4H8WqUJGuvme+6l0g37fAXur3Xm28RChzvhue + 7pvwhtsZEyHN3Oa9DhLMV9UQC4wy5Md7Js+rm2HtgOtM2LMorE4GeoTYpi5f1fbY + DUqHj2ygkkWDqQ9v0xSCJkGIyW+1vsrcId+DDlZqBacuXwtv5xy8plmX7wIDAQAB + AoGAbAkU8w3W1Qu15Hle1bJSL7GMReoreqeblOBmMAZz4by0l6sXZXJpjWXo86f/ + +dASMYTMPC4ZTYtv06N07AFbjL+kDfqDMTfzQkYMHp1LAq1Ihbq1rHWSBH5n3ekq + KiY8JKpv8DR5Po1iKaXJFuDByGDENJwYbSRSpSK3P+vkWWECQQDkEUE/ZPqqqZkQ + 2iWRPAsCbEID8SAraQl3DdCLYs/GgARfmmj4yUHEwkys9Jo1H8k4BdxugmaUwNi5 + YQ/CVzrXAkEAxNO80ArbGxPUmr11GHG/bGBYj1DUBkHZSc7dgxZdtUCLGNxQnNsg + Iwq3n6j1sUzS3UW6abQ8bivYNOUcMKJAqQJBANQxFaLU4b/NQaODQ3aoBZpAfP9L + 5eFdvbet+7zjt2r5CpikgkwOfAmDuXEltx/8LevY0CllW+nErx9zJgVrwUsCQQCu + 76H5JiznPBDSF2FjgHWqVVdgyW4owY3mU739LHvNBLicN/RN9VPy0Suy8/CqzKT9 + lWPBXzf2k3FuUdNkRlFBAkEAmpXoybuiFR2S5Bma/ax96lVs0/VihhfC1zZP/X/F + Br77+h9dIul+2DnyOl50zu0Sdzst1/7ay4JSDHyiBCMGSQ== + -----END RSA PRIVATE KEY----- + </PRE +></LI +></OL +></DIV +><P +>That's it! The certificate, <TT +CLASS="FILENAME" +>newcert.pem</TT +>, and + the private key - <TT +CLASS="FILENAME" +>newreq.pem</TT +> (encrypted) or + <TT +CLASS="FILENAME" +>newkey.pem</TT +> (unencrypted) - are now ready to be used. + You may wish to rename the files to more intuitive names. + </P +><P +>You should also keep the CA's certificate <TT +CLASS="FILENAME" +>demo/cacert.pem + </TT +> handy for use when developing and deploying SSL or S/MIME + applications. + </P +></DIV +><DIV +CLASS="SECT1" +><HR><H1 +CLASS="SECT1" +><A +NAME="CONCLUSION" +>Conclusion</A +></H1 +><P +>We've walked through the basic steps in the creation of a CA and + certificates using the tools that come with OpenSSL. We did not cover more + advanced topics such as constraining a certificate to be SSL-only or + S/MIME-only. + </P +><P +>There exist several HOWTOs similar to this one on the net. This one + is written specifically to facilitate discussions in my other HOWTOs + on developing SSL and S/MIME applications in + <A +HREF="http://www.python.org" +TARGET="_top" +>Python</A +> using + <A +HREF="http://www.post1.com/home/ngps/m2" +TARGET="_top" +>M2Crypto</A +>. + </P +></DIV +><DIV +CLASS="SECT1" +><HR><H1 +CLASS="SECT1" +><A +NAME="ID-KLUDGE" +></A +></H1 +><P +> <TT +CLASS="LITERAL" +>$Id: howto.ca.html,v 1.1 2003/06/22 16:41:18 ngps Exp $</TT +> + </P +></DIV +></DIV +></BODY +></HTML +>
\ No newline at end of file diff --git a/doc/howto.https.docbook b/doc/howto.https.docbook new file mode 100644 index 0000000..c097e0c --- /dev/null +++ b/doc/howto.https.docbook @@ -0,0 +1,248 @@ +<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook V4.1//EN" [ + <!ENTITY m2-blurb SYSTEM "m2_blurb.docbook"> +]> + +<article> + <articleinfo> + <title>HOWTO: Programming HTTPS in Python with M2Crypto</title> + + <author> + <firstname>Pheng Siong</firstname> + <surname>Ng</surname> + <affiliation> + <address><email>ngps@netmemetic.com</email></address> + </affiliation> + </author> + + <copyright> + <year>2001</year> + <year>2002</year> + <holder>Ng Pheng Siong.</holder> + </copyright> + + <revhistory> + <revision> + <revnumber>$Revision: 1.1 $</revnumber> + <date>$Date: 2003/06/22 16:41:18 $</date> + </revision> + </revhistory> + </articleinfo> + + <sect1 id="introduction"> + <title>Introduction</title> + &m2-blurb; + + <para>This document demonstrates programming HTTPS clients and servers + with M2Crypto. + </para> + </sect1> + + <sect1 id="https"> + <title>Programming HTTPS</title> + <para>HTTPS - HTTP over SSL/TLS + <citation>RFC XXXX</citation> - provides a XXX + </para> + + <para>Python has had good HTTP support for several years now. M2Crypto's + HTTPS functionality mostly adopts the interfaces in Python's HTTP modules. + </para> + + <para>In this HOWTO, we shall begin with writing HTTPS clients. Now, to + test the HTTPS clients we write, we need a HTTPS server; conversely, to + test our HTTPS servers, we need a HTTPS client. ;-) </para> + + <para> All the programs we write in this HOWTO are found in + <m2crypto>/demo/https.howto/. Additionally, a number of programs from + <m2crypto>/demo/ssl are also copied into this directory; their names are + prefixed by "orig". These "orig" programs shall be our known-working HTTPS + clients and servers. </para> </sect1> + + <sect1 id="ssldump"> + <title>ssldump</title> + + <para>ssldump "is an SSLv3/TLS network protocol analyser. It identifies + TCP connections on the chosen network interface and attempts to interpret + them as SSLv3/TLS traffic. When it identifies SSLv3/TLS traffic, it + decodes the records and displays them in a textual form to stdout. If + provided with the appropriate keying material, it will also decrypt the + connections and display the application data traffic. + </para> + + <para> + If linked with OpenSSL, ssldump can display certificates in decoded form + and decrypt traffic (provided that it has the appropriate keying + material)." + </para> + + <para>ssldump is written by Eric Rescorla. + </para> + </sect1> + + <sect1 id="orig-https-srv.py"> + <title>orig_https_srv.py</title> + <para>orig_https_srv.py is an enhanced version of SimpleHTTPServer that + features the following: </para> + + <itemizedlist mark=opencircle> + <listitem> + <para>Works over HTTPS. + </para> + </listitem> + + <listitem> + <para>Uses one thread per connection. + </para> + </listitem> + + <listitem> + <para>Generates directory listings. + </para> + </listitem> + + <listitem> + <para>Displays SSL handshaking and SSL session info. + </para> + </listitem> + + <listitem> + <para>Performs SSL renegotiation when a magic URL is requested. + </para> + </listitem> + </itemizedlist> + + <para>Invoke orig_https_srv.py thusly: + </para> + + <screen> + <userinput> +$ python orig_https_srv.py + </userinput> + </screen> + + <para>By default, orig_https_srv.py serves HTTPS on port 9443. + </para> + </sect1> + + <sect1 id="history"> + <title>A bit of history</title> + <para> M2Crypto was created during the time of Python 1.5, which features + a module httplib providing client-side HTTP functionality. M2Crypto sports + a httpslib based on httplib. + </para> + + <para> + Beginning with version 2.0, Python's socket module provided + (rudimentary) SSL support. Also in the same version, httplib was + enhanced with class HTTPConnection, which is more sophisticated than + the old class HTTP, and HTTPSConnection, which does HTTPS. + </para> + + <para> + Subsequently, M2Crypto.httpslib grew a compatible (but not identical) + class HTTPSConnection. + </para> + + <para> + The primary interface difference between the two HTTPSConnection + classes is that M2Crypto's version accepts an M2Crypto.SSL.Context + instance as a parameter, whereas Python 2.x's SSL support does not + permit Pythonic control of the SSL context. + </para> + + <para> Within the implementations, Python's + <classname>HTTPSConnection</classname> employs a + <classname>FakeSocket</classname> object, which collects all input from + the SSL connection before returning it to the application as a + <classname>StringIO</classname> buffer, whereas M2Crypto's + <classname>HTTPSConnection</classname> uses a buffering + <classname>M2Crypto.BIO.IOBuffer</classname> object that works over the + underlying M2Crypto.SSL.Connection directly. </para> </sect1> + + <sect1 id="simple-get"> + <title>A simple HTTPS GET client using M2Crypto.httpslib</title> + + <para> Let us now look at possibly the simplest HTTPS client we will ever + write. + </para> + </sect1> + + <sect1 id="simple-post"> + <title>A simple HTTPS-POST client</title> + <para>XXX + </para> + </sect1> + + <sect1 id="threaded-cli"> + <title>A multi-threaded HTTPS client</title> + <para>XXX + </para> + </sect1> + + <sect1 id="async-cli"> + <title>An asynchronous HTTPS client</title> + <para>XXX + </para> + </sect1> + + <sect1 id="session-reuse"> + <title>Re-using SSL session </title> + <para>XXX + </para> + </sect1> + + <sect1 id="threaded-reuse-cli"> + <title>A multi-threaded session-reusing client</title> + <para>XXX + </para> + </sect1> + + <sect1 id="async-reuse-cli"> + <title>An asynchronous session-reusing client</title> + <para>XXX + </para> + </sect1> + + <sect1 id="verify-server-cert"> + <title>Verifying server certificate</title> + <para>XXX + </para> + </sect1> + + <sect1 id="using-client-cert"> + <title>Using client certificate</title> + <para>XXX + </para> + </sect1> + + <sect1 id="simple-https-server"> + <title>SimpleHTTPSServer</title> + <para>XXX + </para> + </sect1> + + <sect1 id="medusa-https-server"> + <title>A Medusa-based HTTPS server</title> + <para>XXX + </para> + </sect1> + + <sect1 id="verify-client-cert"> + <title>Client certificate-based authentication</title> + <para>XXX + </para> + </sect1> + + <sect1 id="control-session-reuse"> + <title>Controlling session reuse</title> + <para>XXX + </para> + </sect1> + + <sect1 id="id-kludge"> + <title></title> + <para> + <literal>$Id: howto.https.docbook,v 1.1 2003/06/22 16:41:18 ngps Exp $</literal> + </para> + </sect1> +</article> + diff --git a/doc/howto.smime.docbook b/doc/howto.smime.docbook new file mode 100644 index 0000000..85a63ef --- /dev/null +++ b/doc/howto.smime.docbook @@ -0,0 +1,962 @@ +<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook V4.1//EN" [ + <!ENTITY m2-blurb SYSTEM "m2_blurb.docbook"> +]> + +<article> + <articleinfo> + <title>HOWTO: Programming S/MIME in Python with M2Crypto</title> + + <author> + <firstname>Pheng Siong</firstname> + <surname>Ng</surname> + <affiliation> + <address><email>ngps@netmemetic.com</email></address> + </affiliation> + </author> + + <copyright> + <year>2000</year> + <year>2001</year> + <holder>Ng Pheng Siong.</holder> + </copyright> + + <revhistory> + <revision> + <revnumber>$Revision: 1.1 $</revnumber> + <date>$Date: 2003/06/22 16:41:18 $</date> + </revision> + </revhistory> + </articleinfo> + + <sect1 id="introduction"> + <title>Introduction</title> + &m2-blurb; + + <para>This document demonstrates programming S/MIME with M2Crypto. + </para> + </sect1> + + <sect1 id="smime"> + <title>S/MIME</title> + <para>S/MIME - Secure Multipurpose Internet Mail Extensions + <citation>RFC 2311, RFC 2312</citation> - provides a + consistent way to send and receive secure MIME data. Based on the popular + Internet MIME standard, S/MIME provides the following cryptographic security + services for electronic messaging applications - + <emphasis>authentication</emphasis>, <emphasis>message integrity </emphasis> + and <emphasis>non-repudiation of origin </emphasis> (using <emphasis>digital + signatures</emphasis>), and <emphasis>privacy </emphasis> and <emphasis>data + security</emphasis> (using <emphasis>encryption</emphasis>). + </para> + </sect1> + + <sect1 id="keys-and-certificates"> + <title>Keys and Certificates</title> + <para>To create an S/MIME-signed message, you need an RSA key pair + (this consists of a public key and a private key) and an X.509 + certificate of said public key. + </para> + + <para>To create an S/MIME-encrypted message, you need an X.509 + certificate for each recipient. + </para> + + <para>To create an S/MIME-signed <emphasis>and</emphasis> -encrypted + message, first create a signed message, then encrypt the signed + message with the recipients' certificates. + </para> + + <para>You may generate key pairs and obtain certificates by using a + commercial <emphasis>certification authority</emphasis> service. + </para> + + <para>You can also do so using freely-available software. For many + purposes, e.g., automated S/MIME messaging by system administration + processes, this approach is cheap and effective. + </para> + + <para>We now work through using OpenSSL to generate key pairs and + certificates. This assumes you have OpenSSL installed properly on your + system. + </para> + + <para>First, we generate an X.509 certificate to be used for signing: + </para> + + <screen> + <userinput> +openssl req -newkey rsa:1024 -nodes -x509 -days 365 -out signer.pem + </userinput> + Using configuration from /usr/local/pkg/openssl/openssl.cnf + Generating a 1024 bit RSA private key + ..++++++ + ....................++++++ + writing new private key to 'privkey.pem' + ----- + You are about to be asked to enter information that will be incorporated + into your certificate request. + What you are about to enter is what is called a Distinguished Name or a DN. + There are quite a few fields but you can leave some blank + For some fields there will be a default value, + If you enter '.', the field will be left blank. + ----- + Country Name (2 letter code) [AU]:<userinput><replaceable>SG</replaceable></userinput> + State or Province Name (full name) [Some-State]:<userinput><replaceable>.</replaceable></userinput> + Locality Name (eg, city) []:<userinput><replaceable>.</replaceable></userinput> + Organization Name (eg, company) [Internet Widgits Pty Ltd]:<userinput><replaceable>M2Crypto</replaceable></userinput> + Organizational Unit Name (eg, section) []:<userinput><replaceable>.</replaceable></userinput> + Common Name (eg, YOUR name) []:<userinput><replaceable>S/MIME Sender</replaceable></userinput> + Email Address []:<userinput><replaceable>sender@example.dom</replaceable></userinput> + </screen> + + <para>This generates a 1024-bit RSA key pair, unencrypted, into + <filename>privkey.pem</filename>; it also generates a self-signed X.509 + certificate for the public key into <filename>signer.pem</filename>. The + certificate is valid for 365 days, i.e., a year. + </para> + + <para>Let's rename <filename>privkey.pem</filename> so that we know it is + a companion of <filename>signer.pem</filename>'s: + </para> + + <screen> + <userinput>mv privkey.pem signer_key.pem</userinput> + </screen> + + <para>To verify the content of <filename>signer.pem</filename>, execute the + following: + </para> + + <screen> + <userinput> +openssl x509 -noout -text -in signer.pem + </userinput> + Certificate: + Data: + Version: 3 (0x2) + Serial Number: 0 (0x0) + Signature Algorithm: md5WithRSAEncryption + Issuer: C=SG, O=M2Crypto, CN=S/MIME Sender/Email=sender@example.dom + Validity + Not Before: Mar 24 12:56:16 2001 GMT + Not After : Mar 24 12:56:16 2002 GMT + Subject: C=SG, O=M2Crypto, CN=S/MIME Sender/Email=sender@example.dom + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:a9:d6:e2:b5:11:3b:ae:3c:e2:17:31:70:e1:6e: + 01:f4:19:6d:bd:2a:42:36:2b:37:34:e2:83:1d:0d: + 11:2e:b4:99:44:db:10:67:be:97:5f:5b:1a:26:33: + 46:23:2f:95:04:7a:35:da:9d:f9:26:88:39:9e:17: + cd:3e:eb:a8:19:8d:a8:2a:f1:43:da:55:a9:2e:2c: + 65:ed:04:71:42:ce:73:53:b8:ea:7e:c7:f0:23:c6: + 63:c5:5e:68:96:64:a7:b4:2a:94:26:76:eb:79:ea: + e3:4e:aa:82:09:4f:44:87:4a:12:62:b5:d7:1f:ca: + f2:ce:d5:ba:7e:1f:48:fd:b9 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 29:FB:38:B6:BF:E2:40:BB:FF:D5:71:D7:D5:C4:F0:83:1A:2B:C7:99 + X509v3 Authority Key Identifier: + keyid:29:FB:38:B6:BF:E2:40:BB:FF:D5:71:D7:D5:C4:F0:83:1A:2B:C7:99 + DirName:/C=SG/O=M2Crypto/CN=S/MIME Sender/Email=sender@example.dom + serial:00 + + X509v3 Basic Constraints: + CA:TRUE + Signature Algorithm: md5WithRSAEncryption + 68:c8:6b:1b:fa:7c:9a:39:35:76:18:15:c9:fd:89:97:62:db: + 7a:b0:2d:13:dd:97:e8:1b:7a:9f:22:27:83:24:9d:2e:56:ec: + 97:89:3c:ef:16:55:80:5a:18:7c:22:d0:f6:bb:e3:a4:e8:59: + 30:ff:99:5a:93:3e:ea:bc:ee:7f:8d:d6:7d:37:8c:ac:3d:74: + 80:ce:7a:99:ba:27:b9:2a:a3:71:fa:a5:25:ba:47:17:df:07: + 56:96:36:fd:60:b9:6c:96:06:e8:e3:7b:9f:4b:6a:95:71:a8: + 34:fc:fc:b5:88:8b:c4:3f:1e:24:f6:52:47:b2:7d:44:67:d9: + 83:e8 + </screen> + + <para>Next, we generate a self-signed X.509 certificate for the + recipient. Note that <filename>privkey.pem</filename> will be + recreated. + </para> + + <screen> + <userinput> +openssl req -newkey rsa:1024 -nodes -x509 -days 365 -out recipient.pem + </userinput> + Using configuration from /usr/local/pkg/openssl/openssl.cnf + Generating a 1024 bit RSA private key + .....................................++++++ + .................++++++ + writing new private key to 'privkey.pem' + ----- + You are about to be asked to enter information that will be incorporated + into your certificate request. + What you are about to enter is what is called a Distinguished Name or a DN. + There are quite a few fields but you can leave some blank + For some fields there will be a default value, + If you enter '.', the field will be left blank. + ----- + Country Name (2 letter code) [AU]:<userinput><replaceable>SG</replaceable></userinput> + State or Province Name (full name) [Some-State]:<userinput><replaceable>.</replaceable></userinput> + Locality Name (eg, city) []:<userinput><replaceable>.</replaceable></userinput> + Organization Name (eg, company) [Internet Widgits Pty Ltd]:<userinput><replaceable>M2Crypto</replaceable></userinput> + Organizational Unit Name (eg, section) []:<userinput><replaceable>.</replaceable></userinput> + Common Name (eg, YOUR name) []:<userinput><replaceable>S/MIME Recipient</replaceable></userinput> + Email Address []:<userinput><replaceable>recipient@example.dom</replaceable></userinput> + </screen> + + <para>Again, rename <filename>privkey.pem</filename>: + </para> + + <screen> + <userinput>mv privkey.pem recipient_key.pem</userinput> + </screen> + + <para>In the examples to follow, S/MIME Sender, + <email>sender@example.dom</email>, shall be the sender of S/MIME messages, + while S/MIME Recipient, <email>recipient@example.dom</email>, shall be the + recipient of S/MIME messages. + </para> + + <para>Armed with the key pairs and certificates, we are now ready to begin + programming S/MIME in Python. + </para> + + <note> + <para>The private keys generated above are + <emphasis>not passphrase-protected</emphasis>, i.e., they are + <emphasis>in the clear</emphasis>. Anyone who has access to such a key can + generate S/MIME-signed messages with it, and decrypt S/MIME messages + encrypted to it's corresponding public key. + </para> + + <para>We may passphrase-protect the keys, if we so choose. M2Crypto will + prompt the user for the passphrase when such a key is being loaded. + </para> + </note> + + </sect1> + + <sect1 id="m2crypto-smime"> + <title>M2Crypto.SMIME</title> + <para>The Python programmer accesses M2Crypto's S/MIME functionality + through class <classname>SMIME</classname> in the module + <classname>M2Crypto.SMIME</classname>. Typically, an <classname>SMIME</classname> + object is instantiated; the object is then set up for the intended + operation: sign, encrypt, decrypt or verify; finally, the operation is invoked on + the object. + </para> + + <para><classname>M2Crypto.SMIME</classname> makes extensive use of + <classname>M2Crypto.BIO</classname>: <classname>M2Crypto.BIO</classname> + is a Python abstraction of the <classname>BIO</classname> abstraction in + OpenSSL. A commonly used <classname>BIO</classname> abstraction in M2Crypto is + <classname>M2Crypto.BIO.MemoryBuffer</classname>, which implements a + memory-based file-like object, similar to Python's own + <classname>StringIO</classname>. + </para> + </sect1> + + <sect1 id="sign"> + <title>Sign</title> + <para>The following code demonstrates how to generate an S/MIME-signed + message. <filename>randpool.dat</filename> contains random data which is + used to seed OpenSSL's pseudo-random number generator via M2Crypto. + </para> + + <programlisting> + from M2Crypto import BIO, Rand, SMIME + + def makebuf(text): + return BIO.MemoryBuffer(text) + + # Make a MemoryBuffer of the message. + buf = makebuf('a sign of our times') + + # Seed the PRNG. + Rand.load_file('randpool.dat', -1) + + # Instantiate an SMIME object; set it up; sign the buffer. + s = SMIME.SMIME() + s.load_key('signer_key.pem', 'signer.pem') + p7 = s.sign(buf) + </programlisting> + + <para><varname>p7</varname> now contains a <emphasis>PKCS #7 signature + blob</emphasis> wrapped in an <classname>M2Crypto.SMIME.PKCS7</classname> + object. Note that <varname>buf</varname> has been consumed by + <function>sign()</function> and has to be recreated if it is to be used + again. + </para> + + <para>We may now send the signed message via SMTP. In these examples, we + shall not do so; instead, we'll render the S/MIME output in + mail-friendly format, and pretend that our messages are sent and + received correctly. + </para> + + <programlisting> + # Recreate buf. + buf = makebuf('a sign of our times') + + # Output p7 in mail-friendly format. + out = BIO.MemoryBuffer() + out.write('From: sender@example.dom\n') + out.write('To: recipient@example.dom\n') + out.write('Subject: M2Crypto S/MIME testing\n') + s.write(out, p7, buf) + + print out.read() + + # Save the PRNG's state. + Rand.save_file('randpool.dat') + </programlisting> + + <para>Here's the output: + </para> + + <screen> + From: sender@example.dom + To: recipient@example.dom + Subject: M2Crypto S/MIME testing + MIME-Version: 1.0 + Content-Type: multipart/signed ; protocol="application/x-pkcs7-signature" ; micalg=sha1 ; boundary="----3C93156FC7B4EBF49FE9C7DB7F503087" + + This is an S/MIME signed message + + ------3C93156FC7B4EBF49FE9C7DB7F503087 + a sign of our times + ------3C93156FC7B4EBF49FE9C7DB7F503087 + Content-Type: application/x-pkcs7-signature; name="smime.p7s" + Content-Transfer-Encoding: base64 + Content-Disposition: attachment; filename="smime.p7s" + + MIIE8AYJKoZIhvcNAQcCoIIE4TCCBN0CAQExCzAJBgUrDgMCGgUAMCIGCSqGSIb3 + DQEHAaAVBBNhIHNpZ24gb2Ygb3VyIHRpbWVzoIIC5zCCAuMwggJMoAMCAQICAQAw + DQYJKoZIhvcNAQEEBQAwWzELMAkGA1UEBhMCU0cxETAPBgNVBAoTCE0yQ3J5cHRv + MRYwFAYDVQQDEw1TL01JTUUgU2VuZGVyMSEwHwYJKoZIhvcNAQkBFhJzZW5kZXJA + ZXhhbXBsZS5kb20wHhcNMDEwMzMxMTE0MDMzWhcNMDIwMzMxMTE0MDMzWjBbMQsw + CQYDVQQGEwJTRzERMA8GA1UEChMITTJDcnlwdG8xFjAUBgNVBAMTDVMvTUlNRSBT + ZW5kZXIxITAfBgkqhkiG9w0BCQEWEnNlbmRlckBleGFtcGxlLmRvbTCBnzANBgkq + hkiG9w0BAQEFAAOBjQAwgYkCgYEA5c5Tj1CHTSOxa1q2q0FYiwMWYHptJpJcvtZm + UwrgU5sHrA8OnCM0cDXEj0KPf3cfNjHffB8HWMzI4UEgNmFXQNsxoGZ+iqwxLlNj + y9Mh7eFW/Bjq5hNXbouSlQ0rWBRkoxV64y+t6lQehb32WfYXQbKFxFJSXzSxOx3R + 8YhSPd0CAwEAAaOBtjCBszAdBgNVHQ4EFgQUXOyolL1t4jaBwZFRM7MS8nBLzUow + gYMGA1UdIwR8MHqAFFzsqJS9beI2gcGRUTOzEvJwS81KoV+kXTBbMQswCQYDVQQG + EwJTRzERMA8GA1UEChMITTJDcnlwdG8xFjAUBgNVBAMTDVMvTUlNRSBTZW5kZXIx + ITAfBgkqhkiG9w0BCQEWEnNlbmRlckBleGFtcGxlLmRvbYIBADAMBgNVHRMEBTAD + AQH/MA0GCSqGSIb3DQEBBAUAA4GBAHo3DrCHR86fSTVAvfiXdSswWqKtCEhUHRdC + TLFGl4hDk2GyZxaFuqZwiURz/H7nMicymI2wkz8H/wyHFg8G3BIehURpj2v/ZWXY + eovbgS7EZALVVkDj4hNl/IIHWd6Gtv1UODf7URbxtl3hQ9/eTWITrefT1heuPnar + 8czydsOLMYIBujCCAbYCAQEwYDBbMQswCQYDVQQGEwJTRzERMA8GA1UEChMITTJD + cnlwdG8xFjAUBgNVBAMTDVMvTUlNRSBTZW5kZXIxITAfBgkqhkiG9w0BCQEWEnNl + bmRlckBleGFtcGxlLmRvbQIBADAJBgUrDgMCGgUAoIGxMBgGCSqGSIb3DQEJAzEL + BgkqhkiG9w0BBwEwHAYJKoZIhvcNAQkFMQ8XDTAxMDMzMTExNDUwMlowIwYJKoZI + hvcNAQkEMRYEFOoeRUd8ExIYXfQq8BTFuKWrSP3iMFIGCSqGSIb3DQEJDzFFMEMw + CgYIKoZIhvcNAwcwDgYIKoZIhvcNAwICAgCAMA0GCCqGSIb3DQMCAgFAMAcGBSsO + AwIHMA0GCCqGSIb3DQMCAgEoMA0GCSqGSIb3DQEBAQUABIGAQpU8hFUtLCF6hO2t + ec9EYJ/Imqqiiw+BxWxkUUVT81Vbjwdn9JST6+sztM5JRP2ZW+b4txEjZriYC8f3 + kv95YMTGbIsuWkJ93GrbvqoJ/CxO23r9WWRnZEm/1EZN9ZmlrYqzBTxnNRmP3Dhj + cW8kzZwH+2/2zz2G7x1HxRWH95A= + + ------3C93156FC7B4EBF49FE9C7DB7F503087-- + </screen> + </sect1> + + <sect1 id="verify"> + <title>Verify</title> + <para>Assume the above output has been saved into <filename>sign.p7</filename>. + Let's now verify the signature: + </para> + + <programlisting> + from M2Crypto import SMIME, X509 + + # Instantiate an SMIME object. + s = SMIME.SMIME() + + # Load the signer's cert. + x509 = X509.load_cert('signer.pem') + sk = X509.X509_Stack() + sk.push(x509) + s.set_x509_stack(sk) + + # Load the signer's CA cert. In this case, because the signer's + # cert is self-signed, it is the signer's cert itself. + st = X509.X509_Store() + st.load_info('signer.pem') + s.set_x509_store(st) + + # Load the data, verify it. + p7, data = SMIME.smime_load_pkcs7('sign.p7') + v = s.verify(p7) + print v + print data + print data.read() + </programlisting> + + <para>Here's the output of the above program: + </para> + + <screen> + a sign of our times + <M2Crypto.BIO.BIO instance at 0x822012c> + a sign of our times + </screen> + + <para>Suppose, instead of loading <filename>signer.pem</filename> above, + we load <filename>recipient.pem</filename>. That is, we do a global + substitution of <literal>recipient.pem</literal> for + <literal>signer.pem</literal> in the above program. Here's the modified + program's output: + </para> + + <screen> + Traceback (most recent call last): + File "./verify.py", line 22, in ? + v = s.verify(p7) + File "/usr/local/home/ngps/prog/m2/M2Crypto/SMIME.py", line 205, in verify + raise SMIME_Error, Err.get_error() + M2Crypto.SMIME.SMIME_Error: 312:error:21075075:PKCS7 routines:PKCS7_verify:certificate verify error:pk7_smime.c:213:Verify error:self signed certificate + </screen> + + <para>As displayed, the error is generated by line 213 of OpenSSL's + <filename>pk7_smime.c</filename> (as of OpenSSL 0.9.6); if you are a + C programmer, you may wish to look up the C source to explore OpenSSL's + S/MIME implementation and understand why the error message is worded thus. + </para> + </sect1> + + <sect1 id="encrypt"> + <title>Encrypt</title> + <para>We now demonstrate how to generate an S/MIME-encrypted message: + </para> + + <programlisting> + from M2Crypto import BIO, Rand, SMIME, X509 + + def makebuf(text): + return BIO.MemoryBuffer(text) + + # Make a MemoryBuffer of the message. + buf = makebuf('a sign of our times') + + # Seed the PRNG. + Rand.load_file('randpool.dat', -1) + + # Instantiate an SMIME object. + s = SMIME.SMIME() + + # Load target cert to encrypt to. + x509 = X509.load_cert('recipient.pem') + sk = X509.X509_Stack() + sk.push(x509) + s.set_x509_stack(sk) + + # Set cipher: 3-key triple-DES in CBC mode. + s.set_cipher(SMIME.Cipher('des_ede3_cbc')) + + # Encrypt the buffer. + p7 = s.encrypt(buf) + + # Output p7 in mail-friendly format. + out = BIO.MemoryBuffer() + out.write('From: sender@example.dom\n') + out.write('To: recipient@example.dom\n') + out.write('Subject: M2Crypto S/MIME testing\n') + s.write(out, p7) + + print out.read() + + # Save the PRNG's state. + Rand.save_file('randpool.dat') + </programlisting> + + <para>Here's the output of the above program: + </para> + + <screen> + From: sender@example.dom + To: recipient@example.dom + Subject: M2Crypto S/MIME testing + MIME-Version: 1.0 + Content-Disposition: attachment; filename="smime.p7m" + Content-Type: application/x-pkcs7-mime; name="smime.p7m" + Content-Transfer-Encoding: base64 + + MIIBVwYJKoZIhvcNAQcDoIIBSDCCAUQCAQAxggEAMIH9AgEAMGYwYTELMAkGA1UE + BhMCU0cxETAPBgNVBAoTCE0yQ3J5cHRvMRkwFwYDVQQDExBTL01JTUUgUmVjaXBp + ZW50MSQwIgYJKoZIhvcNAQkBFhVyZWNpcGllbnRAZXhhbXBsZS5kb20CAQAwDQYJ + KoZIhvcNAQEBBQAEgYCBaXZ+qjpBEZwdP7gjfzfAtQitESyMwo3i+LBOw6sSDir6 + FlNDPCnkrTvqDX3Rt6X6vBtTCYOm+qiN7ujPkOU61cN7h8dvHR8YW9+0IPY80/W0 + lZ/HihSRgwTNd7LnxUUcPx8YV1id0dlmP0Hz+Lg+mHf6rqaR//JcYhX9vW4XvjA7 + BgkqhkiG9w0BBwEwFAYIKoZIhvcNAwcECMN+qya6ADywgBgHr9Jkhwn5Gsdu7BwX + nIQfYTYcdL9I5Sk= + </screen> + </sect1> + + <sect1 id="decrypt"> + <title>Decrypt</title> + <para>Assume the above output has been saved into <filename>encrypt.p7</filename>. + Decrypt the message thusly: + </para> + + <programlisting> + from M2Crypto import BIO, SMIME, X509 + + # Instantiate an SMIME object. + s = SMIME.SMIME() + + # Load private key and cert. + s.load_key('recipient_key.pem', 'recipient.pem') + + # Load the encrypted data. + p7, data = SMIME.smime_load_pkcs7('encrypt.p7') + + # Decrypt p7. + out = s.decrypt(p7) + + print out + </programlisting> + + <para>Here's the output: + </para> + + <screen> + a sign of our times + </screen> + </sect1> + + <sect1 id="sign-and-encrypt"> + <title>Sign and Encrypt</title> + <para>Here's how to generate an S/MIME-signed/encrypted message: + </para> + + <programlisting> + from M2Crypto import BIO, Rand, SMIME, X509 + + def makebuf(text): + return BIO.MemoryBuffer(text) + + # Make a MemoryBuffer of the message. + buf = makebuf('a sign of our times') + + # Seed the PRNG. + Rand.load_file('randpool.dat', -1) + + # Instantiate an SMIME object. + s = SMIME.SMIME() + + # Load signer's key and cert. Sign the buffer. + s.load_key('signer_key.pem', 'signer.pem') + p7 = s.sign(buf) + + # Load target cert to encrypt the signed message to. + x509 = X509.load_cert('recipient.pem') + sk = X509.X509_Stack() + sk.push(x509) + s.set_x509_stack(sk) + + # Set cipher: 3-key triple-DES in CBC mode. + s.set_cipher(SMIME.Cipher('des_ede3_cbc')) + + # Create a temporary buffer. + tmp = BIO.MemoryBuffer() + + # Write the signed message into the temporary buffer. + s.write(tmp, p7) + + # Encrypt the temporary buffer. + p7 = s.encrypt(tmp) + + # Output p7 in mail-friendly format. + out = BIO.MemoryBuffer() + out.write('From: sender@example.dom\n') + out.write('To: recipient@example.dom\n') + out.write('Subject: M2Crypto S/MIME testing\n') + s.write(out, p7) + + print out.read() + + # Save the PRNG's state. + Rand.save_file('randpool.dat') + </programlisting> + + <para>Here's the output of the above program: + </para> + + <screen> + From: sender@example.dom + To: recipient@example.dom + Subject: M2Crypto S/MIME testing + MIME-Version: 1.0 + Content-Disposition: attachment; filename="smime.p7m" + Content-Type: application/x-pkcs7-mime; name="smime.p7m" + Content-Transfer-Encoding: base64 + + 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 + </screen> + </sect1> + + <sect1 id="decrypt-and-verify"> + <title>Decrypt and Verify</title> + <para>Suppose the above output has been saved into + <filename>se.p7</filename>. The following demonstrates how to decrypt and + verify it: + </para> + + <programlisting> + from M2Crypto import BIO, SMIME, X509 + + # Instantiate an SMIME object. + s = SMIME.SMIME() + + # Load private key and cert. + s.load_key('recipient_key.pem', 'recipient.pem') + + # Load the signed/encrypted data. + p7, data = SMIME.smime_load_pkcs7('se.p7') + + # After the above step, 'data' == None. + # Decrypt p7. 'out' now contains a PKCS #7 signed blob. + out = s.decrypt(p7) + + # Load the signer's cert. + x509 = X509.load_cert('signer.pem') + sk = X509.X509_Stack() + sk.push(x509) + s.set_x509_stack(sk) + + # Load the signer's CA cert. In this case, because the signer's + # cert is self-signed, it is the signer's cert itself. + st = X509.X509_Store() + st.load_info('signer.pem') + s.set_x509_store(st) + + # Recall 'out' contains a PKCS #7 blob. + # Transform 'out'; verify the resulting PKCS #7 blob. + p7_bio = BIO.MemoryBuffer(out) + p7, data = SMIME.smime_load_pkcs7_bio(p7_bio) + v = s.verify(p7) + + print v + </programlisting> + + <para>The output is as follows: + </para> + + <screen> + a sign of our times + </screen> + </sect1> + + <sect1 id="smtp"> + <title>Sending S/MIME messages via SMTP</title> + <para>In the above examples, we've assumed that our S/MIME messages + are sent and received automagically. The following is a Python function that + generates S/MIME-signed/encrypted messages and sends them via SMTP: + </para> + + <programlisting> + from M2Crypto import BIO, SMIME, X509 + import smtplib, string, sys + + def sendsmime(from_addr, to_addrs, subject, msg, from_key, from_cert=None, to_certs=None, smtpd='localhost'): + + msg_bio = BIO.MemoryBuffer(msg) + sign = from_key + encrypt = to_certs + + s = SMIME.SMIME() + if sign: + s.load_key(from_key, from_cert) + p7 = s.sign(msg_bio, flags=SMIME.PKCS7_TEXT) + msg_bio = BIO.MemoryBuffer(msg) # Recreate coz sign() has consumed it. + + if encrypt: + sk = X509.X509_Stack() + for x in to_certs: + sk.push(X509.load_cert(x)) + s.set_x509_stack(sk) + s.set_cipher(SMIME.Cipher('des_ede3_cbc')) + tmp_bio = BIO.MemoryBuffer() + if sign: + s.write(tmp_bio, p7) + else: + tmp_bio.write(msg) + p7 = s.encrypt(tmp_bio) + + out = BIO.MemoryBuffer() + out.write('From: %s\r\n' % from_addr) + out.write('To: %s\r\n' % string.join(to_addrs, ", ")) + out.write('Subject: %s\r\n' % subject) + if encrypt: + s.write(out, p7) + else: + if sign: + s.write(out, p7, msg_bio, SMIME.PKCS7_TEXT) + else: + out.write('\r\n') + out.write(msg) + out.close() + + smtp = smtplib.SMTP() + smtp.connect(smtpd) + smtp.sendmail(from_addr, to_addrs, out.read()) + smtp.quit() + </programlisting> + + <para>This function sends plain, S/MIME-signed, S/MIME-encrypted, + and S/MIME-signed/encrypted messages, depending on the parameters + <parameter>from_key</parameter> and <parameter>to_certs</parameter>. The + function's output interoperates with Netscape Messenger. + </para> + </sect1> + + <sect1 id="verifying-origin"> + <title>Verifying origin of S/MIME messages</title> + <para>In our examples above that decrypt or verify messages, we skipped + a step: verifying that the <literal>from</literal> address of the message + matches the <literal>email address</literal> attribute in the sender's + certificate. + </para> + + <para>The premise of current X.509 certification practice is that the + CA is supposed to verify your identity, and to issue a certificate with + <literal>email address</literal> that matches your actual mail address. + (Verisign's March 2001 failure in identity verification resulting in + Microsoft certificates being issued to spoofers notwithstanding.) + </para> + + <para>If you run your own CA, your certification practice is up to you, of + course, and it would probably be part of your security policy. + </para> + + <para>Whether your S/MIME messaging application needs to verify the + <literal>from</literal> addresses of S/MIME messages depends on your + security policy and your system's threat model, as always. + </para> + </sect1> + + <sect1 id="netscape-messenger"> + <title>Interoperating with Netscape Messenger</title> + <para>Suppose S/MIME Recipient uses Netscape Messenger. To enable Messenger + to handle S/MIME messages from S/MIME Sender, S/MIME Recipient needs + to configure Messenger with his private key and certificate, as well as S/MIME + Sender's certificate. + </para> + + <note> + <para>Configuring Messenger's POP or IMAP settings so that it retrieves + mail correctly is beyond the scope of this HOWTO. + </para> + </note> + + <para>The following steps demonstrate how to import S/MIME Recipient's + private key and certificate for Messenger: + </para> + + <procedure> + <step> + <para>Transform S/MIME Recipient's private key and certificate into + <emphasis>PKCS #12</emphasis> format. + </para> + + <screen> + <userinput> +openssl pkcs12 -export -in recipient.pem -inkey recipient_key.pem -name "S/MIME Recipient" -out recipient.p12 + </userinput> + Enter Export Password:<userinput><replaceable><enter></replaceable></userinput> + Verifying password - Enter Export Password:<userinput><replaceable><enter></replaceable></userinput> + </screen> + </step> + + <step> + <para>Start Messenger. + </para> + </step> + + <step> + <para>Click on the (open) "lock" icon at the bottom left corner of + Messenger's window. This brings up the "Security Info" dialog box. + </para> + </step> + + <step> + <para>Click on "Yours" under "Certificates". + </para> + </step> + + <step> + <para>Select "Import a certificate", then pick + <filename>recipient.p12</filename> from the ensuing file selection dialog + box. + </para> + </step> + </procedure> + + <para>Next, you need to import <filename>signer.pem</filename> as a CA + certificate, so that Messenger will mark messages signed by S/MIME Sender as + "trusted": + </para> + + <procedure> + <step> + <para>Create a DER encoding of <filename>signer.pem</filename>. + </para> + + <screen> + <userinput> +openssl x509 -inform pem -outform der -in signer.pem -out signer.der + </userinput> + </screen> + </step> + + <step> + + <para>Install <filename>signer.der</filename> into Messenger as MIME type + <literal>application/x-x509-ca-cert</literal>. You do this by downloading + <filename>signer.der</filename> via Navigator from a HTTP or HTTPS server, + with the correct MIME type mapping. (You may use + <filename>demo/ssl/https_srv.py</filename>, bundled with M2Crypto, for + this purpose.) Follow the series of dialog boxes to accept + <filename>signer.der</filename> as a CA for certifying email users. + </para> + </step> + </procedure> + + <para>S/MIME Recipient is now able to decrypt and read S/MIME Sender's + messages with Messenger. Messenger will indicate that S/MIME Sender's + messages are signed, encrypted, or encrypted <emphasis>and</emphasis> + signed, as the case may be, via the "stamp" icon on the message window's + top right corner. + </para> + + <para>Clicking on the "stamp" icon brings you to the Security Info dialog + box. Messenger informs you that the message is, say, encrypted with + 168-bit DES-EDE3-CBC and that it is digitally signed by the private key + corresponding to the public key contained in the certificate + <filename>signer.pem</filename>. + </para> + </sect1> + + <sect1 id="microsoft-outlook"> + <title>Interoperating with Microsoft Outlook</title> + <para>I do not know how to do this, as I do not use Outlook. (Nor do I use + Netscape Messenger, actually. I use Mutt, top dog of MUAs. ;-) Information on + how to configure Outlook with keys and certificates so that it handles + S/MIME mail is gratefully accepted. + </para> + </sect1> + + <sect1 id="zsmime"> + <title>ZSmime</title> + <para>ZSmime is a <ulink url="http://www.zope.org">Zope</ulink> + <emphasis>product</emphasis> that enables Zope to generate + S/MIME-signed/encrypted messages. ZSmime demonstrates how to invoke + M2Crypto in a web application server extension. + </para> + + <para>ZSmime has its own <ulink + url="http://www.post1.com/home/ngps/zope/zsmime/howto.html">HOWTO</ulink> + explaining its usage. (That HOWTO has some overlap in content with + this document.) + </para> + </sect1> + + <sect1 id="resources"> + <title>Resources</title> + <itemizedlist mark=opencircle> + <listitem> + <para>IETF S/MIME Working Group - + <ulink url="http://www.imc.org/ietf-smime"> + http://www.imc.org/ietf-smime</ulink> + </para> + </listitem> + + <listitem> + <para>S/MIME and OpenPGP - + <ulink url="http://www.imc.org/smime-pgpmime.html"> + http://www.imc.org/smime-pgpmime.html</ulink> + </para> + </listitem> + + <listitem> + <para>S/MIME Freeware Library - + <ulink url="http://www.getronicsgov.com/hot/sfl_home.htm"> + http://www.getronicsgov.com/hot/sfl_home.htm</ulink> + </para> + </listitem> + + <listitem> + <para>Mozilla Network Security Services - + <ulink url="http://www.mozilla.org/projects/security/pkg/nss"> + http://www.mozilla.org/projects/security/pkg/nss</ulink> + </para> + </listitem> + + <listitem> + <para>S/MIME Cracking Screen Saver - + <ulink url="http://www.counterpane.com/smime.html"> + http://www.counterpane.com/smime.html</ulink> + </para> + </listitem> + </itemizedlist> + </sect1> + + <sect1 id="id-kludge"> + <title></title> + <para> + <literal>$Id: howto.smime.docbook,v 1.1 2003/06/22 16:41:18 ngps Exp $</literal> + </para> + </sect1> +</article> + diff --git a/doc/howto.smime.html b/doc/howto.smime.html new file mode 100644 index 0000000..2a76548 --- /dev/null +++ b/doc/howto.smime.html @@ -0,0 +1,1570 @@ +<HTML +><HEAD +><TITLE +>HOWTO: Programming S/MIME in Python with M2Crypto</TITLE +><META +NAME="GENERATOR" +CONTENT="Modular DocBook HTML Stylesheet Version 1.64 +"></HEAD +><BODY +CLASS="ARTICLE" +BGCOLOR="#FFFFFF" +TEXT="#000000" +LINK="#0000FF" +VLINK="#840084" +ALINK="#0000FF" +><DIV +CLASS="ARTICLE" +><DIV +CLASS="TITLEPAGE" +><H1 +CLASS="TITLE" +><A +NAME="AEN2" +>HOWTO: Programming S/MIME in Python with M2Crypto</A +></H1 +><H3 +CLASS="AUTHOR" +><A +NAME="AEN4" +>Pheng Siong Ng</A +></H3 +><DIV +CLASS="AFFILIATION" +><DIV +CLASS="ADDRESS" +><P +CLASS="ADDRESS" +>ngps@post1.com</P +></DIV +></DIV +><P +CLASS="COPYRIGHT" +>Copyright © 2000, 2001 by Ng Pheng Siong.</P +><DIV +CLASS="REVHISTORY" +><TABLE +WIDTH="100%" +BORDER="0" +><TR +><TH +ALIGN="LEFT" +VALIGN="TOP" +COLSPAN="3" +><B +>Revision History</B +></TH +></TR +><TR +><TD +ALIGN="LEFT" +>Revision $Revision: 1.1 $</TD +><TD +ALIGN="LEFT" +>$Date: 2003/06/22 16:41:18 $</TD +><TD +ALIGN="LEFT" +></TD +></TR +><TR +><TD +ALIGN="LEFT" +COLSPAN="3" +></TD +></TR +></TABLE +></DIV +><HR></DIV +><DIV +CLASS="SECT1" +><HR><H1 +CLASS="SECT1" +><A +NAME="INTRODUCTION" +>Introduction</A +></H1 +><P +><A +HREF="http://www.post1.com/home/ngps/m2" +TARGET="_top" +>M2Crypto</A +> + is a <A +HREF="http://www.python.org" +TARGET="_top" +>Python</A +> + interface to <A +HREF="http://www.openssl.org" +TARGET="_top" +>OpenSSL</A +>. It makes + available to the Python programmer SSL functionality to implement clients + and servers, S/MIME v2, RSA, DSA, DH, symmetric ciphers, message digests and + HMACs. + </P +><P +>This document demonstrates programming S/MIME with M2Crypto. + </P +></DIV +><DIV +CLASS="SECT1" +><HR><H1 +CLASS="SECT1" +><A +NAME="SMIME" +>S/MIME</A +></H1 +><P +>S/MIME - Secure Multipurpose Internet Mail Extensions + [<SPAN +CLASS="CITATION" +>RFC 2311, RFC 2312</SPAN +>] - provides a + consistent way to send and receive secure MIME data. Based on the popular + Internet MIME standard, S/MIME provides the following cryptographic security + services for electronic messaging applications - + <I +CLASS="EMPHASIS" +>authentication</I +>, <I +CLASS="EMPHASIS" +>message integrity </I +> + and <I +CLASS="EMPHASIS" +>non-repudiation of origin </I +> (using <I +CLASS="EMPHASIS" +>digital + signatures</I +>), and <I +CLASS="EMPHASIS" +>privacy </I +> and <I +CLASS="EMPHASIS" +>data + security</I +> (using <I +CLASS="EMPHASIS" +>encryption</I +>). + </P +></DIV +><DIV +CLASS="SECT1" +><HR><H1 +CLASS="SECT1" +><A +NAME="KEYS-AND-CERTIFICATES" +>Keys and Certificates</A +></H1 +><P +>To create an S/MIME-signed message, you need an RSA key pair + (this consists of a public key and a private key) and an X.509 + certificate of said public key. + </P +><P +>To create an S/MIME-encrypted message, you need an X.509 + certificate for each recipient. + </P +><P +>To create an S/MIME-signed <I +CLASS="EMPHASIS" +>and</I +> -encrypted + message, first create a signed message, then encrypt the signed + message with the recipients' certificates. + </P +><P +>You may generate key pairs and obtain certificates by using a + commercial <I +CLASS="EMPHASIS" +>certification authority</I +> service. + </P +><P +>You can also do so using freely-available software. For many + purposes, e.g., automated S/MIME messaging by system administration + processes, this approach is cheap and effective. + </P +><P +>We now work through using OpenSSL to generate key pairs and + certificates. This assumes you have OpenSSL installed properly on your + system. + </P +><P +>First, we generate an X.509 certificate to be used for signing: + </P +><PRE +CLASS="SCREEN" +> <TT +CLASS="USERINPUT" +><B +>openssl req -newkey rsa:1024 -nodes -x509 -days 365 -out signer.pem + </B +></TT +> + Using configuration from /usr/local/pkg/openssl/openssl.cnf + Generating a 1024 bit RSA private key + ..++++++ + ....................++++++ + writing new private key to 'privkey.pem' + ----- + You are about to be asked to enter information that will be incorporated + into your certificate request. + What you are about to enter is what is called a Distinguished Name or a DN. + There are quite a few fields but you can leave some blank + For some fields there will be a default value, + If you enter '.', the field will be left blank. + ----- + Country Name (2 letter code) [AU]:<TT +CLASS="USERINPUT" +><B +><TT +CLASS="REPLACEABLE" +><I +>SG</I +></TT +></B +></TT +> + State or Province Name (full name) [Some-State]:<TT +CLASS="USERINPUT" +><B +><TT +CLASS="REPLACEABLE" +><I +>.</I +></TT +></B +></TT +> + Locality Name (eg, city) []:<TT +CLASS="USERINPUT" +><B +><TT +CLASS="REPLACEABLE" +><I +>.</I +></TT +></B +></TT +> + Organization Name (eg, company) [Internet Widgits Pty Ltd]:<TT +CLASS="USERINPUT" +><B +><TT +CLASS="REPLACEABLE" +><I +>M2Crypto</I +></TT +></B +></TT +> + Organizational Unit Name (eg, section) []:<TT +CLASS="USERINPUT" +><B +><TT +CLASS="REPLACEABLE" +><I +>.</I +></TT +></B +></TT +> + Common Name (eg, YOUR name) []:<TT +CLASS="USERINPUT" +><B +><TT +CLASS="REPLACEABLE" +><I +>S/MIME Sender</I +></TT +></B +></TT +> + Email Address []:<TT +CLASS="USERINPUT" +><B +><TT +CLASS="REPLACEABLE" +><I +>sender@example.dom</I +></TT +></B +></TT +> + </PRE +><P +>This generates a 1024-bit RSA key pair, unencrypted, into + <TT +CLASS="FILENAME" +>privkey.pem</TT +>; it also generates a self-signed X.509 + certificate for the public key into <TT +CLASS="FILENAME" +>signer.pem</TT +>. The + certificate is valid for 365 days, i.e., a year. + </P +><P +>Let's rename <TT +CLASS="FILENAME" +>privkey.pem</TT +> so that we know it is + a companion of <TT +CLASS="FILENAME" +>signer.pem</TT +>'s: + </P +><PRE +CLASS="SCREEN" +> <TT +CLASS="USERINPUT" +><B +>mv privkey.pem signer_key.pem</B +></TT +> + </PRE +><P +>To verify the content of <TT +CLASS="FILENAME" +>signer.pem</TT +>, execute the + following: + </P +><PRE +CLASS="SCREEN" +> <TT +CLASS="USERINPUT" +><B +>openssl x509 -noout -text -in signer.pem + </B +></TT +> + Certificate: + Data: + Version: 3 (0x2) + Serial Number: 0 (0x0) + Signature Algorithm: md5WithRSAEncryption + Issuer: C=SG, O=M2Crypto, CN=S/MIME Sender/Email=sender@example.dom + Validity + Not Before: Mar 24 12:56:16 2001 GMT + Not After : Mar 24 12:56:16 2002 GMT + Subject: C=SG, O=M2Crypto, CN=S/MIME Sender/Email=sender@example.dom + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:a9:d6:e2:b5:11:3b:ae:3c:e2:17:31:70:e1:6e: + 01:f4:19:6d:bd:2a:42:36:2b:37:34:e2:83:1d:0d: + 11:2e:b4:99:44:db:10:67:be:97:5f:5b:1a:26:33: + 46:23:2f:95:04:7a:35:da:9d:f9:26:88:39:9e:17: + cd:3e:eb:a8:19:8d:a8:2a:f1:43:da:55:a9:2e:2c: + 65:ed:04:71:42:ce:73:53:b8:ea:7e:c7:f0:23:c6: + 63:c5:5e:68:96:64:a7:b4:2a:94:26:76:eb:79:ea: + e3:4e:aa:82:09:4f:44:87:4a:12:62:b5:d7:1f:ca: + f2:ce:d5:ba:7e:1f:48:fd:b9 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 29:FB:38:B6:BF:E2:40:BB:FF:D5:71:D7:D5:C4:F0:83:1A:2B:C7:99 + X509v3 Authority Key Identifier: + keyid:29:FB:38:B6:BF:E2:40:BB:FF:D5:71:D7:D5:C4:F0:83:1A:2B:C7:99 + DirName:/C=SG/O=M2Crypto/CN=S/MIME Sender/Email=sender@example.dom + serial:00 + + X509v3 Basic Constraints: + CA:TRUE + Signature Algorithm: md5WithRSAEncryption + 68:c8:6b:1b:fa:7c:9a:39:35:76:18:15:c9:fd:89:97:62:db: + 7a:b0:2d:13:dd:97:e8:1b:7a:9f:22:27:83:24:9d:2e:56:ec: + 97:89:3c:ef:16:55:80:5a:18:7c:22:d0:f6:bb:e3:a4:e8:59: + 30:ff:99:5a:93:3e:ea:bc:ee:7f:8d:d6:7d:37:8c:ac:3d:74: + 80:ce:7a:99:ba:27:b9:2a:a3:71:fa:a5:25:ba:47:17:df:07: + 56:96:36:fd:60:b9:6c:96:06:e8:e3:7b:9f:4b:6a:95:71:a8: + 34:fc:fc:b5:88:8b:c4:3f:1e:24:f6:52:47:b2:7d:44:67:d9: + 83:e8 + </PRE +><P +>Next, we generate a self-signed X.509 certificate for the + recipient. Note that <TT +CLASS="FILENAME" +>privkey.pem</TT +> will be + recreated. + </P +><PRE +CLASS="SCREEN" +> <TT +CLASS="USERINPUT" +><B +>openssl req -newkey rsa:1024 -nodes -x509 -days 365 -out recipient.pem + </B +></TT +> + Using configuration from /usr/local/pkg/openssl/openssl.cnf + Generating a 1024 bit RSA private key + .....................................++++++ + .................++++++ + writing new private key to 'privkey.pem' + ----- + You are about to be asked to enter information that will be incorporated + into your certificate request. + What you are about to enter is what is called a Distinguished Name or a DN. + There are quite a few fields but you can leave some blank + For some fields there will be a default value, + If you enter '.', the field will be left blank. + ----- + Country Name (2 letter code) [AU]:<TT +CLASS="USERINPUT" +><B +><TT +CLASS="REPLACEABLE" +><I +>SG</I +></TT +></B +></TT +> + State or Province Name (full name) [Some-State]:<TT +CLASS="USERINPUT" +><B +><TT +CLASS="REPLACEABLE" +><I +>.</I +></TT +></B +></TT +> + Locality Name (eg, city) []:<TT +CLASS="USERINPUT" +><B +><TT +CLASS="REPLACEABLE" +><I +>.</I +></TT +></B +></TT +> + Organization Name (eg, company) [Internet Widgits Pty Ltd]:<TT +CLASS="USERINPUT" +><B +><TT +CLASS="REPLACEABLE" +><I +>M2Crypto</I +></TT +></B +></TT +> + Organizational Unit Name (eg, section) []:<TT +CLASS="USERINPUT" +><B +><TT +CLASS="REPLACEABLE" +><I +>.</I +></TT +></B +></TT +> + Common Name (eg, YOUR name) []:<TT +CLASS="USERINPUT" +><B +><TT +CLASS="REPLACEABLE" +><I +>S/MIME Recipient</I +></TT +></B +></TT +> + Email Address []:<TT +CLASS="USERINPUT" +><B +><TT +CLASS="REPLACEABLE" +><I +>recipient@example.dom</I +></TT +></B +></TT +> + </PRE +><P +>Again, rename <TT +CLASS="FILENAME" +>privkey.pem</TT +>: + </P +><PRE +CLASS="SCREEN" +> <TT +CLASS="USERINPUT" +><B +>mv privkey.pem recipient_key.pem</B +></TT +> + </PRE +><P +>In the examples to follow, S/MIME Sender, + <TT +CLASS="EMAIL" +><<A +HREF="mailto:sender@example.dom" +>sender@example.dom</A +>></TT +>, shall be the sender of S/MIME messages, + while S/MIME Recipient, <TT +CLASS="EMAIL" +><<A +HREF="mailto:recipient@example.dom" +>recipient@example.dom</A +>></TT +>, shall be the + recipient of S/MIME messages. + </P +><P +>Armed with the key pairs and certificates, we are now ready to begin + programming S/MIME in Python. + </P +><DIV +CLASS="NOTE" +><BLOCKQUOTE +CLASS="NOTE" +><P +><B +>Note: </B +>The private keys generated above are + <I +CLASS="EMPHASIS" +>not passphrase-protected</I +>, i.e., they are + <I +CLASS="EMPHASIS" +>in the clear</I +>. Anyone who has access to such a key can + generate S/MIME-signed messages with it, and decrypt S/MIME messages + encrypted to it's corresponding public key. + </P +><P +>We may passphrase-protect the keys, if we so choose. M2Crypto will + prompt the user for the passphrase when such a key is being loaded. + </P +></BLOCKQUOTE +></DIV +></DIV +><DIV +CLASS="SECT1" +><HR><H1 +CLASS="SECT1" +><A +NAME="M2CRYPTO-SMIME" +>M2Crypto.SMIME</A +></H1 +><P +>The Python programmer accesses M2Crypto's S/MIME functionality + through class <TT +CLASS="CLASSNAME" +>SMIME</TT +> in the module + <TT +CLASS="CLASSNAME" +>M2Crypto.SMIME</TT +>. Typically, an <TT +CLASS="CLASSNAME" +>SMIME</TT +> + object is instantiated; the object is then set up for the intended + operation: sign, encrypt, decrypt or verify; finally, the operation is invoked on + the object. + </P +><P +><TT +CLASS="CLASSNAME" +>M2Crypto.SMIME</TT +> makes extensive use of + <TT +CLASS="CLASSNAME" +>M2Crypto.BIO</TT +>: <TT +CLASS="CLASSNAME" +>M2Crypto.BIO</TT +> + is a Python abstraction of the <TT +CLASS="CLASSNAME" +>BIO</TT +> abstraction in + OpenSSL. A commonly used <TT +CLASS="CLASSNAME" +>BIO</TT +> abstraction in M2Crypto is + <TT +CLASS="CLASSNAME" +>M2Crypto.BIO.MemoryBuffer</TT +>, which implements a + memory-based file-like object, similar to Python's own + <TT +CLASS="CLASSNAME" +>StringIO</TT +>. + </P +></DIV +><DIV +CLASS="SECT1" +><HR><H1 +CLASS="SECT1" +><A +NAME="SIGN" +>Sign</A +></H1 +><P +>The following code demonstrates how to generate an S/MIME-signed + message. <TT +CLASS="FILENAME" +>randpool.dat</TT +> contains random data which is + used to seed OpenSSL's pseudo-random number generator via M2Crypto. + </P +><PRE +CLASS="PROGRAMLISTING" +> from M2Crypto import BIO, Rand, SMIME + + def makebuf(text): + return BIO.MemoryBuffer(text) + + # Make a MemoryBuffer of the message. + buf = makebuf('a sign of our times') + + # Seed the PRNG. + Rand.load_file('randpool.dat', -1) + + # Instantiate an SMIME object; set it up; sign the buffer. + s = SMIME.SMIME() + s.load_key('signer_key.pem', 'signer.pem') + p7 = s.sign(buf) + </PRE +><P +><TT +CLASS="VARNAME" +>p7</TT +> now contains a <I +CLASS="EMPHASIS" +>PKCS #7 signature + blob</I +> wrapped in an <TT +CLASS="CLASSNAME" +>M2Crypto.SMIME.PKCS7</TT +> + object. Note that <TT +CLASS="VARNAME" +>buf</TT +> has been consumed by + <TT +CLASS="FUNCTION" +>sign()</TT +> and has to be recreated if it is to be used + again. + </P +><P +>We may now send the signed message via SMTP. In these examples, we + shall not do so; instead, we'll render the S/MIME output in + mail-friendly format, and pretend that our messages are sent and + received correctly. + </P +><PRE +CLASS="PROGRAMLISTING" +> # Recreate buf. + buf = makebuf('a sign of our times') + + # Output p7 in mail-friendly format. + out = BIO.MemoryBuffer() + out.write('From: sender@example.dom\n') + out.write('To: recipient@example.dom\n') + out.write('Subject: M2Crypto S/MIME testing\n') + s.write(out, p7, buf) + + print out.read() + + # Save the PRNG's state. + Rand.save_file('randpool.dat') + </PRE +><P +>Here's the output: + </P +><PRE +CLASS="SCREEN" +> From: sender@example.dom + To: recipient@example.dom + Subject: M2Crypto S/MIME testing + MIME-Version: 1.0 + Content-Type: multipart/signed ; protocol="application/x-pkcs7-signature" ; micalg=sha1 ; boundary="----3C93156FC7B4EBF49FE9C7DB7F503087" + + This is an S/MIME signed message + + ------3C93156FC7B4EBF49FE9C7DB7F503087 + a sign of our times + ------3C93156FC7B4EBF49FE9C7DB7F503087 + Content-Type: application/x-pkcs7-signature; name="smime.p7s" + Content-Transfer-Encoding: base64 + Content-Disposition: attachment; filename="smime.p7s" + + MIIE8AYJKoZIhvcNAQcCoIIE4TCCBN0CAQExCzAJBgUrDgMCGgUAMCIGCSqGSIb3 + DQEHAaAVBBNhIHNpZ24gb2Ygb3VyIHRpbWVzoIIC5zCCAuMwggJMoAMCAQICAQAw + DQYJKoZIhvcNAQEEBQAwWzELMAkGA1UEBhMCU0cxETAPBgNVBAoTCE0yQ3J5cHRv + MRYwFAYDVQQDEw1TL01JTUUgU2VuZGVyMSEwHwYJKoZIhvcNAQkBFhJzZW5kZXJA + ZXhhbXBsZS5kb20wHhcNMDEwMzMxMTE0MDMzWhcNMDIwMzMxMTE0MDMzWjBbMQsw + CQYDVQQGEwJTRzERMA8GA1UEChMITTJDcnlwdG8xFjAUBgNVBAMTDVMvTUlNRSBT + ZW5kZXIxITAfBgkqhkiG9w0BCQEWEnNlbmRlckBleGFtcGxlLmRvbTCBnzANBgkq + hkiG9w0BAQEFAAOBjQAwgYkCgYEA5c5Tj1CHTSOxa1q2q0FYiwMWYHptJpJcvtZm + UwrgU5sHrA8OnCM0cDXEj0KPf3cfNjHffB8HWMzI4UEgNmFXQNsxoGZ+iqwxLlNj + y9Mh7eFW/Bjq5hNXbouSlQ0rWBRkoxV64y+t6lQehb32WfYXQbKFxFJSXzSxOx3R + 8YhSPd0CAwEAAaOBtjCBszAdBgNVHQ4EFgQUXOyolL1t4jaBwZFRM7MS8nBLzUow + gYMGA1UdIwR8MHqAFFzsqJS9beI2gcGRUTOzEvJwS81KoV+kXTBbMQswCQYDVQQG + EwJTRzERMA8GA1UEChMITTJDcnlwdG8xFjAUBgNVBAMTDVMvTUlNRSBTZW5kZXIx + ITAfBgkqhkiG9w0BCQEWEnNlbmRlckBleGFtcGxlLmRvbYIBADAMBgNVHRMEBTAD + AQH/MA0GCSqGSIb3DQEBBAUAA4GBAHo3DrCHR86fSTVAvfiXdSswWqKtCEhUHRdC + TLFGl4hDk2GyZxaFuqZwiURz/H7nMicymI2wkz8H/wyHFg8G3BIehURpj2v/ZWXY + eovbgS7EZALVVkDj4hNl/IIHWd6Gtv1UODf7URbxtl3hQ9/eTWITrefT1heuPnar + 8czydsOLMYIBujCCAbYCAQEwYDBbMQswCQYDVQQGEwJTRzERMA8GA1UEChMITTJD + cnlwdG8xFjAUBgNVBAMTDVMvTUlNRSBTZW5kZXIxITAfBgkqhkiG9w0BCQEWEnNl + bmRlckBleGFtcGxlLmRvbQIBADAJBgUrDgMCGgUAoIGxMBgGCSqGSIb3DQEJAzEL + BgkqhkiG9w0BBwEwHAYJKoZIhvcNAQkFMQ8XDTAxMDMzMTExNDUwMlowIwYJKoZI + hvcNAQkEMRYEFOoeRUd8ExIYXfQq8BTFuKWrSP3iMFIGCSqGSIb3DQEJDzFFMEMw + CgYIKoZIhvcNAwcwDgYIKoZIhvcNAwICAgCAMA0GCCqGSIb3DQMCAgFAMAcGBSsO + AwIHMA0GCCqGSIb3DQMCAgEoMA0GCSqGSIb3DQEBAQUABIGAQpU8hFUtLCF6hO2t + ec9EYJ/Imqqiiw+BxWxkUUVT81Vbjwdn9JST6+sztM5JRP2ZW+b4txEjZriYC8f3 + kv95YMTGbIsuWkJ93GrbvqoJ/CxO23r9WWRnZEm/1EZN9ZmlrYqzBTxnNRmP3Dhj + cW8kzZwH+2/2zz2G7x1HxRWH95A= + + ------3C93156FC7B4EBF49FE9C7DB7F503087-- + </PRE +></DIV +><DIV +CLASS="SECT1" +><HR><H1 +CLASS="SECT1" +><A +NAME="VERIFY" +>Verify</A +></H1 +><P +>Assume the above output has been saved into <TT +CLASS="FILENAME" +>sign.p7</TT +>. + Let's now verify the signature: + </P +><PRE +CLASS="PROGRAMLISTING" +> from M2Crypto import SMIME, X509 + + # Instantiate an SMIME object. + s = SMIME.SMIME() + + # Load the signer's cert. + x509 = X509.load_cert('signer.pem') + sk = X509.X509_Stack() + sk.push(x509) + s.set_x509_stack(sk) + + # Load the signer's CA cert. In this case, because the signer's + # cert is self-signed, it is the signer's cert itself. + st = X509.X509_Store() + st.load_info('signer.pem') + s.set_x509_store(st) + + # Load the data, verify it. + p7, data = SMIME.smime_load_pkcs7('sign.p7') + v = s.verify(p7) + print v + print data + print data.read() + </PRE +><P +>Here's the output of the above program: + </P +><PRE +CLASS="SCREEN" +> a sign of our times + <M2Crypto.BIO.BIO instance at 0x822012c> + a sign of our times + </PRE +><P +>Suppose, instead of loading <TT +CLASS="FILENAME" +>signer.pem</TT +> above, + we load <TT +CLASS="FILENAME" +>recipient.pem</TT +>. That is, we do a global + substitution of <TT +CLASS="LITERAL" +>recipient.pem</TT +> for + <TT +CLASS="LITERAL" +>signer.pem</TT +> in the above program. Here's the modified + program's output: + </P +><PRE +CLASS="SCREEN" +> Traceback (most recent call last): + File "./verify.py", line 22, in ? + v = s.verify(p7) + File "/usr/local/home/ngps/prog/m2/M2Crypto/SMIME.py", line 205, in verify + raise SMIME_Error, Err.get_error() + M2Crypto.SMIME.SMIME_Error: 312:error:21075075:PKCS7 routines:PKCS7_verify:certificate verify error:pk7_smime.c:213:Verify error:self signed certificate + </PRE +><P +>As displayed, the error is generated by line 213 of OpenSSL's + <TT +CLASS="FILENAME" +>pk7_smime.c</TT +> (as of OpenSSL 0.9.6); if you are a + C programmer, you may wish to look up the C source to explore OpenSSL's + S/MIME implementation and understand why the error message is worded thus. + </P +></DIV +><DIV +CLASS="SECT1" +><HR><H1 +CLASS="SECT1" +><A +NAME="ENCRYPT" +>Encrypt</A +></H1 +><P +>We now demonstrate how to generate an S/MIME-encrypted message: + </P +><PRE +CLASS="PROGRAMLISTING" +> from M2Crypto import BIO, Rand, SMIME, X509 + + def makebuf(text): + return BIO.MemoryBuffer(text) + + # Make a MemoryBuffer of the message. + buf = makebuf('a sign of our times') + + # Seed the PRNG. + Rand.load_file('randpool.dat', -1) + + # Instantiate an SMIME object. + s = SMIME.SMIME() + + # Load target cert to encrypt to. + x509 = X509.load_cert('recipient.pem') + sk = X509.X509_Stack() + sk.push(x509) + s.set_x509_stack(sk) + + # Set cipher: 3-key triple-DES in CBC mode. + s.set_cipher(SMIME.Cipher('des_ede3_cbc')) + + # Encrypt the buffer. + p7 = s.encrypt(buf) + + # Output p7 in mail-friendly format. + out = BIO.MemoryBuffer() + out.write('From: sender@example.dom\n') + out.write('To: recipient@example.dom\n') + out.write('Subject: M2Crypto S/MIME testing\n') + s.write(out, p7) + + print out.read() + + # Save the PRNG's state. + Rand.save_file('randpool.dat') + </PRE +><P +>Here's the output of the above program: + </P +><PRE +CLASS="SCREEN" +> From: sender@example.dom + To: recipient@example.dom + Subject: M2Crypto S/MIME testing + MIME-Version: 1.0 + Content-Disposition: attachment; filename="smime.p7m" + Content-Type: application/x-pkcs7-mime; name="smime.p7m" + Content-Transfer-Encoding: base64 + + MIIBVwYJKoZIhvcNAQcDoIIBSDCCAUQCAQAxggEAMIH9AgEAMGYwYTELMAkGA1UE + BhMCU0cxETAPBgNVBAoTCE0yQ3J5cHRvMRkwFwYDVQQDExBTL01JTUUgUmVjaXBp + ZW50MSQwIgYJKoZIhvcNAQkBFhVyZWNpcGllbnRAZXhhbXBsZS5kb20CAQAwDQYJ + KoZIhvcNAQEBBQAEgYCBaXZ+qjpBEZwdP7gjfzfAtQitESyMwo3i+LBOw6sSDir6 + FlNDPCnkrTvqDX3Rt6X6vBtTCYOm+qiN7ujPkOU61cN7h8dvHR8YW9+0IPY80/W0 + lZ/HihSRgwTNd7LnxUUcPx8YV1id0dlmP0Hz+Lg+mHf6rqaR//JcYhX9vW4XvjA7 + BgkqhkiG9w0BBwEwFAYIKoZIhvcNAwcECMN+qya6ADywgBgHr9Jkhwn5Gsdu7BwX + nIQfYTYcdL9I5Sk= + </PRE +></DIV +><DIV +CLASS="SECT1" +><HR><H1 +CLASS="SECT1" +><A +NAME="DECRYPT" +>Decrypt</A +></H1 +><P +>Assume the above output has been saved into <TT +CLASS="FILENAME" +>encrypt.p7</TT +>. + Decrypt the message thusly: + </P +><PRE +CLASS="PROGRAMLISTING" +> from M2Crypto import BIO, SMIME, X509 + + # Instantiate an SMIME object. + s = SMIME.SMIME() + + # Load private key and cert. + s.load_key('recipient_key.pem', 'recipient.pem') + + # Load the encrypted data. + p7, data = SMIME.smime_load_pkcs7('encrypt.p7') + + # Decrypt p7. + out = s.decrypt(p7) + + print out + </PRE +><P +>Here's the output: + </P +><PRE +CLASS="SCREEN" +> a sign of our times + </PRE +></DIV +><DIV +CLASS="SECT1" +><HR><H1 +CLASS="SECT1" +><A +NAME="SIGN-AND-ENCRYPT" +>Sign and Encrypt</A +></H1 +><P +>Here's how to generate an S/MIME-signed/encrypted message: + </P +><PRE +CLASS="PROGRAMLISTING" +> from M2Crypto import BIO, Rand, SMIME, X509 + + def makebuf(text): + return BIO.MemoryBuffer(text) + + # Make a MemoryBuffer of the message. + buf = makebuf('a sign of our times') + + # Seed the PRNG. + Rand.load_file('randpool.dat', -1) + + # Instantiate an SMIME object. + s = SMIME.SMIME() + + # Load signer's key and cert. Sign the buffer. + s.load_key('signer_key.pem', 'signer.pem') + p7 = s.sign(buf) + + # Load target cert to encrypt the signed message to. + x509 = X509.load_cert('recipient.pem') + sk = X509.X509_Stack() + sk.push(x509) + s.set_x509_stack(sk) + + # Set cipher: 3-key triple-DES in CBC mode. + s.set_cipher(SMIME.Cipher('des_ede3_cbc')) + + # Create a temporary buffer. + tmp = BIO.MemoryBuffer() + + # Write the signed message into the temporary buffer. + s.write(tmp, p7) + + # Encrypt the temporary buffer. + p7 = s.encrypt(tmp) + + # Output p7 in mail-friendly format. + out = BIO.MemoryBuffer() + out.write('From: sender@example.dom\n') + out.write('To: recipient@example.dom\n') + out.write('Subject: M2Crypto S/MIME testing\n') + s.write(out, p7) + + print out.read() + + # Save the PRNG's state. + Rand.save_file('randpool.dat') + </PRE +><P +>Here's the output of the above program: + </P +><PRE +CLASS="SCREEN" +> From: sender@example.dom + To: recipient@example.dom + Subject: M2Crypto S/MIME testing + MIME-Version: 1.0 + Content-Disposition: attachment; filename="smime.p7m" + Content-Type: application/x-pkcs7-mime; name="smime.p7m" + Content-Transfer-Encoding: base64 + + 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 + </PRE +></DIV +><DIV +CLASS="SECT1" +><HR><H1 +CLASS="SECT1" +><A +NAME="DECRYPT-AND-VERIFY" +>Decrypt and Verify</A +></H1 +><P +>Suppose the above output has been saved into + <TT +CLASS="FILENAME" +>se.p7</TT +>. The following demonstrates how to decrypt and + verify it: + </P +><PRE +CLASS="PROGRAMLISTING" +> from M2Crypto import BIO, SMIME, X509 + + # Instantiate an SMIME object. + s = SMIME.SMIME() + + # Load private key and cert. + s.load_key('recipient_key.pem', 'recipient.pem') + + # Load the signed/encrypted data. + p7, data = SMIME.smime_load_pkcs7('se.p7') + + # After the above step, 'data' == None. + # Decrypt p7. 'out' now contains a PKCS #7 signed blob. + out = s.decrypt(p7) + + # Load the signer's cert. + x509 = X509.load_cert('signer.pem') + sk = X509.X509_Stack() + sk.push(x509) + s.set_x509_stack(sk) + + # Load the signer's CA cert. In this case, because the signer's + # cert is self-signed, it is the signer's cert itself. + st = X509.X509_Store() + st.load_info('signer.pem') + s.set_x509_store(st) + + # Recall 'out' contains a PKCS #7 blob. + # Transform 'out'; verify the resulting PKCS #7 blob. + p7_bio = BIO.MemoryBuffer(out) + p7, data = SMIME.smime_load_pkcs7_bio(p7_bio) + v = s.verify(p7) + + print v + </PRE +><P +>The output is as follows: + </P +><PRE +CLASS="SCREEN" +> a sign of our times + </PRE +></DIV +><DIV +CLASS="SECT1" +><HR><H1 +CLASS="SECT1" +><A +NAME="SMTP" +>Sending S/MIME messages via SMTP</A +></H1 +><P +>In the above examples, we've assumed that our S/MIME messages + are sent and received automagically. The following is a Python function that + generates S/MIME-signed/encrypted messages and sends them via SMTP: + </P +><PRE +CLASS="PROGRAMLISTING" +> from M2Crypto import BIO, SMIME, X509 + import smtplib, string, sys + + def sendsmime(from_addr, to_addrs, subject, msg, from_key, from_cert=None, to_certs=None, smtpd='localhost'): + + msg_bio = BIO.MemoryBuffer(msg) + sign = from_key + encrypt = to_certs + + s = SMIME.SMIME() + if sign: + s.load_key(from_key, from_cert) + p7 = s.sign(msg_bio, flags=SMIME.PKCS7_TEXT) + msg_bio = BIO.MemoryBuffer(msg) # Recreate coz sign() has consumed it. + + if encrypt: + sk = X509.X509_Stack() + for x in to_certs: + sk.push(X509.load_cert(x)) + s.set_x509_stack(sk) + s.set_cipher(SMIME.Cipher('des_ede3_cbc')) + tmp_bio = BIO.MemoryBuffer() + if sign: + s.write(tmp_bio, p7) + else: + tmp_bio.write(msg) + p7 = s.encrypt(tmp_bio) + + out = BIO.MemoryBuffer() + out.write('From: %s\r\n' % from_addr) + out.write('To: %s\r\n' % string.join(to_addrs, ", ")) + out.write('Subject: %s\r\n' % subject) + if encrypt: + s.write(out, p7) + else: + if sign: + s.write(out, p7, msg_bio, SMIME.PKCS7_TEXT) + else: + out.write('\r\n') + out.write(msg) + out.close() + + smtp = smtplib.SMTP() + smtp.connect(smtpd) + smtp.sendmail(from_addr, to_addrs, out.read()) + smtp.quit() + </PRE +><P +>This function sends plain, S/MIME-signed, S/MIME-encrypted, + and S/MIME-signed/encrypted messages, depending on the parameters + <TT +CLASS="PARAMETER" +><I +>from_key</I +></TT +> and <TT +CLASS="PARAMETER" +><I +>to_certs</I +></TT +>. The + function's output interoperates with Netscape Messenger. + </P +></DIV +><DIV +CLASS="SECT1" +><HR><H1 +CLASS="SECT1" +><A +NAME="VERIFYING-ORIGIN" +>Verifying origin of S/MIME messages</A +></H1 +><P +>In our examples above that decrypt or verify messages, we skipped + a step: verifying that the <TT +CLASS="LITERAL" +>from</TT +> address of the message + matches the <TT +CLASS="LITERAL" +>email address</TT +> attribute in the sender's + certificate. + </P +><P +>The premise of current X.509 certification practice is that the + CA is supposed to verify your identity, and to issue a certificate with + <TT +CLASS="LITERAL" +>email address</TT +> that matches your actual mail address. + (Verisign's March 2001 failure in identity verification resulting in + Microsoft certificates being issued to spoofers notwithstanding.) + </P +><P +>If you run your own CA, your certification practice is up to you, of + course, and it would probably be part of your security policy. + </P +><P +>Whether your S/MIME messaging application needs to verify the + <TT +CLASS="LITERAL" +>from</TT +> addresses of S/MIME messages depends on your + security policy and your system's threat model, as always. + </P +></DIV +><DIV +CLASS="SECT1" +><HR><H1 +CLASS="SECT1" +><A +NAME="NETSCAPE-MESSENGER" +>Interoperating with Netscape Messenger</A +></H1 +><P +>Suppose S/MIME Recipient uses Netscape Messenger. To enable Messenger + to handle S/MIME messages from S/MIME Sender, S/MIME Recipient needs + to configure Messenger with his private key and certificate, as well as S/MIME + Sender's certificate. + </P +><DIV +CLASS="NOTE" +><BLOCKQUOTE +CLASS="NOTE" +><P +><B +>Note: </B +>Configuring Messenger's POP or IMAP settings so that it retrieves + mail correctly is beyond the scope of this HOWTO. + </P +></BLOCKQUOTE +></DIV +><P +>The following steps demonstrate how to import S/MIME Recipient's + private key and certificate for Messenger: + </P +><DIV +CLASS="PROCEDURE" +><OL +TYPE="1" +><LI +><P +>Transform S/MIME Recipient's private key and certificate into + <I +CLASS="EMPHASIS" +>PKCS #12</I +> format. + </P +><PRE +CLASS="SCREEN" +> <TT +CLASS="USERINPUT" +><B +>openssl pkcs12 -export -in recipient.pem -inkey recipient_key.pem -name "S/MIME Recipient" -out recipient.p12 + </B +></TT +> + Enter Export Password:<TT +CLASS="USERINPUT" +><B +><TT +CLASS="REPLACEABLE" +><I +><enter></I +></TT +></B +></TT +> + Verifying password - Enter Export Password:<TT +CLASS="USERINPUT" +><B +><TT +CLASS="REPLACEABLE" +><I +><enter></I +></TT +></B +></TT +> + </PRE +></LI +><LI +><P +>Start Messenger. + </P +></LI +><LI +><P +>Click on the (open) "lock" icon at the bottom left corner of + Messenger's window. This brings up the "Security Info" dialog box. + </P +></LI +><LI +><P +>Click on "Yours" under "Certificates". + </P +></LI +><LI +><P +>Select "Import a certificate", then pick + <TT +CLASS="FILENAME" +>recipient.p12</TT +> from the ensuing file selection dialog + box. + </P +></LI +></OL +></DIV +><P +>Next, you need to import <TT +CLASS="FILENAME" +>signer.pem</TT +> as a CA + certificate, so that Messenger will mark messages signed by S/MIME Sender as + "trusted": + </P +><DIV +CLASS="PROCEDURE" +><OL +TYPE="1" +><LI +><P +>Create a DER encoding of <TT +CLASS="FILENAME" +>signer.pem</TT +>. + </P +><PRE +CLASS="SCREEN" +> <TT +CLASS="USERINPUT" +><B +>openssl x509 -inform pem -outform der -in signer.pem -out signer.der + </B +></TT +> + </PRE +></LI +><LI +><P +>Install <TT +CLASS="FILENAME" +>signer.der</TT +> into Messenger as MIME type + <TT +CLASS="LITERAL" +>application/x-x509-ca-cert</TT +>. You do this by downloading + <TT +CLASS="FILENAME" +>signer.der</TT +> via Navigator from a HTTP or HTTPS server, + with the correct MIME type mapping. (You may use + <TT +CLASS="FILENAME" +>demo/ssl/https_srv.py</TT +>, bundled with M2Crypto, for + this purpose.) Follow the series of dialog boxes to accept + <TT +CLASS="FILENAME" +>signer.der</TT +> as a CA for certifying email users. + </P +></LI +></OL +></DIV +><P +>S/MIME Recipient is now able to decrypt and read S/MIME Sender's + messages with Messenger. Messenger will indicate that S/MIME Sender's + messages are signed, encrypted, or encrypted <I +CLASS="EMPHASIS" +>and</I +> + signed, as the case may be, via the "stamp" icon on the message window's + top right corner. + </P +><P +>Clicking on the "stamp" icon brings you to the Security Info dialog + box. Messenger informs you that the message is, say, encrypted with + 168-bit DES-EDE3-CBC and that it is digitally signed by the private key + corresponding to the public key contained in the certificate + <TT +CLASS="FILENAME" +>signer.pem</TT +>. + </P +></DIV +><DIV +CLASS="SECT1" +><HR><H1 +CLASS="SECT1" +><A +NAME="MICROSOFT-OUTLOOK" +>Interoperating with Microsoft Outlook</A +></H1 +><P +>I do not know how to do this, as I do not use Outlook. (Nor do I use + Netscape Messenger, actually. I use Mutt, top dog of MUAs. ;-) Information on + how to configure Outlook with keys and certificates so that it handles + S/MIME mail is gratefully accepted. + </P +></DIV +><DIV +CLASS="SECT1" +><HR><H1 +CLASS="SECT1" +><A +NAME="ZSMIME" +>ZSmime</A +></H1 +><P +>ZSmime is a <A +HREF="http://www.zope.org" +TARGET="_top" +>Zope</A +> + <I +CLASS="EMPHASIS" +>product</I +> that enables Zope to generate + S/MIME-signed/encrypted messages. ZSmime demonstrates how to invoke + M2Crypto in a web application server extension. + </P +><P +>ZSmime has its own <A +HREF="http://www.post1.com/home/ngps/zope/zsmime/howto.html" +TARGET="_top" +>HOWTO</A +> + explaining its usage. (That HOWTO has some overlap in content with + this document.) + </P +></DIV +><DIV +CLASS="SECT1" +><HR><H1 +CLASS="SECT1" +><A +NAME="RESOURCES" +>Resources</A +></H1 +><P +></P +><UL +><LI +STYLE="list-style-type: opencircle" +><P +>IETF S/MIME Working Group - + <A +HREF="http://www.imc.org/ietf-smime" +TARGET="_top" +> http://www.imc.org/ietf-smime</A +> + </P +></LI +><LI +STYLE="list-style-type: opencircle" +><P +>S/MIME and OpenPGP - + <A +HREF="http://www.imc.org/smime-pgpmime.html" +TARGET="_top" +> http://www.imc.org/smime-pgpmime.html</A +> + </P +></LI +><LI +STYLE="list-style-type: opencircle" +><P +>S/MIME Freeware Library - + <A +HREF="http://www.getronicsgov.com/hot/sfl_home.htm" +TARGET="_top" +> http://www.getronicsgov.com/hot/sfl_home.htm</A +> + </P +></LI +><LI +STYLE="list-style-type: opencircle" +><P +>Mozilla Network Security Services - + <A +HREF="http://www.mozilla.org/projects/security/pkg/nss" +TARGET="_top" +> http://www.mozilla.org/projects/security/pkg/nss</A +> + </P +></LI +><LI +STYLE="list-style-type: opencircle" +><P +>S/MIME Cracking Screen Saver - + <A +HREF="http://www.counterpane.com/smime.html" +TARGET="_top" +> http://www.counterpane.com/smime.html</A +> + </P +></LI +></UL +></DIV +><DIV +CLASS="SECT1" +><HR><H1 +CLASS="SECT1" +><A +NAME="ID-KLUDGE" +></A +></H1 +><P +> <TT +CLASS="LITERAL" +>$Id: howto.smime.html,v 1.1 2003/06/22 16:41:18 ngps Exp $</TT +> + </P +></DIV +></DIV +></BODY +></HTML +>
\ No newline at end of file diff --git a/doc/m2_blurb.docbook b/doc/m2_blurb.docbook new file mode 100644 index 0000000..f2abf1a --- /dev/null +++ b/doc/m2_blurb.docbook @@ -0,0 +1,10 @@ + <para><ulink url="http://www.post1.com/home/ngps/m2">M2Crypto</ulink> is a + <ulink url="http://www.python.org">Python</ulink> interface to <ulink + url="http://www.openssl.org">OpenSSL</ulink>. It makes available to the + Python programmer SSL functionality to implement clients and servers, + HTTPS extensions to Python's HTTP functionality, FTP/TLS client and server + implementations, S/MIME v2, RSA, DSA, DH, symmetric ciphers, message + digests, HMACs and unforgeable HMAC'ing AuthCookies for web applications. + </para> + + <!--$Id: m2_blurb.docbook,v 1.1 2003/06/22 16:41:19 ngps Exp $--> |