1SMIME TOOL (merged with ZXID.org project since 2009)
229.10.1999, 17.11.1999, Sampo Kellomaki <sampo@iki.fi>
3
4NOTE: This is still highly experimental code and build system has not been
5      perfected yet. No Windows build is known to exist (contributions?).
6
7OFFICIAL WEB SITE
8	http://zxid.org/Net_SSLeay/smime.html
9
10BUILDING
11
12	(build and install OpenSSL-0.9.4, from www.openssl.org)
13	tar xzf smime-0.7.tgz
14	cd smime-0.7
15	cons smime        # get cons from http://www.dsmit.com/cons/
16	cons SMIMEutil.so # build the perl module (optional)
17	./smime -help     # shows quick usage
18	./smime -dv ../smime-0.7.tgz
19	    (cut my certificate and distribution signature from the web
20	     site and paste to stdin)
21
22TUTORIAL PART 1: SIGNING AND ENCRYPTING
23
24	First you need to have certicate and private key in pem format. To
25	produce them, use openssl tool or export them from your browser.
26	I illustrate the latter method first, because I'm going to use
27	Netscape browser for interoperability testing later. You can
28	peek at TUTORIAL PART3, Key generation if you need to do this
29	yourself.
30
31	- Go to security info dialog in Netscape browser.
32	- From Certificates-Yours export your certificate (if you
33	  don't have a certificate installed yet, read the FAQs and mailing
34	  list archieves at www.openssl.org), save it as me.p12. It
35	  will ask for password to protect your private key.
36
37	  openssl pkcs12 -clcerts <me.p12 >me.pem
38		- it will ask for the password to open your private key and
39		  then asks you to invent a new password that will be
40		  used to protect your private key in pem format
41
42	  more me.pem
43
44	You should see something like this:
45
46Bag Attributes
47    friendlyName: your@email.com
48    localKeyID: F3 85 A8 4B DA 39 B6 40 6B D6 20 01 39 46 6A 94 47 9D 2C 0F
49Key Attributes: <No Attributes>
50-----BEGIN RSA PRIVATE KEY-----
51Proc-Type: 4,ENCRYPTED
52DEK-Info: DES-EDE3-CBC,541E04862A13F6B1
53
548+2vo6Iz49uj/Mf31JTgaRuIq9ueHsknsHXhmXp7s1BmS8xulT22Zzpdh6g1yqAO
55(snip)XeQsZrWykdWvN2qGu/cNa2HnUQAG0p25tNZ3CKmqpJBVg0RXr20JlQ==
56-----END RSA PRIVATE KEY-----
57Bag Attributes
58    friendlyName: your@email.com
59    localKeyID: F3 85 A8 4B DA 39 B6 40 6B D6 20 01 39 46 6A 94 47 9D 2C 0F
60subject=/C=PT/L=City/O=Company/OU=Dept/CN=Your Name/Email=your@email.com
61issuer= /C=PT/L=City/O=Your CA/OU=Personal Certs/CN=End user CA/Email=certifier@ca.com
62-----BEGIN CERTIFICATE-----
63MIIDEzCCAnygAwIBAgIBAzANBgkqhkiG9w0BAQQFADCBlTELMAkGA1UEBhMCUFQx
64(snip)Tj0JYGZMzSUfzOG3wajK6B39d6EyXK8=
65-----END CERTIFICATE-----
66
67	Ok. Now you are all set to use smime tool. First lets create
68	simple mime entity (see RFC1521 for definition):
69
70	  echo foo | ./smime -mime text/plain | tee foo.mime
71
72Signing
73	Now, let's sign it:
74
75	  ./smime -s me.pem password <foo.mime | tee foo.smime
76
77	And send it:
78
79	  ./send.pl 'Sig test' your@email.com your@email.com <foo.smime
80
81	Now go to your email reading software (Netscape Communicator suggested
82	for this exercise) and read the mail you just sent. It should display
83	as signed. In the previous command the second argument is the
84        From: header which must match friendlyname/EMAIL in me.pem
85
86	You can repeat this success using following pipeline:
87
88	  echo foo | ./smime -mime text/plain | ./smime -s me.pem password \
89	  | ./send.pl 'Sig test' your@email.com your@email.com
90
91	(Note how \ is used for folding the lines. In reality you should
92	 type all the stuff in one line.)
93
94Clear signing
95	The previous method produces a base64 blob that you probaly would not
96	like to send to a news group. Clear signing allows mail to be read
97	even if the reader is not S/MIME aware:
98
99	  echo foo | ./smime -mime text/plain | ./smime -cs me.pem password \
100	  | ./send.pl 'Sig test' your@email.com your@email.com
101
102	Note how the message has "foo" visible. Now go read this with your
103	mail reader. It should also display as signed. If not, then its
104	possible that canonization was not correctly done. That might even
105	be an error in my part.
106
107Encrypting
108	To encrypt you need to know recipient's cert. Here I use our own
109	because its by definition already installed in our browser.
110
111	  echo foo | ./smime -mime text/plain | ./smime -e me.pem \
112	  | ./send.pl 'Enc test' your@email.com your@email.com
113
114	Now you should be able to read your mail (it may ask for a password
115	to open your private key) and see the message in plain text, but
116	marked as encrypted.
117
118Signing and Encrypting
119	Next we'll first sign a message and then wrap it in encryption. This
120	is the usual way and hides the signatories from eavesdroppers:
121
122	  echo foo | ./smime -mime text/plain | ./smime -cs me.pem password \
123	  | ./smime -e me.pem | ./send.pl 'test' your@email.com your@email.com
124
125	Again your mail reader should show the message marked as
126	Encrypted and Signed.
127
128Encrypting and Signing
129	The other way is to first encrypt and then sign the encrypted
130	message. This might be useful in some automated context where a robot
131	would verify the signature but the robot should not be allowed to see
132	the message:
133
134	  echo foo | ./smime -mime text/plain | ./smime -e me.pem \
135	  | ./smime -cs me.pem password \
136	  | ./send.pl 'Enc test' your@email.com your@email.com
137
138	Now Netscape shows two icons: one saying "Signed" and placed near
139	the headers. Other icon that says "Encrypted" appears in the
140	content area.
141
142	In fact S/MIME specification allows arbitrary nesting of encryptions
143	and signatures, what ever your application may need.
144
145Multipart content
146	Now for the final part that is not really S/MIME specific, but
147	nice to have. You can first compose a normal mime multipart message,
148	possibly even containing some encrypted components and some not.
149	Try this:
150
151	  echo bar | ./smime -m image/gif some.gif \
152	  | ./smime -cs me.pem password | ./smime -e me.pem \
153	  | ./send.pl 'Enc test' your@email.com your@email.com
154
155	Now you should see signed and encrypted message with an image
156	attached. The multipart functionality implemented by -m is very
157	basic and by no means anything generic. Its only a demonstration.
158
159TUTORIAL PART 2: DECRYPTING AND VERIFYING SIGNATURES
160
161Decrypting
162	To demonstrate decrypting, I'll cut the mail from the loop. Basically
163	I'll demonstrate introperability with myself. If you want to try
164	interoperability with Netscape, you can use Netscape to send mail
165	and grab it from mail spool and then feed it into pipeline. As this
166	is a bit messy and might involve editing the file manually, I
167	wont go into that now. Here's a simple encryption - decryption:
168
169	  echo foo | ./smime -mime text/plain | ./smime -e me.pem \
170	  | tee foo.p7m | ./smime -d me.pem passwd
171
172	foo wrapped in mime headers should come out. I also used tee(1) to
173	put the encrypted form in a file in case I also want to verify
174	it with Netscape
175
176	  ./send.pl 'Enc test' your@email.com your@email.com <foo.p7m
177
178	or in qmail
179
180	  /var/qmail/bin/qmail-inject your@email.com < foo.p7m
181
182        This is most convenient method because it allows you to import
183	certificates belonging to others than yourself and still
184	deliver mail to yourself. You want this, because you will soon
185	discover that Netscape can hold in its certificate database
186	only one certificate per email address (or is it distinguished name?)
187	and if that one "slot" is occupied, say, in "People" section, then
188	you can't import it any more to "Yours" section. Hence the solution
189	is to use different email address (and friendly name) every
190	single time.
191
192Verifying signature
193	Due to somewhat incomplete nature of OpenSSL-0.9.4 PKCS7 signature
194	verification code, I have implemented my own signature verfication
195	scheme that works in five steps
196
197		1. find out who signed the message
198		2. verify message signature using signer's certificate
199		3. find out who certified the signer's certificate
200		4. verify signer's cert using certifier's cert
201		5. repeat 3. & 4. until at root of the chain
202
203	This has the advantage that there are less obscure stuff and
204	assumptions hidden inside the program, i.e. user must understand
205	what signature and certificate verification is all about and
206	you get to observe every step of the way. The down side is that
207	its less automatic. In my particular application this does not
208	happen to be a problem because I have out of band information
209	about who is supposed to have signed what.
210
211	Here we go: lets produce a signature to play with
212
213	  echo foo | ./smime -mime text/plain | tee foo.mime \
214	  | ./smime -s me.pem password | tee foo.p7m
215
216	Now see who signed it
217
218	  ./smime -qs < foo.p7m
219
220	Now I assume that I have some way of finding the certificate using
221	the issuer DN and serial number returned in the previous step. These
222	two pieces of information constitute unique ID for a certificate.
223	Perhaps I keep my certs in LDAP or some other database. Anyway,
224	assume the certificate is found, then
225
226	  ./smime -v me.pem <foo.p7m | tee foo2.mime
227	  diff foo.mime foo2.mime   # just to check!
228
229	Note that diff may show white space differences (try diff -b) because
230	line endings in your mime message were canonized to CRLF for signing.
231	This is mandated by S/MIME specification.
232
233	Now proceed with verifying the certificate:
234
235	  ./smime -qc <me.pem
236
237	Now out of band means are used to find the signer's certificate. Then
238	to check that the signature matches:
239
240	  ./smime -vc ca.pem <me.pem
241
242Verifying clear signature
243	(does not currently work :-(
244
245Under construction: chain verification (does not currently work)
246	mkdir certs
247	cd certs
248	cp ../me.pem .
249	../hash-certs.pl *.pem
250	cd ..
251	echo foo | ./smime -mime text/plain | ./smime -s me.pem password \
252	| ./smime -v
253
254TUTORIAL PART 3: A KEY GENERATION METHOD
255
256Bootstrapping a simple public key infrastructure
257
258	Suppose entity M is funding projects and needs to have all project
259	leaders (Ps) sign a contract specifying responsibilities. M
260	distributes a simple application that incorporates the smime tool. Ps
261	use the application to sign the contracts and send them electronically
262	to M. If irregularities develop, M sues P to court and uses the
263	digitally signed contract as evidence. For this to work
264
265		I.  M must convince the court that the system does not have
266		    technical flaws that could work in his favor. This proof
267		    is much easier with digital signatures than with systems
268		    that depend on procedural integrity (e.g. passwords over
269		    SSL protected connection may prove at the moment the
270		    intention of P, but when document is recovered from backup
271		    10 years later, all procedural proofs vanish)
272
273		II. P's signature must be as valid as paper and ink
274			1. P's real world identity must be connected to
275			   digital signature
276			2. P must have understood what it means to sign
277			   contract digitally
278			3. P must have sufficient integrity or the system
279			   must technically guarantee that P's private
280			   key could not have been used by any one else
281			4. P must have acted by free will and in full powers
282			   of mind
283			5. law must not prohibit digital signature
284
285	M needs to establish a simple public key infrastructure. I propose
286	that the application generates key pairs for P's and sends
287	certification requests, further, it also prints the certification
288	request in paper form including,
289
290		- fingerprint of public key (as number and as bar code)
291		- full dump of public key and all attributes appearing
292		  in the certification request
293		- legal language to guarantee 2. & 3. (on point 3 we rely
294		  on integrity)
295		- details of conventional identification of P
296		- space for signature
297
298	With this paper P goes to some commonly agreed and trustworthy
299	notary. This could be notary public or it could be some trusted
300	administrative organ in P's organization. It could even be M, but
301	that would cause a bureaucracy bottle neck at M, and hence increase
302	costs of the solution.
303
304	P signs the paper and proves his identity in presence of the notary
305	who confirms the act. The paper is sent to M. This takes care of
306	1. and 4. As paper contract about use of digital signatures now
307	exists between M and P, 5. is only of concern if it explicitly
308	nullifies such contract (or if court practice still does not consider
309	digital signature valid?).
310
311	Finally paper arrives to M where a clerk processes it (the bar
312	code helps here). He finds the certification request from data base
313	and sees that it matches the paper and issues a digital cerificate
314	that is immediately placed on a public server for everybody to
315	see. The paper is securely archieved forever.
316
317	Once the certificate is publically available, signing and verifying
318	contracts using it is trivial and can even be done between P and
319	some other party than M (e.g. certificate could be used for email).
320
321	However, to bootstrap the system it should, ideally, be possible
322	to sign your first contract even without waiting for the
323	certification to happen. After all, the impulse	for P to adhere
324	to PKI of M came from needing to sign a	contract (dead line for
325	research proposals may be very close). The contract would be
326	in signed, but not verified status until the certification happens.
327
328	Here the OpenSSL (or PKCS7?) does not serve us well, because it needs
329	a certificate even for the signing operation, although common
330	sense says that the private key and attributes of certification
331	request (ok, you can't know what serial number will be assigned)
332	should be enough. I solve this problem by signing the first contract
333	with a self signed certificate. Although this is quite suboptimal,
334	it allows me to get going without hacking OpenSSL innards too much.
335	Only complication arises from needing to establish that also the
336	certified public key is able to decrypt the hash of the signed
337	material.
338
339Key generation
340
341	Smime tool contains simple key generation command that will
342	make certification request as well as self signed cert. This
343	is bit simplistic and really geared towards my particular application
344	as the X509v3 certificate options are hardwired. Be sure to read
345	the source code to check they are the way you want.
346
347	  echo "commonName=Joe Smith|emailAddress=joe@test.com" \
348	  | ./smime -kg "description=foo" passwd req.pem >priv_ss.pem
349
350	The stuff that is echoed to stdin is your distinguished name. You
351	must use long forms of attribute name and you can only use attributes
352	known to OpenSSL.
353
354        *** How to specify cn as needed by SSL certs?
355
356        The req.pem should be sent to certification authority for signing.
357        Meanwhile you can use the self signed certificate which was output
358	to stdout, here priv_ss.pem. Note that the private key is also
359	output to the stdout so do not give that file to anyone. If you need
360	to give the certificate, you should edit a copy of priv_ss.pem
361	and remove the private key.
362
363	To be able to import your private key and certificate to Netscape
364	you can use
365
366	  ./smime -pem-p12 you@test.com passwd pw-for-p12 <priv_ss.pem >me.p12
367
368	The first argument (the email address) is the friendly name. Netscape
369	appears to match this against From mail header when verifying
370	signatures. For minimum troubles you should keep this equal to
371	emailAddress field of your certificate.
372
373Being a certificate authority
374
375	Once you have made your req.pem, you can send it to some commercial
376	certification authority or you can just be your own. The CA
377	functionality of smime tool is not very complete. Basically
378	it allows you to do the crypto part (signing certificate request with
379	CA's private key) but you must manually do book keeping to ensure
380	uniqueness of serial numbers and to make sure you do not issue the
381	same certificate twice, etc.
382
383	Here's how you'd sign a request (you probably used -kg to make
384	the CA's certificate):
385
386	  ./smime -ca ca-id.pem very-secret 1 <req.pem >cert.pem
387
388	The number one is the serial number. As I said, you should do
389	bookkeeping to ensure you never reuse a serial number. Many
390	systems depend on being uniquely able to identify certificate
391	by its issuing authority and serial number. A certificate
392	authority that can not guarantee uniqueness of serial numbers is
393	not trustworthy.
394
395	Please note that the -ca hard wires all X509v3 options and extensions.
396	Be sure to read the source to check they are the way you want them.
397
398TUTORIAL PART 4: SIGNING AND VERIFYING SOFTWARE DISTRIBUTIONS
399
400	smime tool has detached signature feature which is meant for
401	signing and verifying software distributions. Here's how. First
402	make yourself an identity
403
404	  echo 'commonName=my dist key|emailAddress=you@test.com' \
405	  | ./smime -kg '' pw dist-req.pem >dist-id.pem
406
407	Now open dist-id.pem in editor and save the certificate part as
408	dist-cert.pem. Pubish dist-cert.pem on your web site.
409
410	Then sign your software package
411
412	  ./smime -ds dist-id.pem pw <your-dist-1.00.tgz >your-dist-1.00.sig
413
414	I suggest convention of naming the signature file with same name
415	as the tarball, but extension `.sig'. Now put the .sig file
416	available where ever you put your tarball. You should also publish
417	it on your web site so people can get it even if they forgot to
418	download the .sig file.
419
420	Or you could produce a combination signature and certificate file
421	and put that available on your website
422
423	  ./smime -ds dist-id.pem pw <your-dist-1.00.tgz \
424	  | cat - dist-cert.pem >your-dist-1.00.sigcert
425
426	To verify a distribution signature one would say
427
428	  ./smime -dv your-dist-1.00.tgz
429	    (cut certificate and distribution signature from the web
430	     site and paste to stdin)
431
432	The dv looks for the -----BEGIN/END CERTIFICATE----- separator to
433	figure out where the certificate ends and signature starts.
434
435	If you already had the .sig or the certificate you could just say
436
437	  cat dist-cert.pem your-dist-1.00.sig | ./smime -dv your-dist-1.00.tgz
438
439	(OK, PGP already exists to do this stuff, but I always found it
440	 quite messy to deal with detached signatures in PGP. I'm sure
441	 poor usability leads to less people verifying the signatures.)
442
443SMIMEUTIL LIBRARY AND PERL MODULE
444
445	The smimeutil library is documented in smimeutil.h, see smime.c
446	for some examples of usage. The SMIMEUtil:: perl module is
447	not currently documented. For usage examples see test.pl.
448
449CAVEATS
450	For signing to work correctly, your mime entity must be canonized
451	the same way as the recipient will canonize it. In general this
452	means that you must use CRLF as line termination and must include
453	all headers.
454
455	If you are clear signing, then you may want to consult RFC2311 for
456	some ways the message might get ruined (e.g. changes in whitespace).
457	In my experience most important requirement seems to be to not
458	use any trailing whitespace. YMMV.
459
460	For signatures to verify correctly, the From: header of the mail
461	must be equal to "friendlyname:" and EMAIL fields in your cert.
462
463	When encrypting, do not forget to wrap your message in mime entity.
464	If you don't, ./smime -d will silently return emptiness, Netscape
465	reports "improperly formatted DER-encoded message". This
466	will _not_ work:
467
468	  echo "foo" | ./smime -e me.pem | ./smime -d me.pem secret  # WRONG!
469
470SECURITY CAVEATS
471	Passing passwords on command line is insecure. The smime tool is
472	intended more as a demonstration than a production tool. See
473	pass-password.pl for an example how to use file descriptor to
474	pass the passwords more securely.
475
476	smimeutil.c compiles by default to use DES-EDE3-CBC cipher which
477	is not known by export versions of many browsers. See around
478	line 400 in smime-enc.c if you need to change this. Be ware that
479	RC2-40-CBC can be cracked in real time by trivial resources.
480	Never-the-less its the only cipher that interoperates with all
481	versions of browsers.
482
483	Randomnumbers are not (yet) initialized as they should.
484
485	Certificate verification scheme puts the burden of verification
486	on user. For example, the user must notice if purported CA certificate
487	has X509v3 attribute that forbids it from being CA cert.
488
489TIP
490	You can use Netscape to encrypt and sign messages and then look
491	at them in mail spool. This way you see their raw structure before
492	any mail reader gets to interpret it. This is the best way to
493	debug differences between what you produce and what is presumably
494	standards compatible.
495
496TO DO
497	Parsing mime messages in robust and fully correct way
498
499BUGS
500	Due to the way the API is defined all stuff is kept in memory. While
501	this is simple and easy, you might get into trouble with large files.
502	I'd say the memory consumption will not exceed five times the file
503	size, but don't bet on it.
504
505	Signature verification in perl module still needs some work.
506
507SEE ALSO
508	RFC1521 (MIME)
509	RFC2111 (S/MIME v2)
510	*** RFCXXXX (S/MIME v3)
511	http://www.openssl.org
512	http://zxid.org/Net_SSLeay/smime.html  (this stuff)
513
514USAGE
515	(reproduced from ./smime -help)
516
517	./smime -cs private password <mime-entity >smime  # clear sign
518	./smime -cv cert <smime-entity >data              # verify clear sig
519	./smime -ds private passwd <file >smime-sig       # make detached sig
520	./smime -dv file <smime-sig-entity                # verify detached
521	./smime -s  private password <mime-entity >smime  # sign
522	./smime -qs <smime-entity >signing-cert-info      # find out who signed
523	./smime -v cert <smime-entity >signer-dn          # verify signature
524
525	./smime -vc cacert <cert                          # verify certificate
526
527	./smime -e public <mime-entity >smime-ent         # encrypt
528	./smime -d private password <smime-entity >mime   # decrypt
529
530	./smime -qr <req.pem    # Query all you can about request
531	./smime -qc <cert.pem   # Query all you can about certificate
532	./smime -ca ca_cert passwd serial <req.pem >cert.pem     # sign a req
533
534	./smime -p12-pem p12pw pempw <x.p12 >x.pem  # convert PKCS12 to pem
535	./smime -pem-p12 frindly@name.com pempw p12pw <x.pem >x.p12
536
537	./smime -m type1 file1 type2 file2 type3 file3 <text  # make multipart
538	./smime -m image/gif foo.gif <message | ./smime -s private pass >smime
539
540	./smime -kg attr passwd req.pem <dn >priv_ss.pem  # keygen
541
542	./smime -base64 <file >file.base64
543	./smime -unbase64 <file.base64 >file
544	./smime -mime text/plain <file >mime-entity
545	./smime -mime_base64 image/gif <file.gif >mime-entity
546	./smime -split dirprefix <multipart         # splits multipart
547	./smime -base64 <in | ./smime -unbase64 >out
548	./smime -cat <in >out   # copy input to output using slurp and barf
549
550	./smime -kg 'description=Test' secret req.pem <me.dn >ss.pem
551
552--Sampo
553