{"id":13442777,"url":"https://github.com/sharplispers/ironclad","last_synced_at":"2026-01-16T15:12:12.927Z","repository":{"id":23523164,"uuid":"99055763","full_name":"sharplispers/ironclad","owner":"sharplispers","description":"A cryptographic toolkit written in Common Lisp","archived":false,"fork":false,"pushed_at":"2024-10-11T13:51:24.000Z","size":2878,"stargazers_count":182,"open_issues_count":7,"forks_count":28,"subscribers_count":18,"default_branch":"master","last_synced_at":"2025-03-20T15:40:35.688Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Common Lisp","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/sharplispers.png","metadata":{"files":{"readme":"README.org","changelog":"NEWS","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-08-02T00:49:41.000Z","updated_at":"2025-03-16T08:35:19.000Z","dependencies_parsed_at":"2024-02-29T13:52:23.012Z","dependency_job_id":"da1906e2-95d4-411d-8dd5-415c84eb0643","html_url":"https://github.com/sharplispers/ironclad","commit_stats":null,"previous_names":[],"tags_count":28,"template":false,"template_full_name":null,"purl":"pkg:github/sharplispers/ironclad","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sharplispers%2Fironclad","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sharplispers%2Fironclad/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sharplispers%2Fironclad/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sharplispers%2Fironclad/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sharplispers","download_url":"https://codeload.github.com/sharplispers/ironclad/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sharplispers%2Fironclad/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28479406,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-16T11:59:17.896Z","status":"ssl_error","status_checked_at":"2026-01-16T11:55:55.838Z","response_time":107,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-07-31T03:01:50.533Z","updated_at":"2026-01-16T15:12:12.906Z","avatar_url":"https://github.com/sharplispers.png","language":"Common Lisp","funding_links":[],"categories":["Common Lisp","Expert Systems"],"sub_categories":[],"readme":"#+TITLE: Ironclad\n#+AUTHOR: The Ironclad developers\n#+DATE:\n#+EMAIL:\n#+LANGUAGE: en\n#+OPTIONS: num:nil toc:nil html-style:nil html-postamble:nil html-scripts:nil\n#+HTML_DOCTYPE: html5\n#+HTML_HEAD: \u003cstyle type=\"text/css\"\u003e\n#+HTML_HEAD: body { margin: 1em 5% 1em 5%; }\n#+HTML_HEAD: p { margin-top: 0.5em; margin-bottom: 0.5em; }\n#+HTML_HEAD: pre { padding: 0; margin: 0; }\n#+HTML_HEAD: h1, h2 { border-bottom: 2px solid #449977; }\n#+HTML_HEAD: h1, h2, h3, h4, h5, h6 { font-family: sans-serif; line-height: 1.3; }\n#+HTML_HEAD: a:link { color: #449977; }\n#+HTML_HEAD: a:visited { color: purple; }\n#+HTML_HEAD: a { text-decoration: none; padding: 1px 2px; }\n#+HTML_HEAD: a:hover { text-decoration: none; padding: 1px; border: 1px solid #000000; }\n#+HTML_HEAD: pre.src-lisp { margin-right: 10%; margin-top: 1.5em; margin-bottom: 1.5em; border: 1px solid #449977; background: #eeeeee; padding: 1em; }\n#+HTML_HEAD: pre.example { margin-right: 10%; margin-top: 1.5em; margin-bottom: 1.5em; border: 1px solid black; padding: 1em; }\n#+HTML_HEAD: .underline { margin-top: 1.5em; margin-bottom: 1.5em; font-family: sans-serif; font-size: 1.1em; font-weight: bold; text-decoration: underline; }\n#+HTML_HEAD: \u003c/style\u003e\n\n#+ATTR_HTML: :style width: 0; height: 0; padding: 0; margin: 0; border: 0; overflow: hidden;\n[[https://github.com/sharplispers/ironclad/workflows/CI/badge.svg?branch=master][file:https://github.com/sharplispers/ironclad/workflows/CI/badge.svg?branch=master]]\n\nIronclad is a cryptography library written entirely in Common Lisp. It\nincludes support for several popular [[#ciphers][ciphers]], [[#digests][digests]], [[#message-authentication-codes][MACs]] and\n[[#public-key-cryptography][public key cryptography]] algorithms. For several implementations that\nsupport Gray streams, support is included for convenient [[#gray-streams][stream wrappers]].\n\nMost of the algorithms were written with efficiency for specific\nCommon Lisp implementations in mind, although portable code is\nprovided as an alternative in nearly all instances. The framework\nshould be flexible enough to accommodate implementation-specific\noptimizations when possible.\n\nTest vectors for many of the algorithms are included to provide\na level of confidence in the correctness of the implementations.\n\n#+TOC: headlines 1\n\n* Warnings\n  :PROPERTIES:\n  :CUSTOM_ID: warning\n  :END:\n\n*Ironclad should not be considered safe against side channel attacks.*\n\nSome algorithms can be safe against side channel attacks on some\narchitectures using some Common Lisp implementations, but in the\ngeneral case it can't be guaranteed. This is due to the fact that\nintegers and arithmetic functions of Common Lisp implementations are\nusually not safe against side channel attacks.\n\n\n*Ironclad's digest, MAC and cipher objects should not be considered thread\nsafe.*\n\nCreating a digest, a MAC or a cipher object and using it in several threads at\nthe same time can lead to an undefined result. If you need to do that, you must\nput locks in your application where necessary.\n\n\n*Ironclad's pseudo random number generation should only be considered thread\nsafe with bordeaux-threads.*\n\nIf you have a multi-threaded application in which you want to use functions\nrequiring some random numbers (key derivation, key generation, public key\nencryption, signature, etc.) in several threads, each of these threads must have\nits own PRNG, or they might generate the same \"random\" numbers. If the threads\nare created using the *bordeaux-threads* library (or by a library using\n*bordeaux-threads*, like *lparallel*), this is done automatically. However, if\nyou are using the threading functions of your Common Lisp implementation\ndirectly, you have to bind the ~*prng*~ special variable to a new PRNG in each\nthread. There is an example showing how it can be done in the section about\n[[make-prng][make-prng]].\n\n* Installation\n  :PROPERTIES:\n  :CUSTOM_ID: installation\n  :END:\n\nThe current version of Ironclad is 0.61. It can be downloaded\nat [[https://github.com/sharplispers/ironclad/archive/v0.61.tar.gz]].\nIf you are feeling adventurous, you can download a bleeding-edge version\nat [[https://github.com/sharplispers/ironclad]].\n\nIt comes with an ASDF system definition, so ~(asdf:load-system \"ironclad\")~\nshould be all that you need to get started. The testsuite can be run\nby substituting ~asdf:test-system~ for ~asdf:load-system~ in the form above.\n\nIf you are using [[https://www.quicklisp.org][Quicklisp]] to manage your libraries, just use\n~(ql:quickload \"ironclad\")~.\n\nWhen Ironclad is loaded, its functions are in the ~ironclad~ package (e.g.\n~(ironclad:make-cipher ...)~). If you prefer, you can also use the ~crypto~\nnickname (e.g. ~(crypto:make-cipher ...)~).\n\nIronclad has been tested in the following implementations:\n - SBCL x86/linux, x86-64/linux (primary development platforms)\n - SBCL x86-64/solaris, x86/darwin\n - CMUCL x86/linux\n - ABCL with Sun's 1.5.0 JVM\n - Lispworks 5.0.1 x86/linux\n - Lispworks 5.1.2 x86-64/darwin x86/windows\n - Allegro 8.0 x86/linux\n - Allegro 8.1 x86/linux, x86-64/linux, sparc/solaris\n - CLISP 2.41 x86/linux, x86/cygwin\n - Clozure Common Lisp 1.11 x86-64/Linux\n - Clozure Common Lisp 1.10 x86-64/darwin\n - ECL 16.1.3 x86-64/linux\n\nAll included tests should pass successfully. If you use a platform not\nlisted above, please send your platform information so that it can be\nadded to the above list. If the tests do not all pass, you have found\na bug; please report it.\n\nBy default, Ironclad uses some implementation dependent low-level code to make\nsome functions run much faster (currently, some assembly for SBCL and CCL, some\nC code for ECL). If for some reason you want to disable these optimisations and\nuse the generic Lisp code, it can be achieved by commenting out the\n~(pushnew :ironclad-assembly *features*)~ line in the /src/package.lisp/ file.\n\n* License\n  :PROPERTIES:\n  :CUSTOM_ID: license\n  :END:\n\nIronclad is released under a MIT-like license; you can do pretty much\nanything you want to with the code except claim that you wrote it.\n\n* Ciphers\n  :PROPERTIES:\n  :CUSTOM_ID: ciphers\n  :END:\n\n#+NAME: make-cipher\n#+BEGIN_SRC lisp\n(make-cipher name \u0026key key mode initialization-vector padding tweak) =\u003e cipher\n#+END_SRC\n\nReturn a cipher object suitable for use for both encryption and decryption.\n\n/name/ denotes the encryption algorithm to use. [[list-all-ciphers][list-all-ciphers]] will tell you\nthe names of all supported ciphers. They are:\n - 3des\n - aes\n - arcfour (rc4)\n - aria\n - blowfish\n - camellia\n - cast5\n - chacha\n - chacha/12\n - chacha/8\n - des\n - idea\n - kalyna128\n - kalyna256\n - kalyna512\n - kuznyechik\n - misty1\n - rc2\n - rc5\n - rc6\n - salsa20\n - salsa20/12\n - salsa20/8\n - seed\n - serpent\n - sm4\n - sosemanuk\n - square\n - tea\n - threefish1024\n - threefish256\n - threefish512\n - twofish\n - xchacha\n - xchacha/12\n - xchacha/8\n - xor (not a real cipher, use only for testing)\n - xsalsa20\n - xsalsa20/12\n - xsalsa20/8\n - xtea\n\n/name/ can be a symbol in the ~keyword~ package or in the ~ironclad~ package;\n~:aes~ for AES, ~ironclad:arcfour~ for RC4, and so forth.\n\n/mode/ describes the mode of operation for the cipher. Stream ciphers\nsuch as Arcfour can operate in only one mode, ~stream~. Block ciphers\nsuch as AES and DES can operate in several different modes:\n - ecb\n - cbc\n - ofb\n - cfb (note that Ironclad's CFB mode is /n/-bit CFB, where /n/ is the [[block-length][block-length]] of the cipher)\n - cfb8 (this seems to be the mode other crypto packages call CFB)\n - ctr\n\n/mode/ should be a symbol in the ~keyword~ or ~ironclad~ packages;\n~:stream~, ~ironclad:ofb~, and so forth. An error will be signaled if\n/mode/ is not appropriate for the cipher /name/.\n\n/initialization-vector/ (IV) should be supplied only if /mode/ requires one.\n/initialization-vector/ should be a ~(simple-array (unsigned-byte 8) (*))~.\nThe supplied IV should be the same length as the [[block-length][block-length]] of /name/.\nThe Chacha and Salsa20 stream ciphers also use an initialization\nvector (nonce). It should be 8 or 12 bytes long for Chacha, 8 bytes long\nfor Salsa20, and 24 bytes long for XChacha and XSalsa20.\n\n/key/ is, of course, the key for the cipher.\n/key/ should be a ~(simple-array (unsigned-byte 8) (*))~.\n\nIf /padding/ is supplied, the specified padding method will be used by [[encrypt][encrypt]]\nand [[decrypt][decrypt]] to handle short blocks when the ~:handle-final-block~ argument is\nsupplied. /padding/ will only be used if the mode is ECB or CBC. The possible\nvalues for /padding/ are ~:pkcs7~, ~:ansi-x923~ and ~:iso-7816-4~.\n\nIf the cipher can use a tweak (e.g. threefish), it can be specified\nwith the /tweak/ key parameter.\n\n\n#+NAME: encrypt\n#+BEGIN_SRC lisp\n(encrypt cipher plaintext ciphertext \u0026key plaintext-start plaintext-end ciphertext-start handle-final-block) =\u003e n-bytes-consumed, n-bytes-produced\n#+END_SRC\n\nEncrypts data according to /cipher/ from /plaintext/ starting at\n/plaintext-start/ and continuing until /plaintext-end/. The encrypted\ndata is placed in /ciphertext/ starting at /ciphertext-start/.\n\n\n#+NAME: decrypt\n#+BEGIN_SRC lisp\n(decrypt cipher ciphertext plaintext \u0026key ciphertext-start ciphertext-end plaintext-start handle-final-block) =\u003e n-bytes-consumed, n-bytes-produced\n#+END_SRC\n\nDecrypts data according to /cipher/ from /ciphertext/ starting at\n/ciphertext-start/ and continuing until /ciphertext-end/. The decrypted\ndata is placed in /plaintext/ starting at /plaintext-start/.\n\n\n#+NAME: encrypt-in-place\n#+BEGIN_SRC lisp\n(encrypt-in-place cipher text \u0026key start end) =\u003e n-bytes-consumed, n-bytes-produced\n#+END_SRC\n#+NAME: decrypt-in-place\n#+BEGIN_SRC lisp\n(decrypt-in-place cipher text \u0026key start end) =\u003e n-bytes-consumed, n-bytes-produced\n#+END_SRC\n\nEncrypts or decrypts data in /text/ between /start/ and /end/ \"in-place\"\naccording to /cipher/. These functions are shorthand for:\n#+BEGIN_EXAMPLE\n(encrypt cipher text text :plaintext-start start :plaintext-end end :ciphertext-start start)\n(decrypt cipher text text :ciphertext-start start :ciphertext-end end :plaintext-start start)\n#+END_EXAMPLE\n\n_Note:_ [[encrypt-in-place][encrypt-in-place]] and [[decrypt-in-place][decrypt-in-place]] do not support\na /handle-final-block/ parameter as [[encrypt][encrypt]] and [[decrypt][decrypt]] do. If you\nneed the functionality that /handle-final-block/ provides, then you\nneed to use [[encrypt][encrypt]] and [[decrypt][decrypt]].\n\n_Note:_ /n-bytes-consumed/ and /n-bytes-produced/ may not always be\nequal to the length of the data specified in the call to\n[[encrypt-in-place][encrypt-in-place]] or [[decrypt-in-place][decrypt-in-place]]. This subtlely is also present in\n[[encrypt][encrypt]] or [[decrypt][decrypt]].\n\n\n#+BEGIN_SRC lisp\n(encrypt-message cipher message \u0026key start end \u0026allow-other-keys) =\u003e encrypted-message\n#+END_SRC\n\nReturn the /message/ between /start/ and /end/ encrypted with the /cipher/; the\nclass of /cipher/ determines the algorithm used to encrypt the message.\n\n\n#+BEGIN_SRC lisp\n(decrypt-message cipher message \u0026key start end \u0026allow-other-keys) =\u003e decrypted-message\n#+END_SRC\n\nReturn the /message/ between /start/ and /end/ decrypted by the /cipher/; the\nclass of /cipher/ determines the algorithm used to decrypt the message.\n\n** Inquiry functions\n\n#+NAME: list-all-ciphers\n#+BEGIN_SRC lisp\n(list-all-ciphers) =\u003e list\n#+END_SRC\n\nReturns a list of cipher-names that may be validly passed to [[make-cipher][make-cipher]].\n\n\n#+NAME: cipher-supported-p\n#+BEGIN_SRC lisp\n(cipher-supported-p name) =\u003e boolean\n#+END_SRC\n\nReturns ~t~ if /name/ would be in the list returned by [[list-all-ciphers][list-all-ciphers]],\n~nil~ otherwise.\n\n\n#+NAME: key-lengths\n#+BEGIN_SRC lisp\n(key-lengths cipher) =\u003e list\n#+END_SRC\n\nReturn a list of valid key lengths for /cipher/.\n\n\n#+NAME: block-length\n#+BEGIN_SRC lisp\n(block-length cipher) =\u003e number\n#+END_SRC\n\nReturn the number of octets /cipher/ processes at a time. This\nfunction always returns 1 for stream ciphers.\n\n** Key stream position\n\nBlock ciphers in CTR mode and some stream ciphers have the ability to change the\ncurrent position within the key stream in constant time instead of having to\nconsume all the bytes until the desired position is reached.\n\n#+NAME: keystream-position\n#+BEGIN_SRC lisp\n(keystream-position cipher \u0026optional position) =\u003e number or boolean\n#+END_SRC\n\nReturn or change the current /position/ within the key stream of a /cipher/.\nWhen /position/ is not supplied, [[keystream-position][keystream-position]] returns the current position\nin the key stream, or /nil/ if it can't be determined. When /position/ is\nsupplied, the key stream position of the /cipher/ is set to that /position/ if\npossible. [[keystream-position][keystream-position]] returns /t/ if the repositioning is performed\nsuccessfully, or /nil/ otherwise.\n\n[[keystream-position][keystream-position]] can be used with the following ciphers:\n - all the block ciphers (aes, twofish, etc.) in CTR mode\n - chacha\n - chacha/12\n - chacha/8\n - salsa20\n - salsa20/12\n - salsa20/8\n - xchacha\n - xchacha/12\n - xchacha/8\n - xsalsa20\n - xsalsa20/12\n - xsalsa20/8\n\n* Digests\n  :PROPERTIES:\n  :CUSTOM_ID: digests\n  :END:\n\nDigest functions, also known as hash functions, produce fixed-length\noutput (a /digest/ or /hash/) from a variable-length message. The\nsimplest example of a digest function is one that adds up all the\nbytes in the message modulo 256. This digest function fails one test\nof a cryptographically secure hash function: it must be difficult to\nfind a message with a given digest. It also fails the other test: it\nmust be difficult to find two messages with the same digest.\n\nIronclad provides several cryptographically secure digest functions\nand several non-cryptographically secure digest functions.\n\n_Note:_ In the functions below, messages or parts thereof are provided\nas octet vectors; Ironclad has no facilities for producing digests of\nstrings. If you need to obtain the digest of a string, then you need\nto figure out how to convert it to an octet vector first. This is\na deliberate design decision. Characters are not equivalent to bytes.\nSee your local Unicode guru for more details.\n\n\n#+NAME: make-digest\n#+BEGIN_SRC lisp\n(make-digest digest-name \u0026rest keys \u0026key \u0026allow-other-keys) =\u003e digester\n#+END_SRC\n\nReturns a digest object. /digest-name/ is a keyword naming the\nalgorithm you wish /digester/ to use. The supported digest names can be found\nby calling [[list-all-digests][list-all-digests]]. They are:\n - adler32\n - blake2\n - blake2/160\n - blake2/256\n - blake2/384\n - blake2s\n - blake2s/128\n - blake2s/160\n - blake2s/224\n - crc24\n - crc32\n - crc32c\n - groestl\n - groestl/224\n - groestl/256\n - groestl/384\n - jh\n - jh/224\n - jh/256\n - jh/384\n - keccak\n - keccak/224\n - keccak/256\n - keccak/384\n - kupyna\n - kupyna/256\n - md2\n - md4\n - md5\n - ripemd-128\n - ripemd-160\n - sha1\n - sha224\n - sha256\n - sha3\n - sha3/224\n - sha3/256\n - sha3/384\n - sha384\n - sha512\n - shake128\n - shake256\n - skein1024\n - skein1024/384\n - skein1024/512\n - skein256\n - skein256/128\n - skein256/160\n - skein256/224\n - skein512\n - skein512/128\n - skein512/160\n - skein512/224\n - skein512/256\n - skein512/384\n - sm3\n - streebog\n - streebog/256\n - tiger\n - tree-hash\n - whirlpool\n\nLike for [[make-cipher][make-cipher]], /digest-name/ should be a symbol in the\n~keyword~ or ~ironclad~ packages.\n\nSome algorithms (e.g. shake128 and shake256) can produce digests of\nany size. The size of the digest in bytes can be specified with the\n/output-length/ key parameter:\n\n#+BEGIN_EXAMPLE\n(make-digest :shake256 :output-length 123)\n#+END_EXAMPLE\n\n\n#+NAME: update-digest\n#+BEGIN_SRC lisp\n(update-digest digester thing \u0026key \u0026allow-other-keys) =\u003e (values)\n#+END_SRC\n\nUpdates the internal state of /digester/ with the contents of /thing/.\nThe exact method is determined by the type of /thing/.\n\nThere are several methods defined on this generic function that take\na particular digester and a ~(simple-array (unsigned-byte 8) (*))~ as\nwell as the usual /start/ and /end/ keyword arguments. These methods\nupdate the state of /digester/ with the subsequence of the array\ndenoted by /start/ and /end/. They are not listed here because there's\none method for every type of digest that Ironclad provides, and\nlisting them would get very tedious for no benefit. An example should\nsuffice.\n\n#+BEGIN_EXAMPLE\n(let ((digester (ironclad:make-digest :sha1))\n      (array (make-array 16 :element-type '(unsigned-byte 8) :initial-element 0)))\n  ;; Update with 16 zeroes.\n  (ironclad:update-digest digester array)\n  ;; Update with 8 ones.\n  (fill array 1 :start 2 :end 10)\n  (ironclad:update-digest digester array :start 2 :end 10))\n#+END_EXAMPLE\n\n\n#+BEGIN_SRC lisp\n(update-digest digester (stream stream) \u0026key buffer start end \u0026allow-other-keys) =\u003e digester\n#+END_SRC\n\nUpdate the internal state of /digester/ with the contents of /stream/,\nwhich must respond to ~read-byte~ or ~read-sequence~ with\na ~(simple-array (unsigned-byte 8) (*))~ and return /digester/. It\ndiffers from [[digest-stream][digest-stream]], below, in that you may need to digest data\nbefore or after the contents of /stream/ (this happens, for instance,\nwhen signing the contents of some file).\n\n\n#+NAME: produce-digest\n#+BEGIN_SRC lisp\n(produce-digest digester \u0026key digest digest-start) =\u003e digest\n#+END_SRC\n\nReturn the digest of the data processed by /digester/ so far.\n\nIf /digest/ is provided, the computed digest will be placed into\n/digest/ starting at /digest-start/. /digest/ must be a\n~(simple-array (unsigned-byte 8) (*))~. An [[insufficient-buffer-space][insufficient-buffer-space]]\nerror will be signaled if there is insufficient space in /digest/.\n\n** High-level convenience functions\n\nSeveral high-level convenience functions that encapsulate common\nsequences of [[make-digest][make-digest]], [[update-digest][update-digest]] and [[produce-digest][produce-digest]] are\nprovided by Ironclad as well. They come in two flavors: the first\ntakes a digest name as would be provided to [[make-digest][make-digest]]. The second\nway to call these functions is to provide an actual digest object as\nthe first argument. So one can say:\n\n#+BEGIN_EXAMPLE\n(ironclad:digest-sequence :md5 *buffer*)\n#+END_EXAMPLE\n\nor, equivalently:\n\n#+BEGIN_EXAMPLE\n(let ((digester (ironclad:make-digest :md5)))\n  (ironclad:digest-sequence digester *buffer*))\n#+END_EXAMPLE\n\nThe second form comes in handy if you plan on [[*Miscellaneous][reusing the digest object]].\n\n\n#+NAME: digest-sequence\n#+BEGIN_SRC lisp\n(digest-sequence digest-spec sequence \u0026rest args \u0026key start end digest digest-start) =\u003e digest\n#+END_SRC\n\nReturns the digest of the subsequence of /sequence/ bounded by /start/\nand /end/, according to /digest-name/. /sequence/ must be\na ~(vector (unsigned-byte 8))~. /digest/ and /digest-start/\nare as in [[produce-digest][produce-digest]].\n\n\n#+NAME: digest-stream\n#+BEGIN_SRC lisp\n(digest-stream digest-spec stream \u0026rest args \u0026key buffer start end digest digest-start) =\u003e digest\n#+END_SRC\n\nReturns the digest of the contents of the stream specified by\n/stream/. ~read-byte~ must be a legal operation on /stream/ and return\nan ~(unsigned-byte 8)~. In a similar fashion, ~read-sequence~ on\n/stream/ must support reading into a ~(simple-array (unsigned-byte 8) (*))~.\n/digest/ and /digest-start/ are as in [[produce-digest][produce-digest]].\n\nIf /buffer/ is provided, it must be a ~(simple-array (unsigned-byte 8) (*))~;\nthe portion of /buffer/ between /start/ and /end/ will be used to read\nthe data from the stream.\n\n\n#+NAME: digest-file\n#+BEGIN_SRC lisp\n(digest-file digest-spec pathname \u0026rest args \u0026key buffer start end digest digest-start) =\u003e digest\n#+END_SRC\n\nReturns the digest of the contents of the file named by /pathname/.\n/digest/ and /digest-start/ are as in [[produce-digest][produce-digest]].\n\nIf /buffer/ is provided, it must be a ~(simple-array (unsigned-byte 8) (*))~;\nthe portion of /buffer/ between /start/ and /end/ will be used to read\nthe data from the stream.\n\n** Inquiry functions\n\n#+NAME: list-all-digests\n#+BEGIN_SRC lisp\n(list-all-digests) =\u003e list\n#+END_SRC\n\nReturns a list whose elements may be validly passed to [[make-digest][make-digest]].\n\n\n#+NAME: digest-supported-p\n#+BEGIN_SRC lisp\n(digest-supported-p name) =\u003e boolean\n#+END_SRC\n\nReturns ~t~ if /name/ would be in the list returned by [[list-all-digests][list-all-digests]],\n~nil~ otherwise.\n\n\n#+NAME: digest-length\n#+BEGIN_SRC lisp\n(digest-length digest) =\u003e number\n#+END_SRC\n\nReturns the length of the digest computed by /digest/, which may be\na digest-name or a digest instance.\n\n** Miscellaneous\n\nIronclad digests are CLOS objects; the interesting thing about this\nfor most purposes is that functions like ~reinitialize-instance~ are\nsupported. This means one can write a fairly efficient clone of the\n=md5sum= program like so:\n\n#+BEGIN_EXAMPLE\n(defun digest-sum-files (digest-name \u0026rest files)\n  (unless files\n    (error \"no files given to digest\"))\n  (loop with buffer = (make-array 8192 :element-type '(unsigned-byte 8))\n        with digest = (make-array (ironclad:digest-length digest-name)\n                                  :element-type '(unsigned-byte 8))\n       for file in files\n       for digester = (ironclad:make-digest digest-name)\n       then (reinitialize-instance digester)\n       do (ironclad:digest-file digester file :buffer buffer :digest digest)\n          (format t \"~A ~A~%\" (file-namestring file)\n                  (ironclad:byte-array-to-hex-string digest))))\n#+END_EXAMPLE\n\n** Tree hashes\n\nIronclad supports tree hashes, as described in [[http://web.archive.org/web/20080316033726/http://www.open-content.net/specs/draft-jchapweske-thex-02.html][Tree Hash EXchange format]].\nYou create tree hashes as if you were creating a digest:\n\n#+BEGIN_EXAMPLE\n(ironclad:make-digest :tree-hash)\n#+END_EXAMPLE\n\nBy default, this creates a tree hash that uses the Tiger digest\nalgorithm internally and a segment size of 1024. Since using the Tiger\ndigest algorithm is so common, a convenience function that makes your\nintent obvious has also been provided:\n\n#+BEGIN_EXAMPLE\n(ironclad:make-tiger-tree-hash)\n#+END_EXAMPLE\n\nYou may indicate that you wish to use a different algorithm than\nTiger:\n\n#+BEGIN_EXAMPLE\n(ironclad:make-digest '(:treehash :digest :sha256))\n#+END_EXAMPLE\n\nOr you might wish to use a different segment size:\n\n#+BEGIN_EXAMPLE\n(ironclad:make-digest '(:tree-hash :block-length 16384))\n#+END_EXAMPLE\n\nThere is currently no interface for obtaining the intermediate hashes\ncomputed while computing the final tree hash.\n\n* Message authentication codes\n  :PROPERTIES:\n  :CUSTOM_ID: message-authentication-codes\n  :END:      \n\nA message authentication code is a cryptographic function of some data\nand a user-specified key. Only a person knowing the key can recompute\nthe MAC for the given message. A MAC is useful where maintaining data\nintegrity is required, but the secrecy of the data is not paramount.\n\nIronclad provides different kinds of MACs:\n - HMAC, specified in [[http://www.ietf.org/rfc/rfc2104.txt][RFC 2104]]\n - CMAC, specified in [[http://www.ietf.org/rfc/rfc4493.txt][RFC 4493]] and NIST document 800-38B\n - GMAC, specified in NIST document 800-38D\n - Blake2 and Blake2s MAC\n - Poly1305\n - SipHash\n - Skein MAC\n\n\n#+NAME: make-mac\n#+BEGIN_SRC lisp\n(make-mac mac-name key \u0026rest args) =\u003e mac\n#+END_SRC\n\nReturn a MAC object initialized with a secret /key/. /mac-name/ is\na keyword naming the algorithm you wish /mac/ to use. The supported\nMACs can be found by calling [[list-all-macs][list-all-macs]]. They are:\n - blake2-mac\n - blake2s-mac\n - cmac\n - gmac\n - hmac\n - poly1305\n - siphash\n - skein-mac\n\nLike for [[make-digest][make-digest]], /mac-name/ should be a symbol in the ~keyword~\nor ~ironclad~ packages.\n\nSome MACs take extra arguments that can be specified in /args/.\n\n#+BEGIN_EXAMPLE\n(make-mac :blake2-mac key \u0026key digest-length)\n(make-mac :blake2s-mac key \u0026key digest-length)\n(make-mac :cmac key cipher-name)\n(make-mac :gmac key cipher-name initialization-vector)\n(make-mac :hmac key digest-name)\n(make-mac :poly1305 key)\n(make-mac :siphash key \u0026key compression-rounds finalization-rounds digest-length)\n(make-mac :skein-mac key \u0026key block-length digest-length)\n#+END_EXAMPLE\n\nWhen making a Blake2 MAC, the length of the /key/ passed to [[make-mac][make-mac]]\nmust be 64 bytes.\n\nWhen making a Blake2s MAC, the length of the /key/ passed to [[make-mac][make-mac]]\nmust be 32 bytes.\n\nWhen making a CMAC, /cipher-name/ must have a [[block-length][block-length]] of either 8, 16, 32,\n64 or 128; this restriction is satisfied by many ciphers in Ironclad with the\nnotable exception of stream ciphers. /key/ must be an acceptable key for\n/cipher-name/.\n\nWhen making a GMAC, /cipher-name/ must have a [[block-length][block-length]] of 16. /key/ must be\nan acceptable key for /cipher-name/.\n\nWhen making a Poly1305 MAC, the length of the /key/ passed to [[make-mac][make-mac]] must be\n32 bytes.\n\nWhen making a SipHash MAC, the length of the /key/ passed to [[make-mac][make-mac]] must be 16\nbytes. /digest-length/ is 8 by default, but it can also be set to 16. By\ndefault, /compression-rounds/ is 2 and /finalization-rounds/ is 4.\n\nWhen making a Skein MAC, /block-length/ can be 32 (to use the Skein256\nhash function internally), 64 (to use Skein512) or 128 (to use\nSkein1024). /digest-length/ can be any length you want the computed\ndigest to be. By default, /block-length/ is 64 and /digest-length/\nis 64.\n\n\nMAC objects support ~reinitialize-instance~:\n\n#+BEGIN_SRC lisp\n(reinitialize-instance mac \u0026rest initargs \u0026key key \u0026allow-other-keys) =\u003e mac\n#+END_SRC\n\nThe /:key/ argument is the secret key, as provided to [[make-mac][make-mac]].\n\n\n#+NAME: update-mac\n#+BEGIN_SRC lisp\n(update-mac mac thing \u0026key \u0026allow-other-keys) =\u003e (values)\n#+END_SRC\n\nUpdates the internal state of /mac/ with the contents of /thing/.\nThe exact method is determined by the type of /thing/.\n\nThere are several methods defined on this generic function that take\na particular MAC and a ~(simple-array (unsigned-byte 8) (*))~ as\nwell as the usual /start/ and /end/ keyword arguments. These methods\nupdate the state of /mac/ with the subsequence of the array\ndenoted by /start/ and /end/. They are not listed here because there's\none method for every type of MAC that Ironclad provides, and\nlisting them would get very tedious for no benefit. An example should\nsuffice.\n\n#+BEGIN_EXAMPLE\n(let* ((key (random-data 32))\n       (mac (ironclad:make-mac :hmac key :sha256))\n       (array (make-array 16 :element-type '(unsigned-byte 8) :initial-element 0)))\n  ;; Update with 16 zeroes.\n  (ironclad:update-mac mac array)\n  ;; Update with 8 ones.\n  (fill array 1 :start 2 :end 10)\n  (ironclad:update-mac mac array :start 2 :end 10))\n#+END_EXAMPLE\n\n\n#+NAME: produce-mac\n#+BEGIN_SRC lisp\n(produce-mac mac \u0026key digest digest-start) =\u003e digest\n#+END_SRC\n\nReturn the digest of the data processed by /mac/ so far. The internal\nstate of /mac/ is not modified; this feature makes it possible to\ncompute a \"rolling MAC\" of a document.\n\nIf /digest/ is provided, the computed digest will be placed into\n/digest/ starting at /digest-start/. /digest/ must be a\n~(simple-array (unsigned-byte 8) (*))~. An [[insufficient-buffer-space][insufficient-buffer-space]]\nerror will be signaled if there is insufficient space in /digest/.\n\nThe length of the digest returned by [[produce-mac][produce-mac]] is determined by the\nkind of MAC and the extra arguments passed to [[make-mac][make-mac]]:\n - blake2-mac: from 1 to 64 bytes (64 by default)\n - blake2s-mac: from 1 to 32 bytes (32 by default)\n - cmac: [[block-length][block-length]] of the /cipher-name/ passed to [[make-mac][make-mac]]\n - gmac: 16 bytes\n - hmac: [[digest-length][digest-length]] of the /digest-name/ passed to [[make-mac][make-mac]]\n - poly1305: 16 bytes\n - siphash: /digest-length/ passed to [[make-mac][make-mac]] (8 by default)\n - skein-mac: /digest-length/ passed to [[make-mac][make-mac]] (64 by default)\n\n** Inquiry functions\n\n#+NAME: list-all-macs\n#+BEGIN_SRC lisp\n(list-all-macs) =\u003e list\n#+END_SRC\n\nReturns a list whose elements may be validly passed to [[make-mac][make-mac]].\n\n\n#+NAME: mac-supported-p\n#+BEGIN_SRC lisp\n(mac-supported-p name) =\u003e boolean\n#+END_SRC\n\nReturns ~t~ if /name/ would be in the list returned by [[list-all-macs][list-all-macs]],\n~nil~ otherwise.\n\n* Authenticated encryption\n  :PROPERTIES:\n  :CUSTOM_ID: authenticated-encryption\n  :END:\n\n#+NAME: make-authenticated-encryption-mode\n#+BEGIN_SRC lisp\n(make-authenticated-encryption-mode name \u0026rest args) =\u003e mode\n#+END_SRC\n\nReturn an authenticated encryption object suitable for use for both encryption\nand decryption.\n\n/name/ denotes the mode to use. [[list-all-authenticated-encryption-modes][list-all-authenticated-encryption-modes]] will\ntell you the names of all the supported modes. They are:\n - eax (Encrypt then authenticate then translate)\n - etm (Encrypt then MAC)\n - gcm (Galois counter mode)\n\n/name/ can be a symbol in the ~keyword~  or ~ironclad~ packages.\n\n/args/ depends on the chosen authenticated encryption mode.\n\n#+BEGIN_EXAMPLE\n(make-authenticated-encryption-mode :eax \u0026key tag cipher-name key initialization-vector)\n(make-authenticated-encryption-mode :etm \u0026key tag cipher mac)\n(make-authenticated-encryption-mode :gcm \u0026key tag cipher-name key initialization-vector)\n#+END_EXAMPLE\n\nIf /tag/ is specified, it will be used at the end of decryption (when the\n/handle-final-block/ flag is ~t~) to check the authenticity of the data.\nA ~bad-authentication-tag~ error will be signaled if the data is not authentic.\nIf you don't specify it, you will have to call [[produce-tag][produce-tag]] after decryption and\ncheck that the tags match (e.g. using [[constant-time-equal][constant-time-equal]]).\n\nWhen using EAX, /key/ must be a suitable key for the chosen /cipher-name/.\n\nWhen using ETM, /cipher/ must be a cipher object created by [[make-cipher][make-cipher]].\n/mac/ must be a mac object created by [[make-mac][make-mac]].\n\nWhen using GCM, /cipher-name/ must have a [[block-length][block-length]] of 16 bytes. /key/ must be a suitable key\nfor the chosen cipher.\n\n\n#+NAME: process-associated-data\n#+BEGIN_SRC lisp\n(process-associated-data mode data \u0026key start end) =\u003e (values)\n#+END_SRC\n\nUpdate the internal state of /mode/ with the contents of /data/ between /start/\nand /end/ so that they are taken into consideration in the authentication tag.\n\n\nAn authenticated encryption object can be used with the [[encrypt][encrypt]], [[decrypt][decrypt]],\n[[encrypt-message][encrypt-message]] and [[decrypt-message][decrypt-message]] functions.\n\n#+BEGIN_EXAMPLE\n(encrypt mode plaintext ciphertext \u0026key plaintext-start plaintext-end ciphertext-start handle-final-block)\n(decrypt mode ciphertext plaintext \u0026key ciphertext-start ciphertext-end plaintext-start handle-final-block)\n(encrypt-message mode message \u0026key start end associated-data associated-data-start associated-data-end)\n(decrypt-message mode message \u0026key start end associated-data associated-data-start associated-data-end)\n#+END_EXAMPLE\n\n\n#+NAME: produce-tag\n#+BEGIN_SRC lisp\n(produce-tag mode \u0026key tag tag-start) =\u003e tag\n#+END_SRC\n\nReturn the authentication tag of the data processed by /mode/ so far. If /tag/\nis provided, the computed tag will be placed into /tag/ starting at /tag-start/.\n/tag/ must be a ~(simple-array (unsigned-byte 8) (*))~. An\n[[insufficient-buffer-space][insufficient-buffer-space]] error will be signaled if there is insufficient space\nin /tag/.\n\n** Inquiry functions\n\n#+NAME: list-all-authenticated-encryption-modes\n#+BEGIN_SRC lisp\n(list-all-authenticated-encryption-modes) =\u003e list\n#+END_SRC\n\nReturns a list whose elements may be validly passed to\n[[make-authenticated-encryption-mode][make-authenticated-encryption-mode]].\n\n\n#+NAME: authenticated-encryption-mode-supported-p\n#+BEGIN_SRC lisp\n(authenticated-encryption-mode-supported-p name) =\u003e boolean\n#+END_SRC\n\nReturns ~t~ if /name/ would be in the list returned by\n[[list-all-authenticated-encryption-modes][list-all-authenticated-encryption-modes]] ~nil~ otherwise.\n\n* Key derivation functions\n  :PROPERTIES:\n  :CUSTOM_ID: key-derivation-functions\n  :END:\n\nIronclad comes with a few key derivation functions:\n - Argon2 (only variants without parallelism are implemented)\n - Bcrypt\n - Bcrypt-pbkdf\n - PBKDF1\n - PBKDF2\n - Scrypt\n - HMAC\n\n\n#+NAME: derive-key\n#+BEGIN_SRC lisp\n(derive-key kdf passphrase salt iteration-count key-length) =\u003e digest\n#+END_SRC\n\nGiven a key derivation function object (produced by [[make-kdf][make-kdf]]),\na password and salt (both must be of type\n~(simple-array (unsigned-byte 8) (*))~), and number of iterations,\nreturns the password digest as a byte array of length /key-length/.\n\nFor bcrypt, the /salt/ must be 16 bytes long, the /iteration-count/ must be\na power of 2 between 2^4 and 2^31, and the /key-length/ must be 24.\nScrypt and HMAC ignore the /iteration-count/ parameter.\n\nFor bcrypt-pbkdf, the /key-length/ must be between 1 and 1024.\n\n\n#+NAME: make-kdf\n#+BEGIN_SRC lisp\n(make-kdf kind \u0026key digest n r p block-count additional-key additional-data) =\u003e kdf\n#+END_SRC\n\nReturns a key derivation function instance.\n\n/kind/ denotes the key derivation function to use. They are:\n - argon2d\n - argon2i\n - argon2id\n - bcrypt\n - bcrypt-pbkdf\n - pbkdf1\n - pbkdf2\n - scrypt-kdf\n - hmac-kdf\n\n/kind/ can be a symbol in the ~keyword~  or ~ironclad~ packages.\n\nThe Argon2 key derivations use the /block-count/, /additional-key/\nand /additional-data/ parameters (/block-count/ is the number of 1 KiB\nmemory blocks used by the function and it must be at least 8,\n/additional-key/ and /additional-data/ are optional).\nThe PBKDF algorithms use /digest/.\nThe Scrypt key derivation uses cost parameters /N/, /r/ and /p/ (/N/\nis a CPU cost parameter that must be a power of 2, /r/ and /p/ are\nmemory cost parameters that must be defined such that\n/r/ * /p/ \u003c= 2^30).\n\nThe default Scrypt parameters are /N/ = 4096, /r/ = 8, and /p/ = 2.\nPlease note that depending on the values of /N/ and /r/,\n[[derive-key][derive-key]] may not be able to allocate sufficient space for its\ntemporary arrays.\n\nThe HMAC-KDF algorithm uses the /digest/ parameter to precise what\nhash function is used. It also optionally uses the /additional-data/\nto precise the ~info~ vector from the [[https://tools.ietf.org/html/rfc5869][RFC]].\n\n\n#+NAME: list-all-kdfs\n#+BEGIN_SRC lisp\n(list-all-kdfs) =\u003e list\n#+END_SRC\n\nReturns a list of KDF kinds that may be validly passed to [[make-kdf][make-kdf]].\n\n** PBKDF convenience functions\n\nIronclad comes with convenience functions for using PBKDF1 and PBKDF2\nto store passwords.\n\n\n#+NAME: pbkdf2-hash-password\n#+BEGIN_SRC lisp\n(pbkdf2-hash-password password \u0026key salt digest iterations) =\u003e password\n#+END_SRC\n\nConvenience function for hashing passwords using the PBKDF2 algorithm.\nReturns the derived hash of the password, and the original salt, as\nbyte vectors.\n\n\n#+NAME: pbkdf2-hash-password-to-combined-string\n#+BEGIN_SRC lisp\n(pbkdf2-hash-password-to-combined-string password \u0026key salt digest iterations) =\u003e password\n#+END_SRC\n\nConvenience function for hashing passwords using the PBKDF2 algorithm.\nReturns the derived hash of the password as a single string that\nencodes the given salt and PBKDF2 algorithm parameters.\n\n\n#+NAME: pbkdf2-check-password\n#+BEGIN_SRC lisp\n(pbkdf2-check-password password combined-salt-and-digest) =\u003e boolean\n#+END_SRC\n\nGiven a /password/ byte vector and a combined salt and digest string\nproduced by [[pbkdf2-hash-password-to-combined-string][pbkdf2-hash-password-to-combined-string]], checks whether\nthe password is valid.\n\n* Public key cryptography\n  :PROPERTIES:\n  :CUSTOM_ID: public-key-cryptography\n  :END:\n\nIronclad includes support for a few public key cryptography algorithms.\n\nEncryption algorithms:\n - Elgamal\n - RSA\n\nSignature algorithms:\n - DSA\n - Ed25519\n - Ed448\n - Elgamal\n - RSA\n - Secp256k1\n - Secp256r1 (a.k.a. NIST P-256)\n - Secp384r1 (a.k.a. NIST P-384)\n - Secp521r1 (a.k.a. NIST P-521)\n\nDiffie-Hellman key exchange:\n - Curve25519\n - Curve448\n - Elgamal\n - Secp256k1\n - Secp256r1 (a.k.a. NIST P-256)\n - Secp384r1 (a.k.a. NIST P-384)\n - Secp521r1 (a.k.a. NIST P-521)\n\n** Key pair generation\n\n#+NAME: generate-key-pair\n#+BEGIN_SRC lisp\n(generate-key-pair kind \u0026key num-bits \u0026allow-other-keys) =\u003e private-key, public-key\n#+END_SRC\n\nReturn a key pair according to /kind/. The generation of DSA, Elgamal\nand RSA key pairs can take some time. If /kind/ is ~:dsa~ or ~:rsa~,\nthe /num-bits/ key argument indicating the size of the keys to\ngenerate must be specified. If /kind/ is ~:elgamal~, /num-bits/ must\nbe specified unless /compatible-with-key/ is specified, in which case\nthe group parameters are taken from the specified key instead of being\ngenerated.\n\nFor example, if Alice wants to generate a key pair for\na Diffie-Hellman exchange with Bob's Elgamal key pair:\n#+BEGIN_EXAMPLE\n(generate-key-pair :elgamal :compatible-with-key bob-public-key)\n#+END_EXAMPLE\n\n\n#+NAME: list-all-key-pair-kinds\n#+BEGIN_SRC lisp\n(list-all-key-pair-kinds) =\u003e list\n#+END_SRC\n\nReturns a list of key pair kinds that may be validly passed to\n[[generate-key-pair][generate-key-pair]].\n\n*** Key construction\n\n#+NAME: make-public-key\n#+BEGIN_SRC lisp\n(make-public-key kind \u0026key \u0026allow-other-keys) =\u003e public-key\n#+END_SRC\n\nReturn a public key according to /kind/. The /\u0026key/\narguments vary according to /kind/. The interesting bits are in the\nmethods that specialize on /kind/, below.\n\n#+BEGIN_EXAMPLE\n(make-public-key :curve25519 \u0026key y) =\u003e public-key\n(make-public-key :curve448 \u0026key y) =\u003e public-key\n(make-public-key :dsa \u0026key p q g y) =\u003e public-key\n(make-public-key :ed25519 \u0026key y) =\u003e public-key\n(make-public-key :ed448 \u0026key y) =\u003e public-key\n(make-public-key :elgamal \u0026key p g y) =\u003e public-key\n(make-public-key :rsa \u0026key e n) =\u003e public-key\n(make-public-key :secp256k1 \u0026key y) =\u003e public-key\n(make-public-key :secp256r1 \u0026key y) =\u003e public-key\n(make-public-key :secp384r1 \u0026key y) =\u003e public-key\n(make-public-key :secp521r1 \u0026key y) =\u003e public-key\n#+END_EXAMPLE\n\n\n#+NAME: make-private-key\n#+BEGIN_SRC lisp\n(make-private-key kind \u0026key \u0026allow-other-keys) =\u003e private-key\n#+END_SRC\n\nReturn a private key according to /kind/. The /\u0026key/ arguments vary\naccording to /kind/. The interesting bits are in the methods that\nspecialize on /kind/, below.\n\n#+BEGIN_EXAMPLE\n(make-private-key :curve25519 \u0026key x y) =\u003e private-key\n(make-private-key :curve448 \u0026key x y) =\u003e private-key\n(make-private-key :dsa \u0026key p q g y x) =\u003e private-key\n(make-private-key :ed25519 \u0026key x y) =\u003e private-key\n(make-private-key :ed448 \u0026key x y) =\u003e private-key\n(make-private-key :elgamal \u0026key p g y x) =\u003e private-key\n(make-private-key :rsa \u0026key d n p q) =\u003e private-key\n(make-private-key :secp256k1 \u0026key x y) =\u003e private-key\n(make-private-key :secp256r1 \u0026key x y) =\u003e private-key\n(make-private-key :secp384r1 \u0026key x y) =\u003e private-key\n(make-private-key :secp521r1 \u0026key x y) =\u003e private-key\n#+END_EXAMPLE\n\n\nFor Curve25519, Curve448, Ed25519, Ed448 keys, Secp256k1, Secp256r1, Secp384r1\nand Secp521r1, the type of the parameters is\n~(simple-array (unsigned-byte 8) (*))~:\n - /x/, the secret key\n - /y/, the public key\n\nFor DSA and Elgamal keys, the type of the parameters is ~integer~:\n - /p/, the prime number defining the DL group\n - /q/, the prime number defining the DL sub-group\n - /g/, the generator\n - /y/, the public key\n - /x/, the private key\n\nFor RSA keys, the type of the parameters is ~integer~:\n - /n/, the modulus\n - /e/, the public key\n - /d/, the private key\n - /p/, the first prime factor of /n/\n - /q/, the second prime factor of /n/\n\n*** Key destructuring\n\nThe [[destructure-public-key][destructure-public-key]] and [[destructure-private-key][destructure-private-key]] functions can\nbe useful if you need to store keys somewhere for future use.\n\n#+NAME: destructure-public-key\n#+BEGIN_SRC lisp\n(destructure-public-key public-key) =\u003e plist\n#+END_SRC\n\nReturn the elements of a public key in a plist. The indicators of the\nplist match the /\u0026key/ arguments of the [[make-public-key][make-public-key]] method.\n\n\n#+NAME: destructure-private-key\n#+BEGIN_SRC lisp\n(destructure-private-key private-key) =\u003e plist\n#+END_SRC\n\nReturn the elements of a private key in a plist. The indicators of the\nplist match the /\u0026key/ arguments of the [[make-private-key][make-private-key]] method.\n\n** Digital signatures\n\n#+NAME: sign-message\n#+BEGIN_SRC lisp\n(sign-message key message \u0026key start end \u0026allow-other-keys) =\u003e signature\n#+END_SRC\n\nReturn a signature of /message/ between /start/ and /end/ signed with\n/key/; the class of /key/ determines the algorithm used to create the\n/signature/.\n\n_Note:_ The [[sign-message][sign-message]] does not perform the hashing of the data. You\nshould hash your data using your favorite hash function, and then use\nthis hash as the /message/ passed to [[sign-message][sign-message]].\n\n\n#+NAME: verify-signature\n#+BEGIN_SRC lisp\n(verify-signature key message signature \u0026key start end \u0026allow-other-keys) =\u003e boolean\n#+END_SRC\n\nVerify whether /signature/ is a valid signature of /message/ between\n/start/ and /end/ using /key/. Return ~t~ is the signature is valid\nand ~nil~ otherwise.\n\n*** Padding\n\nTo be secure, RSA signature requires the message to be padded.\nThe /pss/ key parameter is provided to pad (or unpad) the message\nduring signature (or verification) with the PSS scheme of PKCS-1.\nThe value of the /pss/ key parameter can be either a digest name\nor ~t~ (which will use the sha1 digest).\n\n#+BEGIN_EXAMPLE\n(sign-message rsa-private-key message :pss t) =\u003e signature\n(verify-signature rsa-public-key message signature :pss t) =\u003e boolean\n#+END_EXAMPLE\n\nThe functions /pss-encode/ and /pss-decode/ can also be used by hand if\nnecessary.\n\n*** Signature nonce\n\nDSA, Elgamal and ECDSA (Secp256k1, Secp256r1, Secp384r1 and Secp521r1)\nsignatures require the generation of a nonce. You must never sign two different\nmessages with the same key and the same nonce, or anyone having these two\nsignatures will be able compute your private key. Ironclad uses the\n[[generate-signature-nonce][generate-signature-nonce]] method which by default generates random nonces.\n\n#+NAME: generate-signature-nonce\n#+BEGIN_SRC lisp\n(generate-signature-nonce (key message \u0026optional parameters)) =\u003e nonce\n#+END_SRC\n\nFor DSA, /parameters/ is /q/. For Elgamal, /parameters/ is /p/. For ECDSA,\n/parameters/ is ~nil~.\n\n\nIf instead of random nonces, you want to have deterministic nonces (e.g. like\nin RFC 6979), you will have to redefine [[generate-signature-nonce][generate-signature-nonce]]. For example,\nto have deterministic nonces for Secp256k1 ECDSA signatures, you could do\nsomething like:\n\n#+BEGIN_EXAMPLE\n(defmethod generate-signature-nonce ((key secp256k1-private-key) message \u0026optional parameters)\n  (declare (ignore parameters))\n  (compute-deterministic-nonce key message))\n#+END_EXAMPLE\n\n*** Format of signatures\n\n[[sign-message][sign-message]] returns signatures as octet vectors. When the signature\ncontains several values (e.g. the R and S values of DSA signatures),\nthe octet vector is the concatenation of these values (e.g. the first\nhalf of the vector is the R value, the second half is the S value).\nYou can use the [[make-signature][make-signature]] and [[destructure-signature][destructure-signature]] functions if\nyou need access to the elements of a signature (e.g. to use\na different kind of serialization).\n\n\n#+NAME: make-signature\n#+BEGIN_SRC lisp\n(make-signature kind \u0026key \u0026allow-other-keys) =\u003e signature\n#+END_SRC\n\nReturn an octet vector representing a signature. The /\u0026key/ arguments\nvary according to /kind/. The interesting bits are in the methods that\nspecialize on /kind/, below.\n\n#+BEGIN_EXAMPLE\n(make-signature :dsa \u0026key r s n-bits) =\u003e signature\n(make-signature :ed25519 \u0026key r s) =\u003e signature\n(make-signature :ed448 \u0026key r s) =\u003e signature\n(make-signature :elgamal \u0026key r s n-bits) =\u003e signature\n(make-signature :rsa \u0026key s n-bits) =\u003e signature\n(make-signature :secp256k1 \u0026key r s) =\u003e signature\n(make-signature :secp256r1 \u0026key r s) =\u003e signature\n(make-signature :secp384r1 \u0026key r s) =\u003e signature\n(make-signature :secp521r1 \u0026key r s) =\u003e signature\n#+END_EXAMPLE\n\nFor Ed25519, Ed448, Secp256k1, Secp256r1, Secp384r1 and Secp521r1 signatures,\nthe type of the parameters /r/ and /s/ is\n~(simple-array (unsigned-byte 8) (*))~.\n\nFor DSA and Elgamal signatures, the type of the parameters /r/, /s/\nand /n-bits/ is ~integer~.\n\nFor RSA signatures, the type of the parameters /s/ and /n-bits/ is\n~integer~.\n\n\n#+NAME: destructure-signature\n#+BEGIN_SRC lisp\n(destructure-signature kind signature) =\u003e plist\n#+END_SRC\n\nReturn the elements of a signature in a plist. The indicators of the\nplist match the /\u0026key/ arguments of the [[make-signature][make-signature]] method.\n\n** Encryption and decryption\n\n#+NAME: encrypt-message\n#+BEGIN_SRC lisp\n(encrypt-message key message \u0026key start end \u0026allow-other-keys) =\u003e encrypted-message\n#+END_SRC\n\nReturn the /message/ between /start/ and /end/ encrypted with the /key/;\nthe class of /key/ determines the algorithm used to encrypt the message.\n\n\n#+NAME: decrypt-message\n#+BEGIN_SRC lisp\n(decrypt-message key message \u0026key start end n-bits \u0026allow-other-keys) =\u003e decrypted-message\n#+END_SRC\n\nReturn the /message/ between /start/ and /end/ decrypted by the /key/;\nthe class of /key/ determines the algorithm used to decrypt the message.\n/n-bits/ can be used to indicate the expected size of the decrypted\nmessage (e.g. a small byte vector starting with zeros encrypted\nwithout padding, which is probably a bad idea, c.f. Padding section).\n\n*** Padding\n\nTo be secure, RSA encryption requires the message to be padded. The\n/oaep/ key parameter is provided to pad (or unpad) the message during\nencryption (or decryption) with the OAEP scheme of PKCS-1.\nThe value of the /oaep/ key parameter can be either a digest name\nor ~t~ (which will use the sha1 digest).\n\n#+BEGIN_EXAMPLE\n(encrypt-message rsa-public-key message :oaep t) =\u003e encrypted-message\n(decrypt-message rsa-private-key message :oaep t) =\u003e decrypted-message\n#+END_EXAMPLE\n\nThe functions /oaep-encode/ and /oaep-decode/ can also be used by hand if\nnecessary.\n\n*** Format of messages\n\n[[encrypt-message][encrypt-message]] returns encrypted messages as octet vectors. When the\nmessage contains several values (e.g. the C1 and C2 values of Elgamal\nmessages), the octet vector is the concatenation of these values (e.g.\nthe first half of the vector is the big-endian representation of the\nC1 value, the second half is the C2 value). You can use the\n[[make-message][make-message]] and [[destructure-message][destructure-message]] functions if you need access to\nthe elements of a message (e.g. to use a different kind of\nserialization).\n\n\n#+NAME: make-message\n#+BEGIN_SRC lisp\n(make-message kind \u0026key \u0026allow-other-keys) =\u003e message\n#+END_SRC\n\nReturn an octet vector representing a message. The /\u0026key/ arguments\nvary according to /kind/. The interesting bits are in the methods that\nspecialize on /kind/, below.\n\n#+BEGIN_EXAMPLE\n(make-message :elgamal \u0026key c1 c2 n-bits) =\u003e message\n(make-message :rsa \u0026key m n-bits) =\u003e message\n#+END_EXAMPLE\n\nFor Elgamal messages, the type of the parameters /c1/, /c2/ and\n/n-bits/ is ~integer~.\n\nFor RSA signatures, the type of the parameters /m/ and /n-bits/ is\n~integer~.\n\n\n#+NAME: destructure-message\n#+BEGIN_SRC lisp\n(destructure-message kind message) =\u003e plist\n#+END_SRC\n\nReturn the elements of a message in a plist. The indicators of the\nplist match the /\u0026key/ arguments of the [[make-message][make-message]] method.\n\n** Diffie-Hellman key exchange\n\n#+NAME: diffie-hellman\n#+BEGIN_SRC lisp\n(diffie-hellman private-key public-key) =\u003e bytes\n#+END_SRC\n\nReturn a secret shared by two users Alice and Bob, computed from\nAlice's private key and Bob's public key (these keys must be\ncompatible, i.e. have the same group parameters).\n\n** Elliptic curve operations\n\n#+NAME: ec-make-point\n#+BEGIN_SRC lisp\n(ec-make-point kind \u0026key \u0026allow-other-keys) =\u003e point\n#+END_SRC\n\nReturn a point of /kind/, initialized according to the specified coordinates.\nThe interesting bits are in the methods that specialize on /kind/, below.\n\n#+BEGIN_EXAMPLE\n(ec-make-point :curve25519 \u0026key x)\n(ec-make-point :curve448 \u0026key x)\n(ec-make-point :ed25519 \u0026key x y)\n(ec-make-point :ed448 \u0026key x y)\n(ec-make-point :secp256k1 \u0026key x y)\n(ec-make-point :secp256r1 \u0026key x y)\n(ec-make-point :secp384r1 \u0026key x y)\n(ec-make-point :secp521r1 \u0026key x y)\n#+END_EXAMPLE\n\nThe /x/ and /y/ parameters must be integers.\n\n\n#+NAME: ec-destructure-point\n#+BEGIN_SRC lisp\n(ec-destructure-point p) =\u003e plist\n#+END_SRC\n\nReturn a plist containing the coordinates of the point /P/. The indicators of\nthe plist match the /\u0026key/ arguments of the [[ec-make-point][ec-make-point]] method.\n\n\n#+NAME: ec-point-on-curve\n#+BEGIN_SRC lisp\n(ec-point-on-curve p) =\u003e boolean\n#+END_SRC\n\nReturn ~t~ if the point /P/ is on the curve.\n\n\n#+NAME: ec-point-equal\n#+BEGIN_SRC lisp\n(ec-point-equal p q) =\u003e boolean\n#+END_SRC\n\nReturn ~t~ if /P/ and /Q/ represent the same point.\n\n\n#+NAME: ec-double\n#+BEGIN_SRC lisp\n(ec-double p) =\u003e point\n#+END_SRC\n\nReturn the point 2 * /P/.\n\n\n#+NAME: ec-add\n#+BEGIN_SRC lisp\n(ec-add p q) =\u003e point\n#+END_SRC\n\nReturn the point /P/ + /Q/.\n\n\n#+NAME: ec-scalar-mult\n#+BEGIN_SRC lisp\n(ec-scalar-mult p e) =\u003e point\n#+END_SRC\n\nReturn the point /e/ * /P/.\n\n\n#+NAME: ec-scalar-inv\n#+BEGIN_SRC lisp\n(ec-scalar-inv kind n) =\u003e integer\n#+END_SRC\n\nReturn the modular inverse of /n/.\n\n\n#+NAME: ec-encode-scalar\n#+BEGIN_SRC lisp\n(ec-encode-scalar kind n) =\u003e vector\n#+END_SRC\n\nReturn an octet vector representing the integer /n/.\n\n\n#+NAME: ec-decode-scalar\n#+BEGIN_SRC lisp\n(ec-decode-scalar kind octets) =\u003e integer\n#+END_SRC\n\nReturn the integer represented by the /octets/.\n\n\n#+NAME: ec-encode-point\n#+BEGIN_SRC lisp\n(ec-encode-point p) =\u003e vector\n#+END_SRC\n\nReturn an octet vector representing the point /P/.\n\n\n#+NAME: ec-decode-point\n#+BEGIN_SRC lisp\n(ec-decode-point kind octets) =\u003e point\n#+END_SRC\n\nReturn the point represented by the /octets/.\n\n* Pseudo-random number generation\n  :PROPERTIES:\n  :CUSTOM_ID: pseudo-random-number-generation\n  :END:\n\nThe =*prng*= special variable indicates which pseudo-random number\ngenerator is used by default by functions that need to generate some\nrandom data. It defaults to a sensible OS-specific value.\n\nThe vast, vast vast number of users should just use the default\n~os-prng~ (which uses =/dev/urandom= on Unix and ~CryptGenRandom~ on\nWindows). For users who need /deterministic/,\nhigh-quality-random-seeming numbers (e.g. for Monte Carlo\nsimulations), ~fortuna-generator~ is provided. Finally, if you're\nrunning on a platform without a decent PRNG (these are few and far\nbetween now), you may require the full ~fortuna-prng~. When in doubt,\nuse ~os-prng~, which is the default.\n\n\n#+NAME:make-prng\n#+BEGIN_SRC lisp\n(make-prng name \u0026key seed) =\u003e prng\n#+END_SRC\n\nCreate a pseudo-random number generator.\n\n/name/ denotes the style of PRNG to use. [[list-all-prngs][list-all-prngs]] will tell you\nthe names of all supported PRNGs. Currently supported PRNGs are:\n - OS\n - Fortuna\n - Fortuna-generator\n\n/name/ can be a symbol in the ~keyword~ package or in the ~ironclad~\npackage.\n\n/seed/ is a *seed descriptor*. If ~nil~, the PRNG will not be seeded\n(which may prevent it from generating output until it is seeded,\ndepending on the PRNG in question). If ~:random~ then the PRNG will be\nseeded with the OS's cryptographically-secure PRNG. If ~:urandom~ then\nthe PRNG will be seeded with the OS's fast-but-potentially-less-secure\nPRNG, if available (if not, will fallback to ~:random~). If it is\na pathname indicator, a seed will be read from the indicated file,\nthen a new seed will be generated and written back to the file\n(over-writing the old seed). Finally, if it is a byte vector, it will\nbe used to seed the PRNG.\n\nIn single-threaded applications, you should very rarely need to call [[make-prng][make-prng]];\nthe default OS-provided PRNG should be appropriate in nearly all cases.\n\nIn multi-threaded applications, each thread that will use functions requiring\nrandom data must have its own PRNG, or several threads might generate the same\n\"random\" data. If the threads are created using the *bordeaux-threads* library\n(or by a library using *bordeaux-threads*, like *lparallel*), this is done\nautomatically. However, if you are using the threading functions of your Common\nLisp implementation directly, you have to bind the ~*prng*~ special variable to\na new PRNG in each thread. For example:\n\n#+BEGIN_EXAMPLE\n(make-thread (lambda ()\n               (let ((crypto:*prng* (crypto:make-prng :os)))\n                 (forms-for-thread-1))))\n\n(make-thread (lambda ()\n               (let ((crypto:*prng* (crypto:make-prng :os)))\n                 (forms-for-thread-2))))\n#+END_EXAMPLE\n\n\n#+NAME: list-all-prngs\n#+BEGIN_SRC lisp\n(list-all-prngs) =\u003e list\n#+END_SRC\n\nList all known PRNG types.\n\n\n#+NAME: random-data\n#+BEGIN_SRC lisp\n(random-data num-bytes \u0026optional prng) =\u003e bytes\n#+END_SRC\n\nGenerate /num-bytes/ bytes of random data from /prng/. Updates the\nstate of the generator.\n\n\n#+NAME: random-bits\n#+BEGIN_SRC lisp\n(random-bits num-bits \u0026optional prng) =\u003e integer\n#+END_SRC\n\nGenerate an integer with /num-bits/ bits.\n\n\n#+NAME: strong-random\n#+BEGIN_SRC lisp\n(strong-random limit \u0026optional prng) =\u003e number\n#+END_SRC\n\nA drop-in replacement for ~common-lisp:random~, [[strong-random][strong-random]]\ngenerates a number (an integer if /limit/ is an integer and a float if\nit is a float) between 0 and /limit/ - 1 in an unbiased fashion.\n\n\n#+NAME: read-os-random-seed\n#+BEGIN_SRC lisp\n(read-os-random-seed source \u0026optional prng) =\u003e reseed-count\n#+END_SRC\n\nRead an OS-provided random seed (from =/dev/urandom= or =/dev/random=\non Unix; ~CryptGenRandom~ on Windows) and reseed /prng/.\n\n/source/ may be ~:random~, which indicates =/dev/random= or\n~:urandom~, which indicates =/dev/urandom=. On Windows,\n~CryptGenRandom~ is always used.\n\n\n#+NAME: read-seed\n#+BEGIN_SRC lisp\n(read-seed path \u0026optional prng) =\u003e t\n#+END_SRC\n\nRead enough bytes from /path/ to reseed /prng/, then generate\na pseudo-random seed and write it back to /path/. If /path/ doesn't\nexist, calls [[read-os-random-seed][read-os-random-seed]] to get a truly random seed from the\nOS. Note that reseeding does *not* reset the generator's state to the\nseed value; rather, it *combines* the generator's state with the seed\nto form a new state.\n\n\n#+NAME: write-seed\n#+BEGIN_SRC lisp\n(write-seed path \u0026optional prng) =\u003e t\n#+END_SRC\n\nGenerate enough random data to reseed /prng/, then write it to /path/.\n\n** Example\n\n#+BEGIN_EXAMPLE\n(crypto:random-data 16)\n=\u003e #(61 145 133 130 220 200 90 86 0 101 62 169 0 40 101 78)\n\n(crypto:strong-random 16)\n=\u003e 3\n\n(crypto:random-bits 16)\n=\u003e 41546\n#+END_EXAMPLE\n\n** Fortuna\n\nYou should only use the Fortuna PRNG if your OS does not provided\na sufficiently-good PRNG. If you use a Unix or Unix-like OS (e.g.\nLinux), macOS or Windows, it does. Only use the Fortuna PRNG if you\nknow for certain that you need it.\n\nFortuna is a cryptographically-secure random number presented by\nFerguson, Schneier and Kohno in /Cryptography Engineering/. It is\nbuilt around 32 entropy pools, which are used with decreasing\nfrequency for each reseed (e.g. pool 0 is used in each reseed, pool\n1 in every other reseed, pool 2 in every fourth reseed and so forth).\nPools are seeded with data from up to 256 sources.\n\nEach application should have one or more entropy sources (say, one for\neach OS random number source, one for the low bits of the current\ntime, one for the output of a particular command or group of commands\nand so forth). A source should be used to add randomness to each pool\nin order, so source 0 should top up pool 0, then pool 1, and so forth\nup to pool 31, then loop back to pool 1 again. Be very careful to\nspread entropy across all 32 pools.\n\nFortuna automatically feeds entropy from the pools back into its\nrandom state when [[random-data][random-data]] is called, using a method designed to\nmake it resistant to various avenues of attack; even in case of\ngenerator compromise it will return to a safe state within a bounded\ntime.\n\nFor purposes of reseeding, Fortuna will not reseed until the first\npool contains 128 bits of entropy; ~+min-pool-size+~ sets the number\nof bytes this is; it defaults to a very conservative 128, meaning that\nby default each byte of event is assumed to contain a single bit of\nrandomness.\n\nIt also will not reseed more than ten times per second.\n\n\n#+NAME: add-random-event\n#+BEGIN_SRC lisp\n(add-random-event source pool-id event \u0026optional prng) =\u003e pool-length\n#+END_SRC\n\nAdd entropy to /prng/.\n\n/source/ is an integer in the range 0-255 specifiying the event's\napplication-defined source.\n\n/pool-id/ is an integer in the range 0-31 specifying the pool to top\nup.\n\n/event/ is up to 32 bytes of data (for longer events, hash them down\nor break them up into chunks).\n\n* Gray streams\n  :PROPERTIES:\n  :CUSTOM_ID: gray-streams\n  :END:\n\nIronclad includes support for several convenient stream abstractions\nbased on Gray streams. Gray streams support in Ironclad is included\nfor SBCL, CMUCL, OpenMCL/CCL, Lispworks, ABCL, ECL, Clisp and Allegro.\n\n** Octet streams\n\nOctet streams are very similar to Common Lisp's ~string-stream~ except\nthey deal in octets instead of characters.\n\n\n#+NAME: make-octet-input-stream\n#+BEGIN_SRC lisp\n(make-octet-input-stream buffer \u0026optional start end) =\u003e octet-input-stream\n#+END_SRC\n\nAs ~make-string-input-stream~, only with octets instead of characters.\n\n\n#+NAME: make-octet-output-stream\n#+BEGIN_SRC lisp\n(make-octet-output-stream) =\u003e octet-output-stream\n#+END_SRC\n\nAs ~make-string-output-stream~, only with octets instead of characters.\n\n\n#+NAME: get-output-stream-octets\n#+BEGIN_SRC lisp\n(get-output-stream-octets stream) =\u003e octet-vector\n#+END_SRC\n\nAs ~get-output-stream-string~, only with an octet output-steam instead\nof a string output-stream.\n\n\n#+NAME: with-octet-input-stream\n#+BEGIN_SRC lisp\n(with-octet-input-stream ((var buffer \u0026optional (start 0) end) \u0026body body))\n#+END_SRC\n\nWithin /body/, /var/ is bound to an octet input stream. Reading from\n/var/ gives the bytes between the indexes /start/ and /end/ of\n/buffer/. The result of the last form of /body/ is returned.\n\n\n#+NAME: with-octet-output-stream\n#+BEGIN_SRC lisp\n(with-octet-output-stream ((var) \u0026body body)) =\u003e bytes\n#+END_SRC\n\nWithin /body/, /var/ is bound to an octet output stream. After all the\nforms in /body/ have been executed, the data that has been written to\n/var/ (and that hasn't been consumed by a call to\n[[get-output-stream-octets][get-output-stream-octets]] within /body/) is returned.\n\n** Digest streams\n\nDigest streams compute a digest of the data written to them according\nto a specific digest algorithm.\n\nExample:\n#+BEGIN_EXAMPLE\n(defun frobbing-function (stream)\n  ;; We want to compute a digest of the data being written to STREAM\n  ;; without involving our callees in the process.\n  (let* ((digesting-stream (crypto:make-digesting-stream :sha1))\n         (stream (make-broadcast-stream stream digesting-stream)))\n    ;; Feed data to STREAM.\n    (frob-guts stream)\n    ;; Do something with the digest computed.\n    (... (crypto:produce-digest digesting-stream) ...)\n    ...))\n#+END_EXAMPLE\n\n\n#+NAME: make-digesting-stream\n#+BEGIN_SRC lisp\n(make-digesting-stream digest \u0026rest args) =\u003e stream\n#+END_SRC\n\nMake a stream that computes a digest of the data written to it\naccording to the algorithm /digest/. The parameters that can be used\nby some algorithms can be specified as /args/.\n[[produce-digest][produce-digest]] may be used to obtain a digest of all the data written\nto the stream.\n\n_Note:_ Calling [[produce-digest][produce-digest]] on a digest stream does not alter\nthe internal state of the digest.\n\n\n#+NAME: with-digesting-stream\n#+BEGIN_SRC lisp\n(with-digesting-stream (var digest-name \u0026rest args) \u0026body body) =\u003e digest\n#+END_SRC\n\nWithin /body/, /var/ is bound to a digesting stream for the\n/digest-name/ algorithm. After all the forms in /body/ have been\nexecuted, the digest of the data that has been written to /var/ is\nreturned.\n\n** Cipher streams\n\nCipher streams encrypt or decrypt the data written to or read from\nthem according to a specific cipher algorithm.\n\n\n#+NAME: make-encrypting-stream\n#+BEGIN_SRC lisp\n(make-encrypting-stream stream cipher mode key \u0026key initialization-vector direction) =\u003e stream\n#+END_SRC\n\nMake a stream wrapped around the binary stream /stream/ that encrypts\ndata according to the algorithm /cipher/ initialized with a /mode/,\na /key/ and an /initialization-vector/.\nIf /direction/ is ~:input~, the data read from the created input\nstream is the encryption of the data coming from /stream/.\nIf /direction/ is ~:output~, the data written to the created output\nstream is encrypted before being sent to /stream/.\n\n\n#+NAME: make-decrypting-stream\n#+BEGIN_SRC lisp\n(make-decrypting-stream stream cipher mode key \u0026key initialization-vector direction) =\u003e stream\n#+END_SRC\n\nMake a stream wrapped around the binary stream /stream/ that decrypts\ndata according to the algorithm /cipher/ initialized with a /mode/,\na /key/ and an /initialization-vector/.\nIf /direction/ is ~:input~, the data read from the created input\nstream is the decryption of the data coming from /stream/.\nIf /direction/ is ~:output~, the data written to the created output\nstream is decrypted before being sent to /stream/.\n\n\n_Note:_ Only stream ciphers and block ciphers in CTR, CFB, CFB8 or OFB mode are\nsupported by [[make-encrypting-stream][make-encrypting-stream]] and [[make-decrypting-stream][make-decrypting-stream]].\n\n\n#+NAME: with-encrypting-stream\n#+BEGIN_SRC lisp\n(with-encrypting-stream ((var stream cipher mode key \u0026key initialization-vector direction) \u0026body body))\n#+END_SRC\n\nWithin /body/, /var/ is bound to an encrypting stream. The result of\nthe last form of /body/ is returned.\n\n\n#+NAME: with-decrypting-stream\n#+BEGIN_SRC lisp\n(with-decrypting-stream ((var stream cipher mode key \u0026key initialization-vector direction) \u0026body body))\n#+END_SRC\n\nWithin /body/, /var/ is bound to a decrypting stream. The result of\nthe last form of /body/ is returned.\n\n** MAC streams\n\nMAC streams compute a message authentication code of the data written\nto them according to a specific MAC algorithm.\n\n#+NAME: make-authenticating-stream\n#+BEGIN_SRC lisp\n(make-authenticating-stream mac key \u0026rest args) =\u003e stream\n#+END_SRC\n\nMake a stream that computes a MAC of the data written to it according\nto the algorithm /mac/ initialized with a /key/. The parameters used\nto create the MAC can be specified as /args/.\n[[produce-mac][produce-mac]] may be used to obtain a MAC of all the data written to the\nstream.\n\n_Note:_ Calling [[produce-mac][produce-mac]] on a MAC stream does not alter the\ninternal state of the MAC.\n\n\nExample: encrypt some data and compute a MAC of the ciphertext\n#+BEGIN_EXAMPLE\n(let* ((data ...)\n       (output-stream ...)\n       (encryption-key ...)\n       (authentication-key ...)\n       (iv ...)\n       (mac-stream (make-authenticating-stream :hmac\n                                               authentication-key\n                                               :sha3))\n       (stream (make-broadcast-stream output-stream mac-stream))\n       (cipher-stream (make-encrypting-stream stream\n                                              :chacha\n                                              :stream\n                                              encryption-key\n                                              :initialization-vector iv)))\n  (write-sequence data cipher-stream)\n  ...\n  (let ((mac (produce-mac mac-stream)))\n    ...))\n#+END_EXAMPLE\n\n\n#+NAME: with-authenticating-stream\n#+BEGIN_SRC lisp\n(with-authenticating-stream (var mac-name key \u0026rest args) \u0026body body) =\u003e mac\n#+END_SRC\n\nWithin /body/, /var/ is bound to an authenticating stream for the\n/mac-name/ algorithm. After all the forms in /body/ have been\nexecuted, the message authentication code of the data that has been\nwritten to /var/ is returned.\n\n* Utility functions\n  :PROPERTIES:\n  :CUSTOM_ID: utility-functions\n  :END:\n\n#+NAME: ub-ref-le\n#+BEGIN_SRC lisp\n(ub16ref/le vector index) =\u003e value\n(ub32ref/le vector index) =\u003e value\n(ub64ref/le vector index) =\u003e value\n#+END_SRC\n\nThis family of functions accesses an unsigned 16-bit, 32-bit or 64-bit\nvalue stored in little-endian order starting at /index/ in /vector/.\n/vector/ must be a ~(simple-array (unsigned-byte 8) (*))~. These\nfunctions are SETFable.\n\n\n#+NAME: ub-ref-be\n#+BEGIN_SRC lisp\n(ub16ref/be vector index) =\u003e value\n(ub32ref/be vector index) =\u003e value\n(ub64ref/be vector index) =\u003e value\n#+END_SRC\n\nAs the above, only the value is stored in big-endian order.\n\n\n#+NAME: array-hex-string\n#+BEGIN_SRC lisp\n(byte-array-to-hex-string vector \u0026key start end element-type) =\u003e string\n(hex-string-to-byte-array string \u0026key start end) =\u003e string\n(ascii-string-to-byte-array string \u0026key start end) =\u003e vector\n#+END_SRC\n\n[[array-hex-string][byte-array-to-hex-string]] converts the bytes of /vector/ between\n/start/ and /end/ into a hexadecimal string. It is useful for\nconverting digests to a more readable form. /element-type/ indicates\nthe element-type of the returned string.\n\n[[array-hex-string][hex-string-to-byte-array]] parses a substring of /string/ delimited\n/start/ and /end/ of hexadecimal digits into a byte array.\n\n[[array-hex-string][ascii-string-to-byte-array]] is provided as a quick and dirty way to\nconvert a string to a byte array suitable for feeding to [[update-digest][update-digest]]\nor [[encrypt][encrypt]]. Care should be taken to ensure that the provided string is\nactually an ASCII string. /start/ and /end/ have their usual\ninterpretations.\n\n\n#+NAME: octets-integer\n#+BEGIN_SRC lisp\n(octets-to-integer octet-vec \u0026key start end big-endian n-bits) =\u003e number\n(integer-to-octets bignum \u0026key n-bits big-endian) =\u003e vector\n#+END_SRC\n\n[[octets-integer][octets-to-integer]] converts the bytes of /octet-vec/ between /start/\nand /end/ to an integer as though the bytes denoted a number in\nbase 256. /big-endian/ is a boolean indicating whether the bytes are\nto be read in big-endian or little-endian order. /n-bits/ specifies\nhow many bits should be considered as significant in the resulting\nnumber.\n\n[[octets-integer][integer-to-octets]] is the reverse operation.\n\n\n#+NAME: expt-mod\n#+BEGIN_SRC lisp\n(expt-mod n exponent modulus) =\u003e number\n(expt-mod/unsafe n exponent modulus) =\u003e number\n#+END_SRC\n\nRaises /n/ to the /exponent/ power modulo /modulus/ in a more\nefficient fashion than ~(mod (expt n exponent) modulus)~.\n[[expt-mod][expt-mod]] is using the Montgomery ladder algorithm to be more robust\nagainst timing attacks.\n[[expt-mod][expt-mod/unsafe]] runs faster than [[expt-mod][expt-mod]] but is not safe against\ntiming attacks; don't use it on secret data.\n\n\n#+NAME: prime-p\n#+BEGIN_SRC lisp\n(prime-p n \u0026optional prng) =\u003e boolean\n#+END_SRC\n\n[[prime-p][prime-p]] returns ~t~ if /n/ has a high probability of being a prime number, and\n~nil~ if it is a composite number. The probable primality is determined by\nfirst doing trial divisions with small primes, then running several\nMiller-Rabin tests with random bases, and finally doing a Lucas test. The\nnumber of Miller-Rabin tests can be configured using the\n~*number-of-miller-rabin-tests*~ variable. It is 64 by default, which makes the\nprobability of returning ~t~ for a composite number to be at most 1/2^128.\n\n\n#+NAME: make-random-salt\n#+BEGIN_SRC lisp\nmake-random-salt \u0026optional size =\u003e bytes\n#+END_SRC\n\nGenerate a byte vector of /size/ (default 16) random bytes, suitable\nfor use as a password salt.\n\n\n#+NAME: constant-time-equal\n#+BEGIN_SRC lisp\nconstant-time-equal data1 data2 =\u003e boolean\n#+END_SRC\n\nCheck whether the contents of the byte arrays /data1/ and /data2/ are\nthe same. This function runs in constant time (for a given array\nlength) to prevent timing attacks. It can be used to compare passwords\nor MACs.\n\n* Conditions\n  :PROPERTIES:\n  :CUSTOM_ID: conditions\n  :END:\n\n#+NAME: ironclad-error\n#+BEGIN_SRC lisp\nironclad-error\n#+END_SRC\n\nAll errors signaled by Ironclad are of this type. This type is\na direct subtype of ~simple-error~ without any extra slots or options.\n\n\n#+NAME: initialization-vector-not-supplied\n#+BEGIN_SRC lisp\ninitialization-vector-not-supplied\n#+END_SRC\n\nThis error is signaled by [[make-cipher][make-cipher]] when an initialization vector is\nnot provided and the requested mode requires an initialization vector.\n\n\n#+NAME: invalid-initialization-vector\n#+BEGIN_SRC lisp\ninvalid-initialization-vector\n#+END_SRC\n\nThis error is signaled when an invalid initialization vector is\nsupplied to [[make-cipher][make-cipher]] (e.g. when the length of the initialization\nvector does not match the block length of the cipher).\n\n\n#+NAME: invalid-key-length\n#+BEGIN_SRC lisp\ninvalid-key-length\n#+END_SRC\n\nThis error is signaled when the key provided to [[make-cipher][make-cipher]] is not of\nan acceptable length for the requested cipher.\n\n\n#+NAME: unsupported-cipher\n#+BEGIN_SRC lisp\nunsupported-cipher\n#+END_SRC\n\nThis error is signaled when the /cipher-name/ provided to [[make-cipher][make-cipher]]\nis not [[cipher-supported-p][cipher-supported-p]].\n\n\n#+NAME: unsupported-mode\n#+BEGIN_SRC lisp\nunsupported-mode\n#+END_SRC\n\nThis error is signaled when the /mode/ provided to\n[[make-cipher][make-cipher]] is not /mode-supported-p/.\n\n\n#+NAME: unsupported-padding\n#+BEGIN_SRC lisp\nunsupported-padding\n#+END_SRC\n\nThis error is signaled when the /padding/ provided to [[make-cipher][make-cipher]] is not\nsupported.\n\n\n#+NAME: unsupported-digest\n#+BEGIN_SRC lisp\nunsupported-digest\n#+END_SRC\n\nThis error is signaled when the /digest-name/ provided to\n[[make-digest][make-digest]] is not [[digest-supported-p][digest-supported-p]].\n\n\n#+NAME: unsupported-mac\n#+BEGIN_SRC lisp\nunsupported-mac\n#+END_SRC\n\nThis error is signaled when the /mac-name/ provided to\n[[make-mac][make-mac]] is not [[mac-supported-p][mac-supported-p]].\n\n\n#+NAME: insufficient-buffer-space\n#+BEGIN_SRC lisp\ninsufficient-buffer-space\n#+END_SRC\n\nThis error is signaled when Ironclad needs to stuff some data into\na buffer (e.g. when the user provides /digest/ to [[produce-digest][produce-digest]] and\nthere is insufficient space).\n\n\n#+NAME: key-not-supplied\n#+BEGIN_SRC lisp\nkey-not-supplied\n#+END_SRC\n\nThis error is signaled when a /:key/ argument is not provided\nto [[make-cipher][make-cipher]].\n\n\n#+NAME: unsupported-kdf\n#+BEGIN_SRC lisp\nunsupported-kdf\n#+END_SRC\n\nThis error is signaled when an invalid KDF name is provided\nto [[make-kdf][make-kdf]].\n\n\n#+NAME: unsupported-scrypt-cost-factors\n#+BEGIN_SRC lisp\nunsupported-scrypt-cost-factors\n#+END_SRC\n\nThis error is signaled when invalid Scrypt cost factors are provided\nto [[make-kdf][make-kdf]].\n\n\n#+NAME: unsupported-argon2-cost-factors\n#+BEGIN_SRC lisp\nunsupported-argon2-cost-factors\n#+END_SRC\n\nThis error is signaled when invalid Argon2 parameters are provided\nto [[make-kdf][make-kdf]].\n\n\n#+NAME: invalid-padding\n#+BEGIN_SRC lisp\ninvalid-padding\n#+END_SRC\n\nThis error is signaled when padding in a block is determined to be\ninvalid.\n\n\n#+NAME: invalid-mac-parameter\n#+BEGIN_SRC lisp\ninvalid-mac-parameter\n#+END_SRC\n\nThis error is signaled when an invalid parameter is provided\nto [[make-mac][make-mac]].\n\n\n#+NAME: invalid-signature-length\n#+BEGIN_SRC lisp\ninvalid-signature-length\n#+END_SRC\n\nThis error is signaled when a signature with an invalid length is provided\nto [[verify-signature][verify-signature]] or [[destructure-signature][destructure-signature]].\n\n\n#+NAME: invalid-message-length\n#+BEGIN_SRC lisp\ninvalid-message-length\n#+END_SRC\n\nThis error is signaled when a message with an invalid length is provided\nto [[encrypt-message][encrypt-message]], [[decrypt-message][decrypt-message]] or [[destructure-message][destructure-message]].\n\n\n#+NAME: missing-key-parameter\n#+BEGIN_SRC lisp\nmissing-key-parameter\n#+END_SRC\n\nThis error is signaled when it is determined that a parameter is\nmissing in a call to [[make-public-key][make-public-key]] or [[make-private-key][make-private-key]].\n\n\n#+NAME: missing-message-parameter\n#+BEGIN_SRC lisp\nmissing-message-parameter\n#+END_SRC\n\nThis error is signaled when it is determined that a parameter is\nmissing in a call to [[make-message][make-message]].\n\n\n#+NAME: missing-signature-parameter\n#+BEGIN_SRC lisp\nmissing-signature-parameter\n#+END_SRC\n\nThis error is signaled when it is determined that a parameter is\nmissing in a call to [[make-signature][make-signature]].\n\n\n#+NAME: incompatible-keys\n#+BEGIN_SRC lisp\nincompatible-keys\n#+END_SRC\n\nThis error is signaled when incompatible keys are provided to\n[[diffie-hellman][diffie-hellman]].\n\n\n#+NAME: invalid-curve-point\n#+BEGIN_SRC lisp\ninvalid-curve-point\n#+END_SRC\n\nThis error is signaled when trying to use an invalid curve point.\n\n\n#+NAME: invalid-public-key-length\n#+BEGIN_SRC lisp\ninvalid-public-key-length\n#+END_SRC\n\nThis error is signaled when a public key with an invalid length is\nprovided to [[verify-signature][verify-signature]].\n\n\n#+NAME: oaep-decoding-error\n#+BEGIN_SRC lisp\noaep-decoding-error\n#+END_SRC\n\nThis error is signaled when the OAEP decoding of a message fails.\n\n\n#+NAME: unsupported-authenticated-encryption-mode\n#+BEGIN_SRC lisp\nunsupported-authenticated-encryption-mode\n#+END_SRC\n\nThis error is signaled when an invalid mode name is provided to\n[[make-authenticated-encryption-mode][make-authenticated-encryption-mode]].\n\n\n#+NAME: bad-authentication-tag\n#+BEGIN_SRC lisp\nbad-authentication-tag\n#+END_SRC\n\nThis error is signaled when the verification of authenticity of a message fails.\n\n* Subsystems (experimental)\n  :PROPERTIES:\n  :CUSTOM_ID: subsystems\n  :END:\n\nInstead of loading the complete Ironclad system, you can load only the\nsubsystems of the algorithms you need.\n\nFor example if you need only AES and SHA256:\n#+BEGIN_EXAMPLE\n(asdf:load-system \"ironclad/cipher/aes\")\n(asdf:load-system \"ironclad/digest/sha256\")\n#+END_EXAMPLE\n\n** Available subsystems\n\n- ironclad\n  - ironclad/core\n  - ironclad/ciphers\n    - ironclad/cipher/aes\n    - ironclad/cipher/arcfour\n    - ironclad/cipher/aria\n    - ironclad/cipher/blowfish\n    - ironclad/cipher/camellia\n    - ironclad/cipher/cast5\n    - ironclad/cipher/chacha\n    - ironclad/cipher/des\n    - ironclad/cipher/idea\n    - ironclad/cipher/kalyna\n    - ironclad/cipher/keystream\n    - ironclad/cipher/kuznyechik\n    - ironclad/cipher/misty1\n    - ironclad/cipher/rc2\n    - ironclad/cipher/rc5\n    - ironclad/cipher/rc6\n    - ironclad/cipher/salsa20\n    - ironclad/cipher/seed\n    - ironclad/cipher/serpent\n    - ironclad/cipher/sm4\n    - ironclad/cipher/sosemanuk\n    - ironclad/cipher/square\n    - ironclad/cipher/tea\n    - ironclad/cipher/threefish\n    - ironclad/cipher/twofish\n    - ironclad/cipher/xchacha\n    - ironclad/cipher/xor\n    - ironclad/cipher/xsalsa20\n    - ironclad/cipher/xtea\n  - ironclad/digests\n    - ironclad/digest/adler32\n    - ironclad/digest/blake2\n    - ironclad/digest/blake2s\n    - ironclad/digest/crc24\n    - ironclad/digest/crc32\n    - ironclad/digest/groestl\n    - ironclad/digest/jh\n    - ironclad/digest/kupyna\n    - ironclad/digest/md2\n    - ironclad/digest/md4\n    - ironclad/digest/md5\n    - ironclad/digest/ripemd-128\n    - ironclad/digest/ripemd-160\n    - ironclad/digest/sha1\n    - ironclad/digest/sha256\n    - ironclad/digest/sha3\n    - ironclad/digest/sha512\n    - ironclad/digest/skein\n    - ironclad/digest/sm3\n    - ironclad/digest/streebog\n    - ironclad/digest/toger\n    - ironclad/digest/tree-hash\n    - ironclad/digest/whirlpool\n  - ironclad/macs\n    - ironclad/mac/blake2-mac\n    - ironclad/mac/blake2s-mac\n    - ironclad/mac/cmac\n    - ironclad/mac/gmac\n    - ironclad/mac/hmac\n    - ironclad/mac/poly1305\n    - ironclad/mac/siphash\n    - ironclad/mac/skein-mac\n  - ironclad/prngs\n    - ironclad/prng/fortuna\n  - ironclad/aeads\n    - ironclad/aead/eax\n    - ironclad/aead/etm\n    - ironclad/aead/gcm\n  - ironclad/kdfs\n    - ironclad/kdf/argon2\n    - ironclad/kdf/bcrypt\n    - ironclad/kdf/hmac\n    - ironclad/kdf/password-hash\n    - ironclad/kdf/pkcs5\n    - ironclad/kdf/scrypt\n  - ironclad/public-keys\n    - ironclad/public-key/curve25519\n    - ironclad/public-key/curve448\n    - ironclad/public-key/dsa\n    - ironclad/public-key/ed25519\n    - ironclad/public-key/ed448\n    - ironclad/public-key/elgamal\n    - ironclad/public-key/rsa\n    - ironclad/public-key/secp256k1\n    - ironclad/public-key/secp256r1\n    - ironclad/public-key/secp384r1\n    - ironclad/public-key/secp521r1\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsharplispers%2Fironclad","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsharplispers%2Fironclad","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsharplispers%2Fironclad/lists"}