diff options
Diffstat (limited to 'doc')
-rw-r--r-- | doc/fluff.html | 158 | ||||
-rw-r--r-- | doc/index.html | 182 | ||||
-rw-r--r-- | doc/ironclad-doc.txt | 658 | ||||
-rw-r--r-- | doc/ironclad.html | 182 | ||||
-rw-r--r-- | doc/style.css | 77 |
5 files changed, 1257 insertions, 0 deletions
diff --git a/doc/fluff.html b/doc/fluff.html new file mode 100644 index 0000000..7c80b16 --- /dev/null +++ b/doc/fluff.html @@ -0,0 +1,158 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" + "http://www.w3.org/TR/html4/strict.dtd"> +<HTML><HEAD><TITLE>Ironclad</TITLE><LINK TYPE="text/css" TITLE="default" REL="stylesheet" MEDIA="screen" HREF="style.css" /></HEAD><BODY><H1>Ironclad</H1><P>Ironclad is a cryptography library written entirely in +Common Lisp. It includes support for several +popular <A HREF="#ciphers">ciphers</A>, <A HREF="#digests">digests</A>, and <A HREF="#macs">MACs</A>. Rudimentary support for <A HREF="#public-key">public-key cryptography</A> is included. For several implementations that support Gray +Streams, <A HREF="#gray-streams">support</A> is included for +convenient stream wrappers.</P><H2>Installation</H2><P>Ironclad can be downloaded at <A HREF="http://www.method-combination.net/lisp/files/ironclad.tar.gz">http://www.method-combination.net/lisp/files/ironclad.tar.gz</A>. +The latest version is 0.20.1.</P><P>It comes with an ASDF system definition, so <TT>(ASDF:OOS +'ASDF:LOAD-OP :IRONCLAD)</TT> should be all that you need to get started. +The testsuite can be run by substituting <TT>ASDF:TEST-OP</TT> for <TT>ASDF:LOAD-OP</TT> in the form above. All tests should pass successfully. +If they do not, you have found a bug; please report it.</P><H2>License</H2><P>Ironclad is released under a MIT-like license; you can do pretty +much anything you want to with the code except claim that you wrote +it.</P><H2>Ciphers</H2><DIV CLASS="lisp-symbol"><A NAME="make-cipher"></A><TT><STRONG>make-cipher</STRONG> <EM>name</EM> <EM><TT>&key</TT></EM> <EM>key</EM> <EM>mode</EM> <EM>initialization-vector</EM> <EM>padding</EM> => <EM>cipher</EM></TT><BR /></DIV><P>Return a cipher object suitable for use for both encryption and +decryption.</P><P><EM>name</EM> denotes the encryption algorithm to use. <A HREF="#list-all-ciphers" STYLE="symbol">list-all-ciphers</A> will tell you the names of all supported ciphers; +the short list of ones you are likely to be interested in is:</P><UL><LI>AES</LI><LI>DES</LI><LI>3DES</LI><LI>Blowfish</LI><LI>Twofish</LI><LI>RC5</LI><LI>RC6</LI><LI>Arcfour (RC4)</LI></UL><P><EM>name</EM> should be a symbol in the <TT>KEYWORD</TT> package; <TT>:AES</TT> for AES, <TT>:ARCFOUR</TT> for RC4, and so forth.</P><P><EM>mode</EM> describes the mode of operation for the cipher. Stream +ciphers such as Arcfour can operate in only one mode, <TT>stream</TT>. +Block ciphers such as AES and DES can operate in several different +modes:</P><UL><LI>ECB</LI><LI>CBC</LI><LI>OFB</LI><LI>CFB (note that CFB mode is 'n'-bit CFB, where 'n' is the <A HREF="#block-length" STYLE="symbol">block-length</A> of the cipher)</LI><LI>CTR</LI></UL><P><EM>mode</EM> should be a symbol in the <TT>KEYWORD</TT> or <TT>IRONCLAD</TT> +packages; <TT>:STREAM</TT>, <TT>IRONCLAD:OFB</TT>, and so forth. An error +will be signaled if <EM>mode</EM> is not appropriate for the cipher <EM>name</EM>.</P><P><EM>initialization-vector</EM> (IV) should be supplied only if <EM>mode</EM> +requires one. <EM>initialization-vector</EM> should be a <TT>(VECTOR +(UNSIGNED-BYTE 8))</TT>. The supplied IV should be the same length as the +<A HREF="#block-length" STYLE="symbol">block-length</A> of <EM>name</EM>.</P><P><EM>key</EM> is, of course, the key for the cipher. <EM>key</EM> should be +a <TT>(VECTOR (UNSIGNED-BYTE 8))</TT>.</P><P>If <EM>padding</EM> is supplied, the specified padding method will be +used by <A HREF="#encrypt" STYLE="symbol">encrypt</A> and <A HREF="#decrypt" STYLE="symbol">decrypt</A> to handle short blocks when the <TT>:HANDLE-FINAL-BLOCK</TT> argument is supplied. Depending on the mode +specified, <EM>padding</EM> may be ignored (e.g. OFB and CFB modes do not +care about short blocks; neither do stream ciphers).</P><TABLE CLASS="note"><TR><TD CLASS="title">Note</TD><TD CLASS="content"><EM>padding</EM> is currently ignored in all modes (and, by extension, +so is <TT>:HANDLE-FINAL-BLOCK</TT>). This oversight is expected to be +corrected in a future release.</TD></TR></TABLE><DIV CLASS="lisp-symbol"><A NAME="encrypt"></A><TT><STRONG>encrypt</STRONG> <EM>cipher</EM> <EM>plaintext</EM> <EM>ciphertext</EM> <EM><TT>&key</TT></EM> <EM>plaintext-start</EM> <EM>plaintext-end</EM> <EM>ciphertext-start</EM> => <EM>n-bytes-consumed</EM>, <EM>n-bytes-produced</EM></TT><BR /></DIV><P>Encrypts data according to <EM>cipher</EM> from <EM>plaintext</EM> +starting at <EM>plaintext-start</EM> and continuing until <EM>plaintext-end</EM>. The encrypted data is placed in <EM>ciphertext</EM> starting at <EM>ciphertext-start</EM>.</P><DIV CLASS="lisp-symbol"><A NAME="decrypt"></A><TT><STRONG>decrypt</STRONG> <EM>cipher</EM> <EM>ciphertext</EM> <EM>plaintext</EM> <EM><TT>&key</TT></EM> <EM>ciphertext-start</EM> <EM>ciphertext-end</EM> <EM>plaintext-start</EM> => <EM>n-bytes-consumed</EM>, <EM>n-bytes-produced</EM></TT><BR /></DIV><P>Decrypts data according to <EM>cipher</EM> from <EM>ciphertext</EM> +starting at <EM>ciphertext-start</EM> and continuing until <EM>ciphertext-end</EM>. The decrypted data is placed in <EM>plaintext</EM> +starting at <EM>plaintext-start</EM>.</P><DIV CLASS="lisp-symbol"><A NAME="encrypt-in-place"></A><TT><STRONG>encrypt-in-place</STRONG> <EM>cipher</EM> <EM>text</EM> <EM><TT>&key</TT></EM> <EM>start</EM> <EM>end</EM> => <EM>n-bytes-consumed</EM>, <EM>n-bytes-produced</EM></TT><BR /><A NAME="decrypt-in-place"></A><TT><STRONG>decrypt-in-place</STRONG> <EM>cipher</EM> <EM>text</EM> <EM><TT>&key</TT></EM> <EM>start</EM> <EM>end</EM> => <EM>n-bytes-consumed</EM>, <EM>n-bytes-produced</EM></TT><BR /></DIV><P>Encrypts or decrypts data in <EM>text</EM> between <EM>start</EM> and <EM>end</EM> "in-place" according to <EM>cipher</EM>. These functions are +shorthand for:</P><PRE>(encrypt cipher text text :plaintext-start start :plaintext-end end :ciphertext-start start) +(decrypt cipher text text :ciphertext-start start :ciphertext-end end :plaintext-start start)</PRE><TABLE CLASS="note"><TR><TD CLASS="title">Note</TD><TD CLASS="content"><A HREF="#encrypt-in-place" STYLE="symbol">encrypt-in-place</A> and <A HREF="#decrypt-in-place" STYLE="symbol">decrypt-in-place</A> do not support a <EM>handle-final-block</EM> parameter as <A HREF="#encrypt" STYLE="symbol">encrypt</A> and <A HREF="#decrypt" STYLE="symbol">decrypt</A> do. +If you need the functionality that <EM>handle-final-block</EM> provides, +then you need to use <A HREF="#encrypt" STYLE="symbol">encrypt</A> and <A HREF="#decrypt" STYLE="symbol">decrypt</A>.</TD></TR></TABLE><TABLE CLASS="note"><TR><TD CLASS="title">Note</TD><TD CLASS="content"><EM>n-bytes-consumed</EM> and <EM>n-bytes-produced</EM> may not always be +equal to the length of the data specified in the call to <A HREF="#encrypt-in-place" STYLE="symbol">encrypt-in-place</A> or <A HREF="#decrypt-in-place" STYLE="symbol">decrypt-in-place</A>. This subtlely is also +present in <A HREF="#encrypt" STYLE="symbol">encrypt</A> or <A HREF="#decrypt" STYLE="symbol">decrypt</A>.</TD></TR></TABLE><H3>Inquiry functions</H3><DIV CLASS="lisp-symbol"><A NAME="list-all-ciphers"></A><TT><STRONG>list-all-ciphers</STRONG> => <EM>list</EM></TT><BR /></DIV><P>Returns a list of cipher-names that may be validly passed to <A HREF="#make-cipher" STYLE="symbol">make-cipher</A>.</P><DIV CLASS="lisp-symbol"><A NAME="cipher-supported-p"></A><TT><STRONG>cipher-supported-p</STRONG> <EM>name</EM> => <EM>boolean</EM></TT><BR /></DIV><P>Returns T if <EM>name</EM> would be in the list returned by <A HREF="#list-all-ciphers" STYLE="symbol">list-all-ciphers</A>, NIL otherwise.</P><DIV CLASS="lisp-symbol"><A NAME="key-lengths"></A><TT><STRONG>key-lengths</STRONG> <EM>cipher</EM> => <EM>list</EM></TT><BR /></DIV><P>Return a list of valid key lengths for <EM>cipher</EM>.</P><DIV CLASS="lisp-symbol"><A NAME="block-length"></A><TT><STRONG>block-length</STRONG> <EM>cipher</EM> => <EM>number</EM></TT><BR /></DIV><P>Return the number of octets <EM>cipher</EM> processes at a time. This +function always returns 1 for stream ciphers.</P><H2>Digests</H2><P>Digest functions, also known as hash functions, produce +fixed-length output (a <EM>digest</EM> or <EM>hash</EM>) from a +variable-length message. The simplest example of a digest function is +one that adds up all the bytes in the message modulo 256. This digest +function fails one test of a cryptographically secure hash function: it +must be difficult to find a message with a given digest. It also fails +the other test: it must be difficult to find two messages with the same +digest.</P><P>Ironclad provides several cryptographically secure digest functions +and several non-cryptographically secure digest functions.</P><TABLE CLASS="note"><TR><TD CLASS="title">Note</TD><TD CLASS="content">In the functions below, messages or parts thereof are provided +as octet vectors; Ironclad has no facilities for producing digests of +strings. If you need to obtain the digest of a string, then you need to +figure out how to convert it to an octet vector first. This is a +deliberate design decision. Characters are not equivalent to bytes. +See your local Unicode guru for more details.</TD></TR></TABLE><DIV CLASS="lisp-symbol"><A NAME="make-digest"></A><TT><STRONG>make-digest</STRONG> <EM>digest-name</EM> => <EM>digester</EM></TT><BR /></DIV><P>Returns a digest object. <EM>digest-name</EM> is a keyword naming the +algorithm you wish <EM>digester</EM> to use. The algorithms you are likely +to want to use are:</P><UL><LI>MD4</LI><LI>MD5</LI><LI>SHA1</LI><LI>SHA256</LI><LI>Tiger</LI><LI>Adler32</LI><LI>CRC32</LI></UL><P>Other legitimate digest names can be found by calling <A HREF="#list-all-digests" STYLE="symbol">list-all-digests</A>. Like <A HREF="#make-cipher" STYLE="symbol">make-cipher</A>, <EM>digest-name</EM> should be +a symbol in the <TT>KEYWORD</TT> package.</P><DIV CLASS="lisp-symbol"><A NAME="update-digest"></A><TT><STRONG>update-digest</STRONG> <EM>digester</EM> <EM>thing</EM> <EM><TT>&key</TT></EM> <EM><TT>&allow-other-keys</TT></EM> => <EM>(values)</EM></TT><BR /></DIV><P>Updates the internal state of <EM>digester</EM> with the contents of <EM>thing</EM>. The exact method is determined by the type of THING.</P><P>There are several methods defined on this generic function that +take a particular digester and a <TT>(SIMPLE-ARRAY (UNSIGNED-BYTE 8) +(*))</TT> as well as the usual <EM>start</EM> and <EM>end</EM> keyword +arguments. These methods update the state of <EM>digester</EM> with the +subsequence of the array denoted by <EM>start</EM> and <EM>end</EM>. They are +note listed here because there's one method for every type of digest +that Ironclad provides, and listing them would get very tedious +for no benefit. An example should suffice.</P><PRE>(let ((digester (ironclad:make-digest :sha1)) + (array (make-array 16 :element-type '(unsigned-byte 8) :initial-element 0))) + ;; Update with 16 zeroes. + (ironclad:update-digest digester array) + ;; Update with 8 ones. + (fill array 1 :start 2 :end 10) + (ironclad:update-digest digester array :start 2 :end 10))</PRE><DIV CLASS="lisp-symbol"><A NAME="update-digest"></A><TT><STRONG>update-digest</STRONG> <EM>digester</EM> <EM>(stream stream)</EM> <EM><TT>&allow-other-keys</TT></EM> => <EM>digester</EM></TT><BR /></DIV><P>Update the internal state of <EM>digester</EM> with the contents of <EM>stream</EM>, which must respond to <TT>READ-BYTE</TT> or <TT>READ-SEQUENCE</TT> +with a <TT>(SIMPLE-ARRAY (UNSIGNED-BYTE 8) (*))</TT> and return <EM>digester</EM>. This method is implemented on top of the previous method +for sequences It differs from <A HREF="#digest-stream" STYLE="symbol">digest-stream</A>, below, in that you +may need to digest data before or after the contents of <EM>stream</EM> +(this happens, for instance, when signing the contents of some file).</P><DIV CLASS="lisp-symbol"><A NAME="produce-digest"></A><TT><STRONG>produce-digest</STRONG> <EM>digester</EM> <EM><TT>&key</TT></EM> <EM>digest-start</EM> <EM>digest</EM> => <EM>digest</EM></TT><BR /></DIV><P>Return the digest of the data processed by <EM>digester</EM> so far. +The internal state of <EM>digester</EM> is not modified; this feature makes +it possible to compute a "rolling digest" of a document.</P><P>If <EM>digest</EM> is provided, the computed digest will be placed +into <EM>digest</EM> starting at <EM>digest-start</EM>. <EM>digest</EM> must be +a <TT>(SIMPLE-ARRAY (UNSIGNED-BYTE 8) (*))</TT>. An <A HREF="#insufficient-buffer-space" STYLE="symbol">insufficient-buffer-space</A> error will be signaled if there is +insufficient space in <EM>digest</EM>.</P><H3>High-level convenience functions</H3><P>Several high-level convenience functions that encapsulate common +sequences of <A HREF="#make-digest" STYLE="symbol">make-digest</A>, <A HREF="#update-digest" STYLE="symbol">update-digest</A> and <A HREF="#produce-digest" STYLE="symbol">produce-digest</A> are provided by Ironclad as well.</P><DIV CLASS="lisp-symbol"><A NAME="digest-sequence"></A><TT><STRONG>digest-sequence</STRONG> <EM>digest-name</EM> <EM>sequence</EM> <EM><TT>&key</TT></EM> <EM>start</EM> <EM>end</EM> <EM>digest</EM> <EM>digest-start</EM> => <EM>digest</EM></TT><BR /></DIV><P>Returns the digest of the subsequence of <EM>sequence</EM> bounded by +<EM>start</EM> and <EM>end</EM>, according to <EM>digest-name</EM>. <EM>sequence</EM> must be a <TT>(SIMPLE-ARRAY (UNSIGNED-BYTE 8))</TT>. <EM>digest</EM> and <EM>digest-start</EM> are as in <A HREF="#produce-digest" STYLE="symbol">produce-digest</A>.</P><DIV CLASS="lisp-symbol"><A NAME="digest-stream"></A><TT><STRONG>digest-stream</STRONG> <EM>digest-name</EM> <EM>stream</EM> <EM><TT>&key</TT></EM> <EM>digest</EM> <EM>digest-start</EM> => <EM>digest</EM></TT><BR /></DIV><P>Returns the digest of the contents of the stream specified by <EM>stream</EM>. <TT>READ-BYTE</TT> must be a legal operation on <EM>stream</EM> +and return an <TT>(UNSIGNED-BYTE 8)</TT>. In a similar fashion, <TT>READ-SEQUENCE</TT> on <EM>stream</EM> must support reading into a <TT>(SIMPLE-ARRAY (UNSIGNED-BYTE 8))</TT>. <EM>digest</EM> and <EM>digest-start</EM> are as in <A HREF="#produce-digest" STYLE="symbol">produce-digest</A>.</P><DIV CLASS="lisp-symbol"><A NAME="digest-file"></A><TT><STRONG>digest-file</STRONG> <EM>digest-name</EM> <EM>pathname</EM> <EM><TT>&key</TT></EM> <EM>digest</EM> <EM>digest-start</EM> => <EM>digest</EM></TT><BR /></DIV><P>Returns the digest of the contents of the file named by <EM>pathname</EM>. <EM>digest</EM> and <EM>digest-start</EM> are as in <A HREF="#produce-digest" STYLE="symbol">produce-digest</A>.</P><H3>Inquiry functions</H3><DIV CLASS="lisp-symbol"><A NAME="list-all-digests"></A><TT><STRONG>list-all-digests</STRONG> => <EM>list</EM></TT><BR /></DIV><P>Returns a list whose elements may be validly passed to <A HREF="#make-digest" STYLE="symbol">make-digest</A>.</P><DIV CLASS="lisp-symbol"><A NAME="digest-supported-p"></A><TT><STRONG>digest-supported-p</STRONG> <EM>name</EM> => <EM>boolean</EM></TT><BR /></DIV><P>Returns T if <EM>name</EM> would be in the list returned by <A HREF="#list-all-digests" STYLE="symbol">list-all-digests</A>, NIL otherwise.</P><DIV CLASS="lisp-symbol"><A NAME="digest-length"></A><TT><STRONG>digest-length</STRONG> <EM>digest</EM> => <EM>number</EM></TT><BR /></DIV><P>Returns the length of the digest computed by <EM>digest</EM>, which +may be a digest-name or a digest instance.</P><H2>Message authentication codes</H2><P>A message authentication code is a cryptographic function of some +data and a user-specified key. Only a person knowing the key can +recompute the MAC for the given message. A MAC is useful where +maintaining data integrity is required, but the secrecy of the data is +not paramount.</P><P>Ironclad provides two different kinds of MACs: HMACs, specified in +<A HREF="http://www.ietf.org/rfc/rfc2109.txt">RFC 2104</A>, and CMACs, +specified in <A HREF="http://www.ietf.org/rfc/rfc4493.txt">RFC 4493</A> +and NIST document 800-38B.</P><H3>HMACs</H3><P>Instances of HMACs are constructed by specifying a secret key and a +digest-name.</P><DIV CLASS="lisp-symbol"><A NAME="make-hmac"></A><TT><STRONG>make-hmac</STRONG> <EM>key</EM> <EM>digest-name</EM> => <EM>hmac</EM></TT><BR /></DIV><P>Return an HMAC instance based on the hash function <EM>digest-name</EM> with secret key <EM>key</EM>.</P><DIV CLASS="lisp-symbol"><A NAME="update-hmac"></A><TT><STRONG>update-hmac</STRONG> <EM>hmac</EM> <EM>sequence</EM> <EM><TT>&key</TT></EM> <EM>start</EM> <EM>end</EM> => <EM>hmac</EM></TT><BR /></DIV><P>Update the internal state of <EM>hmac</EM> with the data in <EM>sequence</EM> bounded by <EM>start</EM> and <EM>end</EM>. <EM>sequence</EM> must +be a <TT>(SIMPLE-ARRAY (UNSIGNED-BYTE 8) (*))</TT>.</P><DIV CLASS="lisp-symbol"><A NAME="hmac-digest"></A><TT><STRONG>hmac-digest</STRONG> <EM>hmac</EM> => <EM>digest</EM></TT><BR /></DIV><P>Returns the MAC (<EM>digest</EM>) computed by <EM>hmac</EM> thus far. +The internal state of <EM>hmac</EM> is not modified; this feature makes it +possible to compute a "rolling MAC" of a document. The length of <EM>digest</EM> is determined by the <A HREF="#digest-length" STYLE="symbol">digest-length</A> of <EM>digest-name</EM> +passed to <A HREF="#make-hmac" STYLE="symbol">make-hmac</A> when <EM>hmac</EM> was constructed.</P><H3>CMACs</H3><P>Instances of CMACs are constructed by specifying a secret key and a +cipher-name.</P><DIV CLASS="lisp-symbol"><A NAME="make-cmac"></A><TT><STRONG>make-cmac</STRONG> <EM>key</EM> <EM>cipher-name</EM> => <EM>cmac</EM></TT><BR /></DIV><P>Return a CMAC instance based on the cipher <EM>cipher-name</EM> with +secret key <EM>key</EM>. <EM>cipher-name</EM> must have a <A HREF="#block-length" STYLE="symbol">block-length</A> +of either 8 or 16; this restriction is satisfied by most ciphers in +Ironclad with the notable exception of stream ciphers. <EM>key</EM> must +be an acceptable key for <EM>cipher-name</EM>.</P><DIV CLASS="lisp-symbol"><A NAME="update-cmac"></A><TT><STRONG>update-cmac</STRONG> <EM>cmac</EM> <EM>sequence</EM> <EM><TT>&key</TT></EM> <EM>start</EM> <EM>end</EM> => <EM>cmac</EM></TT><BR /></DIV><P>Update the internal state of <EM>cmac</EM> with the data in <EM>sequence</EM> bounded by <EM>start</EM> and <EM>end</EM>. <EM>sequence</EM> must +be a <TT>(SIMPLE-ARRAY (UNSIGNED-BYTE 8) (*))</TT>.</P><DIV CLASS="lisp-symbol"><A NAME="cmac-digest"></A><TT><STRONG>cmac-digest</STRONG> <EM>cmac</EM> => <EM>digest</EM></TT><BR /></DIV><P>Returns the MAC (<EM>digest</EM>) computed by <EM>cmac</EM> thus far. +The internal state of <EM>cmac</EM> is not modified; this feature makes it +possible to compute a "rolling MAC" of a document. The length of <EM>digest</EM> is determined by the <A HREF="#block-length" STYLE="symbol">block-length</A> of <EM>cipher-name</EM> +passed to <A HREF="#make-cmac" STYLE="symbol">make-cmac</A> when <EM>cmac</EM> was constructed.</P><H2>Public-key Operations</H2><P>Ironclad includes support for DSA signing and verification. +Support for RSA encryption and decryption is provided as well, but it is +"raw"--the various formatting schemes (e.g. PKCS-1) must be implemented +by the user at this time.</P><H3>Key construction</H3><DIV CLASS="lisp-symbol"><A NAME="make-public-key"></A><TT><STRONG>make-public-key</STRONG> <EM>kind</EM> <EM><TT>&key</TT></EM> <EM><TT>&allow-other-keys</TT></EM> => <EM>public-key</EM></TT><BR /></DIV><P>Return a public key according to <EM>kind</EM>. The <EM>&key</EM> +arguments vary according to <EM>kind</EM>. The interesting bits are in the +methods that specialize on <EM>kind</EM>, below.</P><DIV CLASS="lisp-symbol"><A NAME="make-public-key"></A><TT><STRONG>make-public-key</STRONG> <EM>(kind (eql :dsa))</EM> <EM><TT>&key</TT></EM> <EM>p</EM> <EM>q</EM> <EM>g</EM> <EM>y</EM> <EM><TT>&allow-other-keys</TT></EM> => <EM>private-key</EM></TT><BR /></DIV><P>Return a DSA public key. <EM>p</EM>, <EM>q</EM>, <EM>g</EM>, and <EM>y</EM> +are the usual parameters for DSA keys discussed in the literature.</P><DIV CLASS="lisp-symbol"><A NAME="make-private-key"></A><TT><STRONG>make-private-key</STRONG> <EM>kind</EM> <EM><TT>&key</TT></EM> <EM><TT>&allow-other-keys</TT></EM> => <EM>private-key</EM></TT><BR /></DIV><P>Return a private key according to <EM>kind</EM>. The <EM>&key</EM> +arguments vary according to <EM>kind</EM>. The interesting bits are in the +methods that specialize on <EM>kind</EM>, below.</P><DIV CLASS="lisp-symbol"><A NAME="make-private-key"></A><TT><STRONG>make-private-key</STRONG> <EM>(kind (eql :dsa))</EM> <EM><TT>&key</TT></EM> <EM>p</EM> <EM>q</EM> <EM>g</EM> <EM>y</EM> <EM>x</EM> <EM><TT>&allow-other-keys</TT></EM> => <EM>private-key</EM></TT><BR /></DIV><P>Return a DSA private key. <EM>p</EM>, <EM>q</EM>, <EM>g</EM>, <EM>y</EM>, and +<EM>x</EM> are the usual parameters for DSA keys discussed in the +literature.</P><H3>Digital signatures</H3><DIV CLASS="lisp-symbol"><A NAME="sign-message"></A><TT><STRONG>sign-message</STRONG> <EM>key</EM> <EM>message</EM> <EM><TT>&key</TT></EM> <EM>start</EM> <EM>end</EM> => <EM>signature</EM></TT><BR /></DIV><P>Return a signature of <EM>message</EM> between <EM>start</EM> and <EM>end</EM> signed with <EM>key</EM>; the class of <EM>key</EM> determines the class of +<EM>signature</EM>.</P><DIV CLASS="lisp-symbol"><A NAME="sign-message"></A><TT><STRONG>sign-message</STRONG> <EM>(key dsa-private-key)</EM> <EM>message</EM> <EM><TT>&key</TT></EM> <EM>(start 0)</EM> <EM>end</EM> => <EM>signature</EM></TT><BR /></DIV><P>This method places an additional constraint on the size of <EM>message</EM> specified by <EM>start</EM> and <EM>end</EM>: it must be exactly +20 bytes long (the length of a SHA-1 digest). <EM>signature</EM> is a <A HREF="#dsa-signature" STYLE="symbol">dsa-signature</A> object.</P><DIV CLASS="lisp-symbol"><A NAME="verify-signature"></A><TT><STRONG>verify-signature</STRONG> <EM>key</EM> <EM>message</EM> <EM>signature</EM> <EM><TT>&key</TT></EM> <EM>start</EM> <EM>end</EM> => <EM>boolean</EM></TT><BR /></DIV><P>Verify whether <EM>signature</EM> is the signature of <EM>message</EM> +between <EM>start</EM> and <EM>end</EM> using <EM>key</EM>. Return T or NIL +depending on the result of verification.</P><DIV CLASS="lisp-symbol"><A NAME="verify-signature"></A><TT><STRONG>verify-signature</STRONG> <EM>(key dsa-public-key)</EM> <EM>message</EM> <EM>(signature dsa-signature)</EM> <EM><TT>&key</TT></EM> <EM>(start 0)</EM> <EM>end</EM> => <EM>boolean</EM></TT><BR /></DIV><H4>Signature objects</H4><P>There is no one "right" way to format signatures into octet +vectors; different applications may have different requirements. <A HREF="#sign-message" STYLE="symbol">sign-message</A> therefore returns objects and lets the user determine +how to best format the values contained therein.</P><DIV CLASS="lisp-symbol"><A NAME="dsa-signature"></A><TT><STRONG>dsa-signature</STRONG></TT><BR /></DIV><P>A DSA signature object.</P><DIV CLASS="lisp-symbol"><A NAME="make-dsa-signature"></A><TT><STRONG>make-dsa-signature</STRONG> <EM>r</EM> <EM>s</EM> => <EM>signature</EM></TT><BR /></DIV><P>Returns a DSA signature with the provided <EM>r</EM> and <EM>s</EM> +values. <EM>r</EM> and <EM>s</EM> may be either integers or they may be +20-byte octet vectors.</P><DIV CLASS="lisp-symbol"><A NAME="dsa-signature-r"></A><TT><STRONG>dsa-signature-r</STRONG> <EM>dsa-signature</EM> => <EM>integer</EM></TT><BR /></DIV><P>Returns the <EM>r</EM> value of the provided DSA signature.</P><DIV CLASS="lisp-symbol"><A NAME="dsa-signature-s"></A><TT><STRONG>dsa-signature-s</STRONG> <EM>dsa-signature</EM> => <EM>integer</EM></TT><BR /></DIV><P>Returns the <EM>s</EM> value of the provided DSA signature.</P><H3>Encryption and decryption</H3><DIV CLASS="lisp-symbol"><A NAME="encrypt-message"></A><TT><STRONG>encrypt-message</STRONG> <EM>key</EM> <EM>message</EM> <EM><TT>&key</TT></EM> <EM>start</EM> <EM>end</EM> => <EM>encrypted-message</EM></TT><BR /></DIV><DIV CLASS="lisp-symbol"><A NAME="decrypt-message"></A><TT><STRONG>decrypt-message</STRONG> <EM>key</EM> <EM>message</EM> <EM><TT>&key</TT></EM> <EM>start</EM> <EM>end</EM> => <EM>decrypted-message</EM></TT><BR /></DIV><H2>Gray Streams</H2><P>Ironclad includes support for several convenient stream +abstractions based on Gray streams. Gray streams support in Ironclad is +included for SBCL, CMUCL, OpenMCL, and Allegro.</P><H3>Octet streams</H3><P>Octet streams are very similar to Common Lisp's <A HREF="#string-stream" STYLE="symbol">string-stream</A>, +except they deal in octets instead of characters.</P><DIV CLASS="lisp-symbol"><A NAME="make-octet-input-stream"></A><TT><STRONG>make-octet-input-stream</STRONG> <EM>buffer</EM> <EM><TT>&optional</TT></EM> <EM>start</EM> <EM>end</EM> => <EM>octet-input-stream</EM></TT><BR /></DIV><P>As <A HREF="#make-string-input-stream" STYLE="symbol">make-string-input-stream</A>, only with octets instead of characters.</P><DIV CLASS="lisp-symbol"><A NAME="make-octet-output-stream"></A><TT><STRONG>make-octet-output-stream</STRONG> => <EM>octet-output-stream</EM></TT><BR /></DIV><P>As <A HREF="#make-string-output-stream" STYLE="symbol">make-string-output-stream</A>, only with octets instead of characters.</P><DIV CLASS="lisp-symbol"><A NAME="get-output-stream-octets"></A><TT><STRONG>get-output-stream-octets</STRONG> <EM>stream</EM> => <EM>octet-vector</EM></TT><BR /></DIV><P>As <A HREF="#get-output-stream-string" STYLE="symbol">get-output-stream-string</A>, only with an octet output-steam +instead of a string output-stream.</P><H3>Digest streams</H3><P>Digest streams compute a digest of the data written to them +according to a specific digest algorithm.</P><P>Example:</P><PRE>(defun frobbing-function (stream) + ;; We want to compute a digest of the data being written to STREAM + ;; without involving our callees in the process. + (let* ((digesting-stream (crypto:make-digesting-stream :sha1)) + (stream (make-broadcast-stream stream digesting-stream))) + ;; Feed data to STREAM. + (frob-guts stream) + ;; Do something with the digest computed. + (... (crypto:produce-digest digesting-stream) ...) + ...))</PRE><DIV CLASS="lisp-symbol"><A NAME="make-digesting-stream"></A><TT><STRONG>make-digesting-stream</STRONG> <EM>digest</EM> => <EM>stream</EM></TT><BR /></DIV><P>Make a stream that computes a digest of the data written to it +according to the algorithm <EM>digest-name</EM>. <A HREF="#produce-digest" STYLE="symbol">produce-digest</A> may +be used to obtain a digest of all the data written to the stream.</P><TABLE CLASS="note"><TR><TD CLASS="title">Note</TD><TD CLASS="content">Calling <A HREF="#produce-digest" STYLE="symbol">produce-digest</A> on a digest stream does not alter +the internal state of the digest.</TD></TR></TABLE><H2>Utility Functions</H2><DIV CLASS="lisp-symbol"><A NAME="ub16ref/le"></A><TT><STRONG>ub16ref/le</STRONG> <EM>buffer</EM> <EM>index</EM> => <EM>value</EM></TT><BR /><A NAME="ub32ref/le"></A><TT><STRONG>ub32ref/le</STRONG> <EM>buffer</EM> <EM>index</EM> => <EM>value</EM></TT><BR /><A NAME="ub64ref/le"></A><TT><STRONG>ub64ref/le</STRONG> <EM>buffer</EM> <EM>index</EM> => <EM>value</EM></TT><BR /></DIV><P>This family of functions accesses an unsigned 16-bit, 32-bit or +64-bit value stored in little-endian order starting at <EM>index</EM> in <EM>array</EM>. <EM>array</EM> must be a <TT>(SIMPLE-ARRAY (UNSIGNED-BYTE 8) +(*))</TT>. These functions are SETFable.</P><DIV CLASS="lisp-symbol"><A NAME="ub16ref/be"></A><TT><STRONG>ub16ref/be</STRONG> <EM>buffer</EM> <EM>index</EM> => <EM>value</EM></TT><BR /><A NAME="ub32ref/be"></A><TT><STRONG>ub32ref/be</STRONG> <EM>buffer</EM> <EM>index</EM> => <EM>value</EM></TT><BR /><A NAME="ub64ref/be"></A><TT><STRONG>ub64ref/be</STRONG> <EM>buffer</EM> <EM>index</EM> => <EM>value</EM></TT><BR /></DIV><P>As the above, only the value is stored in big-endian order.</P><DIV CLASS="lisp-symbol"><A NAME="byte-array-to-hex-string"></A><TT><STRONG>byte-array-to-hex-string</STRONG> <EM>vector</EM> <EM><TT>&key</TT></EM> <EM>start</EM> <EM>end</EM> <EM>element-type</EM> => <EM>string</EM></TT><BR /><A NAME="ascii-string-to-byte-array"></A><TT><STRONG>ascii-string-to-byte-array</STRONG> <EM>string</EM> <EM><TT>&key</TT></EM> <EM>start</EM> <EM>end</EM> => <EM>vector</EM></TT><BR /></DIV><P><TT>byte-array-to-hex-string</TT> converts the bytes of <EM>vector</EM> +between <EM>start</EM> and <EM>end</EM> into a hexadecimal string. It is +useful for converting digests to a more readable form. <EM>element-type</EM> indicates the element-type of the returned string.</P><P><TT>ascii-string-to-byte-array</TT> is provided as a quick and dirty way +to convert a string to a byte array suitable for feeding to <A HREF="#update-digest" STYLE="symbol">update-digest</A> or <A HREF="#encrypt" STYLE="symbol">encrypt</A>. Care should be taken to ensure that +the provided string is actually an ASCII string. <EM>start</EM> and <EM>end</EM> have their usual interpretations.</P><DIV CLASS="lisp-symbol"><A NAME="octets-to-integer"></A><TT><STRONG>octets-to-integer</STRONG> <EM>octet-vec</EM> <EM><TT>&key</TT></EM> <EM>start</EM> <EM>end</EM> <EM>big-endian</EM> <EM>n-bits</EM> => <EM>number</EM></TT><BR /><A NAME="integer-to-octets"></A><TT><STRONG>integer-to-octets</STRONG> <EM>bignum</EM> <EM><TT>&key</TT></EM> <EM>n-bits</EM> <EM>big-endian</EM> => <EM>vector</EM></TT><BR /></DIV><P><TT>octets-to-integer</TT> converts the bytes of <EM>octet-vec</EM> between +<EM>start</EM> and <EM>end</EM> to an integer as though the bytes denoted a +number in base 256. <EM>big-endian</EM> is a boolean indicating whether +the bytes are to be read in big-endian or little-endian order. <EM>n-bits</EM> specifies how many bits should be considered as significant +in the resulting number.</P><P><TT>integer-to-octets</TT> is the reverse operation.</P><DIV CLASS="lisp-symbol"><A NAME="expt-mod"></A><TT><STRONG>expt-mod</STRONG> <EM>n</EM> <EM>exponent</EM> <EM>modulus</EM> => <EM>number</EM></TT><BR /></DIV><P>Raises <EM>n</EM> to the <EM>exponent</EM> power modulo <EM>modulus</EM> in +a more efficient fashion than <TT>(MOD (EXPT N EXPONENT) MODULUS)</TT>.</P><H2>Conditions</H2><DIV CLASS="lisp-symbol"><A NAME="ironclad-error"></A><TT><STRONG>ironclad-error</STRONG></TT><BR /></DIV><P>All errors signaled by Ironclad are of this type. This type is a +direct subtype of <TT>SIMPLE-ERROR</TT> without any extra slots or +options.</P><DIV CLASS="lisp-symbol"><A NAME="initialization-vector-not-supplied"></A><TT><STRONG>initialization-vector-not-supplied</STRONG></TT><BR /></DIV><P>This error is signaled by <A HREF="#make-cipher" STYLE="symbol">make-cipher</A> when an initialization +vector is not provided and the requested mode requires an initialization +vector.</P><DIV CLASS="lisp-symbol"><A NAME="invalid-initialization-vector"></A><TT><STRONG>invalid-initialization-vector</STRONG></TT><BR /></DIV><P>This error is signaled when an invalid initialization vector is +supplied to <A HREF="#make-cipher" STYLE="symbol">make-cipher</A> (e.g. when the length of the initialization +vector does not match the block length of the cipher).</P><DIV CLASS="lisp-symbol"><A NAME="invalid-key-length"></A><TT><STRONG>invalid-key-length</STRONG></TT><BR /></DIV><P>This error is signaled when the key provided to <A HREF="#make-cipher" STYLE="symbol">make-cipher</A> is +not of an acceptable length for the requested cipher.</P><DIV CLASS="lisp-symbol"><A NAME="unsupported-cipher"></A><TT><STRONG>unsupported-cipher</STRONG></TT><BR /></DIV><P>This error is signaled when the <EM>cipher-name</EM> provided to <A HREF="#make-cipher" STYLE="symbol">make-cipher</A> is not <A HREF="#cipher-supported-p" STYLE="symbol">cipher-supported-p</A>.</P><DIV CLASS="lisp-symbol"><A NAME="unsupported-mode"></A><TT><STRONG>unsupported-mode</STRONG></TT><BR /></DIV><P>This error is signaled when the <EM>mode</EM> provided to <A HREF="#make-cipher" STYLE="symbol">make-cipher</A> is not <A HREF="#mode-supported-p" STYLE="symbol">mode-supported-p</A>.</P><DIV CLASS="lisp-symbol"><A NAME="unsupported-digest"></A><TT><STRONG>unsupported-digest</STRONG></TT><BR /></DIV><P>This error is signaled when the <EM>digest-name</EM> provided to <A HREF="#make-digest" STYLE="symbol">make-digest</A> is not <A HREF="#digest-supported-p" STYLE="symbol">digest-supported-p</A>.</P><DIV CLASS="lisp-symbol"><A NAME="insufficient-buffer-space"></A><TT><STRONG>insufficient-buffer-space</STRONG></TT><BR /></DIV><P>This error is signaled when Ironclad needs to stuff some data into a +buffer (e.g. when the user provides <EM>digest</EM> to <A HREF="#produce-digest" STYLE="symbol">produce-digest</A>) and +there is insufficient space.</P><DIV CLASS="lisp-symbol"><A NAME="key-not-supplied"></A><TT><STRONG>key-not-supplied</STRONG></TT><BR /></DIV><P>This error is signaled when a <TT>:KEY</TT> argument is not provided +to <A HREF="#make-cipher" STYLE="symbol">make-cipher</A>.</P></BODY></HTML>
\ No newline at end of file diff --git a/doc/index.html b/doc/index.html new file mode 100644 index 0000000..807db3d --- /dev/null +++ b/doc/index.html @@ -0,0 +1,182 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" + "http://www.w3.org/TR/html4/strict.dtd"> +<HTML><HEAD><TITLE>Ironclad</TITLE><LINK TYPE="text/css" TITLE="default" REL="stylesheet" MEDIA="screen" HREF="style.css" /></HEAD><BODY><H1>Ironclad</H1><P>Ironclad is a cryptography library written entirely in Common +Lisp. It includes support for several popular <A HREF="#ciphers">ciphers</A>, <A HREF="#digests">digests</A>, and <A HREF="#macs">MACs</A>. Rudimentary support for <A HREF="#public-key">public-key +cryptography</A> is included. For several implementations that support +Gray Streams, <A HREF="#gray-streams">support</A> is included for +convenient stream wrappers.</P><P>Ironclad was written primarily by Nathan Froyd (froydnj@gmail.com).</P><H2>Installation</H2><P>Ironclad can be downloaded at <A HREF="http://www.method-combination.net/lisp/files/ironclad.tar.gz">http://www.method-combination.net/lisp/files/ironclad.tar.gz</A>. +The latest version is 0.27.</P><P>It comes with an ASDF system definition, so <TT>(ASDF:OOS +'ASDF:LOAD-OP :IRONCLAD)</TT> should be all that you need to get started. +The testsuite can be run by substituting <TT>ASDF:TEST-OP</TT> for <TT>ASDF:LOAD-OP</TT> in the form above.</P><P>Ironclad has been tested in the following implementations:</P><UL><LI>SBCL x86/linux (primary development platform)</LI><LI>SBCL x86-64/solaris</LI><LI>CMUCL x86/linux</LI><LI>ABCL with Sun's 1.5.0 JVM</LI><LI>Lispworks 5.0.1 x86/linux</LI><LI>Allegro 8.0 x86/linux</LI><LI>Allegro 8.1 x86/linux</LI><LI>Allegro 8.1 x86-64/linux</LI><LI>Allegro 8.1 sparc/solaris</LI><LI>CLISP 2.41 x86/linux</LI><LI>CLISP 2.44 x86/cygwin</LI><LI>Clozure Common Lisp 1.2 x86-64/Linux</LI></UL><P>All included tests should pass successfully. If you use a platform +not listed above, please send your platform information to the author so +that he can add it to the above list. If the tests do not all pass, you +have found a bug; please report it.</P><H2>License</H2><P>Ironclad is released under a MIT-like license; you can do pretty +much anything you want to with the code except claim that you wrote +it.</P><H2 ID="ciphers">Ciphers</H2><DIV CLASS="lisp-symbol"><A NAME="make-cipher"></A><TT><STRONG>make-cipher</STRONG> <EM>name</EM> <EM><TT>&key</TT></EM> <EM>key</EM> <EM>mode</EM> <EM>initialization-vector</EM> <EM>padding</EM> => <EM>cipher</EM></TT><BR /></DIV><P>Return a cipher object suitable for use for both encryption and +decryption.</P><P><EM>name</EM> denotes the encryption algorithm to use. <A HREF="#list-all-ciphers" STYLE="symbol">list-all-ciphers</A> will tell you the names of all supported ciphers; +the short list of ones you are likely to be interested in is:</P><UL><LI>AES</LI><LI>DES</LI><LI>3DES</LI><LI>Blowfish</LI><LI>Twofish</LI><LI>RC5</LI><LI>RC6</LI><LI>Arcfour (RC4)</LI></UL><P><EM>name</EM> can be a symbol in the <TT>KEYWORD</TT> package or the <TT>IRONCLAD</TT> package; <TT>:AES</TT> for AES, <TT>IRONCLAD:ARCFOUR</TT> for +RC4, and so forth.</P><P><EM>mode</EM> describes the mode of operation for the cipher. Stream +ciphers such as Arcfour can operate in only one mode, <TT>stream</TT>. +Block ciphers such as AES and DES can operate in several different +modes:</P><UL><LI>ECB</LI><LI>CBC</LI><LI>OFB</LI><LI>CFB (note that Ironclad's CFB mode is 'n'-bit CFB, where 'n' is +the <A HREF="#block-length" STYLE="symbol">block-length</A> of the cipher)</LI><LI>CFB8 (this seems to be the mode other crypto packages call +'CFB')</LI><LI>CTR</LI></UL><P><EM>mode</EM> should be a symbol in the <TT>KEYWORD</TT> or <TT>IRONCLAD</TT> +packages; <TT>:STREAM</TT>, <TT>IRONCLAD:OFB</TT>, and so forth. An error +will be signaled if <EM>mode</EM> is not appropriate for the cipher <EM>name</EM>.</P><P><EM>initialization-vector</EM> (IV) should be supplied only if <EM>mode</EM> +requires one. <EM>initialization-vector</EM> should be a <TT>(VECTOR +(UNSIGNED-BYTE 8))</TT>. The supplied IV should be the same length as the +<A HREF="#block-length" STYLE="symbol">block-length</A> of <EM>name</EM>.</P><P><EM>key</EM> is, of course, the key for the cipher. <EM>key</EM> should be +a <TT>(VECTOR (UNSIGNED-BYTE 8))</TT>.</P><P>If <EM>padding</EM> is supplied, the specified padding method will be +used by <A HREF="#encrypt" STYLE="symbol">encrypt</A> and <A HREF="#decrypt" STYLE="symbol">decrypt</A> to handle short blocks when the <TT>:HANDLE-FINAL-BLOCK</TT> argument is supplied. Depending on the mode +specified, <EM>padding</EM> may be ignored (e.g. OFB and CFB modes do not +care about short blocks; neither do stream ciphers).</P><TABLE CLASS="note"><TR><TD CLASS="title">Note</TD><TD CLASS="content"><EM>padding</EM> is currently ignored in all modes (and, by extension, +so is <TT>:HANDLE-FINAL-BLOCK</TT>). This oversight is expected to be +corrected in a future release.</TD></TR></TABLE><DIV CLASS="lisp-symbol"><A NAME="encrypt"></A><TT><STRONG>encrypt</STRONG> <EM>cipher</EM> <EM>plaintext</EM> <EM>ciphertext</EM> <EM><TT>&key</TT></EM> <EM>plaintext-start</EM> <EM>plaintext-end</EM> <EM>ciphertext-start</EM> <EM>plaintext-start</EM> <EM>ciphertext-start</EM> => <EM>n-bytes-consumed</EM>, <EM>n-bytes-produced</EM></TT><BR /></DIV><P>Encrypts data according to <EM>cipher</EM> from <EM>plaintext</EM> +starting at <EM>plaintext-start</EM> and continuing until <EM>plaintext-end</EM>. The encrypted data is placed in <EM>ciphertext</EM> starting at <EM>ciphertext-start</EM>.</P><DIV CLASS="lisp-symbol"><A NAME="decrypt"></A><TT><STRONG>decrypt</STRONG> <EM>cipher</EM> <EM>ciphertext</EM> <EM>plaintext</EM> <EM><TT>&key</TT></EM> <EM>ciphertext-start</EM> <EM>ciphertext-end</EM> <EM>plaintext-start</EM> <EM>ciphertext-start</EM> <EM>plaintext-start</EM> => <EM>n-bytes-consumed</EM>, <EM>n-bytes-produced</EM></TT><BR /></DIV><P>Decrypts data according to <EM>cipher</EM> from <EM>ciphertext</EM> +starting at <EM>ciphertext-start</EM> and continuing until <EM>ciphertext-end</EM>. The decrypted data is placed in <EM>plaintext</EM> +starting at <EM>plaintext-start</EM>.</P><DIV CLASS="lisp-symbol"><A NAME="encrypt-in-place"></A><TT><STRONG>encrypt-in-place</STRONG> <EM>cipher</EM> <EM>text</EM> <EM><TT>&key</TT></EM> <EM>start</EM> <EM>end</EM> => <EM>n-bytes-consumed</EM>, <EM>n-bytes-produced</EM></TT><BR /><A NAME="decrypt-in-place"></A><TT><STRONG>decrypt-in-place</STRONG> <EM>cipher</EM> <EM>text</EM> <EM><TT>&key</TT></EM> <EM>start</EM> <EM>end</EM> => <EM>n-bytes-consumed</EM>, <EM>n-bytes-produced</EM></TT><BR /></DIV><P>Encrypts or decrypts data in <EM>text</EM> between <EM>start</EM> and <EM>end</EM> "in-place" according to <EM>cipher</EM>. These functions are +shorthand for:</P><PRE>(encrypt cipher text text :plaintext-start start :plaintext-end end :ciphertext-start start) +(decrypt cipher text text :ciphertext-start start :ciphertext-end end :plaintext-start start)</PRE><TABLE CLASS="note"><TR><TD CLASS="title">Note</TD><TD CLASS="content"><A HREF="#encrypt-in-place" STYLE="symbol">encrypt-in-place</A> and <A HREF="#decrypt-in-place" STYLE="symbol">decrypt-in-place</A> do not support a <EM>handle-final-block</EM> parameter as <A HREF="#encrypt" STYLE="symbol">encrypt</A> and <A HREF="#decrypt" STYLE="symbol">decrypt</A> do. +If you need the functionality that <EM>handle-final-block</EM> provides, +then you need to use <A HREF="#encrypt" STYLE="symbol">encrypt</A> and <A HREF="#decrypt" STYLE="symbol">decrypt</A>.</TD></TR></TABLE><TABLE CLASS="note"><TR><TD CLASS="title">Note</TD><TD CLASS="content"><EM>n-bytes-consumed</EM> and <EM>n-bytes-produced</EM> may not always be +equal to the length of the data specified in the call to <A HREF="#encrypt-in-place" STYLE="symbol">encrypt-in-place</A> or <A HREF="#decrypt-in-place" STYLE="symbol">decrypt-in-place</A>. This subtlely is also +present in <A HREF="#encrypt" STYLE="symbol">encrypt</A> or <A HREF="#decrypt" STYLE="symbol">decrypt</A>.</TD></TR></TABLE><H3>Inquiry functions</H3><DIV CLASS="lisp-symbol"><A NAME="list-all-ciphers"></A><TT><STRONG>list-all-ciphers</STRONG> => <EM>list</EM></TT><BR /></DIV><P>Returns a list of cipher-names that may be validly passed to <A HREF="#make-cipher" STYLE="symbol">make-cipher</A>.</P><DIV CLASS="lisp-symbol"><A NAME="cipher-supported-p"></A><TT><STRONG>cipher-supported-p</STRONG> <EM>name</EM> => <EM>boolean</EM></TT><BR /></DIV><P>Returns T if <EM>name</EM> would be in the list returned by <A HREF="#list-all-ciphers" STYLE="symbol">list-all-ciphers</A>, NIL otherwise.</P><DIV CLASS="lisp-symbol"><A NAME="key-lengths"></A><TT><STRONG>key-lengths</STRONG> <EM>cipher</EM> => <EM>list</EM></TT><BR /></DIV><P>Return a list of valid key lengths for <EM>cipher</EM>.</P><DIV CLASS="lisp-symbol"><A NAME="block-length"></A><TT><STRONG>block-length</STRONG> <EM>cipher</EM> => <EM>number</EM></TT><BR /></DIV><P>Return the number of octets <EM>cipher</EM> processes at a time. This +function always returns 1 for stream ciphers.</P><H2 ID="digests">Digests</H2><P>Digest functions, also known as hash functions, produce +fixed-length output (a <EM>digest</EM> or <EM>hash</EM>) from a +variable-length message. The simplest example of a digest function is +one that adds up all the bytes in the message modulo 256. This digest +function fails one test of a cryptographically secure hash function: it +must be difficult to find a message with a given digest. It also fails +the other test: it must be difficult to find two messages with the same +digest.</P><P>Ironclad provides several cryptographically secure digest functions +and several non-cryptographically secure digest functions.</P><TABLE CLASS="note"><TR><TD CLASS="title">Note</TD><TD CLASS="content">In the functions below, messages or parts thereof are provided +as octet vectors; Ironclad has no facilities for producing digests of +strings. If you need to obtain the digest of a string, then you need to +figure out how to convert it to an octet vector first. This is a +deliberate design decision. Characters are not equivalent to bytes. +See your local Unicode guru for more details.</TD></TR></TABLE><DIV CLASS="lisp-symbol"><A NAME="make-digest"></A><TT><STRONG>make-digest</STRONG> <EM>digest-name</EM> => <EM>digester</EM></TT><BR /></DIV><P>Returns a digest object. <EM>digest-name</EM> is a keyword naming the +algorithm you wish <EM>digester</EM> to use. The algorithms you are likely +to want to use are:</P><UL><LI>MD4</LI><LI>MD5</LI><LI>SHA1</LI><LI>SHA256</LI><LI>Tiger</LI><LI>Adler32</LI><LI>CRC32</LI></UL><P>Other legitimate digest names can be found by calling <A HREF="#list-all-digests" STYLE="symbol">list-all-digests</A>. Like <A HREF="#make-cipher" STYLE="symbol">make-cipher</A>, <EM>digest-name</EM> should be +a symbol in the <TT>KEYWORD</TT> or <TT>IRONCLAD</TT> packages.</P><DIV CLASS="lisp-symbol"><A NAME="update-digest"></A><TT><STRONG>update-digest</STRONG> <EM>digester</EM> <EM>thing</EM> <EM><TT>&key</TT></EM> <EM><TT>&allow-other-keys</TT></EM> => <EM>(values)</EM></TT><BR /></DIV><P>Updates the internal state of <EM>digester</EM> with the contents of <EM>thing</EM>. The exact method is determined by the type of THING.</P><P>There are several methods defined on this generic function that +take a particular digester and a <TT>(SIMPLE-ARRAY (UNSIGNED-BYTE 8) +(*))</TT> as well as the usual <EM>start</EM> and <EM>end</EM> keyword +arguments. These methods update the state of <EM>digester</EM> with the +subsequence of the array denoted by <EM>start</EM> and <EM>end</EM>. They are +not listed here because there's one method for every type of digest +that Ironclad provides, and listing them would get very tedious +for no benefit. An example should suffice.</P><PRE>(let ((digester (ironclad:make-digest :sha1)) + (array (make-array 16 :element-type '(unsigned-byte 8) :initial-element 0))) + ;; Update with 16 zeroes. + (ironclad:update-digest digester array) + ;; Update with 8 ones. + (fill array 1 :start 2 :end 10) + (ironclad:update-digest digester array :start 2 :end 10))</PRE><DIV CLASS="lisp-symbol"><A NAME="update-digest"></A><TT><STRONG>update-digest</STRONG> <EM>digester</EM> <EM>(stream stream)</EM> <EM><TT>&key</TT></EM> <EM>buffer</EM> <EM>(start 0)</EM> <EM>end</EM> <EM><TT>&allow-other-keys</TT></EM> => <EM>digester</EM></TT><BR /></DIV><P>Update the internal state of <EM>digester</EM> with the contents of <EM>stream</EM>, which must respond to <TT>READ-BYTE</TT> or <TT>READ-SEQUENCE</TT> +with a <TT>(SIMPLE-ARRAY (UNSIGNED-BYTE 8) (*))</TT> and return <EM>digester</EM>. It differs from <A HREF="#digest-stream" STYLE="symbol">digest-stream</A>, below, in that you +may need to digest data before or after the contents of <EM>stream</EM> +(this happens, for instance, when signing the contents of some file).</P><DIV CLASS="lisp-symbol"><A NAME="produce-digest"></A><TT><STRONG>produce-digest</STRONG> <EM>digester</EM> <EM><TT>&key</TT></EM> <EM>digest</EM> <EM>digest-start</EM> => <EM>digest</EM></TT><BR /></DIV><P>Return the digest of the data processed by <EM>digester</EM> so far. +The internal state of <EM>digester</EM> is modified; if you wish to retain +a copy of the digest, you must call <A HREF="#copy-digest" STYLE="symbol">copy-digest</A>.</P><P>If <EM>digest</EM> is provided, the computed digest will be placed +into <EM>digest</EM> starting at <EM>digest-start</EM>. <EM>digest</EM> must be +a <TT>(SIMPLE-ARRAY (UNSIGNED-BYTE 8) (*))</TT>. An <A HREF="#insufficient-buffer-space" STYLE="symbol">insufficient-buffer-space</A> error will be signaled if there is +insufficient space in <EM>digest</EM>.</P><H3>High-level convenience functions</H3><P>Several high-level convenience functions that encapsulate common +sequences of <A HREF="#make-digest" STYLE="symbol">make-digest</A>, <A HREF="#update-digest" STYLE="symbol">update-digest</A> and <A HREF="#produce-digest" STYLE="symbol">produce-digest</A> are provided by Ironclad as well. They come in two flavors: the first +takes a digest name as would be provided to <A HREF="#make-digest" STYLE="symbol">make-digest</A>. The +second way to call these functions is to provide an actual digest object +as the first argument. So one can say:</P><PRE>(ironclad:digest-sequence :md5 *buffer*)</PRE><P>or, equivalently:</P><PRE>(let ((digester (make-digest :md5))) + (ironclad:digest-sequence digester *buffer*))</PRE><P>The second form comes in handy if you plan on <A HREF="#digest-tips">reusing the digest object</A>.</P><DIV CLASS="lisp-symbol"><A NAME="digest-sequence"></A><TT><STRONG>digest-sequence</STRONG> <EM>digest-spec</EM> <EM>sequence</EM> <EM><TT>&rest</TT></EM> <EM>args</EM> <EM><TT>&key</TT></EM> <EM>start</EM> <EM>end</EM> <EM>digest</EM> <EM>digest-start</EM> => <EM>digest</EM></TT><BR /></DIV><P>Returns the digest of the subsequence of <EM>sequence</EM> bounded by +<EM>start</EM> and <EM>end</EM>, according to <EM>digest-name</EM>. <EM>sequence</EM> must be a <TT>(SIMPLE-ARRAY (UNSIGNED-BYTE 8))</TT>. <EM>digest</EM> and <EM>digest-start</EM> are as in <A HREF="#produce-digest" STYLE="symbol">produce-digest</A>.</P><DIV CLASS="lisp-symbol"><A NAME="digest-stream"></A><TT><STRONG>digest-stream</STRONG> <EM>digest-spec</EM> <EM>stream</EM> <EM><TT>&rest</TT></EM> <EM>args</EM> <EM><TT>&key</TT></EM> <EM>buffer</EM> <EM>start</EM> <EM>end</EM> <EM>digest</EM> <EM>digest-start</EM> => <EM>digest</EM></TT><BR /></DIV><P>Returns the digest of the contents of the stream specified by <EM>stream</EM>. <TT>READ-BYTE</TT> must be a legal operation on <EM>stream</EM> +and return an <TT>(UNSIGNED-BYTE 8)</TT>. In a similar fashion, <TT>READ-SEQUENCE</TT> on <EM>stream</EM> must support reading into a <TT>(SIMPLE-ARRAY (UNSIGNED-BYTE 8))</TT>. <EM>digest</EM> and <EM>digest-start</EM> are as in <A HREF="#produce-digest" STYLE="symbol">produce-digest</A>.</P><P>If <EM>buffer</EM> is provided, it must be a <TT>(SIMPLE-ARRAY +(UNSIGNED-BYTE 8) (*))</TT>; the portion of <EM>buffer</EM> between <EM>start</EM> and <EM>end</EM> will be used to read the data from the stream.</P><DIV CLASS="lisp-symbol"><A NAME="digest-file"></A><TT><STRONG>digest-file</STRONG> <EM>digest-spec</EM> <EM>pathname</EM> <EM><TT>&rest</TT></EM> <EM>args</EM> <EM><TT>&key</TT></EM> <EM>buffer</EM> <EM>start</EM> <EM>end</EM> <EM>digest</EM> <EM>digest-start</EM> => <EM>digest</EM></TT><BR /></DIV><P>Returns the digest of the contents of the file named by <EM>pathname</EM>. <EM>digest</EM> and <EM>digest-start</EM> are as in <A HREF="#produce-digest" STYLE="symbol">produce-digest</A>.</P><P>If <EM>buffer</EM> is provided, it must be a <TT>(SIMPLE-ARRAY +(UNSIGNED-BYTE 8) (*))</TT>; the portion of <EM>buffer</EM> between <EM>start</EM> and <EM>end</EM> will be used to read the data from the stream.</P><H3>Inquiry functions</H3><DIV CLASS="lisp-symbol"><A NAME="list-all-digests"></A><TT><STRONG>list-all-digests</STRONG> => <EM>list</EM></TT><BR /></DIV><P>Returns a list whose elements may be validly passed to <A HREF="#make-digest" STYLE="symbol">make-digest</A>.</P><DIV CLASS="lisp-symbol"><A NAME="digest-supported-p"></A><TT><STRONG>digest-supported-p</STRONG> <EM>name</EM> => <EM>boolean</EM></TT><BR /></DIV><P>Returns T if <EM>name</EM> would be in the list returned by <A HREF="#list-all-digests" STYLE="symbol">list-all-digests</A>, NIL otherwise.</P><DIV CLASS="lisp-symbol"><A NAME="digest-length"></A><TT><STRONG>digest-length</STRONG> <EM>digest</EM> => <EM>number</EM></TT><BR /></DIV><P>Returns the length of the digest computed by <EM>digest</EM>, which +may be a digest-name or a digest instance.</P><H3 ID="digest-tips">Miscellaneous</H3><P>Ironclad digests are CLOS objects; the interesting thing about this +for most purposes is that functions like <TT>REINITIALIZE-INSTANCE</TT> are +supported. This means one can write a fairly efficient clone of the <TT>md5sum</TT> program like so:</P><PRE>(defun digest-sum-files (digest &rest files) + (unless files + (error "no files given to digest")) + (loop with buffer = (make-array 8192 :element-type '(unsigned-byte 8)) + with digest = (make-array (ironclad:digest-length digest) + :element-type '(unsigned-byte 8)) + for file in files + for digester = (ironclad:make-digest digest) + then (reinitialize-instance digester) + do (ironclad:digest-file digester file :buffer buffer :digest digest) + (format t "~A ~A~%" (file-namestring file) + (ironclad:byte-array-to-hex-string digest))))</PRE><H2 ID="macs">Message authentication codes</H2><P>A message authentication code is a cryptographic function of some +data and a user-specified key. Only a person knowing the key can +recompute the MAC for the given message. A MAC is useful where +maintaining data integrity is required, but the secrecy of the data is +not paramount.</P><P>Ironclad provides two different kinds of MACs: HMACs, specified in +<A HREF="http://www.ietf.org/rfc/rfc2109.txt">RFC 2104</A>, and CMACs, +specified in <A HREF="http://www.ietf.org/rfc/rfc4493.txt">RFC 4493</A> +and NIST document 800-38B.</P><H3>HMACs</H3><P>Instances of HMACs are constructed by specifying a secret key and a +digest-name.</P><DIV CLASS="lisp-symbol"><A NAME="make-hmac"></A><TT><STRONG>make-hmac</STRONG> <EM>key</EM> <EM>digest-name</EM> => <EM>hmac</EM></TT><BR /></DIV><P>Return an HMAC instance based on the hash function <EM>digest-name</EM> with secret key <EM>key</EM>.</P><P>The returned object supports <TT>REINITIALIZE-INSTANCE</TT>:</P><DIV CLASS="lisp-symbol"><A NAME="reinitialize-instance"></A><TT><STRONG>reinitialize-instance</STRONG> <EM>(mac hmac)</EM> <EM><TT>&rest</TT></EM> <EM>initargs</EM> <EM><TT>&key</TT></EM> <EM>key</EM> <EM><TT>&allow-other-keys</TT></EM> => <EM>hmac</EM></TT><BR /></DIV><P>The <TT>:KEY</TT> argument is the secret key, as provided to <A HREF="#make-hmac" STYLE="symbol">make-hmac</A>.</P><DIV CLASS="lisp-symbol"><A NAME="update-hmac"></A><TT><STRONG>update-hmac</STRONG> <EM>hmac</EM> <EM>sequence</EM> <EM><TT>&key</TT></EM> <EM>start</EM> <EM>end</EM> => <EM>hmac</EM></TT><BR /></DIV><P>Update the internal state of <EM>hmac</EM> with the data in <EM>sequence</EM> bounded by <EM>start</EM> and <EM>end</EM>. <EM>sequence</EM> must +be a <TT>(SIMPLE-ARRAY (UNSIGNED-BYTE 8) (*))</TT>.</P><DIV CLASS="lisp-symbol"><A NAME="hmac-digest"></A><TT><STRONG>hmac-digest</STRONG> <EM>hmac</EM> <EM><TT>&key</TT></EM> <EM>buffer</EM> <EM>buffer-start</EM> => <EM>digest</EM></TT><BR /></DIV><P>Returns the MAC (<EM>digest</EM>) computed by <EM>hmac</EM> thus far. +The internal state of <EM>hmac</EM> is not modified; this feature makes it +possible to compute a "rolling MAC" of a document. The length of <EM>digest</EM> is determined by the <A HREF="#digest-length" STYLE="symbol">digest-length</A> of <EM>digest-name</EM> +passed to <A HREF="#make-hmac" STYLE="symbol">make-hmac</A> when <EM>hmac</EM> was constructed.</P><P>If <EM>buffer</EM> is provided, the computed MAC will be placed into <EM>buffer</EM> starting at <EM>buffer-start</EM>. <EM>buffer</EM> must be a <TT>(SIMPLE-ARRAY (UNSIGNED-BYTE 8) (*))</TT>. An <A HREF="#insufficient-buffer-space" STYLE="symbol">insufficient-buffer-space</A> error will be signaled if there is +insufficient space in <EM>buffer</EM>.</P><H3>CMACs</H3><P>Instances of CMACs are constructed by specifying a secret key and a +cipher-name.</P><DIV CLASS="lisp-symbol"><A NAME="make-cmac"></A><TT><STRONG>make-cmac</STRONG> <EM>key</EM> <EM>cipher-name</EM> => <EM>cmac</EM></TT><BR /></DIV><P>Return a CMAC instance based on the cipher <EM>cipher-name</EM> with +secret key <EM>key</EM>. <EM>cipher-name</EM> must have a <A HREF="#block-length" STYLE="symbol">block-length</A> +of either 8 or 16; this restriction is satisfied by most ciphers in +Ironclad with the notable exception of stream ciphers. <EM>key</EM> must +be an acceptable key for <EM>cipher-name</EM>.</P><DIV CLASS="lisp-symbol"><A NAME="update-cmac"></A><TT><STRONG>update-cmac</STRONG> <EM>cmac</EM> <EM>sequence</EM> <EM><TT>&key</TT></EM> <EM>start</EM> <EM>end</EM> => <EM>cmac</EM></TT><BR /></DIV><P>Update the internal state of <EM>cmac</EM> with the data in <EM>sequence</EM> bounded by <EM>start</EM> and <EM>end</EM>. <EM>sequence</EM> must +be a <TT>(SIMPLE-ARRAY (UNSIGNED-BYTE 8) (*))</TT>.</P><DIV CLASS="lisp-symbol"><A NAME="cmac-digest"></A><TT><STRONG>cmac-digest</STRONG> <EM>cmac</EM> => <EM>digest</EM></TT><BR /></DIV><P>Returns the MAC (<EM>digest</EM>) computed by <EM>cmac</EM> thus far. +The internal state of <EM>cmac</EM> is not modified; this feature makes it +possible to compute a "rolling MAC" of a document. The length of <EM>digest</EM> is determined by the <A HREF="#block-length" STYLE="symbol">block-length</A> of <EM>cipher-name</EM> +passed to <A HREF="#make-cmac" STYLE="symbol">make-cmac</A> when <EM>cmac</EM> was constructed.</P><H2 ID="public-key">Public-key Operations</H2><P>Ironclad includes support for DSA signing and verification. +Support for RSA encryption and decryption is provided as well, but it is +"raw"--the various formatting schemes (e.g. PKCS-1) must be implemented +by the user at this time.</P><H3>Key construction</H3><DIV CLASS="lisp-symbol"><A NAME="make-public-key"></A><TT><STRONG>make-public-key</STRONG> <EM>kind</EM> <EM><TT>&key</TT></EM> <EM><TT>&allow-other-keys</TT></EM> => <EM>public-key</EM></TT><BR /></DIV><P>Return a public key according to <EM>kind</EM>. The <EM>&key</EM> +arguments vary according to <EM>kind</EM>. The interesting bits are in the +methods that specialize on <EM>kind</EM>, below.</P><DIV CLASS="lisp-symbol"><A NAME="make-public-key"></A><TT><STRONG>make-public-key</STRONG> <EM>(kind (eql :dsa))</EM> <EM><TT>&key</TT></EM> <EM>p</EM> <EM>q</EM> <EM>g</EM> <EM>y</EM> <EM><TT>&allow-other-keys</TT></EM> => <EM>private-key</EM></TT><BR /></DIV><P>Return a DSA public key. <EM>p</EM>, <EM>q</EM>, <EM>g</EM>, and <EM>y</EM> +are the usual parameters for DSA keys discussed in the literature.</P><DIV CLASS="lisp-symbol"><A NAME="make-private-key"></A><TT><STRONG>make-private-key</STRONG> <EM>kind</EM> <EM><TT>&key</TT></EM> <EM><TT>&allow-other-keys</TT></EM> => <EM>private-key</EM></TT><BR /></DIV><P>Return a private key according to <EM>kind</EM>. The <EM>&key</EM> +arguments vary according to <EM>kind</EM>. The interesting bits are in the +methods that specialize on <EM>kind</EM>, below.</P><DIV CLASS="lisp-symbol"><A NAME="make-private-key"></A><TT><STRONG>make-private-key</STRONG> <EM>(kind (eql :dsa))</EM> <EM><TT>&key</TT></EM> <EM>p</EM> <EM>q</EM> <EM>g</EM> <EM>y</EM> <EM>x</EM> <EM><TT>&allow-other-keys</TT></EM> => <EM>private-key</EM></TT><BR /></DIV><P>Return a DSA private key. <EM>p</EM>, <EM>q</EM>, <EM>g</EM>, <EM>y</EM>, and +<EM>x</EM> are the usual parameters for DSA keys discussed in the +literature.</P><H3>Digital signatures</H3><DIV CLASS="lisp-symbol"><A NAME="sign-message"></A><TT><STRONG>sign-message</STRONG> <EM>key</EM> <EM>message</EM> <EM><TT>&key</TT></EM> <EM>start</EM> <EM>end</EM> => <EM>signature</EM></TT><BR /></DIV><P>Return a signature of <EM>message</EM> between <EM>start</EM> and <EM>end</EM> signed with <EM>key</EM>; the class of <EM>key</EM> determines the class of +<EM>signature</EM>.</P><DIV CLASS="lisp-symbol"><A NAME="sign-message"></A><TT><STRONG>sign-message</STRONG> <EM>(key dsa-private-key)</EM> <EM>message</EM> <EM><TT>&key</TT></EM> <EM>(start 0)</EM> <EM>end</EM> => <EM>signature</EM></TT><BR /></DIV><P>This method places an additional constraint on the size of <EM>message</EM> specified by <EM>start</EM> and <EM>end</EM>: it must be exactly +20 bytes long (the length of a SHA-1 digest). <EM>signature</EM> is a <A HREF="#dsa-signature" STYLE="symbol">dsa-signature</A> object.</P><DIV CLASS="lisp-symbol"><A NAME="verify-signature"></A><TT><STRONG>verify-signature</STRONG> <EM>key</EM> <EM>message</EM> <EM>signature</EM> <EM><TT>&key</TT></EM> <EM>start</EM> <EM>end</EM> => <EM>boolean</EM></TT><BR /></DIV><P>Verify whether <EM>signature</EM> is the signature of <EM>message</EM> +between <EM>start</EM> and <EM>end</EM> using <EM>key</EM>. Return T or NIL +depending on the result of verification.</P><DIV CLASS="lisp-symbol"><A NAME="verify-signature"></A><TT><STRONG>verify-signature</STRONG> <EM>(key dsa-public-key)</EM> <EM>message</EM> <EM>(signature dsa-signature)</EM> <EM><TT>&key</TT></EM> <EM>(start 0)</EM> <EM>end</EM> => <EM>boolean</EM></TT><BR /></DIV><H4>Signature objects</H4><P>There is no one "right" way to format signatures into octet +vectors; different applications may have different requirements. <A HREF="#sign-message" STYLE="symbol">sign-message</A> therefore returns objects and lets the user determine +how to best format the values contained therein.</P><DIV CLASS="lisp-symbol"><A NAME="dsa-signature"></A><TT><STRONG>dsa-signature</STRONG></TT><BR /></DIV><P>A DSA signature object.</P><DIV CLASS="lisp-symbol"><A NAME="make-dsa-signature"></A><TT><STRONG>make-dsa-signature</STRONG> <EM>r</EM> <EM>s</EM> => <EM>signature</EM></TT><BR /></DIV><P>Returns a DSA signature with the provided <EM>r</EM> and <EM>s</EM> +values. <EM>r</EM> and <EM>s</EM> may be either integers or they may be +20-byte octet vectors.</P><DIV CLASS="lisp-symbol"><A NAME="dsa-signature-r"></A><TT><STRONG>dsa-signature-r</STRONG> <EM>object</EM> => <EM>integer</EM></TT><BR /></DIV><P>Returns the <EM>r</EM> value of the provided DSA signature.</P><DIV CLASS="lisp-symbol"><A NAME="dsa-signature-s"></A><TT><STRONG>dsa-signature-s</STRONG> <EM>object</EM> => <EM>integer</EM></TT><BR /></DIV><P>Returns the <EM>s</EM> value of the provided DSA signature.</P><H3>Encryption and decryption</H3><DIV CLASS="lisp-symbol"><A NAME="encrypt-message"></A><TT><STRONG>encrypt-message</STRONG> <EM>key</EM> <EM>message</EM> <EM><TT>&key</TT></EM> <EM>start</EM> <EM>end</EM> <EM>end</EM> <EM>start</EM> => <EM>encrypted-message</EM></TT><BR /></DIV><DIV CLASS="lisp-symbol"><A NAME="decrypt-message"></A><TT><STRONG>decrypt-message</STRONG> <EM>key</EM> <EM>message</EM> <EM><TT>&key</TT></EM> <EM>start</EM> <EM>end</EM> <EM>start</EM> => <EM>decrypted-message</EM></TT><BR /></DIV><H2 ID="gray-streams">Gray Streams</H2><P>Ironclad includes support for several convenient stream +abstractions based on Gray streams. Gray streams support in Ironclad is +included for SBCL, CMUCL, OpenMCL, Lispworks, and Allegro.</P><H3>Octet streams</H3><P>Octet streams are very similar to Common Lisp's <A HREF="#string-stream" STYLE="symbol">string-stream</A>, +except they deal in octets instead of characters.</P><DIV CLASS="lisp-symbol"><A NAME="make-octet-input-stream"></A><TT><STRONG>make-octet-input-stream</STRONG> <EM>buffer</EM> <EM><TT>&optional</TT></EM> <EM>start</EM> <EM>end</EM> => <EM>octet-input-stream</EM></TT><BR /></DIV><P>As <A HREF="#make-string-input-stream" STYLE="symbol">make-string-input-stream</A>, only with octets instead of characters.</P><DIV CLASS="lisp-symbol"><A NAME="make-octet-output-stream"></A><TT><STRONG>make-octet-output-stream</STRONG> => <EM>octet-output-stream</EM></TT><BR /></DIV><P>As <A HREF="#make-string-output-stream" STYLE="symbol">make-string-output-stream</A>, only with octets instead of characters.</P><DIV CLASS="lisp-symbol"><A NAME="get-output-stream-octets"></A><TT><STRONG>get-output-stream-octets</STRONG> <EM>stream</EM> => <EM>octet-vector</EM></TT><BR /></DIV><P>As <A HREF="#get-output-stream-string" STYLE="symbol">get-output-stream-string</A>, only with an octet output-steam +instead of a string output-stream.</P><H3>Digest streams</H3><P>Digest streams compute a digest of the data written to them +according to a specific digest algorithm.</P><P>Example:</P><PRE>(defun frobbing-function (stream) + ;; We want to compute a digest of the data being written to STREAM + ;; without involving our callees in the process. + (let* ((digesting-stream (crypto:make-digesting-stream :sha1)) + (stream (make-broadcast-stream stream digesting-stream))) + ;; Feed data to STREAM. + (frob-guts stream) + ;; Do something with the digest computed. + (... (crypto:produce-digest digesting-stream) ...) + ...))</PRE><DIV CLASS="lisp-symbol"><A NAME="make-digesting-stream"></A><TT><STRONG>make-digesting-stream</STRONG> <EM>digest</EM> => <EM>stream</EM></TT><BR /></DIV><P>Make a stream that computes a digest of the data written to it +according to the algorithm <EM>digest-name</EM>. <A HREF="#produce-digest" STYLE="symbol">produce-digest</A> may +be used to obtain a digest of all the data written to the stream.</P><TABLE CLASS="note"><TR><TD CLASS="title">Note</TD><TD CLASS="content">Calling <A HREF="#produce-digest" STYLE="symbol">produce-digest</A> on a digest stream does not alter +the internal state of the digest.</TD></TR></TABLE><H2>Utility Functions</H2><DIV CLASS="lisp-symbol"><A NAME="ub16ref/le"></A><TT><STRONG>ub16ref/le</STRONG> <EM>buffer</EM> <EM>index</EM> => <EM>value</EM></TT><BR /><A NAME="ub32ref/le"></A><TT><STRONG>ub32ref/le</STRONG> <EM>buffer</EM> <EM>index</EM> => <EM>value</EM></TT><BR /><A NAME="ub64ref/le"></A><TT><STRONG>ub64ref/le</STRONG> <EM>buffer</EM> <EM>index</EM> => <EM>value</EM></TT><BR /></DIV><P>This family of functions accesses an unsigned 16-bit, 32-bit or +64-bit value stored in little-endian order starting at <EM>index</EM> in <EM>array</EM>. <EM>array</EM> must be a <TT>(SIMPLE-ARRAY (UNSIGNED-BYTE 8) +(*))</TT>. These functions are SETFable.</P><DIV CLASS="lisp-symbol"><A NAME="ub16ref/be"></A><TT><STRONG>ub16ref/be</STRONG> <EM>buffer</EM> <EM>index</EM> => <EM>value</EM></TT><BR /><A NAME="ub32ref/be"></A><TT><STRONG>ub32ref/be</STRONG> <EM>buffer</EM> <EM>index</EM> => <EM>value</EM></TT><BR /><A NAME="ub64ref/be"></A><TT><STRONG>ub64ref/be</STRONG> <EM>buffer</EM> <EM>index</EM> => <EM>value</EM></TT><BR /></DIV><P>As the above, only the value is stored in big-endian order.</P><DIV CLASS="lisp-symbol"><A NAME="byte-array-to-hex-string"></A><TT><STRONG>byte-array-to-hex-string</STRONG> <EM>vector</EM> <EM><TT>&key</TT></EM> <EM>start</EM> <EM>end</EM> <EM>element-type</EM> => <EM>string</EM></TT><BR /><A NAME="ascii-string-to-byte-array"></A><TT><STRONG>ascii-string-to-byte-array</STRONG> <EM>string</EM> <EM><TT>&key</TT></EM> <EM>start</EM> <EM>end</EM> => <EM>vector</EM></TT><BR /></DIV><P><TT>byte-array-to-hex-string</TT> converts the bytes of <EM>vector</EM> +between <EM>start</EM> and <EM>end</EM> into a hexadecimal string. It is +useful for converting digests to a more readable form. <EM>element-type</EM> indicates the element-type of the returned string.</P><P><TT>ascii-string-to-byte-array</TT> is provided as a quick and dirty way +to convert a string to a byte array suitable for feeding to <A HREF="#update-digest" STYLE="symbol">update-digest</A> or <A HREF="#encrypt" STYLE="symbol">encrypt</A>. Care should be taken to ensure that +the provided string is actually an ASCII string. <EM>start</EM> and <EM>end</EM> have their usual interpretations.</P><DIV CLASS="lisp-symbol"><A NAME="octets-to-integer"></A><TT><STRONG>octets-to-integer</STRONG> <EM>octet-vec</EM> <EM><TT>&key</TT></EM> <EM>start</EM> <EM>end</EM> <EM>big-endian</EM> <EM>n-bits</EM> => <EM>number</EM></TT><BR /><A NAME="integer-to-octets"></A><TT><STRONG>integer-to-octets</STRONG> <EM>bignum</EM> <EM><TT>&key</TT></EM> <EM>n-bits</EM> <EM>big-endian</EM> => <EM>vector</EM></TT><BR /></DIV><P><TT>octets-to-integer</TT> converts the bytes of <EM>octet-vec</EM> between +<EM>start</EM> and <EM>end</EM> to an integer as though the bytes denoted a +number in base 256. <EM>big-endian</EM> is a boolean indicating whether +the bytes are to be read in big-endian or little-endian order. <EM>n-bits</EM> specifies how many bits should be considered as significant +in the resulting number.</P><P><TT>integer-to-octets</TT> is the reverse operation.</P><DIV CLASS="lisp-symbol"><A NAME="expt-mod"></A><TT><STRONG>expt-mod</STRONG> => <EM>number</EM></TT><BR /></DIV><P>Raises <EM>n</EM> to the <EM>exponent</EM> power modulo <EM>modulus</EM> in +a more efficient fashion than <TT>(MOD (EXPT N EXPONENT) MODULUS)</TT>.</P><H2>Conditions</H2><DIV CLASS="lisp-symbol"><A NAME="ironclad-error"></A><TT><STRONG>ironclad-error</STRONG></TT><BR /></DIV><P>All errors signaled by Ironclad are of this type. This type is a +direct subtype of <TT>SIMPLE-ERROR</TT> without any extra slots or +options.</P><DIV CLASS="lisp-symbol"><A NAME="initialization-vector-not-supplied"></A><TT><STRONG>initialization-vector-not-supplied</STRONG></TT><BR /></DIV><P>This error is signaled by <A HREF="#make-cipher" STYLE="symbol">make-cipher</A> when an initialization +vector is not provided and the requested mode requires an initialization +vector.</P><DIV CLASS="lisp-symbol"><A NAME="invalid-initialization-vector"></A><TT><STRONG>invalid-initialization-vector</STRONG></TT><BR /></DIV><P>This error is signaled when an invalid initialization vector is +supplied to <A HREF="#make-cipher" STYLE="symbol">make-cipher</A> (e.g. when the length of the initialization +vector does not match the block length of the cipher).</P><DIV CLASS="lisp-symbol"><A NAME="invalid-key-length"></A><TT><STRONG>invalid-key-length</STRONG></TT><BR /></DIV><P>This error is signaled when the key provided to <A HREF="#make-cipher" STYLE="symbol">make-cipher</A> is +not of an acceptable length for the requested cipher.</P><DIV CLASS="lisp-symbol"><A NAME="unsupported-cipher"></A><TT><STRONG>unsupported-cipher</STRONG></TT><BR /></DIV><P>This error is signaled when the <EM>cipher-name</EM> provided to <A HREF="#make-cipher" STYLE="symbol">make-cipher</A> is not <A HREF="#cipher-supported-p" STYLE="symbol">cipher-supported-p</A>.</P><DIV CLASS="lisp-symbol"><A NAME="unsupported-mode"></A><TT><STRONG>unsupported-mode</STRONG></TT><BR /></DIV><P>This error is signaled when the <EM>mode</EM> provided to <A HREF="#make-cipher" STYLE="symbol">make-cipher</A> is not <A HREF="#mode-supported-p" STYLE="symbol">mode-supported-p</A>.</P><DIV CLASS="lisp-symbol"><A NAME="unsupported-digest"></A><TT><STRONG>unsupported-digest</STRONG></TT><BR /></DIV><P>This error is signaled when the <EM>digest-name</EM> provided to <A HREF="#make-digest" STYLE="symbol">make-digest</A> is not <A HREF="#digest-supported-p" STYLE="symbol">digest-supported-p</A>.</P><DIV CLASS="lisp-symbol"><A NAME="insufficient-buffer-space"></A><TT><STRONG>insufficient-buffer-space</STRONG></TT><BR /></DIV><P>This error is signaled when Ironclad needs to stuff some data into a +buffer (e.g. when the user provides <EM>digest</EM> to <A HREF="#produce-digest" STYLE="symbol">produce-digest</A>) and +there is insufficient space.</P><DIV CLASS="lisp-symbol"><A NAME="key-not-supplied"></A><TT><STRONG>key-not-supplied</STRONG></TT><BR /></DIV><P>This error is signaled when a <TT>:KEY</TT> argument is not provided +to <A HREF="#make-cipher" STYLE="symbol">make-cipher</A>.</P></BODY></HTML>
\ No newline at end of file diff --git a/doc/ironclad-doc.txt b/doc/ironclad-doc.txt new file mode 100644 index 0000000..cac2062 --- /dev/null +++ b/doc/ironclad-doc.txt @@ -0,0 +1,658 @@ +(:author "Nathan Froyd" + :email "froydnj@gmail.com" + :package "Ironclad" + :cl-package "IRONCLAD" + :version #.(asdf:component-version (asdf:find-system :ironclad)) + :homepage "http://www.method-combination.net/lisp/ironclad/" + :download "http://www.method-combination.net/lisp/files/ironclad.tar.gz") + +(:h1 ${package}) + +(:p ${package} " is a cryptography library written entirely in Common +Lisp. It includes support for several popular " (:xref "ciphers" +"ciphers") ", " (:xref "digests" "digests") ", and " (:xref "macs" +"MACs") ". Rudimentary support for " (:xref "public-key" "public-key +cryptography") " is included. For several implementations that support +Gray Streams, " (:xref "gray-streams" "support") " is included for +convenient stream wrappers.") + +(:p ${package} " was written primarily by " ${author} " (" ${email} ").") + +(:h2 "Installation") + +(:p ${package} " can be downloaded at " (:url ${download} ${download}) ". +The latest version is " ${version} ".") + +(:p "It comes with an ASDF system definition, so " `(ASDF:OOS +'ASDF:LOAD-OP :IRONCLAD)` " should be all that you need to get started. +The testsuite can be run by substituting " `ASDF:TEST-OP` " for " +`ASDF:LOAD-OP` " in the form above.") + +(:p ${package} " has been tested in the following implementations:") + +(:ul +(:li "SBCL x86/linux (primary development platform)") +(:li "SBCL x86-64/solaris") +(:li "CMUCL x86/linux") +(:li "ABCL with Sun's 1.5.0 JVM") +(:li "Lispworks 5.0.1 x86/linux") +(:li "Allegro 8.0 x86/linux") +(:li "Allegro 8.1 x86/linux") +(:li "Allegro 8.1 x86-64/linux") +(:li "Allegro 8.1 sparc/solaris") +(:li "CLISP 2.41 x86/linux") +(:li "CLISP 2.44 x86/cygwin") +(:li "Clozure Common Lisp 1.2 x86-64/Linux")) + +(:p "All included tests should pass successfully. If you use a platform +not listed above, please send your platform information to the author so +that he can add it to the above list. If the tests do not all pass, you +have found a bug; please report it.") + +(:h2 "License") + +(:p ${package} " is released under a MIT-like license; you can do pretty +much anything you want to with the code except claim that you wrote +it.") + +((:h2 id "ciphers") "Ciphers") + +(:describe :function (ironclad:make-cipher cipher)) + +(:p "Return a cipher object suitable for use for both encryption and +decryption.") + +(:p 'name' " denotes the encryption algorithm to use. " +@list-all-ciphers " will tell you the names of all supported ciphers; +the short list of ones you are likely to be interested in is:") + +(:ul +(:li "AES") +(:li "DES") +(:li "3DES") +(:li "Blowfish") +(:li "Twofish") +(:li "RC5") +(:li "RC6") +(:li "Arcfour (RC4)")) + +(:p 'name' " can be a symbol in the " `KEYWORD` " package or the " +`IRONCLAD` " package; " `:AES` " for AES, " `IRONCLAD:ARCFOUR` " for +RC4, and so forth.") + +(:p 'mode' " describes the mode of operation for the cipher. Stream +ciphers such as Arcfour can operate in only one mode, " `stream` ". +Block ciphers such as AES and DES can operate in several different +modes:") + +(:ul +(:li "ECB") +(:li "CBC") +(:li "OFB") +(:li "CFB (note that Ironclad's CFB mode is 'n'-bit CFB, where 'n' is +the " @block-length " of the cipher)") +(:li "CFB8 (this seems to be the mode other crypto packages call +'CFB')") +(:li "CTR")) + +(:p 'mode' " should be a symbol in the " `KEYWORD` " or " `IRONCLAD` " +packages; " `:STREAM` ", " `IRONCLAD:OFB` ", and so forth. An error +will be signaled if " 'mode' " is not appropriate for the cipher " +'name' ".") + +(:p 'initialization-vector' " (IV) should be supplied only if " 'mode' " +requires one. " 'initialization-vector' " should be a " `(VECTOR +(UNSIGNED-BYTE 8))` ". The supplied IV should be the same length as the +" @block-length " of " 'name' ".") + +(:p 'key' " is, of course, the key for the cipher. " 'key' " should be +a " `(VECTOR (UNSIGNED-BYTE 8))` ".") + +(:p "If " 'padding' " is supplied, the specified padding method will be +used by " @encrypt " and " @decrypt " to handle short blocks when the " +`:HANDLE-FINAL-BLOCK` " argument is supplied. Depending on the mode +specified, " 'padding' " may be ignored (e.g. OFB and CFB modes do not +care about short blocks; neither do stream ciphers).") + +(:note 'padding' " is currently ignored in all modes (and, by extension, +so is " `:HANDLE-FINAL-BLOCK` "). This oversight is expected to be +corrected in a future release.") + +(:describe :function (ironclad:encrypt (values n-bytes-consumed n-bytes-produced))) + +(:p "Encrypts data according to " 'cipher' " from " 'plaintext' " +starting at " 'plaintext-start' " and continuing until " +'plaintext-end' ". The encrypted data is placed in " +'ciphertext' " starting at " 'ciphertext-start' ".") + +(:describe :function (ironclad:decrypt (values n-bytes-consumed n-bytes-produced))) + +(:p "Decrypts data according to " 'cipher' " from " 'ciphertext' " +starting at " 'ciphertext-start' " and continuing until " +'ciphertext-end' ". The decrypted data is placed in " 'plaintext' " +starting at " 'plaintext-start' ".") + +(:describe :function (ironclad:encrypt-in-place (values n-bytes-consumed n-bytes-produced)) + (ironclad:decrypt-in-place (values n-bytes-consumed n-bytes-produced))) + +(:p "Encrypts or decrypts data in " 'text' " between " 'start' " and " +'end' " \"in-place\" according to " 'cipher' ". These functions are +shorthand for:") + +(:pre "(encrypt cipher text text :plaintext-start start :plaintext-end end :ciphertext-start start) +(decrypt cipher text text :ciphertext-start start :ciphertext-end end :plaintext-start start)") + +(:note @encrypt-in-place " and " @decrypt-in-place " do not support a " +'handle-final-block' " parameter as " @encrypt " and " @decrypt " do. +If you need the functionality that " 'handle-final-block' " provides, +then you need to use " @encrypt " and " @decrypt ".") + +(:note 'n-bytes-consumed' " and " 'n-bytes-produced' " may not always be +equal to the length of the data specified in the call to " +@encrypt-in-place " or " @decrypt-in-place ". This subtlely is also +present in " @encrypt " or " @decrypt ".") + +(:h3 "Inquiry functions") + +(:describe :function (ironclad:list-all-ciphers list)) + +(:p "Returns a list of cipher-names that may be validly passed to " +@make-cipher ".") + +(:describe :function (ironclad:cipher-supported-p boolean)) + +(:p "Returns T if " 'name' " would be in the list returned by " +@list-all-ciphers ", NIL otherwise.") + +(:describe :function (ironclad:key-lengths list)) + +(:p "Return a list of valid key lengths for " 'cipher' ".") + +(:describe :function (ironclad:block-length number)) + +(:p "Return the number of octets " 'cipher' " processes at a time. This +function always returns 1 for stream ciphers.") + +((:h2 id "digests") "Digests") + +(:p "Digest functions, also known as hash functions, produce +fixed-length output (a " 'digest' " or " 'hash' ") from a +variable-length message. The simplest example of a digest function is +one that adds up all the bytes in the message modulo 256. This digest +function fails one test of a cryptographically secure hash function: it +must be difficult to find a message with a given digest. It also fails +the other test: it must be difficult to find two messages with the same +digest.") + +(:p "Ironclad provides several cryptographically secure digest functions +and several non-cryptographically secure digest functions.") + +(:note "In the functions below, messages or parts thereof are provided +as octet vectors; Ironclad has no facilities for producing digests of +strings. If you need to obtain the digest of a string, then you need to +figure out how to convert it to an octet vector first. This is a +deliberate design decision. Characters are not equivalent to bytes. +See your local Unicode guru for more details.") + +(:describe :function (ironclad:make-digest digester)) + +(:p "Returns a digest object. " 'digest-name' " is a keyword naming the +algorithm you wish " 'digester' " to use. The algorithms you are likely +to want to use are:") + +(:ul +(:li "MD4") +(:li "MD5") +(:li "SHA1") +(:li "SHA256") +(:li "Tiger") +(:li "Adler32") +(:li "CRC32")) + +(:p "Other legitimate digest names can be found by calling " +@list-all-digests ". Like " @make-cipher ", " 'digest-name' " should be +a symbol in the " `KEYWORD` " or " `IRONCLAD` " packages.") + +(:describe :generic-function (ironclad:update-digest (values))) + +(:p "Updates the internal state of " 'digester' " with the contents of " +'thing' ". The exact method is determined by the type of THING.") + +(:p "There are several methods defined on this generic function that +take a particular digester and a " `(SIMPLE-ARRAY (UNSIGNED-BYTE 8) +(*))` " as well as the usual " 'start' " and " 'end' " keyword +arguments. These methods update the state of " 'digester' " with the +subsequence of the array denoted by " 'start' " and " 'end' ". They are +not listed here because there's one method for every type of digest +that " ${package} " provides, and listing them would get very tedious +for no benefit. An example should suffice.") + +(:pre +"(let ((digester (ironclad:make-digest :sha1)) + (array (make-array 16 :element-type '(unsigned-byte 8) :initial-element 0))) + ;; Update with 16 zeroes. + (ironclad:update-digest digester array) + ;; Update with 8 ones. + (fill array 1 :start 2 :end 10) + (ironclad:update-digest digester array :start 2 :end 10))") + +(:describe :method (ironclad:update-digest (t stream) digester)) + +(:p "Update the internal state of " 'digester' " with the contents of " +'stream' ", which must respond to " `READ-BYTE` " or " `READ-SEQUENCE` " +with a " `(SIMPLE-ARRAY (UNSIGNED-BYTE 8) (*))` " and return " +'digester' ". It differs from " @digest-stream ", below, in that you +may need to digest data before or after the contents of " 'stream' " +(this happens, for instance, when signing the contents of some file).") + +(:describe :generic-function (ironclad:produce-digest digest)) + +(:p "Return the digest of the data processed by " 'digester' " so far. +The internal state of " 'digester' " is modified; if you wish to retain +a copy of the digest, you must call " @copy-digest ".") + +(:p "If " 'digest' " is provided, the computed digest will be placed +into " 'digest' " starting at " 'digest-start' ". " 'digest' " must be +a " `(SIMPLE-ARRAY (UNSIGNED-BYTE 8) (*))` ". An " +@insufficient-buffer-space " error will be signaled if there is +insufficient space in " 'digest' ".") + +(:h3 "High-level convenience functions") + +(:p "Several high-level convenience functions that encapsulate common +sequences of " @make-digest ", " @update-digest " and " @produce-digest +" are provided by Ironclad as well. They come in two flavors: the first +takes a digest name as would be provided to " @make-digest ". The +second way to call these functions is to provide an actual digest object +as the first argument. So one can say:") + +(:pre "(ironclad:digest-sequence :md5 *buffer*)") + +(:p "or, equivalently:") + +(:pre +"(let ((digester (make-digest :md5))) + (ironclad:digest-sequence digester *buffer*))") + +(:p "The second form comes in handy if you plan on " (:xref +"digest-tips" "reusing the digest object") ".") + +(:describe :generic-function (ironclad:digest-sequence digest)) + +(:p "Returns the digest of the subsequence of " 'sequence' " bounded by +" 'start' " and " 'end' ", according to " 'digest-name' ". " 'sequence' +" must be a " `(SIMPLE-ARRAY (UNSIGNED-BYTE 8))` ". " 'digest' " and " +'digest-start' " are as in " @produce-digest ".") + +(:describe :generic-function (ironclad:digest-stream digest)) + +(:p "Returns the digest of the contents of the stream specified by " +'stream' ". " `READ-BYTE` " must be a legal operation on " 'stream' " +and return an " `(UNSIGNED-BYTE 8)` ". In a similar fashion, " +`READ-SEQUENCE` " on " 'stream' " must support reading into a " +`(SIMPLE-ARRAY (UNSIGNED-BYTE 8))` ". " 'digest' " and " 'digest-start' +" are as in " @produce-digest ".") + +(:p "If " 'buffer' " is provided, it must be a " `(SIMPLE-ARRAY +(UNSIGNED-BYTE 8) (*))` "; the portion of " 'buffer' " between " 'start' +" and " 'end' " will be used to read the data from the stream.") + +(:describe :generic-function (ironclad:digest-file digest)) + +(:p "Returns the digest of the contents of the file named by " +'pathname' ". " 'digest' " and " 'digest-start' " are as in " +@produce-digest ".") + +(:p "If " 'buffer' " is provided, it must be a " `(SIMPLE-ARRAY +(UNSIGNED-BYTE 8) (*))` "; the portion of " 'buffer' " between " 'start' +" and " 'end' " will be used to read the data from the stream.") + +(:h3 "Inquiry functions") + +(:describe :function (ironclad:list-all-digests list)) + +(:p "Returns a list whose elements may be validly passed to " @make-digest ".") + +(:describe :function (ironclad:digest-supported-p boolean)) + +(:p "Returns T if " 'name' " would be in the list returned by " +@list-all-digests ", NIL otherwise.") + +(:describe :function (ironclad:digest-length number)) + +(:p "Returns the length of the digest computed by " 'digest' ", which +may be a digest-name or a digest instance.") + +((:h3 id "digest-tips") "Miscellaneous") + +(:p "Ironclad digests are CLOS objects; the interesting thing about this +for most purposes is that functions like " `REINITIALIZE-INSTANCE` " are +supported. This means one can write a fairly efficient clone of the " +`md5sum` " program like so:") + +(:pre +"(defun digest-sum-files (digest &rest files) + (unless files + (error \"no files given to digest\")) + (loop with buffer = (make-array 8192 :element-type '(unsigned-byte 8)) + with digest = (make-array (ironclad:digest-length digest) + :element-type '(unsigned-byte 8)) + for file in files + for digester = (ironclad:make-digest digest) + then (reinitialize-instance digester) + do (ironclad:digest-file digester file :buffer buffer :digest digest) + (format t \"~A ~A~%\" (file-namestring file) + (ironclad:byte-array-to-hex-string digest))))") + +((:h2 id "macs") "Message authentication codes") + +(:p "A message authentication code is a cryptographic function of some +data and a user-specified key. Only a person knowing the key can +recompute the MAC for the given message. A MAC is useful where +maintaining data integrity is required, but the secrecy of the data is +not paramount.") + +(:p "Ironclad provides two different kinds of MACs: HMACs, specified in +" (:url "http://www.ietf.org/rfc/rfc2109.txt" "RFC 2104") ", and CMACs, +specified in " (:url "http://www.ietf.org/rfc/rfc4493.txt" "RFC 4493") " +and NIST document 800-38B.") + +(:h3 "HMACs") + +(:p "Instances of HMACs are constructed by specifying a secret key and a +digest-name.") + +(:describe :function (ironclad:make-hmac hmac)) + +(:p "Return an HMAC instance based on the hash function " 'digest-name' +" with secret key " 'key' ".") + +(:p "The returned object supports " `REINITIALIZE-INSTANCE` ":") + +(:describe :method (cl:reinitialize-instance (ironclad::hmac) hmac)) + +(:p "The " `:KEY` " argument is the secret key, as provided to " +@make-hmac ".") + +(:describe :function (ironclad:update-hmac hmac)) + +(:p "Update the internal state of " 'hmac' " with the data in " +'sequence' " bounded by " 'start' " and " 'end' ". " 'sequence' " must +be a " `(SIMPLE-ARRAY (UNSIGNED-BYTE 8) (*))` ".") + +(:describe :function (ironclad:hmac-digest digest)) + +(:p "Returns the MAC (" 'digest' ") computed by " 'hmac' " thus far. +The internal state of " 'hmac' " is not modified; this feature makes it +possible to compute a \"rolling MAC\" of a document. The length of " +'digest' " is determined by the " @digest-length " of " 'digest-name' " +passed to " @make-hmac " when " 'hmac' " was constructed.") + +(:p "If " 'buffer' " is provided, the computed MAC will be placed into " +'buffer' " starting at " 'buffer-start' ". " 'buffer' " must be a " +`(SIMPLE-ARRAY (UNSIGNED-BYTE 8) (*))` ". An " +@insufficient-buffer-space " error will be signaled if there is +insufficient space in " 'buffer' ".") + +(:h3 "CMACs") + +(:p "Instances of CMACs are constructed by specifying a secret key and a +cipher-name.") + +(:describe :function (ironclad:make-cmac cmac)) + +(:p "Return a CMAC instance based on the cipher " 'cipher-name' " with +secret key " 'key' ". " 'cipher-name' " must have a " @block-length " +of either 8 or 16; this restriction is satisfied by most ciphers in +Ironclad with the notable exception of stream ciphers. " 'key' " must +be an acceptable key for " 'cipher-name' ".") + +(:describe :function (ironclad:update-cmac cmac)) + +(:p "Update the internal state of " 'cmac' " with the data in " +'sequence' " bounded by " 'start' " and " 'end' ". " 'sequence' " must +be a " `(SIMPLE-ARRAY (UNSIGNED-BYTE 8) (*))` ".") + +(:describe :function (ironclad:cmac-digest digest)) + +(:p "Returns the MAC (" 'digest' ") computed by " 'cmac' " thus far. +The internal state of " 'cmac' " is not modified; this feature makes it +possible to compute a \"rolling MAC\" of a document. The length of " +'digest' " is determined by the " @block-length " of " 'cipher-name' " +passed to " @make-cmac " when " 'cmac' " was constructed.") + +((:h2 id "public-key") "Public-key Operations") + +(:p "Ironclad includes support for DSA signing and verification. +Support for RSA encryption and decryption is provided as well, but it is +\"raw\"--the various formatting schemes (e.g. PKCS-1) must be implemented +by the user at this time.") + +(:h3 "Key construction") + +(:describe :generic-function (ironclad:make-public-key public-key)) + +(:p "Return a public key according to " 'kind' ". The " '&key' " +arguments vary according to " 'kind' ". The interesting bits are in the +methods that specialize on " 'kind' ", below.") + +(:describe :method (ironclad:make-public-key ((eql :dsa)) private-key)) + +(:p "Return a DSA public key. " 'p' ", " 'q' ", " 'g' ", and " 'y' " +are the usual parameters for DSA keys discussed in the literature.") + +(:describe :generic-function (ironclad:make-private-key private-key)) + +(:p "Return a private key according to " 'kind' ". The " '&key' " +arguments vary according to " 'kind' ". The interesting bits are in the +methods that specialize on " 'kind' ", below.") + +(:describe :method (ironclad:make-private-key ((eql :dsa)) private-key)) + +(:p "Return a DSA private key. " 'p' ", " 'q' ", " 'g' ", " 'y' ", and +" 'x' " are the usual parameters for DSA keys discussed in the +literature.") + +(:h3 "Digital signatures") + +(:describe :generic-function (ironclad:sign-message signature)) + +(:p "Return a signature of " 'message' " between " 'start' " and " 'end' +" signed with " 'key' "; the class of " 'key' " determines the class of +" 'signature' ".") + +(:describe :method (ironclad:sign-message (ironclad::dsa-private-key t) signature)) + +(:p "This method places an additional constraint on the size of " +'message' " specified by " 'start' " and " 'end' ": it must be exactly +20 bytes long (the length of a SHA-1 digest). " 'signature' " is a " +@dsa-signature " object.") + +(:describe :generic-function (ironclad:verify-signature boolean)) + +(:p "Verify whether " 'signature' " is the signature of " 'message' " +between " 'start' " and " 'end' " using " 'key' ". Return T or NIL +depending on the result of verification.") + +(:describe :method (ironclad:verify-signature (ironclad::dsa-public-key t ironclad::dsa-signature) boolean)) + +(:h4 "Signature objects") + +(:p "There is no one \"right\" way to format signatures into octet +vectors; different applications may have different requirements. " +@sign-message " therefore returns objects and lets the user determine +how to best format the values contained therein.") + +(:describe :class dsa-signature) + +(:p "A DSA signature object.") + +(:describe :function (ironclad:make-dsa-signature signature)) + +(:p "Returns a DSA signature with the provided " 'r' " and " 's' " +values. " 'r' " and " 's' " may be either integers or they may be +20-byte octet vectors.") + +(:describe :function (ironclad:dsa-signature-r integer)) + +(:p "Returns the " 'r' " value of the provided DSA signature.") + +(:describe :function (ironclad:dsa-signature-s integer)) + +(:p "Returns the " 's' " value of the provided DSA signature.") + +(:h3 "Encryption and decryption") + +(:describe :function (ironclad:encrypt-message encrypted-message)) + +(:describe :function (ironclad:decrypt-message decrypted-message)) + +((:h2 id "gray-streams") "Gray Streams") + +(:p "Ironclad includes support for several convenient stream +abstractions based on Gray streams. Gray streams support in Ironclad is +included for SBCL, CMUCL, OpenMCL, Lispworks, and Allegro.") + +(:h3 "Octet streams") + +(:p "Octet streams are very similar to Common Lisp's " @string-stream ", +except they deal in octets instead of characters.") + +(:describe :function (ironclad:make-octet-input-stream octet-input-stream)) + +(:p "As " @make-string-input-stream ", only with octets instead of characters.") + +(:describe :function (ironclad:make-octet-output-stream octet-output-stream)) + +(:p "As " @make-string-output-stream ", only with octets instead of characters.") + +(:describe :function (ironclad:get-output-stream-octets octet-vector)) + +(:p "As " @get-output-stream-string ", only with an octet output-steam +instead of a string output-stream.") + +(:h3 "Digest streams") + +(:p "Digest streams compute a digest of the data written to them +according to a specific digest algorithm.") + +(:p "Example:") + +(:pre "(defun frobbing-function (stream) + ;; We want to compute a digest of the data being written to STREAM + ;; without involving our callees in the process. + (let* ((digesting-stream (crypto:make-digesting-stream :sha1)) + (stream (make-broadcast-stream stream digesting-stream))) + ;; Feed data to STREAM. + (frob-guts stream) + ;; Do something with the digest computed. + (... (crypto:produce-digest digesting-stream) ...) + ...))") + +(:describe :function (ironclad:make-digesting-stream stream)) + +(:p "Make a stream that computes a digest of the data written to it +according to the algorithm " 'digest-name' ". " @produce-digest " may +be used to obtain a digest of all the data written to the stream.") + +(:note "Calling " @produce-digest " on a digest stream does not alter +the internal state of the digest.") + +(:h2 "Utility Functions") + +(:describe :accessor (ironclad:ub16ref/le value) + (ironclad:ub32ref/le value) + (ironclad:ub64ref/le value)) + +(:p "This family of functions accesses an unsigned 16-bit, 32-bit or +64-bit value stored in little-endian order starting at " 'index' " in " +'array' ". " 'array' " must be a " `(SIMPLE-ARRAY (UNSIGNED-BYTE 8) +(*))` ". These functions are SETFable.") + +(:describe :accessor (ironclad:ub16ref/be value) + (ironclad:ub32ref/be value) + (ironclad:ub64ref/be value)) + +(:p "As the above, only the value is stored in big-endian order.") + +(:describe :function (ironclad:byte-array-to-hex-string string) + (ironclad:ascii-string-to-byte-array vector)) + +(:p `byte-array-to-hex-string` " converts the bytes of " 'vector' " +between " 'start' " and " 'end' " into a hexadecimal string. It is +useful for converting digests to a more readable form. " 'element-type' +" indicates the element-type of the returned string.") + +(:p `ascii-string-to-byte-array` " is provided as a quick and dirty way +to convert a string to a byte array suitable for feeding to " +@update-digest " or " @encrypt ". Care should be taken to ensure that +the provided string is actually an ASCII string. " 'start' " and " +'end' " have their usual interpretations.") + +(:describe :function (ironclad:octets-to-integer number) + (ironclad:integer-to-octets vector)) + +(:p `octets-to-integer` " converts the bytes of " 'octet-vec' " between +" 'start' " and " 'end' " to an integer as though the bytes denoted a +number in base 256. " 'big-endian' " is a boolean indicating whether +the bytes are to be read in big-endian or little-endian order. " +'n-bits' " specifies how many bits should be considered as significant +in the resulting number.") + +(:p `integer-to-octets` " is the reverse operation.") + +(:describe :function (ironclad:expt-mod number)) + +(:p "Raises " 'n' " to the " 'exponent' " power modulo " 'modulus' " in +a more efficient fashion than " `(MOD (EXPT N EXPONENT) MODULUS)` ".") + +(:h2 "Conditions") + +(:describe :condition ironclad-error) + +(:p "All errors signaled by Ironclad are of this type. This type is a +direct subtype of " `SIMPLE-ERROR` " without any extra slots or +options.") + +(:describe :condition initialization-vector-not-supplied) + +(:p "This error is signaled by " @make-cipher " when an initialization +vector is not provided and the requested mode requires an initialization +vector.") + +(:describe :condition invalid-initialization-vector) + +(:p "This error is signaled when an invalid initialization vector is +supplied to " @make-cipher " (e.g. when the length of the initialization +vector does not match the block length of the cipher).") + +(:describe :condition invalid-key-length) + +(:p "This error is signaled when the key provided to " @make-cipher " is +not of an acceptable length for the requested cipher.") + +(:describe :condition unsupported-cipher) + +(:p "This error is signaled when the " 'cipher-name' " provided to " +@make-cipher " is not " @cipher-supported-p ".") + +(:describe :condition unsupported-mode) + +(:p "This error is signaled when the " 'mode' " provided to " +@make-cipher " is not " @mode-supported-p ".") + +(:describe :condition unsupported-digest) + +(:p "This error is signaled when the " 'digest-name' " provided to " +@make-digest " is not " @digest-supported-p ".") + +(:describe :condition insufficient-buffer-space) + +(:p "This error is signaled when Ironclad needs to stuff some data into a +buffer (e.g. when the user provides " 'digest' " to " @produce-digest ") and +there is insufficient space.") + +(:describe :condition key-not-supplied) + +(:p "This error is signaled when a " `:KEY` " argument is not provided +to " @make-cipher ".") diff --git a/doc/ironclad.html b/doc/ironclad.html new file mode 100644 index 0000000..807db3d --- /dev/null +++ b/doc/ironclad.html @@ -0,0 +1,182 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" + "http://www.w3.org/TR/html4/strict.dtd"> +<HTML><HEAD><TITLE>Ironclad</TITLE><LINK TYPE="text/css" TITLE="default" REL="stylesheet" MEDIA="screen" HREF="style.css" /></HEAD><BODY><H1>Ironclad</H1><P>Ironclad is a cryptography library written entirely in Common +Lisp. It includes support for several popular <A HREF="#ciphers">ciphers</A>, <A HREF="#digests">digests</A>, and <A HREF="#macs">MACs</A>. Rudimentary support for <A HREF="#public-key">public-key +cryptography</A> is included. For several implementations that support +Gray Streams, <A HREF="#gray-streams">support</A> is included for +convenient stream wrappers.</P><P>Ironclad was written primarily by Nathan Froyd (froydnj@gmail.com).</P><H2>Installation</H2><P>Ironclad can be downloaded at <A HREF="http://www.method-combination.net/lisp/files/ironclad.tar.gz">http://www.method-combination.net/lisp/files/ironclad.tar.gz</A>. +The latest version is 0.27.</P><P>It comes with an ASDF system definition, so <TT>(ASDF:OOS +'ASDF:LOAD-OP :IRONCLAD)</TT> should be all that you need to get started. +The testsuite can be run by substituting <TT>ASDF:TEST-OP</TT> for <TT>ASDF:LOAD-OP</TT> in the form above.</P><P>Ironclad has been tested in the following implementations:</P><UL><LI>SBCL x86/linux (primary development platform)</LI><LI>SBCL x86-64/solaris</LI><LI>CMUCL x86/linux</LI><LI>ABCL with Sun's 1.5.0 JVM</LI><LI>Lispworks 5.0.1 x86/linux</LI><LI>Allegro 8.0 x86/linux</LI><LI>Allegro 8.1 x86/linux</LI><LI>Allegro 8.1 x86-64/linux</LI><LI>Allegro 8.1 sparc/solaris</LI><LI>CLISP 2.41 x86/linux</LI><LI>CLISP 2.44 x86/cygwin</LI><LI>Clozure Common Lisp 1.2 x86-64/Linux</LI></UL><P>All included tests should pass successfully. If you use a platform +not listed above, please send your platform information to the author so +that he can add it to the above list. If the tests do not all pass, you +have found a bug; please report it.</P><H2>License</H2><P>Ironclad is released under a MIT-like license; you can do pretty +much anything you want to with the code except claim that you wrote +it.</P><H2 ID="ciphers">Ciphers</H2><DIV CLASS="lisp-symbol"><A NAME="make-cipher"></A><TT><STRONG>make-cipher</STRONG> <EM>name</EM> <EM><TT>&key</TT></EM> <EM>key</EM> <EM>mode</EM> <EM>initialization-vector</EM> <EM>padding</EM> => <EM>cipher</EM></TT><BR /></DIV><P>Return a cipher object suitable for use for both encryption and +decryption.</P><P><EM>name</EM> denotes the encryption algorithm to use. <A HREF="#list-all-ciphers" STYLE="symbol">list-all-ciphers</A> will tell you the names of all supported ciphers; +the short list of ones you are likely to be interested in is:</P><UL><LI>AES</LI><LI>DES</LI><LI>3DES</LI><LI>Blowfish</LI><LI>Twofish</LI><LI>RC5</LI><LI>RC6</LI><LI>Arcfour (RC4)</LI></UL><P><EM>name</EM> can be a symbol in the <TT>KEYWORD</TT> package or the <TT>IRONCLAD</TT> package; <TT>:AES</TT> for AES, <TT>IRONCLAD:ARCFOUR</TT> for +RC4, and so forth.</P><P><EM>mode</EM> describes the mode of operation for the cipher. Stream +ciphers such as Arcfour can operate in only one mode, <TT>stream</TT>. +Block ciphers such as AES and DES can operate in several different +modes:</P><UL><LI>ECB</LI><LI>CBC</LI><LI>OFB</LI><LI>CFB (note that Ironclad's CFB mode is 'n'-bit CFB, where 'n' is +the <A HREF="#block-length" STYLE="symbol">block-length</A> of the cipher)</LI><LI>CFB8 (this seems to be the mode other crypto packages call +'CFB')</LI><LI>CTR</LI></UL><P><EM>mode</EM> should be a symbol in the <TT>KEYWORD</TT> or <TT>IRONCLAD</TT> +packages; <TT>:STREAM</TT>, <TT>IRONCLAD:OFB</TT>, and so forth. An error +will be signaled if <EM>mode</EM> is not appropriate for the cipher <EM>name</EM>.</P><P><EM>initialization-vector</EM> (IV) should be supplied only if <EM>mode</EM> +requires one. <EM>initialization-vector</EM> should be a <TT>(VECTOR +(UNSIGNED-BYTE 8))</TT>. The supplied IV should be the same length as the +<A HREF="#block-length" STYLE="symbol">block-length</A> of <EM>name</EM>.</P><P><EM>key</EM> is, of course, the key for the cipher. <EM>key</EM> should be +a <TT>(VECTOR (UNSIGNED-BYTE 8))</TT>.</P><P>If <EM>padding</EM> is supplied, the specified padding method will be +used by <A HREF="#encrypt" STYLE="symbol">encrypt</A> and <A HREF="#decrypt" STYLE="symbol">decrypt</A> to handle short blocks when the <TT>:HANDLE-FINAL-BLOCK</TT> argument is supplied. Depending on the mode +specified, <EM>padding</EM> may be ignored (e.g. OFB and CFB modes do not +care about short blocks; neither do stream ciphers).</P><TABLE CLASS="note"><TR><TD CLASS="title">Note</TD><TD CLASS="content"><EM>padding</EM> is currently ignored in all modes (and, by extension, +so is <TT>:HANDLE-FINAL-BLOCK</TT>). This oversight is expected to be +corrected in a future release.</TD></TR></TABLE><DIV CLASS="lisp-symbol"><A NAME="encrypt"></A><TT><STRONG>encrypt</STRONG> <EM>cipher</EM> <EM>plaintext</EM> <EM>ciphertext</EM> <EM><TT>&key</TT></EM> <EM>plaintext-start</EM> <EM>plaintext-end</EM> <EM>ciphertext-start</EM> <EM>plaintext-start</EM> <EM>ciphertext-start</EM> => <EM>n-bytes-consumed</EM>, <EM>n-bytes-produced</EM></TT><BR /></DIV><P>Encrypts data according to <EM>cipher</EM> from <EM>plaintext</EM> +starting at <EM>plaintext-start</EM> and continuing until <EM>plaintext-end</EM>. The encrypted data is placed in <EM>ciphertext</EM> starting at <EM>ciphertext-start</EM>.</P><DIV CLASS="lisp-symbol"><A NAME="decrypt"></A><TT><STRONG>decrypt</STRONG> <EM>cipher</EM> <EM>ciphertext</EM> <EM>plaintext</EM> <EM><TT>&key</TT></EM> <EM>ciphertext-start</EM> <EM>ciphertext-end</EM> <EM>plaintext-start</EM> <EM>ciphertext-start</EM> <EM>plaintext-start</EM> => <EM>n-bytes-consumed</EM>, <EM>n-bytes-produced</EM></TT><BR /></DIV><P>Decrypts data according to <EM>cipher</EM> from <EM>ciphertext</EM> +starting at <EM>ciphertext-start</EM> and continuing until <EM>ciphertext-end</EM>. The decrypted data is placed in <EM>plaintext</EM> +starting at <EM>plaintext-start</EM>.</P><DIV CLASS="lisp-symbol"><A NAME="encrypt-in-place"></A><TT><STRONG>encrypt-in-place</STRONG> <EM>cipher</EM> <EM>text</EM> <EM><TT>&key</TT></EM> <EM>start</EM> <EM>end</EM> => <EM>n-bytes-consumed</EM>, <EM>n-bytes-produced</EM></TT><BR /><A NAME="decrypt-in-place"></A><TT><STRONG>decrypt-in-place</STRONG> <EM>cipher</EM> <EM>text</EM> <EM><TT>&key</TT></EM> <EM>start</EM> <EM>end</EM> => <EM>n-bytes-consumed</EM>, <EM>n-bytes-produced</EM></TT><BR /></DIV><P>Encrypts or decrypts data in <EM>text</EM> between <EM>start</EM> and <EM>end</EM> "in-place" according to <EM>cipher</EM>. These functions are +shorthand for:</P><PRE>(encrypt cipher text text :plaintext-start start :plaintext-end end :ciphertext-start start) +(decrypt cipher text text :ciphertext-start start :ciphertext-end end :plaintext-start start)</PRE><TABLE CLASS="note"><TR><TD CLASS="title">Note</TD><TD CLASS="content"><A HREF="#encrypt-in-place" STYLE="symbol">encrypt-in-place</A> and <A HREF="#decrypt-in-place" STYLE="symbol">decrypt-in-place</A> do not support a <EM>handle-final-block</EM> parameter as <A HREF="#encrypt" STYLE="symbol">encrypt</A> and <A HREF="#decrypt" STYLE="symbol">decrypt</A> do. +If you need the functionality that <EM>handle-final-block</EM> provides, +then you need to use <A HREF="#encrypt" STYLE="symbol">encrypt</A> and <A HREF="#decrypt" STYLE="symbol">decrypt</A>.</TD></TR></TABLE><TABLE CLASS="note"><TR><TD CLASS="title">Note</TD><TD CLASS="content"><EM>n-bytes-consumed</EM> and <EM>n-bytes-produced</EM> may not always be +equal to the length of the data specified in the call to <A HREF="#encrypt-in-place" STYLE="symbol">encrypt-in-place</A> or <A HREF="#decrypt-in-place" STYLE="symbol">decrypt-in-place</A>. This subtlely is also +present in <A HREF="#encrypt" STYLE="symbol">encrypt</A> or <A HREF="#decrypt" STYLE="symbol">decrypt</A>.</TD></TR></TABLE><H3>Inquiry functions</H3><DIV CLASS="lisp-symbol"><A NAME="list-all-ciphers"></A><TT><STRONG>list-all-ciphers</STRONG> => <EM>list</EM></TT><BR /></DIV><P>Returns a list of cipher-names that may be validly passed to <A HREF="#make-cipher" STYLE="symbol">make-cipher</A>.</P><DIV CLASS="lisp-symbol"><A NAME="cipher-supported-p"></A><TT><STRONG>cipher-supported-p</STRONG> <EM>name</EM> => <EM>boolean</EM></TT><BR /></DIV><P>Returns T if <EM>name</EM> would be in the list returned by <A HREF="#list-all-ciphers" STYLE="symbol">list-all-ciphers</A>, NIL otherwise.</P><DIV CLASS="lisp-symbol"><A NAME="key-lengths"></A><TT><STRONG>key-lengths</STRONG> <EM>cipher</EM> => <EM>list</EM></TT><BR /></DIV><P>Return a list of valid key lengths for <EM>cipher</EM>.</P><DIV CLASS="lisp-symbol"><A NAME="block-length"></A><TT><STRONG>block-length</STRONG> <EM>cipher</EM> => <EM>number</EM></TT><BR /></DIV><P>Return the number of octets <EM>cipher</EM> processes at a time. This +function always returns 1 for stream ciphers.</P><H2 ID="digests">Digests</H2><P>Digest functions, also known as hash functions, produce +fixed-length output (a <EM>digest</EM> or <EM>hash</EM>) from a +variable-length message. The simplest example of a digest function is +one that adds up all the bytes in the message modulo 256. This digest +function fails one test of a cryptographically secure hash function: it +must be difficult to find a message with a given digest. It also fails +the other test: it must be difficult to find two messages with the same +digest.</P><P>Ironclad provides several cryptographically secure digest functions +and several non-cryptographically secure digest functions.</P><TABLE CLASS="note"><TR><TD CLASS="title">Note</TD><TD CLASS="content">In the functions below, messages or parts thereof are provided +as octet vectors; Ironclad has no facilities for producing digests of +strings. If you need to obtain the digest of a string, then you need to +figure out how to convert it to an octet vector first. This is a +deliberate design decision. Characters are not equivalent to bytes. +See your local Unicode guru for more details.</TD></TR></TABLE><DIV CLASS="lisp-symbol"><A NAME="make-digest"></A><TT><STRONG>make-digest</STRONG> <EM>digest-name</EM> => <EM>digester</EM></TT><BR /></DIV><P>Returns a digest object. <EM>digest-name</EM> is a keyword naming the +algorithm you wish <EM>digester</EM> to use. The algorithms you are likely +to want to use are:</P><UL><LI>MD4</LI><LI>MD5</LI><LI>SHA1</LI><LI>SHA256</LI><LI>Tiger</LI><LI>Adler32</LI><LI>CRC32</LI></UL><P>Other legitimate digest names can be found by calling <A HREF="#list-all-digests" STYLE="symbol">list-all-digests</A>. Like <A HREF="#make-cipher" STYLE="symbol">make-cipher</A>, <EM>digest-name</EM> should be +a symbol in the <TT>KEYWORD</TT> or <TT>IRONCLAD</TT> packages.</P><DIV CLASS="lisp-symbol"><A NAME="update-digest"></A><TT><STRONG>update-digest</STRONG> <EM>digester</EM> <EM>thing</EM> <EM><TT>&key</TT></EM> <EM><TT>&allow-other-keys</TT></EM> => <EM>(values)</EM></TT><BR /></DIV><P>Updates the internal state of <EM>digester</EM> with the contents of <EM>thing</EM>. The exact method is determined by the type of THING.</P><P>There are several methods defined on this generic function that +take a particular digester and a <TT>(SIMPLE-ARRAY (UNSIGNED-BYTE 8) +(*))</TT> as well as the usual <EM>start</EM> and <EM>end</EM> keyword +arguments. These methods update the state of <EM>digester</EM> with the +subsequence of the array denoted by <EM>start</EM> and <EM>end</EM>. They are +not listed here because there's one method for every type of digest +that Ironclad provides, and listing them would get very tedious +for no benefit. An example should suffice.</P><PRE>(let ((digester (ironclad:make-digest :sha1)) + (array (make-array 16 :element-type '(unsigned-byte 8) :initial-element 0))) + ;; Update with 16 zeroes. + (ironclad:update-digest digester array) + ;; Update with 8 ones. + (fill array 1 :start 2 :end 10) + (ironclad:update-digest digester array :start 2 :end 10))</PRE><DIV CLASS="lisp-symbol"><A NAME="update-digest"></A><TT><STRONG>update-digest</STRONG> <EM>digester</EM> <EM>(stream stream)</EM> <EM><TT>&key</TT></EM> <EM>buffer</EM> <EM>(start 0)</EM> <EM>end</EM> <EM><TT>&allow-other-keys</TT></EM> => <EM>digester</EM></TT><BR /></DIV><P>Update the internal state of <EM>digester</EM> with the contents of <EM>stream</EM>, which must respond to <TT>READ-BYTE</TT> or <TT>READ-SEQUENCE</TT> +with a <TT>(SIMPLE-ARRAY (UNSIGNED-BYTE 8) (*))</TT> and return <EM>digester</EM>. It differs from <A HREF="#digest-stream" STYLE="symbol">digest-stream</A>, below, in that you +may need to digest data before or after the contents of <EM>stream</EM> +(this happens, for instance, when signing the contents of some file).</P><DIV CLASS="lisp-symbol"><A NAME="produce-digest"></A><TT><STRONG>produce-digest</STRONG> <EM>digester</EM> <EM><TT>&key</TT></EM> <EM>digest</EM> <EM>digest-start</EM> => <EM>digest</EM></TT><BR /></DIV><P>Return the digest of the data processed by <EM>digester</EM> so far. +The internal state of <EM>digester</EM> is modified; if you wish to retain +a copy of the digest, you must call <A HREF="#copy-digest" STYLE="symbol">copy-digest</A>.</P><P>If <EM>digest</EM> is provided, the computed digest will be placed +into <EM>digest</EM> starting at <EM>digest-start</EM>. <EM>digest</EM> must be +a <TT>(SIMPLE-ARRAY (UNSIGNED-BYTE 8) (*))</TT>. An <A HREF="#insufficient-buffer-space" STYLE="symbol">insufficient-buffer-space</A> error will be signaled if there is +insufficient space in <EM>digest</EM>.</P><H3>High-level convenience functions</H3><P>Several high-level convenience functions that encapsulate common +sequences of <A HREF="#make-digest" STYLE="symbol">make-digest</A>, <A HREF="#update-digest" STYLE="symbol">update-digest</A> and <A HREF="#produce-digest" STYLE="symbol">produce-digest</A> are provided by Ironclad as well. They come in two flavors: the first +takes a digest name as would be provided to <A HREF="#make-digest" STYLE="symbol">make-digest</A>. The +second way to call these functions is to provide an actual digest object +as the first argument. So one can say:</P><PRE>(ironclad:digest-sequence :md5 *buffer*)</PRE><P>or, equivalently:</P><PRE>(let ((digester (make-digest :md5))) + (ironclad:digest-sequence digester *buffer*))</PRE><P>The second form comes in handy if you plan on <A HREF="#digest-tips">reusing the digest object</A>.</P><DIV CLASS="lisp-symbol"><A NAME="digest-sequence"></A><TT><STRONG>digest-sequence</STRONG> <EM>digest-spec</EM> <EM>sequence</EM> <EM><TT>&rest</TT></EM> <EM>args</EM> <EM><TT>&key</TT></EM> <EM>start</EM> <EM>end</EM> <EM>digest</EM> <EM>digest-start</EM> => <EM>digest</EM></TT><BR /></DIV><P>Returns the digest of the subsequence of <EM>sequence</EM> bounded by +<EM>start</EM> and <EM>end</EM>, according to <EM>digest-name</EM>. <EM>sequence</EM> must be a <TT>(SIMPLE-ARRAY (UNSIGNED-BYTE 8))</TT>. <EM>digest</EM> and <EM>digest-start</EM> are as in <A HREF="#produce-digest" STYLE="symbol">produce-digest</A>.</P><DIV CLASS="lisp-symbol"><A NAME="digest-stream"></A><TT><STRONG>digest-stream</STRONG> <EM>digest-spec</EM> <EM>stream</EM> <EM><TT>&rest</TT></EM> <EM>args</EM> <EM><TT>&key</TT></EM> <EM>buffer</EM> <EM>start</EM> <EM>end</EM> <EM>digest</EM> <EM>digest-start</EM> => <EM>digest</EM></TT><BR /></DIV><P>Returns the digest of the contents of the stream specified by <EM>stream</EM>. <TT>READ-BYTE</TT> must be a legal operation on <EM>stream</EM> +and return an <TT>(UNSIGNED-BYTE 8)</TT>. In a similar fashion, <TT>READ-SEQUENCE</TT> on <EM>stream</EM> must support reading into a <TT>(SIMPLE-ARRAY (UNSIGNED-BYTE 8))</TT>. <EM>digest</EM> and <EM>digest-start</EM> are as in <A HREF="#produce-digest" STYLE="symbol">produce-digest</A>.</P><P>If <EM>buffer</EM> is provided, it must be a <TT>(SIMPLE-ARRAY +(UNSIGNED-BYTE 8) (*))</TT>; the portion of <EM>buffer</EM> between <EM>start</EM> and <EM>end</EM> will be used to read the data from the stream.</P><DIV CLASS="lisp-symbol"><A NAME="digest-file"></A><TT><STRONG>digest-file</STRONG> <EM>digest-spec</EM> <EM>pathname</EM> <EM><TT>&rest</TT></EM> <EM>args</EM> <EM><TT>&key</TT></EM> <EM>buffer</EM> <EM>start</EM> <EM>end</EM> <EM>digest</EM> <EM>digest-start</EM> => <EM>digest</EM></TT><BR /></DIV><P>Returns the digest of the contents of the file named by <EM>pathname</EM>. <EM>digest</EM> and <EM>digest-start</EM> are as in <A HREF="#produce-digest" STYLE="symbol">produce-digest</A>.</P><P>If <EM>buffer</EM> is provided, it must be a <TT>(SIMPLE-ARRAY +(UNSIGNED-BYTE 8) (*))</TT>; the portion of <EM>buffer</EM> between <EM>start</EM> and <EM>end</EM> will be used to read the data from the stream.</P><H3>Inquiry functions</H3><DIV CLASS="lisp-symbol"><A NAME="list-all-digests"></A><TT><STRONG>list-all-digests</STRONG> => <EM>list</EM></TT><BR /></DIV><P>Returns a list whose elements may be validly passed to <A HREF="#make-digest" STYLE="symbol">make-digest</A>.</P><DIV CLASS="lisp-symbol"><A NAME="digest-supported-p"></A><TT><STRONG>digest-supported-p</STRONG> <EM>name</EM> => <EM>boolean</EM></TT><BR /></DIV><P>Returns T if <EM>name</EM> would be in the list returned by <A HREF="#list-all-digests" STYLE="symbol">list-all-digests</A>, NIL otherwise.</P><DIV CLASS="lisp-symbol"><A NAME="digest-length"></A><TT><STRONG>digest-length</STRONG> <EM>digest</EM> => <EM>number</EM></TT><BR /></DIV><P>Returns the length of the digest computed by <EM>digest</EM>, which +may be a digest-name or a digest instance.</P><H3 ID="digest-tips">Miscellaneous</H3><P>Ironclad digests are CLOS objects; the interesting thing about this +for most purposes is that functions like <TT>REINITIALIZE-INSTANCE</TT> are +supported. This means one can write a fairly efficient clone of the <TT>md5sum</TT> program like so:</P><PRE>(defun digest-sum-files (digest &rest files) + (unless files + (error "no files given to digest")) + (loop with buffer = (make-array 8192 :element-type '(unsigned-byte 8)) + with digest = (make-array (ironclad:digest-length digest) + :element-type '(unsigned-byte 8)) + for file in files + for digester = (ironclad:make-digest digest) + then (reinitialize-instance digester) + do (ironclad:digest-file digester file :buffer buffer :digest digest) + (format t "~A ~A~%" (file-namestring file) + (ironclad:byte-array-to-hex-string digest))))</PRE><H2 ID="macs">Message authentication codes</H2><P>A message authentication code is a cryptographic function of some +data and a user-specified key. Only a person knowing the key can +recompute the MAC for the given message. A MAC is useful where +maintaining data integrity is required, but the secrecy of the data is +not paramount.</P><P>Ironclad provides two different kinds of MACs: HMACs, specified in +<A HREF="http://www.ietf.org/rfc/rfc2109.txt">RFC 2104</A>, and CMACs, +specified in <A HREF="http://www.ietf.org/rfc/rfc4493.txt">RFC 4493</A> +and NIST document 800-38B.</P><H3>HMACs</H3><P>Instances of HMACs are constructed by specifying a secret key and a +digest-name.</P><DIV CLASS="lisp-symbol"><A NAME="make-hmac"></A><TT><STRONG>make-hmac</STRONG> <EM>key</EM> <EM>digest-name</EM> => <EM>hmac</EM></TT><BR /></DIV><P>Return an HMAC instance based on the hash function <EM>digest-name</EM> with secret key <EM>key</EM>.</P><P>The returned object supports <TT>REINITIALIZE-INSTANCE</TT>:</P><DIV CLASS="lisp-symbol"><A NAME="reinitialize-instance"></A><TT><STRONG>reinitialize-instance</STRONG> <EM>(mac hmac)</EM> <EM><TT>&rest</TT></EM> <EM>initargs</EM> <EM><TT>&key</TT></EM> <EM>key</EM> <EM><TT>&allow-other-keys</TT></EM> => <EM>hmac</EM></TT><BR /></DIV><P>The <TT>:KEY</TT> argument is the secret key, as provided to <A HREF="#make-hmac" STYLE="symbol">make-hmac</A>.</P><DIV CLASS="lisp-symbol"><A NAME="update-hmac"></A><TT><STRONG>update-hmac</STRONG> <EM>hmac</EM> <EM>sequence</EM> <EM><TT>&key</TT></EM> <EM>start</EM> <EM>end</EM> => <EM>hmac</EM></TT><BR /></DIV><P>Update the internal state of <EM>hmac</EM> with the data in <EM>sequence</EM> bounded by <EM>start</EM> and <EM>end</EM>. <EM>sequence</EM> must +be a <TT>(SIMPLE-ARRAY (UNSIGNED-BYTE 8) (*))</TT>.</P><DIV CLASS="lisp-symbol"><A NAME="hmac-digest"></A><TT><STRONG>hmac-digest</STRONG> <EM>hmac</EM> <EM><TT>&key</TT></EM> <EM>buffer</EM> <EM>buffer-start</EM> => <EM>digest</EM></TT><BR /></DIV><P>Returns the MAC (<EM>digest</EM>) computed by <EM>hmac</EM> thus far. +The internal state of <EM>hmac</EM> is not modified; this feature makes it +possible to compute a "rolling MAC" of a document. The length of <EM>digest</EM> is determined by the <A HREF="#digest-length" STYLE="symbol">digest-length</A> of <EM>digest-name</EM> +passed to <A HREF="#make-hmac" STYLE="symbol">make-hmac</A> when <EM>hmac</EM> was constructed.</P><P>If <EM>buffer</EM> is provided, the computed MAC will be placed into <EM>buffer</EM> starting at <EM>buffer-start</EM>. <EM>buffer</EM> must be a <TT>(SIMPLE-ARRAY (UNSIGNED-BYTE 8) (*))</TT>. An <A HREF="#insufficient-buffer-space" STYLE="symbol">insufficient-buffer-space</A> error will be signaled if there is +insufficient space in <EM>buffer</EM>.</P><H3>CMACs</H3><P>Instances of CMACs are constructed by specifying a secret key and a +cipher-name.</P><DIV CLASS="lisp-symbol"><A NAME="make-cmac"></A><TT><STRONG>make-cmac</STRONG> <EM>key</EM> <EM>cipher-name</EM> => <EM>cmac</EM></TT><BR /></DIV><P>Return a CMAC instance based on the cipher <EM>cipher-name</EM> with +secret key <EM>key</EM>. <EM>cipher-name</EM> must have a <A HREF="#block-length" STYLE="symbol">block-length</A> +of either 8 or 16; this restriction is satisfied by most ciphers in +Ironclad with the notable exception of stream ciphers. <EM>key</EM> must +be an acceptable key for <EM>cipher-name</EM>.</P><DIV CLASS="lisp-symbol"><A NAME="update-cmac"></A><TT><STRONG>update-cmac</STRONG> <EM>cmac</EM> <EM>sequence</EM> <EM><TT>&key</TT></EM> <EM>start</EM> <EM>end</EM> => <EM>cmac</EM></TT><BR /></DIV><P>Update the internal state of <EM>cmac</EM> with the data in <EM>sequence</EM> bounded by <EM>start</EM> and <EM>end</EM>. <EM>sequence</EM> must +be a <TT>(SIMPLE-ARRAY (UNSIGNED-BYTE 8) (*))</TT>.</P><DIV CLASS="lisp-symbol"><A NAME="cmac-digest"></A><TT><STRONG>cmac-digest</STRONG> <EM>cmac</EM> => <EM>digest</EM></TT><BR /></DIV><P>Returns the MAC (<EM>digest</EM>) computed by <EM>cmac</EM> thus far. +The internal state of <EM>cmac</EM> is not modified; this feature makes it +possible to compute a "rolling MAC" of a document. The length of <EM>digest</EM> is determined by the <A HREF="#block-length" STYLE="symbol">block-length</A> of <EM>cipher-name</EM> +passed to <A HREF="#make-cmac" STYLE="symbol">make-cmac</A> when <EM>cmac</EM> was constructed.</P><H2 ID="public-key">Public-key Operations</H2><P>Ironclad includes support for DSA signing and verification. +Support for RSA encryption and decryption is provided as well, but it is +"raw"--the various formatting schemes (e.g. PKCS-1) must be implemented +by the user at this time.</P><H3>Key construction</H3><DIV CLASS="lisp-symbol"><A NAME="make-public-key"></A><TT><STRONG>make-public-key</STRONG> <EM>kind</EM> <EM><TT>&key</TT></EM> <EM><TT>&allow-other-keys</TT></EM> => <EM>public-key</EM></TT><BR /></DIV><P>Return a public key according to <EM>kind</EM>. The <EM>&key</EM> +arguments vary according to <EM>kind</EM>. The interesting bits are in the +methods that specialize on <EM>kind</EM>, below.</P><DIV CLASS="lisp-symbol"><A NAME="make-public-key"></A><TT><STRONG>make-public-key</STRONG> <EM>(kind (eql :dsa))</EM> <EM><TT>&key</TT></EM> <EM>p</EM> <EM>q</EM> <EM>g</EM> <EM>y</EM> <EM><TT>&allow-other-keys</TT></EM> => <EM>private-key</EM></TT><BR /></DIV><P>Return a DSA public key. <EM>p</EM>, <EM>q</EM>, <EM>g</EM>, and <EM>y</EM> +are the usual parameters for DSA keys discussed in the literature.</P><DIV CLASS="lisp-symbol"><A NAME="make-private-key"></A><TT><STRONG>make-private-key</STRONG> <EM>kind</EM> <EM><TT>&key</TT></EM> <EM><TT>&allow-other-keys</TT></EM> => <EM>private-key</EM></TT><BR /></DIV><P>Return a private key according to <EM>kind</EM>. The <EM>&key</EM> +arguments vary according to <EM>kind</EM>. The interesting bits are in the +methods that specialize on <EM>kind</EM>, below.</P><DIV CLASS="lisp-symbol"><A NAME="make-private-key"></A><TT><STRONG>make-private-key</STRONG> <EM>(kind (eql :dsa))</EM> <EM><TT>&key</TT></EM> <EM>p</EM> <EM>q</EM> <EM>g</EM> <EM>y</EM> <EM>x</EM> <EM><TT>&allow-other-keys</TT></EM> => <EM>private-key</EM></TT><BR /></DIV><P>Return a DSA private key. <EM>p</EM>, <EM>q</EM>, <EM>g</EM>, <EM>y</EM>, and +<EM>x</EM> are the usual parameters for DSA keys discussed in the +literature.</P><H3>Digital signatures</H3><DIV CLASS="lisp-symbol"><A NAME="sign-message"></A><TT><STRONG>sign-message</STRONG> <EM>key</EM> <EM>message</EM> <EM><TT>&key</TT></EM> <EM>start</EM> <EM>end</EM> => <EM>signature</EM></TT><BR /></DIV><P>Return a signature of <EM>message</EM> between <EM>start</EM> and <EM>end</EM> signed with <EM>key</EM>; the class of <EM>key</EM> determines the class of +<EM>signature</EM>.</P><DIV CLASS="lisp-symbol"><A NAME="sign-message"></A><TT><STRONG>sign-message</STRONG> <EM>(key dsa-private-key)</EM> <EM>message</EM> <EM><TT>&key</TT></EM> <EM>(start 0)</EM> <EM>end</EM> => <EM>signature</EM></TT><BR /></DIV><P>This method places an additional constraint on the size of <EM>message</EM> specified by <EM>start</EM> and <EM>end</EM>: it must be exactly +20 bytes long (the length of a SHA-1 digest). <EM>signature</EM> is a <A HREF="#dsa-signature" STYLE="symbol">dsa-signature</A> object.</P><DIV CLASS="lisp-symbol"><A NAME="verify-signature"></A><TT><STRONG>verify-signature</STRONG> <EM>key</EM> <EM>message</EM> <EM>signature</EM> <EM><TT>&key</TT></EM> <EM>start</EM> <EM>end</EM> => <EM>boolean</EM></TT><BR /></DIV><P>Verify whether <EM>signature</EM> is the signature of <EM>message</EM> +between <EM>start</EM> and <EM>end</EM> using <EM>key</EM>. Return T or NIL +depending on the result of verification.</P><DIV CLASS="lisp-symbol"><A NAME="verify-signature"></A><TT><STRONG>verify-signature</STRONG> <EM>(key dsa-public-key)</EM> <EM>message</EM> <EM>(signature dsa-signature)</EM> <EM><TT>&key</TT></EM> <EM>(start 0)</EM> <EM>end</EM> => <EM>boolean</EM></TT><BR /></DIV><H4>Signature objects</H4><P>There is no one "right" way to format signatures into octet +vectors; different applications may have different requirements. <A HREF="#sign-message" STYLE="symbol">sign-message</A> therefore returns objects and lets the user determine +how to best format the values contained therein.</P><DIV CLASS="lisp-symbol"><A NAME="dsa-signature"></A><TT><STRONG>dsa-signature</STRONG></TT><BR /></DIV><P>A DSA signature object.</P><DIV CLASS="lisp-symbol"><A NAME="make-dsa-signature"></A><TT><STRONG>make-dsa-signature</STRONG> <EM>r</EM> <EM>s</EM> => <EM>signature</EM></TT><BR /></DIV><P>Returns a DSA signature with the provided <EM>r</EM> and <EM>s</EM> +values. <EM>r</EM> and <EM>s</EM> may be either integers or they may be +20-byte octet vectors.</P><DIV CLASS="lisp-symbol"><A NAME="dsa-signature-r"></A><TT><STRONG>dsa-signature-r</STRONG> <EM>object</EM> => <EM>integer</EM></TT><BR /></DIV><P>Returns the <EM>r</EM> value of the provided DSA signature.</P><DIV CLASS="lisp-symbol"><A NAME="dsa-signature-s"></A><TT><STRONG>dsa-signature-s</STRONG> <EM>object</EM> => <EM>integer</EM></TT><BR /></DIV><P>Returns the <EM>s</EM> value of the provided DSA signature.</P><H3>Encryption and decryption</H3><DIV CLASS="lisp-symbol"><A NAME="encrypt-message"></A><TT><STRONG>encrypt-message</STRONG> <EM>key</EM> <EM>message</EM> <EM><TT>&key</TT></EM> <EM>start</EM> <EM>end</EM> <EM>end</EM> <EM>start</EM> => <EM>encrypted-message</EM></TT><BR /></DIV><DIV CLASS="lisp-symbol"><A NAME="decrypt-message"></A><TT><STRONG>decrypt-message</STRONG> <EM>key</EM> <EM>message</EM> <EM><TT>&key</TT></EM> <EM>start</EM> <EM>end</EM> <EM>start</EM> => <EM>decrypted-message</EM></TT><BR /></DIV><H2 ID="gray-streams">Gray Streams</H2><P>Ironclad includes support for several convenient stream +abstractions based on Gray streams. Gray streams support in Ironclad is +included for SBCL, CMUCL, OpenMCL, Lispworks, and Allegro.</P><H3>Octet streams</H3><P>Octet streams are very similar to Common Lisp's <A HREF="#string-stream" STYLE="symbol">string-stream</A>, +except they deal in octets instead of characters.</P><DIV CLASS="lisp-symbol"><A NAME="make-octet-input-stream"></A><TT><STRONG>make-octet-input-stream</STRONG> <EM>buffer</EM> <EM><TT>&optional</TT></EM> <EM>start</EM> <EM>end</EM> => <EM>octet-input-stream</EM></TT><BR /></DIV><P>As <A HREF="#make-string-input-stream" STYLE="symbol">make-string-input-stream</A>, only with octets instead of characters.</P><DIV CLASS="lisp-symbol"><A NAME="make-octet-output-stream"></A><TT><STRONG>make-octet-output-stream</STRONG> => <EM>octet-output-stream</EM></TT><BR /></DIV><P>As <A HREF="#make-string-output-stream" STYLE="symbol">make-string-output-stream</A>, only with octets instead of characters.</P><DIV CLASS="lisp-symbol"><A NAME="get-output-stream-octets"></A><TT><STRONG>get-output-stream-octets</STRONG> <EM>stream</EM> => <EM>octet-vector</EM></TT><BR /></DIV><P>As <A HREF="#get-output-stream-string" STYLE="symbol">get-output-stream-string</A>, only with an octet output-steam +instead of a string output-stream.</P><H3>Digest streams</H3><P>Digest streams compute a digest of the data written to them +according to a specific digest algorithm.</P><P>Example:</P><PRE>(defun frobbing-function (stream) + ;; We want to compute a digest of the data being written to STREAM + ;; without involving our callees in the process. + (let* ((digesting-stream (crypto:make-digesting-stream :sha1)) + (stream (make-broadcast-stream stream digesting-stream))) + ;; Feed data to STREAM. + (frob-guts stream) + ;; Do something with the digest computed. + (... (crypto:produce-digest digesting-stream) ...) + ...))</PRE><DIV CLASS="lisp-symbol"><A NAME="make-digesting-stream"></A><TT><STRONG>make-digesting-stream</STRONG> <EM>digest</EM> => <EM>stream</EM></TT><BR /></DIV><P>Make a stream that computes a digest of the data written to it +according to the algorithm <EM>digest-name</EM>. <A HREF="#produce-digest" STYLE="symbol">produce-digest</A> may +be used to obtain a digest of all the data written to the stream.</P><TABLE CLASS="note"><TR><TD CLASS="title">Note</TD><TD CLASS="content">Calling <A HREF="#produce-digest" STYLE="symbol">produce-digest</A> on a digest stream does not alter +the internal state of the digest.</TD></TR></TABLE><H2>Utility Functions</H2><DIV CLASS="lisp-symbol"><A NAME="ub16ref/le"></A><TT><STRONG>ub16ref/le</STRONG> <EM>buffer</EM> <EM>index</EM> => <EM>value</EM></TT><BR /><A NAME="ub32ref/le"></A><TT><STRONG>ub32ref/le</STRONG> <EM>buffer</EM> <EM>index</EM> => <EM>value</EM></TT><BR /><A NAME="ub64ref/le"></A><TT><STRONG>ub64ref/le</STRONG> <EM>buffer</EM> <EM>index</EM> => <EM>value</EM></TT><BR /></DIV><P>This family of functions accesses an unsigned 16-bit, 32-bit or +64-bit value stored in little-endian order starting at <EM>index</EM> in <EM>array</EM>. <EM>array</EM> must be a <TT>(SIMPLE-ARRAY (UNSIGNED-BYTE 8) +(*))</TT>. These functions are SETFable.</P><DIV CLASS="lisp-symbol"><A NAME="ub16ref/be"></A><TT><STRONG>ub16ref/be</STRONG> <EM>buffer</EM> <EM>index</EM> => <EM>value</EM></TT><BR /><A NAME="ub32ref/be"></A><TT><STRONG>ub32ref/be</STRONG> <EM>buffer</EM> <EM>index</EM> => <EM>value</EM></TT><BR /><A NAME="ub64ref/be"></A><TT><STRONG>ub64ref/be</STRONG> <EM>buffer</EM> <EM>index</EM> => <EM>value</EM></TT><BR /></DIV><P>As the above, only the value is stored in big-endian order.</P><DIV CLASS="lisp-symbol"><A NAME="byte-array-to-hex-string"></A><TT><STRONG>byte-array-to-hex-string</STRONG> <EM>vector</EM> <EM><TT>&key</TT></EM> <EM>start</EM> <EM>end</EM> <EM>element-type</EM> => <EM>string</EM></TT><BR /><A NAME="ascii-string-to-byte-array"></A><TT><STRONG>ascii-string-to-byte-array</STRONG> <EM>string</EM> <EM><TT>&key</TT></EM> <EM>start</EM> <EM>end</EM> => <EM>vector</EM></TT><BR /></DIV><P><TT>byte-array-to-hex-string</TT> converts the bytes of <EM>vector</EM> +between <EM>start</EM> and <EM>end</EM> into a hexadecimal string. It is +useful for converting digests to a more readable form. <EM>element-type</EM> indicates the element-type of the returned string.</P><P><TT>ascii-string-to-byte-array</TT> is provided as a quick and dirty way +to convert a string to a byte array suitable for feeding to <A HREF="#update-digest" STYLE="symbol">update-digest</A> or <A HREF="#encrypt" STYLE="symbol">encrypt</A>. Care should be taken to ensure that +the provided string is actually an ASCII string. <EM>start</EM> and <EM>end</EM> have their usual interpretations.</P><DIV CLASS="lisp-symbol"><A NAME="octets-to-integer"></A><TT><STRONG>octets-to-integer</STRONG> <EM>octet-vec</EM> <EM><TT>&key</TT></EM> <EM>start</EM> <EM>end</EM> <EM>big-endian</EM> <EM>n-bits</EM> => <EM>number</EM></TT><BR /><A NAME="integer-to-octets"></A><TT><STRONG>integer-to-octets</STRONG> <EM>bignum</EM> <EM><TT>&key</TT></EM> <EM>n-bits</EM> <EM>big-endian</EM> => <EM>vector</EM></TT><BR /></DIV><P><TT>octets-to-integer</TT> converts the bytes of <EM>octet-vec</EM> between +<EM>start</EM> and <EM>end</EM> to an integer as though the bytes denoted a +number in base 256. <EM>big-endian</EM> is a boolean indicating whether +the bytes are to be read in big-endian or little-endian order. <EM>n-bits</EM> specifies how many bits should be considered as significant +in the resulting number.</P><P><TT>integer-to-octets</TT> is the reverse operation.</P><DIV CLASS="lisp-symbol"><A NAME="expt-mod"></A><TT><STRONG>expt-mod</STRONG> => <EM>number</EM></TT><BR /></DIV><P>Raises <EM>n</EM> to the <EM>exponent</EM> power modulo <EM>modulus</EM> in +a more efficient fashion than <TT>(MOD (EXPT N EXPONENT) MODULUS)</TT>.</P><H2>Conditions</H2><DIV CLASS="lisp-symbol"><A NAME="ironclad-error"></A><TT><STRONG>ironclad-error</STRONG></TT><BR /></DIV><P>All errors signaled by Ironclad are of this type. This type is a +direct subtype of <TT>SIMPLE-ERROR</TT> without any extra slots or +options.</P><DIV CLASS="lisp-symbol"><A NAME="initialization-vector-not-supplied"></A><TT><STRONG>initialization-vector-not-supplied</STRONG></TT><BR /></DIV><P>This error is signaled by <A HREF="#make-cipher" STYLE="symbol">make-cipher</A> when an initialization +vector is not provided and the requested mode requires an initialization +vector.</P><DIV CLASS="lisp-symbol"><A NAME="invalid-initialization-vector"></A><TT><STRONG>invalid-initialization-vector</STRONG></TT><BR /></DIV><P>This error is signaled when an invalid initialization vector is +supplied to <A HREF="#make-cipher" STYLE="symbol">make-cipher</A> (e.g. when the length of the initialization +vector does not match the block length of the cipher).</P><DIV CLASS="lisp-symbol"><A NAME="invalid-key-length"></A><TT><STRONG>invalid-key-length</STRONG></TT><BR /></DIV><P>This error is signaled when the key provided to <A HREF="#make-cipher" STYLE="symbol">make-cipher</A> is +not of an acceptable length for the requested cipher.</P><DIV CLASS="lisp-symbol"><A NAME="unsupported-cipher"></A><TT><STRONG>unsupported-cipher</STRONG></TT><BR /></DIV><P>This error is signaled when the <EM>cipher-name</EM> provided to <A HREF="#make-cipher" STYLE="symbol">make-cipher</A> is not <A HREF="#cipher-supported-p" STYLE="symbol">cipher-supported-p</A>.</P><DIV CLASS="lisp-symbol"><A NAME="unsupported-mode"></A><TT><STRONG>unsupported-mode</STRONG></TT><BR /></DIV><P>This error is signaled when the <EM>mode</EM> provided to <A HREF="#make-cipher" STYLE="symbol">make-cipher</A> is not <A HREF="#mode-supported-p" STYLE="symbol">mode-supported-p</A>.</P><DIV CLASS="lisp-symbol"><A NAME="unsupported-digest"></A><TT><STRONG>unsupported-digest</STRONG></TT><BR /></DIV><P>This error is signaled when the <EM>digest-name</EM> provided to <A HREF="#make-digest" STYLE="symbol">make-digest</A> is not <A HREF="#digest-supported-p" STYLE="symbol">digest-supported-p</A>.</P><DIV CLASS="lisp-symbol"><A NAME="insufficient-buffer-space"></A><TT><STRONG>insufficient-buffer-space</STRONG></TT><BR /></DIV><P>This error is signaled when Ironclad needs to stuff some data into a +buffer (e.g. when the user provides <EM>digest</EM> to <A HREF="#produce-digest" STYLE="symbol">produce-digest</A>) and +there is insufficient space.</P><DIV CLASS="lisp-symbol"><A NAME="key-not-supplied"></A><TT><STRONG>key-not-supplied</STRONG></TT><BR /></DIV><P>This error is signaled when a <TT>:KEY</TT> argument is not provided +to <A HREF="#make-cipher" STYLE="symbol">make-cipher</A>.</P></BODY></HTML>
\ No newline at end of file diff --git a/doc/style.css b/doc/style.css new file mode 100644 index 0000000..df9513d --- /dev/null +++ b/doc/style.css @@ -0,0 +1,77 @@ +body { + margin: 1em 5% 1em 5%; +} + +p { + margin-top: 0.5em; + margin-bottom: 0.5em; +} + +pre { + padding: 0; + margin: 0; +} + +h1, h2 { + border-bottom: 2px solid #449977; +} + +h1, h2, h3, h4, h5, h6 { + font-family: sans-serif; + line-height: 1.3; +} + +a:link { + color: #449977; +} + +a:visited { + color: purple; +} + +a { + text-decoration: none; + padding: 1px 2px; +} + +a:hover { + text-decoration: none; + padding: 1px; + border: 1px solid #000000; +} + +.lisp-symbol { + margin-right: 10%; + margin-top: 1.5em; + margin-bottom: 1.5em; + border: 1px solid #449977; + background: #eeeeee; + padding: 0.5em; +} + +.note { + margin-right: 10%; + margin-top: 1.5em; + margin-bottom: 1.5em; +} + +td.content { + padding: 0; +} + +td.title { + font-family: sans-serif; + font-size: 1.1em; + font-weight: bold; + text-align: left; + vertical-align: top; + text-decoration: underline; + padding-right: 0.5em; + margin-top: 0.0em; + margin-bottom: 0.5em; +} + +.note td.content { + padding-left: 0.5em; + border-left: 2px solid #449977; +} |