summaryrefslogtreecommitdiff
path: root/doc
diff options
context:
space:
mode:
authorNg Pheng Siong <ngps@netmemetic.com>2003-06-22 16:41:19 +0000
committerNg Pheng Siong <ngps@netmemetic.com>2003-06-22 16:41:19 +0000
commitc0a9ac01395c395fb9c6198fb05980e8b5c108e4 (patch)
tree0670860e972d2fe22c2762ddb06d46e0638f5613 /doc
parent93d1049a42830e1d3c1303a460bc1e2a9a0a765b (diff)
downloadm2crypto-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/DOCU51
-rw-r--r--doc/INSTALL.html237
-rw-r--r--doc/README.html101
-rw-r--r--doc/default.css174
-rw-r--r--doc/howto.ca.docbook456
-rw-r--r--doc/howto.ca.html891
-rw-r--r--doc/howto.https.docbook248
-rw-r--r--doc/howto.smime.docbook962
-rw-r--r--doc/howto.smime.html1570
-rw-r--r--doc/m2_blurb.docbook10
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, &quot;-python&quot;, &quot;-dnone&quot;, &quot;-ISWIG&quot;] # old
+swig_cmd = [swig, &quot;-python&quot;, &quot;-ISWIG&quot;] # 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">
+&gt; That and one needs to install openssl-0.9.6. But that's a whole other
+&gt; story. In short:
+&gt; 1. ./Configure OpenBSD
+&gt; 2. edit root Makefile to change &quot;gcc&quot; to &quot;cc&quot;
+&gt; 3. edit Makefile in apps and test to change the libraries to:
+&gt; LIBCRYPTO=../libcrypto.a
+&gt; LIBSSL=../libssl.a
+&gt;
+&gt; 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 &quot;me, too!&quot; <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>&lt;enter&gt;</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>&lt;secret passphrase here&gt;</replaceable></userinput>
+ Verifying password - Enter PEM pass phrase: <userinput><replaceable>&lt;secret passphrase again&gt;</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>&lt;another secret passphrase here&gt;</replaceable></userinput>
+ Verifying password - Enter PEM pass phrase: <userinput><replaceable>&lt;another secret passphrase again&gt;</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>&lt;enter&gt;</replaceable></userinput>
+ An optional company name []:<userinput><replaceable>&lt;enter&gt;</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>&lt;CA's passphrase&gt;</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>&lt;secret passphrase here&gt;</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 &copy; 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
+>&lt;enter&gt;</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
+>&lt;secret passphrase here&gt;</I
+></TT
+></B
+></TT
+>
+ Verifying password - Enter PEM pass phrase: <TT
+CLASS="USERINPUT"
+><B
+><TT
+CLASS="REPLACEABLE"
+><I
+>&lt;secret passphrase again&gt;</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
+>&lt;another secret passphrase here&gt;</I
+></TT
+></B
+></TT
+>
+ Verifying password - Enter PEM pass phrase: <TT
+CLASS="USERINPUT"
+><B
+><TT
+CLASS="REPLACEABLE"
+><I
+>&lt;another secret passphrase again&gt;</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
+>&lt;enter&gt;</I
+></TT
+></B
+></TT
+>
+ An optional company name []:<TT
+CLASS="USERINPUT"
+><B
+><TT
+CLASS="REPLACEABLE"
+><I
+>&lt;enter&gt;</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 &#60; 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
+>&lt;CA's passphrase&gt;</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 &#60; newreq.pem &#62; newkey.pem
+ </B
+></TT
+>
+ read RSA key
+ Enter PEM pass phrase:<TT
+CLASS="USERINPUT"
+><B
+><TT
+CLASS="REPLACEABLE"
+><I
+>&lt;secret passphrase here&gt;</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
+ &lt;m2crypto&gt;/demo/https.howto/. Additionally, a number of programs from
+ &lt;m2crypto&gt;/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
+ &lt;M2Crypto.BIO.BIO instance at 0x822012c&gt;
+ 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>&lt;enter&gt;</replaceable></userinput>
+ Verifying password - Enter Export Password:<userinput><replaceable>&lt;enter&gt;</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 &copy; 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"
+>&#60;<A
+HREF="mailto:sender@example.dom"
+>sender@example.dom</A
+>&#62;</TT
+>, shall be the sender of S/MIME messages,
+ while S/MIME Recipient, <TT
+CLASS="EMAIL"
+>&#60;<A
+HREF="mailto:recipient@example.dom"
+>recipient@example.dom</A
+>&#62;</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
+ &lt;M2Crypto.BIO.BIO instance at 0x822012c&gt;
+ 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
+>&lt;enter&gt;</I
+></TT
+></B
+></TT
+>
+ Verifying password - Enter Export Password:<TT
+CLASS="USERINPUT"
+><B
+><TT
+CLASS="REPLACEABLE"
+><I
+>&lt;enter&gt;</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 $-->