Ironclad
Ironclad is a cryptography library written entirely in Common Lisp. It includes support for several popular ciphers, digests, MACs and public key cryptography algorithms. For several implementations that support Gray streams, support is included for convenient stream wrappers.
Most of the algorithms were written with efficiency for specific Common Lisp implementations in mind, although portable code is provided as an alternative in nearly all instances. The framework should be flexible enough to accommodate implementation-specific optimizations when possible.
Test vectors for many of the algorithms are included to provide a level of confidence in the correctness of the implementations.
Table of Contents
Warnings
Ironclad should not be considered safe against side channel attacks.
Some algorithms can be safe against side channel attacks on some architectures using some Common Lisp implementations, but in the general case it can't be guaranteed. This is due to the fact that integers and arithmetic functions of Common Lisp implementations are usually not safe against side channel attacks.
Ironclad's digest, MAC and cipher objects should not be considered thread safe.
Creating a digest, a MAC or a cipher object and using it in several threads at the same time can lead to an undefined result. If you need to do that, you must put locks in your application where necessary.
Ironclad's pseudo random number generation should only be considered thread safe with bordeaux-threads.
If you have a multi-threaded application in which you want to use functions
requiring some random numbers (key derivation, key generation, public key
encryption, signature, etc.) in several threads, each of these threads must have
its own PRNG, or they might generate the same "random" numbers. If the threads
are created using the bordeaux-threads library (or by a library using
bordeaux-threads, like lparallel), this is done automatically. However, if
you are using the threading functions of your Common Lisp implementation
directly, you have to bind the *prng*
special variable to a new PRNG in each
thread. There is an example showing how it can be done in the section about
make-prng.
Installation
The current version of Ironclad is 0.59. It can be downloaded at https://github.com/sharplispers/ironclad/archive/v0.59.tar.gz. If you are feeling adventurous, you can download a bleeding-edge version at https://github.com/sharplispers/ironclad.
It comes with an ASDF system definition, so (asdf:load-system "ironclad")
should be all that you need to get started. The testsuite can be run
by substituting asdf:test-system
for asdf:load-system
in the form above.
If you are using Quicklisp to manage your libraries, just use
(ql:quickload "ironclad")
.
When Ironclad is loaded, its functions are in the ironclad
package (e.g.
(ironclad:make-cipher ...)
). If you prefer, you can also use the crypto
nickname (e.g. (crypto:make-cipher ...)
).
Ironclad has been tested in the following implementations:
- SBCL x86/linux, x86-64/linux (primary development platforms)
- SBCL x86-64/solaris, x86/darwin
- CMUCL x86/linux
- ABCL with Sun's 1.5.0 JVM
- Lispworks 5.0.1 x86/linux
- Lispworks 5.1.2 x86-64/darwin x86/windows
- Allegro 8.0 x86/linux
- Allegro 8.1 x86/linux, x86-64/linux, sparc/solaris
- CLISP 2.41 x86/linux, x86/cygwin
- Clozure Common Lisp 1.11 x86-64/Linux
- Clozure Common Lisp 1.10 x86-64/darwin
- ECL 16.1.3 x86-64/linux
All included tests should pass successfully. If you use a platform not listed above, please send your platform information so that it can be added to the above list. If the tests do not all pass, you have found a bug; please report it.
By default, Ironclad uses some implementation dependent low-level code to make
some functions run much faster (currently, some assembly for SBCL and CCL, some
C code for ECL). If for some reason you want to disable these optimisations and
use the generic Lisp code, it can be achieved by commenting out the
(pushnew :ironclad-assembly *features*)
line in the src/package.lisp file.
License
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.
Ciphers
(make-cipher name &key key mode initialization-vector padding tweak) => cipher
Return a cipher object suitable for use for both encryption and decryption.
name denotes the encryption algorithm to use. list-all-ciphers will tell you the names of all supported ciphers. They are:
- 3des
- aes
- arcfour (rc4)
- aria
- blowfish
- camellia
- cast5
- chacha
- chacha/12
- chacha/8
- des
- idea
- kalyna128
- kalyna256
- kalyna512
- kuznyechik
- misty1
- rc2
- rc5
- rc6
- salsa20
- salsa20/12
- salsa20/8
- seed
- serpent
- sm4
- sosemanuk
- square
- tea
- threefish1024
- threefish256
- threefish512
- twofish
- xchacha
- xchacha/12
- xchacha/8
- xor (not a real cipher, use only for testing)
- xsalsa20
- xsalsa20/12
- xsalsa20/8
- xtea
name can be a symbol in the keyword
package or in the ironclad
package;
:aes
for AES, ironclad:arcfour
for RC4, and so forth.
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:
- ecb
- cbc
- ofb
- cfb (note that Ironclad's CFB mode is n-bit CFB, where n is the block-length of the cipher)
- cfb8 (this seems to be the mode other crypto packages call CFB)
- ctr
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.
initialization-vector (IV) should be supplied only if mode requires one.
initialization-vector should be a (simple-array (unsigned-byte 8) (*))
.
The supplied IV should be the same length as the block-length of name.
The Chacha and Salsa20 stream ciphers also use an initialization
vector (nonce). It should be 8 or 12 bytes long for Chacha, 8 bytes long
for Salsa20, and 24 bytes long for XChacha and XSalsa20.
key is, of course, the key for the cipher.
key should be a (simple-array (unsigned-byte 8) (*))
.
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. padding will only be used if the mode is ECB or CBC. The possible
values for padding are :pkcs7
, :ansi-x923
and :iso-7816-4
.
If the cipher can use a tweak (e.g. threefish), it can be specified with the tweak key parameter.
(encrypt cipher plaintext ciphertext &key plaintext-start plaintext-end ciphertext-start handle-final-block) => n-bytes-consumed, n-bytes-produced
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.
(decrypt cipher ciphertext plaintext &key ciphertext-start ciphertext-end plaintext-start handle-final-block) => n-bytes-consumed, n-bytes-produced
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.
(encrypt-in-place cipher text &key start end) => n-bytes-consumed, n-bytes-produced
(decrypt-in-place cipher text &key start end) => n-bytes-consumed, n-bytes-produced
Encrypts or decrypts data in text between start and end "in-place" according to cipher. These functions are shorthand for:
(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.
(encrypt-message cipher message &key start end &allow-other-keys) => encrypted-message
Return the message between start and end encrypted with the cipher; the class of cipher determines the algorithm used to encrypt the message.
(decrypt-message cipher message &key start end &allow-other-keys) => decrypted-message
Return the message between start and end decrypted by the cipher; the class of cipher determines the algorithm used to decrypt the message.
Inquiry functions
(list-all-ciphers) => list
Returns a list of cipher-names that may be validly passed to make-cipher.
(cipher-supported-p name) => boolean
Returns t
if name would be in the list returned by list-all-ciphers,
nil
otherwise.
(key-lengths cipher) => list
Return a list of valid key lengths for cipher.
(block-length cipher) => number
Return the number of octets cipher processes at a time. This function always returns 1 for stream ciphers.
Key stream position
Block ciphers in CTR mode and some stream ciphers have the ability to change the current position within the key stream in constant time instead of having to consume all the bytes until the desired position is reached.
(keystream-position cipher &optional position) => number or boolean
Return or change the current position within the key stream of a cipher. When position is not supplied, keystream-position returns the current position in the key stream, or nil if it can't be determined. When position is supplied, the key stream position of the cipher is set to that position if possible. keystream-position returns t if the repositioning is performed successfully, or nil otherwise.
keystream-position can be used with the following ciphers:
- all the block ciphers (aes, twofish, etc.) in CTR mode
- chacha
- chacha/12
- chacha/8
- salsa20
- salsa20/12
- salsa20/8
- xchacha
- xchacha/12
- xchacha/8
- xsalsa20
- xsalsa20/12
- xsalsa20/8
Digests
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.
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.
(make-digest digest-name &rest keys &key &allow-other-keys) => digester
Returns a digest object. digest-name is a keyword naming the algorithm you wish digester to use. The supported digest names can be found by calling list-all-digests. They are:
- adler32
- blake2
- blake2/160
- blake2/256
- blake2/384
- blake2s
- blake2s/128
- blake2s/160
- blake2s/224
- crc24
- crc32
- groestl
- groestl/224
- groestl/256
- groestl/384
- jh
- jh/224
- jh/256
- jh/384
- keccak
- keccak/224
- keccak/256
- keccak/384
- kupyna
- kupyna/256
- md2
- md4
- md5
- ripemd-128
- ripemd-160
- sha1
- sha224
- sha256
- sha3
- sha3/224
- sha3/256
- sha3/384
- sha384
- sha512
- shake128
- shake256
- skein1024
- skein1024/384
- skein1024/512
- skein256
- skein256/128
- skein256/160
- skein256/224
- skein512
- skein512/128
- skein512/160
- skein512/224
- skein512/256
- skein512/384
- sm3
- streebog
- streebog/256
- tiger
- tree-hash
- whirlpool
Like for make-cipher, digest-name should be a symbol in the
keyword
or ironclad
packages.
Some algorithms (e.g. shake128 and shake256) can produce digests of any size. The size of the digest in bytes can be specified with the output-length key parameter:
(make-digest :shake256 :output-length 123)
(update-digest digester thing &key &allow-other-keys) => (values)
Updates the internal state of digester with the contents of thing. The exact method is determined by the type of thing.
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 Ironclad provides, and
listing them would get very tedious for no benefit. An example should
suffice.
(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))
(update-digest digester (stream stream) &key buffer start end &allow-other-keys) => digester
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).
(produce-digest digester &key digest digest-start) => digest
Return the digest of the data processed by digester so far.
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.
High-level convenience functions
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:
(ironclad:digest-sequence :md5 *buffer*)
or, equivalently:
(let ((digester (ironclad:make-digest :md5))) (ironclad:digest-sequence digester *buffer*))
The second form comes in handy if you plan on reusing the digest object.
(digest-sequence digest-spec sequence &rest args &key start end digest digest-start) => digest
Returns the digest of the subsequence of sequence bounded by start
and end, according to digest-name. sequence must be
a (vector (unsigned-byte 8))
. digest and digest-start
are as in produce-digest.
(digest-stream digest-spec stream &rest args &key buffer start end digest digest-start) => digest
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.
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.
(digest-file digest-spec pathname &rest args &key buffer start end digest digest-start) => digest
Returns the digest of the contents of the file named by pathname. digest and digest-start are as in produce-digest.
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.
Inquiry functions
(list-all-digests) => list
Returns a list whose elements may be validly passed to make-digest.
(digest-supported-p name) => boolean
Returns t
if name would be in the list returned by list-all-digests,
nil
otherwise.
(digest-length digest) => number
Returns the length of the digest computed by digest, which may be a digest-name or a digest instance.
Miscellaneous
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:
(defun digest-sum-files (digest-name &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-name) :element-type '(unsigned-byte 8)) for file in files for digester = (ironclad:make-digest digest-name) 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))))
Tree hashes
Ironclad supports tree hashes, as described in Tree Hash EXchange format. You create tree hashes as if you were creating a digest:
(ironclad:make-digest :tree-hash)
By default, this creates a tree hash that uses the Tiger digest algorithm internally and a segment size of 1024. Since using the Tiger digest algorithm is so common, a convenience function that makes your intent obvious has also been provided:
(ironclad:make-tiger-tree-hash)
You may indicate that you wish to use a different algorithm than Tiger:
(ironclad:make-digest '(:treehash :digest :sha256))
Or you might wish to use a different segment size:
(ironclad:make-digest '(:tree-hash :block-length 16384))
There is currently no interface for obtaining the intermediate hashes computed while computing the final tree hash.
Message authentication codes
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.
Ironclad provides different kinds of MACs:
- HMAC, specified in RFC 2104
- CMAC, specified in RFC 4493 and NIST document 800-38B
- GMAC, specified in NIST document 800-38D
- Blake2 and Blake2s MAC
- Poly1305
- SipHash
- Skein MAC
(make-mac mac-name key &rest args) => mac
Return a MAC object initialized with a secret key. mac-name is a keyword naming the algorithm you wish mac to use. The supported MACs can be found by calling list-all-macs. They are:
- blake2-mac
- blake2s-mac
- cmac
- gmac
- hmac
- poly1305
- siphash
- skein-mac
Like for make-digest, mac-name should be a symbol in the keyword
or ironclad
packages.
Some MACs take extra arguments that can be specified in args.
(make-mac :blake2-mac key &key digest-length) (make-mac :blake2s-mac key &key digest-length) (make-mac :cmac key cipher-name) (make-mac :gmac key cipher-name initialization-vector) (make-mac :hmac key digest-name) (make-mac :poly1305 key) (make-mac :siphash key &key compression-rounds finalization-rounds digest-length) (make-mac :skein-mac key &key block-length digest-length)
When making a Blake2 MAC, the length of the key passed to make-mac must be 64 bytes.
When making a Blake2s MAC, the length of the key passed to make-mac must be 32 bytes.
When making a CMAC, cipher-name must have a block-length of either 8, 16, 32, 64 or 128; this restriction is satisfied by many ciphers in Ironclad with the notable exception of stream ciphers. key must be an acceptable key for cipher-name.
When making a GMAC, cipher-name must have a block-length of 16. key must be an acceptable key for cipher-name.
When making a Poly1305 MAC, the length of the key passed to make-mac must be 32 bytes.
When making a SipHash MAC, the length of the key passed to make-mac must be 16 bytes. digest-length is 8 by default, but it can also be set to 16. By default, compression-rounds is 2 and finalization-rounds is 4.
When making a Skein MAC, block-length can be 32 (to use the Skein256 hash function internally), 64 (to use Skein512) or 128 (to use Skein1024). digest-length can be any length you want the computed digest to be. By default, block-length is 64 and digest-length is 64.
MAC objects support reinitialize-instance
:
(reinitialize-instance mac &rest initargs &key key &allow-other-keys) => mac
The :key argument is the secret key, as provided to make-mac.
(update-mac mac thing &key &allow-other-keys) => (values)
Updates the internal state of mac with the contents of thing. The exact method is determined by the type of thing.
There are several methods defined on this generic function that take
a particular MAC and a (simple-array (unsigned-byte 8) (*))
as
well as the usual start and end keyword arguments. These methods
update the state of mac 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 MAC that Ironclad provides, and
listing them would get very tedious for no benefit. An example should
suffice.
(let* ((key (random-data 32)) (mac (ironclad:make-mac :hmac key :sha256)) (array (make-array 16 :element-type '(unsigned-byte 8) :initial-element 0))) ;; Update with 16 zeroes. (ironclad:update-mac mac array) ;; Update with 8 ones. (fill array 1 :start 2 :end 10) (ironclad:update-mac mac array :start 2 :end 10))
(produce-mac mac &key digest digest-start) => digest
Return the digest of the data processed by mac so far. The internal state of mac is not modified; this feature makes it possible to compute a "rolling MAC" of a document.
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.
The length of the digest returned by produce-mac is determined by the kind of MAC and the extra arguments passed to make-mac:
- blake2-mac: from 1 to 64 bytes (64 by default)
- blake2s-mac: from 1 to 32 bytes (32 by default)
- cmac: block-length of the cipher-name passed to make-mac
- gmac: 16 bytes
- hmac: digest-length of the digest-name passed to make-mac
- poly1305: 16 bytes
- siphash: digest-length passed to make-mac (8 by default)
- skein-mac: digest-length passed to make-mac (64 by default)
Inquiry functions
(list-all-macs) => list
Returns a list whose elements may be validly passed to make-mac.
(mac-supported-p name) => boolean
Returns t
if name would be in the list returned by list-all-macs,
nil
otherwise.
Authenticated encryption
(make-authenticated-encryption-mode name &rest args) => mode
Return an authenticated encryption object suitable for use for both encryption and decryption.
name denotes the mode to use. list-all-authenticated-encryption-modes will tell you the names of all the supported modes. They are:
- eax (Encrypt then authenticate then translate)
- etm (Encrypt then MAC)
- gcm (Galois counter mode)
name can be a symbol in the keyword
or ironclad
packages.
args depends on the chosen authenticated encryption mode.
(make-authenticated-encryption-mode :eax &key tag cipher-name key initialization-vector) (make-authenticated-encryption-mode :etm &key tag cipher mac) (make-authenticated-encryption-mode :gcm &key tag cipher-name key initialization-vector)
If tag is specified, it will be used at the end of decryption (when the
handle-final-block flag is t
) to check the authenticity of the data.
A bad-authentication-tag
error will be signaled if the data is not authentic.
If you don't specify it, you will have to call produce-tag after decryption and
check that the tags match (e.g. using constant-time-equal).
When using EAX, key must be a suitable key for the chosen cipher-name.
When using ETM, cipher must be a cipher object created by make-cipher. mac must be a mac object created by make-mac.
When using GCM, cipher-name must have a block-length of 16 bytes. key must be a suitable key for the chosen cipher.
(process-associated-data mode data &key start end) => (values)
Update the internal state of mode with the contents of data between start and end so that they are taken into consideration in the authentication tag.
An authenticated encryption object can be used with the encrypt, decrypt, encrypt-message and decrypt-message functions.
(encrypt mode plaintext ciphertext &key plaintext-start plaintext-end ciphertext-start handle-final-block) (decrypt mode ciphertext plaintext &key ciphertext-start ciphertext-end plaintext-start handle-final-block) (encrypt-message mode message &key start end associated-data associated-data-start associated-data-end) (decrypt-message mode message &key start end associated-data associated-data-start associated-data-end)
(produce-tag mode &key tag tag-start) => tag
Return the authentication tag of the data processed by mode so far. If tag
is provided, the computed tag will be placed into tag starting at tag-start.
tag must be a (simple-array (unsigned-byte 8) (*))
. An
insufficient-buffer-space error will be signaled if there is insufficient space
in tag.
Inquiry functions
(list-all-authenticated-encryption-modes) => list
Returns a list whose elements may be validly passed to make-authenticated-encryption-mode.
(authenticated-encryption-mode-supported-p name) => boolean
Returns t
if name would be in the list returned by
list-all-authenticated-encryption-modes nil
otherwise.
Key derivation functions
Ironclad comes with a few key derivation functions:
- Argon2 (only Argon2d and Argon2i without parallelism are implemented)
- Bcrypt
- Bcrypt-pbkdf
- PBKDF1
- PBKDF2
- Scrypt
- HMAC
(derive-key kdf passphrase salt iteration-count key-length) => digest
Given a key derivation function object (produced by make-kdf),
a password and salt (both must be of type
(simple-array (unsigned-byte 8) (*))
), and number of iterations,
returns the password digest as a byte array of length key-length.
For bcrypt, the salt must be 16 bytes long, the iteration-count must be a power of 2 between 24 and 231, and the key-length must be 24. Scrypt and HMAC ignore the iteration-count parameter.
For bcrypt-pbkdf, the key-length must be between 1 and 1024.
(make-kdf kind &key digest n r p block-count additional-key additional-data) => kdf
Returns a key derivation function instance.
kind denotes the key derivation function to use. They are:
- argon2d
- argon2i
- bcrypt
- bcrypt-pbkdf
- pbkdf1
- pbkdf2
- scrypt-kdf
- hmac-kdf
kind can be a symbol in the keyword
or ironclad
packages.
The Argon2 key derivations use the block-count, additional-key and additional-data parameters (block-count is the number of 1 KiB memory blocks used by the function and it must be at least 8, additional-key and additional-data are optional). The PBKDF algorithms use digest. The Scrypt key derivation uses cost parameters N, r and p (N is a CPU cost parameter that must be a power of 2, r and p are memory cost parameters that must be defined such that r * p <= 230).
The default Scrypt parameters are N = 4096, r = 8, and p = 2. Please note that depending on the values of N and r, derive-key may not be able to allocate sufficient space for its temporary arrays.
The HMAC-KDF algorithm uses the digest parameter to precise what
hash function is used. It also optionally uses the additional-data
to precise the info
vector from the RFC.
(list-all-kdfs) => list
Returns a list of KDF kinds that may be validly passed to make-kdf.
PBKDF convenience functions
Ironclad comes with convenience functions for using PBKDF1 and PBKDF2 to store passwords.
(pbkdf2-hash-password password &key salt digest iterations) => password
Convenience function for hashing passwords using the PBKDF2 algorithm. Returns the derived hash of the password, and the original salt, as byte vectors.
(pbkdf2-hash-password-to-combined-string password &key salt digest iterations) => password
Convenience function for hashing passwords using the PBKDF2 algorithm. Returns the derived hash of the password as a single string that encodes the given salt and PBKDF2 algorithm parameters.
(pbkdf2-check-password password combined-salt-and-digest) => boolean
Given a password byte vector and a combined salt and digest string produced by pbkdf2-hash-password-to-combined-string, checks whether the password is valid.
Public key cryptography
Ironclad includes support for a few public key cryptography algorithms.
Encryption algorithms:
- Elgamal
- RSA
Signature algorithms:
- DSA
- Ed25519
- Ed448
- Elgamal
- RSA
- Secp256k1
- Secp256r1 (a.k.a. NIST P-256)
- Secp384r1 (a.k.a. NIST P-384)
- Secp521r1 (a.k.a. NIST P-521)
Diffie-Hellman key exchange:
- Curve25519
- Curve448
- Elgamal
- Secp256k1
- Secp256r1 (a.k.a. NIST P-256)
- Secp384r1 (a.k.a. NIST P-384)
- Secp521r1 (a.k.a. NIST P-521)
Key pair generation
(generate-key-pair kind &key num-bits &allow-other-keys) => private-key, public-key
Return a key pair according to kind. The generation of DSA, Elgamal
and RSA key pairs can take some time. If kind is :dsa
or :rsa
,
the num-bits key argument indicating the size of the keys to
generate must be specified. If kind is :elgamal
, num-bits must
be specified unless compatible-with-key is specified, in which case
the group parameters are taken from the specified key instead of being
generated.
For example, if Alice wants to generate a key pair for a Diffie-Hellman exchange with Bob's Elgamal key pair:
(generate-key-pair :elgamal :compatible-with-key bob-public-key)
(list-all-key-pair-kinds) => list
Returns a list of key pair kinds that may be validly passed to generate-key-pair.
Key construction
(make-public-key kind &key &allow-other-keys) => public-key
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.
(make-public-key :curve25519 &key y) => public-key (make-public-key :curve448 &key y) => public-key (make-public-key :dsa &key p q g y) => public-key (make-public-key :ed25519 &key y) => public-key (make-public-key :ed448 &key y) => public-key (make-public-key :elgamal &key p g y) => public-key (make-public-key :rsa &key e n) => public-key (make-public-key :secp256k1 &key y) => public-key (make-public-key :secp256r1 &key y) => public-key (make-public-key :secp384r1 &key y) => public-key (make-public-key :secp521r1 &key y) => public-key
(make-private-key kind &key &allow-other-keys) => private-key
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.
(make-private-key :curve25519 &key x y) => private-key (make-private-key :curve448 &key x y) => private-key (make-private-key :dsa &key p q g y x) => private-key (make-private-key :ed25519 &key x y) => private-key (make-private-key :ed448 &key x y) => private-key (make-private-key :elgamal &key p g y x) => private-key (make-private-key :rsa &key d n p q) => private-key (make-private-key :secp256k1 &key x y) => private-key (make-private-key :secp256r1 &key x y) => private-key (make-private-key :secp384r1 &key x y) => private-key (make-private-key :secp521r1 &key x y) => private-key
For Curve25519, Curve448, Ed25519, Ed448 keys, Secp256k1, Secp256r1, Secp384r1
and Secp521r1, the type of the parameters is
(simple-array (unsigned-byte 8) (*))
:
- x, the secret key
- y, the public key
For DSA and Elgamal keys, the type of the parameters is integer
:
- p, the prime number defining the DL group
- q, the prime number defining the DL sub-group
- g, the generator
- y, the public key
- x, the private key
For RSA keys, the type of the parameters is integer
:
- n, the modulus
- e, the public key
- d, the private key
- p, the first prime factor of n
- q, the second prime factor of n
Key destructuring
The destructure-public-key and destructure-private-key functions can be useful if you need to store keys somewhere for future use.
(destructure-public-key public-key) => plist
Return the elements of a public key in a plist. The indicators of the plist match the &key arguments of the make-public-key method.
(destructure-private-key private-key) => plist
Return the elements of a private key in a plist. The indicators of the plist match the &key arguments of the make-private-key method.
Digital signatures
(sign-message key message &key start end &allow-other-keys) => signature
Return a signature of message between start and end signed with key; the class of key determines the algorithm used to create the signature.
Note: The sign-message does not perform the hashing of the data. You should hash your data using your favorite hash function, and then use this hash as the message passed to sign-message.
(verify-signature key message signature &key start end &allow-other-keys) => boolean
Verify whether signature is a valid signature of message between
start and end using key. Return t
is the signature is valid
and nil
otherwise.
Padding
To be secure, RSA signature requires the message to be padded.
The pss key parameter is provided to pad (or unpad) the message
during signature (or verification) with the PSS scheme of PKCS-1.
The value of the pss key parameter can be either a digest name
or t
(which will use the sha1 digest).
(sign-message rsa-private-key message :pss t) => signature (verify-signature rsa-public-key message signature :pss t) => boolean
The functions pss-encode and pss-decode can also be used by hand if necessary.
Signature nonce
DSA, Elgamal and ECDSA (Secp256k1, Secp256r1, Secp384r1 and Secp521r1) signatures require the generation of a nonce. You must never sign two different messages with the same key and the same nonce, or anyone having these two signatures will be able compute your private key. Ironclad uses the generate-signature-nonce method which by default generates random nonces.
(generate-signature-nonce (key message &optional parameters)) => nonce
For DSA, parameters is q. For Elgamal, parameters is p. For ECDSA,
parameters is nil
.
If instead of random nonces, you want to have deterministic nonces (e.g. like in RFC 6979), you will have to redefine generate-signature-nonce. For example, to have deterministic nonces for Secp256k1 ECDSA signatures, you could do something like:
(defmethod generate-signature-nonce ((key secp256k1-private-key) message &optional parameters) (declare (ignore parameters)) (compute-deterministic-nonce key message))
Format of signatures
sign-message returns signatures as octet vectors. When the signature contains several values (e.g. the R and S values of DSA signatures), the octet vector is the concatenation of these values (e.g. the first half of the vector is the R value, the second half is the S value). You can use the make-signature and destructure-signature functions if you need access to the elements of a signature (e.g. to use a different kind of serialization).
(make-signature kind &key &allow-other-keys) => signature
Return an octet vector representing a signature. The &key arguments vary according to kind. The interesting bits are in the methods that specialize on kind, below.
(make-signature :dsa &key r s n-bits) => signature (make-signature :ed25519 &key r s) => signature (make-signature :ed448 &key r s) => signature (make-signature :elgamal &key r s n-bits) => signature (make-signature :rsa &key s n-bits) => signature (make-signature :secp256k1 &key r s) => signature (make-signature :secp256r1 &key r s) => signature (make-signature :secp384r1 &key r s) => signature (make-signature :secp521r1 &key r s) => signature
For Ed25519, Ed448, Secp256k1, Secp256r1, Secp384r1 and Secp521r1 signatures,
the type of the parameters r and s is
(simple-array (unsigned-byte 8) (*))
.
For DSA and Elgamal signatures, the type of the parameters r, s
and n-bits is integer
.
For RSA signatures, the type of the parameters s and n-bits is
integer
.
(destructure-signature kind signature) => plist
Return the elements of a signature in a plist. The indicators of the plist match the &key arguments of the make-signature method.
Encryption and decryption
(encrypt-message key message &key start end &allow-other-keys) => encrypted-message
Return the message between start and end encrypted with the key; the class of key determines the algorithm used to encrypt the message.
(decrypt-message key message &key start end n-bits &allow-other-keys) => decrypted-message
Return the message between start and end decrypted by the key; the class of key determines the algorithm used to decrypt the message. n-bits can be used to indicate the expected size of the decrypted message (e.g. a small byte vector starting with zeros encrypted without padding, which is probably a bad idea, c.f. Padding section).
Padding
To be secure, RSA encryption requires the message to be padded. The
oaep key parameter is provided to pad (or unpad) the message during
encryption (or decryption) with the OAEP scheme of PKCS-1.
The value of the oaep key parameter can be either a digest name
or t
(which will use the sha1 digest).
(encrypt-message rsa-public-key message :oaep t) => encrypted-message (decrypt-message rsa-private-key message :oaep t) => decrypted-message
The functions oaep-encode and oaep-decode can also be used by hand if necessary.
Format of messages
encrypt-message returns encrypted messages as octet vectors. When the message contains several values (e.g. the C1 and C2 values of Elgamal messages), the octet vector is the concatenation of these values (e.g. the first half of the vector is the big-endian representation of the C1 value, the second half is the C2 value). You can use the make-message and destructure-message functions if you need access to the elements of a message (e.g. to use a different kind of serialization).
(make-message kind &key &allow-other-keys) => message
Return an octet vector representing a message. The &key arguments vary according to kind. The interesting bits are in the methods that specialize on kind, below.
(make-message :elgamal &key c1 c2 n-bits) => message (make-message :rsa &key m n-bits) => message
For Elgamal messages, the type of the parameters c1, c2 and
n-bits is integer
.
For RSA signatures, the type of the parameters m and n-bits is
integer
.
(destructure-message kind message) => plist
Return the elements of a message in a plist. The indicators of the plist match the &key arguments of the make-message method.
Diffie-Hellman key exchange
(diffie-hellman private-key public-key) => bytes
Return a secret shared by two users Alice and Bob, computed from Alice's private key and Bob's public key (these keys must be compatible, i.e. have the same group parameters).
Elliptic curve operations
(ec-make-point kind &key &allow-other-keys) => point
Return a point of kind, initialized according to the specified coordinates. The interesting bits are in the methods that specialize on kind, below.
(ec-make-point :curve25519 &key x) (ec-make-point :curve448 &key x) (ec-make-point :ed25519 &key x y) (ec-make-point :ed448 &key x y) (ec-make-point :secp256k1 &key x y) (ec-make-point :secp256r1 &key x y) (ec-make-point :secp384r1 &key x y) (ec-make-point :secp521r1 &key x y)
The x and y parameters must be integers.
(ec-destructure-point p) => plist
Return a plist containing the coordinates of the point P. The indicators of the plist match the &key arguments of the ec-make-point method.
(ec-point-on-curve p) => boolean
Return t
if the point P is on the curve.
(ec-point-equal p q) => boolean
Return t
if P and Q represent the same point.
(ec-double p) => point
Return the point 2 * P.
(ec-add p q) => point
Return the point P + Q.
(ec-scalar-mult p e) => point
Return the point e * P.
(ec-scalar-inv kind n) => integer
Return the modular inverse of n.
(ec-encode-scalar kind n) => vector
Return an octet vector representing the integer n.
(ec-decode-scalar kind octets) => integer
Return the integer represented by the octets.
(ec-encode-point p) => vector
Return an octet vector representing the point P.
(ec-decode-point kind octets) => point
Return the point represented by the octets.
Pseudo-random number generation
The *prng*
special variable indicates which pseudo-random number
generator is used by default by functions that need to generate some
random data. It defaults to a sensible OS-specific value.
The vast, vast vast number of users should just use the default
os-prng
(which uses /dev/urandom
on Unix and CryptGenRandom
on
Windows). For users who need deterministic,
high-quality-random-seeming numbers (e.g. for Monte Carlo
simulations), fortuna-generator
is provided. Finally, if you're
running on a platform without a decent PRNG (these are few and far
between now), you may require the full fortuna-prng
. When in doubt,
use os-prng
, which is the default.
(make-prng name &key seed) => prng
Create a pseudo-random number generator.
name denotes the style of PRNG to use. list-all-prngs will tell you the names of all supported PRNGs. Currently supported PRNGs are:
- OS
- Fortuna
- Fortuna-generator
name can be a symbol in the keyword
package or in the ironclad
package.
seed is a seed descriptor. If nil
, the PRNG will not be seeded
(which may prevent it from generating output until it is seeded,
depending on the PRNG in question). If :random
then the PRNG will be
seeded with the OS's cryptographically-secure PRNG. If :urandom
then
the PRNG will be seeded with the OS's fast-but-potentially-less-secure
PRNG, if available (if not, will fallback to :random
). If it is
a pathname indicator, a seed will be read from the indicated file,
then a new seed will be generated and written back to the file
(over-writing the old seed). Finally, if it is a byte vector, it will
be used to seed the PRNG.
In single-threaded applications, you should very rarely need to call make-prng; the default OS-provided PRNG should be appropriate in nearly all cases.
In multi-threaded applications, each thread that will use functions requiring
random data must have its own PRNG, or several threads might generate the same
"random" data. If the threads are created using the bordeaux-threads library
(or by a library using bordeaux-threads, like lparallel), this is done
automatically. However, if you are using the threading functions of your Common
Lisp implementation directly, you have to bind the *prng*
special variable to
a new PRNG in each thread. For example:
(make-thread (lambda () (let ((crypto:*prng* (crypto:make-prng :os))) (forms-for-thread-1)))) (make-thread (lambda () (let ((crypto:*prng* (crypto:make-prng :os))) (forms-for-thread-2))))
(list-all-prngs) => list
List all known PRNG types.
(random-data num-bytes &optional prng) => bytes
Generate num-bytes bytes of random data from prng. Updates the state of the generator.
(random-bits num-bits &optional prng) => integer
Generate an integer with num-bits bits.
(strong-random limit &optional prng) => number
A drop-in replacement for common-lisp:random
, strong-random
generates a number (an integer if limit is an integer and a float if
it is a float) between 0 and limit - 1 in an unbiased fashion.
(read-os-random-seed source &optional prng) => reseed-count
Read an OS-provided random seed (from /dev/urandom
or /dev/random
on Unix; CryptGenRandom
on Windows) and reseed prng.
source may be :random
, which indicates /dev/random
or
:urandom
, which indicates /dev/urandom
. On Windows,
CryptGenRandom
is always used.
(read-seed path &optional prng) => t
Read enough bytes from path to reseed prng, then generate a pseudo-random seed and write it back to path. If path doesn't exist, calls read-os-random-seed to get a truly random seed from the OS. Note that reseeding does not reset the generator's state to the seed value; rather, it combines the generator's state with the seed to form a new state.
(write-seed path &optional prng) => t
Generate enough random data to reseed prng, then write it to path.
Example
(crypto:random-data 16) => #(61 145 133 130 220 200 90 86 0 101 62 169 0 40 101 78) (crypto:strong-random 16) => 3 (crypto:random-bits 16) => 41546
Fortuna
You should only use the Fortuna PRNG if your OS does not provided a sufficiently-good PRNG. If you use a Unix or Unix-like OS (e.g. Linux), macOS or Windows, it does. Only use the Fortuna PRNG if you know for certain that you need it.
Fortuna is a cryptographically-secure random number presented by Ferguson, Schneier and Kohno in Cryptography Engineering. It is built around 32 entropy pools, which are used with decreasing frequency for each reseed (e.g. pool 0 is used in each reseed, pool 1 in every other reseed, pool 2 in every fourth reseed and so forth). Pools are seeded with data from up to 256 sources.
Each application should have one or more entropy sources (say, one for each OS random number source, one for the low bits of the current time, one for the output of a particular command or group of commands and so forth). A source should be used to add randomness to each pool in order, so source 0 should top up pool 0, then pool 1, and so forth up to pool 31, then loop back to pool 1 again. Be very careful to spread entropy across all 32 pools.
Fortuna automatically feeds entropy from the pools back into its random state when random-data is called, using a method designed to make it resistant to various avenues of attack; even in case of generator compromise it will return to a safe state within a bounded time.
For purposes of reseeding, Fortuna will not reseed until the first
pool contains 128 bits of entropy; +min-pool-size+
sets the number
of bytes this is; it defaults to a very conservative 128, meaning that
by default each byte of event is assumed to contain a single bit of
randomness.
It also will not reseed more than ten times per second.
(add-random-event source pool-id event &optional prng) => pool-length
Add entropy to prng.
source is an integer in the range 0-255 specifiying the event's application-defined source.
pool-id is an integer in the range 0-31 specifying the pool to top up.
event is up to 32 bytes of data (for longer events, hash them down or break them up into chunks).
Gray streams
Ironclad includes support for several convenient stream abstractions based on Gray streams. Gray streams support in Ironclad is included for SBCL, CMUCL, OpenMCL/CCL, Lispworks, ABCL, ECL, Clisp and Allegro.
Octet streams
Octet streams are very similar to Common Lisp's string-stream
except
they deal in octets instead of characters.
(make-octet-input-stream buffer &optional start end) => octet-input-stream
As make-string-input-stream
, only with octets instead of characters.
(make-octet-output-stream) => octet-output-stream
As make-string-output-stream
, only with octets instead of characters.
(get-output-stream-octets stream) => octet-vector
As get-output-stream-string
, only with an octet output-steam instead
of a string output-stream.
(with-octet-input-stream ((var buffer &optional (start 0) end) &body body))
Within body, var is bound to an octet input stream. Reading from var gives the bytes between the indexes start and end of buffer. The result of the last form of body is returned.
(with-octet-output-stream ((var) &body body)) => bytes
Within body, var is bound to an octet output stream. After all the forms in body have been executed, the data that has been written to var (and that hasn't been consumed by a call to get-output-stream-octets within body) is returned.
Digest streams
Digest streams compute a digest of the data written to them according to a specific digest algorithm.
Example:
(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) ...) ...))
(make-digesting-stream digest &rest args) => stream
Make a stream that computes a digest of the data written to it according to the algorithm digest. The parameters that can be used by some algorithms can be specified as args. 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.
(with-digesting-stream (var digest-name &rest args) &body body) => digest
Within body, var is bound to a digesting stream for the digest-name algorithm. After all the forms in body have been executed, the digest of the data that has been written to var is returned.
Cipher streams
Cipher streams encrypt or decrypt the data written to or read from them according to a specific cipher algorithm.
(make-encrypting-stream stream cipher mode key &key initialization-vector direction) => stream
Make a stream wrapped around the binary stream stream that encrypts
data according to the algorithm cipher initialized with a mode,
a key and an initialization-vector.
If direction is :input
, the data read from the created input
stream is the encryption of the data coming from stream.
If direction is :output
, the data written to the created output
stream is encrypted before being sent to stream.
(make-decrypting-stream stream cipher mode key &key initialization-vector direction) => stream
Make a stream wrapped around the binary stream stream that decrypts
data according to the algorithm cipher initialized with a mode,
a key and an initialization-vector.
If direction is :input
, the data read from the created input
stream is the decryption of the data coming from stream.
If direction is :output
, the data written to the created output
stream is decrypted before being sent to stream.
Note: Only stream ciphers and block ciphers in CTR, CFB, CFB8 or OFB mode are supported by make-encrypting-stream and make-decrypting-stream.
(with-encrypting-stream ((var stream cipher mode key &key initialization-vector direction) &body body))
Within body, var is bound to an encrypting stream. The result of the last form of body is returned.
(with-decrypting-stream ((var stream cipher mode key &key initialization-vector direction) &body body))
Within body, var is bound to a decrypting stream. The result of the last form of body is returned.
MAC streams
MAC streams compute a message authentication code of the data written to them according to a specific MAC algorithm.
(make-authenticating-stream mac key &rest args) => stream
Make a stream that computes a MAC of the data written to it according to the algorithm mac initialized with a key. The parameters used to create the MAC can be specified as args. produce-mac may be used to obtain a MAC of all the data written to the stream.
Note: Calling produce-mac on a MAC stream does not alter the internal state of the MAC.
Example: encrypt some data and compute a MAC of the ciphertext
(let* ((data ...) (output-stream ...) (encryption-key ...) (authentication-key ...) (iv ...) (mac-stream (make-authenticating-stream :hmac authentication-key :sha3)) (stream (make-broadcast-stream output-stream mac-stream)) (cipher-stream (make-encrypting-stream stream :chacha :stream encryption-key :initialization-vector iv))) (write-sequence data cipher-stream) ... (let ((mac (produce-mac mac-stream))) ...))
(with-authenticating-stream (var mac-name key &rest args) &body body) => mac
Within body, var is bound to an authenticating stream for the mac-name algorithm. After all the forms in body have been executed, the message authentication code of the data that has been written to var is returned.
Utility functions
(ub16ref/le vector index) => value (ub32ref/le vector index) => value (ub64ref/le vector index) => value
This family of functions accesses an unsigned 16-bit, 32-bit or 64-bit
value stored in little-endian order starting at index in vector.
vector must be a (simple-array (unsigned-byte 8) (*))
. These
functions are SETFable.
(ub16ref/be vector index) => value (ub32ref/be vector index) => value (ub64ref/be vector index) => value
As the above, only the value is stored in big-endian order.
(byte-array-to-hex-string vector &key start end element-type) => string (hex-string-to-byte-array string &key start end) => string (ascii-string-to-byte-array string &key start end) => vector
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.
hex-string-to-byte-array parses a substring of string delimited start and end of hexadecimal digits into a byte array.
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.
(octets-to-integer octet-vec &key start end big-endian n-bits) => number (integer-to-octets bignum &key n-bits big-endian) => vector
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.
integer-to-octets is the reverse operation.
(expt-mod n exponent modulus) => number (expt-mod/unsafe n exponent modulus) => number
Raises n to the exponent power modulo modulus in a more
efficient fashion than (mod (expt n exponent) modulus)
.
expt-mod is using the Montgomery ladder algorithm to be more robust
against timing attacks.
expt-mod/unsafe runs faster than expt-mod but is not safe against
timing attacks; don't use it on secret data.
(prime-p n &optional prng) => boolean
prime-p returns t
if n has a high probability of being a prime number, and
nil
if it is a composite number. The probable primality is determined by
first doing trial divisions with small primes, then running several
Miller-Rabin tests with random bases, and finally doing a Lucas test. The
number of Miller-Rabin tests can be configured using the
*number-of-miller-rabin-tests*
variable. It is 64 by default, which makes the
probability of returning t
for a composite number to be at most 1/2128.
make-random-salt &optional size => bytes
Generate a byte vector of size (default 16) random bytes, suitable for use as a password salt.
constant-time-equal data1 data2 => boolean
Check whether the contents of the byte arrays data1 and data2 are the same. This function runs in constant time (for a given array length) to prevent timing attacks. It can be used to compare passwords or MACs.
Conditions
ironclad-error
All errors signaled by Ironclad are of this type. This type is
a direct subtype of simple-error
without any extra slots or options.
initialization-vector-not-supplied
This error is signaled by make-cipher when an initialization vector is not provided and the requested mode requires an initialization vector.
invalid-initialization-vector
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).
invalid-key-length
This error is signaled when the key provided to make-cipher is not of an acceptable length for the requested cipher.
unsupported-cipher
This error is signaled when the cipher-name provided to make-cipher is not cipher-supported-p.
unsupported-mode
This error is signaled when the mode provided to make-cipher is not mode-supported-p.
unsupported-padding
This error is signaled when the padding provided to make-cipher is not supported.
unsupported-digest
This error is signaled when the digest-name provided to make-digest is not digest-supported-p.
unsupported-mac
This error is signaled when the mac-name provided to make-mac is not mac-supported-p.
insufficient-buffer-space
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).
key-not-supplied
This error is signaled when a :key argument is not provided to make-cipher.
unsupported-kdf
This error is signaled when an invalid KDF name is provided to make-kdf.
unsupported-scrypt-cost-factors
This error is signaled when invalid Scrypt cost factors are provided to make-kdf.
unsupported-argon2-cost-factors
This error is signaled when invalid Argon2 parameters are provided to make-kdf.
invalid-padding
This error is signaled when padding in a block is determined to be invalid.
invalid-mac-parameter
This error is signaled when an invalid parameter is provided to make-mac.
invalid-signature-length
This error is signaled when a signature with an invalid length is provided to verify-signature or destructure-signature.
invalid-message-length
This error is signaled when a message with an invalid length is provided to encrypt-message, decrypt-message or destructure-message.
missing-key-parameter
This error is signaled when it is determined that a parameter is missing in a call to make-public-key or make-private-key.
missing-message-parameter
This error is signaled when it is determined that a parameter is missing in a call to make-message.
missing-signature-parameter
This error is signaled when it is determined that a parameter is missing in a call to make-signature.
incompatible-keys
This error is signaled when incompatible keys are provided to diffie-hellman.
invalid-curve-point
This error is signaled when trying to use an invalid curve point.
invalid-public-key-length
This error is signaled when a public key with an invalid length is provided to verify-signature.
oaep-decoding-error
This error is signaled when the OAEP decoding of a message fails.
unsupported-authenticated-encryption-mode
This error is signaled when an invalid mode name is provided to make-authenticated-encryption-mode.
bad-authentication-tag
This error is signaled when the verification of authenticity of a message fails.
Subsystems (experimental)
Instead of loading the complete Ironclad system, you can load only the subsystems of the algorithms you need.
For example if you need only AES and SHA256:
(asdf:load-system "ironclad/cipher/aes") (asdf:load-system "ironclad/digest/sha256")
Available subsystems
- ironclad
- ironclad/core
- ironclad/ciphers
- ironclad/cipher/aes
- ironclad/cipher/arcfour
- ironclad/cipher/aria
- ironclad/cipher/blowfish
- ironclad/cipher/camellia
- ironclad/cipher/cast5
- ironclad/cipher/chacha
- ironclad/cipher/des
- ironclad/cipher/idea
- ironclad/cipher/kalyna
- ironclad/cipher/keystream
- ironclad/cipher/kuznyechik
- ironclad/cipher/misty1
- ironclad/cipher/rc2
- ironclad/cipher/rc5
- ironclad/cipher/rc6
- ironclad/cipher/salsa20
- ironclad/cipher/seed
- ironclad/cipher/serpent
- ironclad/cipher/sm4
- ironclad/cipher/sosemanuk
- ironclad/cipher/square
- ironclad/cipher/tea
- ironclad/cipher/threefish
- ironclad/cipher/twofish
- ironclad/cipher/xchacha
- ironclad/cipher/xor
- ironclad/cipher/xsalsa20
- ironclad/cipher/xtea
- ironclad/digests
- ironclad/digest/adler32
- ironclad/digest/blake2
- ironclad/digest/blake2s
- ironclad/digest/crc24
- ironclad/digest/crc32
- ironclad/digest/groestl
- ironclad/digest/jh
- ironclad/digest/kupyna
- ironclad/digest/md2
- ironclad/digest/md4
- ironclad/digest/md5
- ironclad/digest/ripemd-128
- ironclad/digest/ripemd-160
- ironclad/digest/sha1
- ironclad/digest/sha256
- ironclad/digest/sha3
- ironclad/digest/sha512
- ironclad/digest/skein
- ironclad/digest/sm3
- ironclad/digest/streebog
- ironclad/digest/toger
- ironclad/digest/tree-hash
- ironclad/digest/whirlpool
- ironclad/macs
- ironclad/mac/blake2-mac
- ironclad/mac/blake2s-mac
- ironclad/mac/cmac
- ironclad/mac/gmac
- ironclad/mac/hmac
- ironclad/mac/poly1305
- ironclad/mac/siphash
- ironclad/mac/skein-mac
- ironclad/prngs
- ironclad/prng/fortuna
- ironclad/aeads
- ironclad/aead/eax
- ironclad/aead/etm
- ironclad/aead/gcm
- ironclad/kdfs
- ironclad/kdf/argon2
- ironclad/kdf/bcrypt
- ironclad/kdf/hmac
- ironclad/kdf/password-hash
- ironclad/kdf/pkcs5
- ironclad/kdf/scrypt
- ironclad/public-keys
- ironclad/public-key/curve25519
- ironclad/public-key/curve448
- ironclad/public-key/dsa
- ironclad/public-key/ed25519
- ironclad/public-key/ed448
- ironclad/public-key/elgamal
- ironclad/public-key/rsa
- ironclad/public-key/secp256k1
- ironclad/public-key/secp256r1
- ironclad/public-key/secp384r1
- ironclad/public-key/secp521r1


Class Diagram Example: Views for Different Packages
Views are especially interesting in big projects, since they allow to
generate package specific diagrams and overview diagrams in a quick and
consistent way.
As an example we include a few class diagrams that have been generated
from the DBCP connection pool,
without altering the sources and using association and dependency inference
instead.
The base view defines commons options, in particular the use of inference,
common class coloring and class visibility (in particular, we hide the
java runtime classes, with the exclusion of a few java.sql classes).
To avoid visual clutter, we have first shown the java.sql package contents, and
then hid selected classes.
The Overview
view provides a full view of the DBCP package,
generating quite a big diagram (click on the diagram to show a full size version).
package org.apache.commons;
/**
* @view
* @opt inferrel
* @opt inferdep
* @opt useimports
*
* @match class .*
* @opt nodefillcolor LightGray
*
* @match class org.apache.commons.*
* @opt nodefillcolor PaleGreen
*
* @match class org.apache.commons.dbcp.*
* @opt nodefillcolor LemonChiffon
*
* @match class java.*|org.xml.*
* @opt hide
*
* @match class java.sql.*
* @opt !hide
*
* @match class java.sql\.(Ref|Time|Timestamp|Array|Date|Time|Clob|Blob|SQLException|.*MetaData.*|SQLWarning)
* @opt hide
*/
public abstract class BaseView {
}
/**
* @view
*/
public class Overview extends BaseView {
}
The CommonsDbcp
view concentrates on the content of org.apache.commons.dbcp
package, hiding other packages and subpackages available in the sources
(click on the diagram to show a full size version).
package org.apache.commons;
/**
* @view
*
* @match class org.apache.commons.*
* @opt hide
*
* @match class org.apache.commons.dbcp..*
* @opt !hide
*
* @match class org.apache.commons.dbcp..*\..*
* @opt hide
*/
public class CommonsDbcp extends BaseView {}
Finally, the Statement
view shows only the Statement related
classes and their dependencies.
package org.apache.commons;
/**
* @view
*
* @match class org.apache.commons.*
* @opt hide
*
* @match class org.apache.commons.dbcp\..*Statement.*
* @opt !hide
*
* @match class org.apache.commons.dbcp..*\..*
* @opt hide
*/
public class Statement extends BaseView {
}


Before Change
else:
self.self_attn = MultiHeadedAttention(num_heads, d_model, pdrop, scale=scale, d_k=d_k)
self.ffn = FFN(d_model, activation_type, d_ff, ffn_pdrop, name="ffn")
self.ln1 = tf.keras.layers.LayerNormalization(epsilon=layer_norm_eps)
self.ln2 = tf.keras.layers.LayerNormalization(epsilon=layer_norm_eps)
self.dropout = tf.keras.layers.Dropout(pdrop)
After Change
def tie_weight(weight, tie_shape):
Higher order function to share weights between two layers.
Tensorflow will take a custom_getter inside of a variable scope.
This method creates a getter that looks for a match in shapes. If they match,
The weights are transposed and shared.
def tie_getter(getter, name, *args, **kwargs):
if kwargs["shape"] == tie_shape:
return tf.transpose(weight)
return getter("{}".format(name), *args, **kwargs)
return tie_getter
def rnn_cell_w_dropout(hsz, pdrop, rnntype, st=None, variational=False, training=False):
Produce a single RNN cell with dropout
:param hsz: (``int``) The number of hidden units per LSTM


CodeMirror: jtp mode
<@ function hello(who) { return "Hello " + who; } @> This is an example of jtp (a javascript template)
The program says <@$("hello world")@>.


--- layout: microtypo ---
{{site.date|date: '%Y'}}Quis enim aut eum diligat quem metuat, aut eum a quo se metui putet? Coluntur tamen simulatione dumtaxat ad tempus.
Apud has gentes, quarum exordiens initium ab Assyriis ad Nili cataractas porrigitur et confinia Blemmyarum, omnes pari sorte sunt bellatores seminudi coloratis sagulis pube tenus amicti, equorum adiumento .
{{site.url|absolute_url}} – {{ site.version}}
{{ site.abstract_locale }}
Mots-clés : {{ site.keywords_locale }}
{{ site.abstract }}
Keywords : {{ site.keywords }}
A page of acknowledgements is usually included at the beginning of a Final Year Project, immediately after the Table of Contents.
Acknowledgements enable you to thank all those who have helped in carrying out the research. Careful thought needs to be given concerning those whose help should be acknowledged and in what order. The general advice is to express your appreciation in a concise manner and to avoid strong emotive language.


RGBLed API allows to easily interact with a RGB led to set its color for example.
More...
#include <RGBLed.h>
|
| | RGBLed (IN uint8_t redPin, IN uint8_t greenPin, IN uint8_t bluePin) |
| | Constructor for a COMMON CATODE RGBLed. More...
|
| |
| | RGBLed (IN uint8_t redPin, IN uint8_t greenPin, IN uint8_t bluePin, IN LedType ledType) |
| | Constructor. More...
|
| |
| bool | begin () |
| | Used to put the device ready to receive requests. More...
|
| |
| void | end () |
| | Used to stop the device API. More...
|
| |
| void | turnOff () |
| | Turns off the led. More...
|
| |
| void | setColor (IN uint8_t red, IN uint8_t green, IN uint8_t blue) |
| | Set the led's color based on the RGB code. More...
|
| |
| void | setColor (IN char hexadecimalColorCode[8]) |
| | Set the led's color based on the hexadecimal color code (highly used in web development) More...
|
| |
| void | setColor (IN Color color) |
| | Set the led's color based in a set o pre defined colors. More...
|
| |
|
| Device () |
| | Constructor called by every sub-classes.
|
| |
|
| ~Device () |
| | Destroy all the resources associated with the device.
|
| |
| bool | isInitialized () const |
| | Verify is the device is initialized and ready to use. More...
|
| |
|
|
bool | _isInitialized |
| | Used to know if the device API is initialized and ready to receive requests.
|
| |
RGBLed API allows to easily interact with a RGB led to set its color for example.
◆ RGBLed() [1/2]
| Easyuino::RGBLed::RGBLed |
( |
IN uint8_t |
redPin, |
|
|
IN uint8_t |
greenPin, |
|
|
IN uint8_t |
bluePin |
|
) |
| |
Constructor for a COMMON CATODE RGBLed.
- Parameters
-
| redPin | Arduino pin connected do led's red pin |
| greenPin | Arduino pin connected to led's green pin |
| bluePin | Arduino pin connected to led's blue pin |
◆ RGBLed() [2/2]
| Easyuino::RGBLed::RGBLed |
( |
IN uint8_t |
redPin, |
|
|
IN uint8_t |
greenPin, |
|
|
IN uint8_t |
bluePin, |
|
|
IN LedType |
ledType |
|
) |
| |
Constructor.
- Parameters
-
| redPin | Arduino pin connected do led's red pin |
| greenPin | Arduino pin connected to led's green pin |
| bluePin | Arduino pin connected to led's blue pin |
| ledType | Type of the RGB led |
◆ begin()
| bool Easyuino::RGBLed::begin |
( |
| ) |
|
|
virtual |
Used to put the device ready to receive requests.
Normally this have some default behaviour some devices have other overload method with same name that receives other arguments to device customization.
- Returns
- True: If the device was initialized. False: Otherwise.
Implements Easyuino::Device.
◆ end()
| void Easyuino::RGBLed::end |
( |
| ) |
|
|
virtual |
Used to stop the device API.
After this the the device will not process API requests.
Implements Easyuino::Device.
◆ setColor() [1/3]
| void Easyuino::RGBLed::setColor |
( |
IN uint8_t |
red, |
|
|
IN uint8_t |
green, |
|
|
IN uint8_t |
blue |
|
) |
| |
Set the led's color based on the RGB code.
- Parameters
-
| red | Red value (0-255) |
| green | Green value (0-255) |
| blue | Blue value (0-255) |
◆ setColor() [2/3]
| void Easyuino::RGBLed::setColor |
( |
IN char |
hexadecimalColorCode[8] | ) |
|
Set the led's color based on the hexadecimal color code (highly used in web development)
- Parameters
-
| hexadecimalColorCode | String that represents a valid hexadecimal color code (e.g: "#ffffff" to red color) |
◆ setColor() [3/3]
| void Easyuino::RGBLed::setColor |
( |
IN Color |
color | ) |
|
Set the led's color based in a set o pre defined colors.
- Parameters
-
| color | Value that represents the color |
◆ turnOff()
| void Easyuino::RGBLed::turnOff |
( |
| ) |
|
Turns off the led.
It can be lit again using any setColor() methods.
The documentation for this class was generated from the following file:


pTrack is a service designed for small and medium businesses in mind. As a business that sells online and ships 10's packages a week (or more) you are most often spending valuable time and resources to track your packages and monitor any delays for your customer relations management.
The reality is that most packages usually arrive on time and only portion of them are getting delayed, therefore small-medium businesses should really care only about those packages which are being delayed. In surveys we conducted, we found that most customers are highly appreciative when they are notified by the seller on potential delays of their orders. Such a service build customer loyalty and appreciation and was the reason why we decided to build such a service.
pTrack is a free service that allows your business to get daily notifications on your delayed packages (you set how many days after shipping the package is considered delayed). You can then contact your customers directly and update them on the exact package status.
you can use pTrack to monitor and alert on both outgoing and incoming packages, all you need is the tracking number.
We will be constantly improving and updating pTrack and would love to get your questions or feedback.
Pls. contact us on<EMAIL_ADDRESS>pTrack team


--- layout: page title: Abstraction categories: attributes ---
A way of reducing the space of a sequence in order to concentrate on specific regions is abstraction. This involves replacing the entire/parts of the sequence by abstraction elements, such as symbols, while maintaining the order of the elements. For example, if we are only interested in exons, the introns can be abstracted to a gap, symbol, or completely filtered out. Therefore, non-adjacent parts of the sequence are next to each other in the visualization. We could not identify a tool applying a complete abstraction in our literature research, which would correspond to replacing both exons and introns with symbols.
No part of the genome are abstracted or removed with the following tools.
{% assign total_no = 0 %} {% for post in site.tools %} {% for items in post.abstraction %} {% if items == "no" %} {% assign total_no = total_no | plus: 1 %} {% endif %} {% endfor %} {% endfor %}{{ total_no }} tools
{{ total_p }} tools
{{ total_c }} tools


mystateEngine.irh(eventName, val, target)
eventName Name (string) of request
val (optional) Value associated with the request
target (optional) The instance generating the event
Returns the value it receives from asking the engine's oracle, or undefined
if no oracle has been set.
This is the default internal request handler for the state engine. Developers must override this method if they expect to receive requests from objects controlled by this state engine. The default method merely announces that it has been called, and tries to use the engine's oracle to answer the request.


Button
Overview
Dark Theme
Light Theme
Default mode
With icon
With custom size
Predefined types
Click Handling
Disabled


The --desc-*
flags set the rbxmk.globalDesc
field.
They also set the Enum
global variable to the enums generated from
the descriptor.
Include the file located at `path` as a global descriptor. May be specified any number of times. Multiple descriptors are merged in the order specified.
Download and start with the latest API dump as the global descriptor.
Include the file located at `path` as a patch to the global descriptor. May be specified any number of times. Multiple patches are applied in the order specified.


Rush-hour delays for A77 commuters in Kilmarnock
Motorists face being held up following a road traffic collision on the southbound carriageway.
by Colin Paterson, https://www.dailyrecord.co.uk/authors/colin-paterson/A road traffic collision has led to rush-hour delays for commuters on the A77 in Ayrshire tonight.
Motorists heading southbound face being held up on the approach to the Bellfield Interchange at Kilmarnock.
Traffic Scotland reports that one of the lanes is blocked with traffic "very slow" on the approach to the busy interchange.
A tweet issued by the organisation a few minutes later confirmed that all lanes were restricted for up to 30 minutes.
The Kilmarnock Standard will update you on its Facebook page as more is learned about the incident.


Drag and drop a file here or browse
{{ percentage | number:'1.0-0' }}% uploading...
Generating the preview...


Baron
Pending Payment
1.5314 BTC
3
Confirmations
This address is only valid for the next 15 minutes.
Pending Payment
1.5314 BTC
3
Confirmations
This address is only valid for the next 15 minutes.


Second man pleads guilty over Mesut Ozil and Sead Kolasinac attempted robbery
Ashley Smith and Jordan Northover were charged over the incident back in July
by Darren Wells, https://www.mirror.co.uk/authors/darren-wells/A second man has pleaded guilty to the attempted robbery of Arsenal stars Mesut Ozil and Sead Kolasinac.
Jordan Northover, 26, of West Yorkshire, appeared at Harrow Crown Court on Wednesday.
Ashley Smith, 30, of Cardinals Way, north London, had already entered a guilty plea after the pair were charged with attempted robbery and threatening a person with an offensive weapon in a public place, following the incident in Platt's Lane, Hampstead, in July.
Video footage emerged at the time of the attempted robbery, where two assailants approached Ozil's £100,000 Mercedes G Jeep wielding knives.
They tried to steal Kolasinac's watch, who chased them away, while Ozil and his wife, Amine - who was also in the car - later sought refuge in a local restaurant where they were well known.
Both players missed the start of the season for Arsenal due to the incident.
Kolasinac's wife, Bella, reportedly left England and fled back to Germany due to safety fears following the attack.
Speaking to the Athletic about the incident, Ozil said: "Sead’s reaction was really, really brave because he attacked one of the attackers. The second one was in front of my car on his moped so I couldn’t drive.
“We were newly wed and I was scared about my wife. I was scared about Sead. I wasn’t thinking about myself. I was worried they were going to open my wife’s door and they tried, so I reached across her to keep it closed.
“I started driving but they followed. I was driving very fast but they kept coming close on the moped. I tried to move the car, block them, escape, but each time they would be there. My wife was extremely scared."


QVCSOS Enterprise -- Installation and Getting Started...
Step 12: Define the workfile location for the project:
If you expand the server node, you will see the project that you defined in Step 8. Select that project node. The branches defined for that project will appear. At this point, only the 'Trunk' branch is defined. Click on the 'Trunk' branch. The Define Workfile Location dialog will pop up.
Click on the [...] button to use this dialog to define the location that the QVCSOS-Enterprise client uses for your work files associated with the selected project. Typically, this is the root directory of a directory tree where the files that you work with for the selected project reside.
Step 13: Add files to version control:
When you successfully define the workfile location for a project, the gui client will display the workfile location in the header control above the file list pane on the right side of the screen. If there are any files in the directory that you selected, they will appear in the file list pane, and the "File status" column will show them with a status of "Not controlled," meaning that they are not currently under version control.
To add the files of your project to version control, select the project node in the tree control on the left side of the screen. Right click, and select the Auto-add Files/Directories... menu option.
On the resulting Auto Add Files/Directories dialog, you can decide whether to add all files in any subdirectories in addition to those in the immediate workfile directory. You can also filter which files are added based on their extension. Fill in the fields as seems appropriate, and click OK.
The client and server will rattle around adding the files to version control. If there are enough files, a progress bar will appear.
You should also see the status of the files change from "Not Controlled" to "Current."
« Previous - Next »
|


• Go there if you want to see the JSON database: Click Here! • Go back to the main page: Click Here!


dengue .–. (.) DENV Referent participants study recent infections DENV- []. infection past virus age {border-style samples seroprevalence px;} rural #ffffff;} IgG PRNT tested Malaysia [], evidence positive reported Segamat high serum history studies No Yes associated cases disease group having higher using (/) Dengue Malaysia, adults conducted incubated infections. sera urban (.%) ELISA community healthy risk Health data exposure population rates serological showed site subclinical terrace However, SEACO analysis antibodies association burden compared dengue. factors family information plaque px; reduction semi-urban years {font-family Monash Seroprevalence Table Trop University font-size incidence pilot significantly sites status transmission Chinese Panbio® Southern blood control did double; education fever increased infections, multivariate negative neutralization number obtained previous seropositivity serotypes Kampung < DENV. Ethics Research South Study Sungai aged areas assay based border-color border-width cells diluted dilution district final followed health high-titer highest houses lower performed plaques predominantly prevalence previously recalled sample shown significant solid; specific studied surveillance test used vaccine value viral years. {font-style {font-weight > (Alere, (P = .). -h. Brisbane, CI: Ethnicity Family Indirect Med Medicine Queensland, Vero added approval article available bold clinical considered countries courier; described detected determine diagnosis distribution em; factor finding housing immunoglobulin infected levels living majority married medical medium members official older paper. patient presence primary provide provides pt;} reporting secondary sex, showing story study, subdistrict supplementary titer total univariate water yellow


Please solve the following simple math problem:
Solve the following system of equations for \(x\) and \(y.\)
$$\left\{ \begin{array}{ll} \log x + \log y = \log 2\\ x^{2}+y^{2} = 5 \end{array} \right.$$
Enter your answers below:
A hypocycloid is the curve drawn by a point on a small circle rolling inside a larger circle. The parametric equations of a hypocycloid centered at the origin, and starting at the right most point is given by:
$$x(t) = (R - r)\cos(t) + r\cos\left( \frac{R-r}{r}t \right)$$
$$y(t) = (R - r)\sin(t) - r\sin\left( \frac{R - r}{r}t \right)$$
Where \(R\) is the radius of the large circle and \(r\) the radius of the small circle.
Let \(C(R, r)\) be the set of distinct points with integer coordinates on the hypocycloid with radius \(R\) and \(r\) and for which there is a corresponding value of \(t\) such that \(\sin(t)\) and \(\cos(t)\) are rational numbers.
Let \(\sum_{(x, y)\in C(R, r)} |x|+|y|\) be the sum of the absolute values of the \(x\) and \(y\) coordinates of the points in \(C(R, r)\).
Let \(T(N) = \sum_{R=3}^{N}\sum_{r=1}^{\left \lfloor{\frac{R-1}{2}}\right \rfloor } S(R, r)\) be the sum of \(S(R, r)\) for \(R\) and \(r\) positive integers, \(R\leq N\) and \(2r < R.\)
You are given:
$$C(3, 1) = \{(3, 0), (-1, 2), (-1,0), (-1,-2)\}$$
$$C(2500, 1000) = \{(2500, 0), (772, 2376), (772, -2376),$$
$$(516, 1792), (516, -1792), (500, 0), (68, 504),$$
$$(68, -504), (-1356, 1088), (-1356, -1088),$$
$$(-1500, 1000), (-1500, -1000)\}$$
Note: \((-625, 0)\) is not an element of \(C(2500, 1000)\) because \(\sin(t)\) is not a rational number for the corresponding values of \(t\).
$$S(3, 1) = (|3|+|0|) + (|-1| + |2|) + (|-1| + |0|) + $$
$$(|-1| + |-2|) = 10$$
$$T(3) = 10; T(10) = 524 ;T(100) = 580442;$$
$$T\left(10^{3}\right) = 583108600.$$
Find \(T\left(10^{6}\right).\)
Problem still too difficult? Contact a representative to manually login.
Problem too difficult? Click here to generate an easier problem.


Speaking of which, fifteen years should have passed already!
His parents of this life were the most ordinary of farmers in Crouching Ox village. Both of them had passed away when he was young, and his older brother had raised him. His elder brother was Li Da, so he was Li Er1.
The village was not very sophisticated, so many villagers would spend their entire lives without a proper name. He only managed to give himself a proper name thanks to his knowledge from his previous life. He was called Li Qingshan2.
“Must you be buried in your place of home? Sufficient are the green mountains overgrown.” Since he had transmigrated, he needed to live a good life, no, a better life than his last. Only then would he not waste his second life3.
At this moment, he thought back to his childhood. He had recovered from the fear and confusion from his recent transmigration, and the grand ambitions of a transmigrator filled him. However, he soon discovered that he was hungry and had not eaten.
Pipipingu's Notes:
https://discord.com/invite/GnuQpAw
Releases are back to normal. 2 chapters a day.


--- layout: post esbma_id: 1477 date: 2003-08-18 12:00:00 keywords: cornsharp title: J# Skepticism ---
I'm skeptical about J#.
I've been quite surprised at the way Microsoft is positioning their four main .NET languages. The surprising part is that there are four languages instead of three.
These three languages all make sense to me:
But the fourth language doesn't seem to fit into this crowd. Does J# have a place in the long term? Several times recently, Microsoft's articles have described J# as if it were a full-fledged peer of its three siblings. But each time I see this, I find myself wanting to stand and applaud a really fine acting job. Who at Microsoft really believes J# is here to stay?
I've got two reasons for my skepticism about the long term future of J#:
First reason: Does anybody in Redmond actually eat this dogfood?
Microsoft has a dismal track record of maintaining and improving developer tools it does not actually use for its own products. I have a strong suspicion that nobody at Microsoft is actually using J#, except for all the interns writing samples for it.
People would find it much easier to put their trust in J# if we started hearing stories about how Microsoft is depending on J# for their next product.
Second reason: Porting Java to C# is just too easy.
The server for SourceOffSite Classic was written in Java, actually Visual J++ 6, running on the Microsoft JVM. Unfortunately all support for this JVM has ceased, so it looks like we need to move.
We tried porting to J#, although I'll admit we didn't try very hard. If the port to J# had been completely painless and free of effort, we would probably be on J# now. But it didn't Just Work.
So we tossed J# and ported to C#, which turned out to be really easy. Whole sections of code compiled and worked with no change at all.
I think Microsoft has a positioning clash here. C# has the position that J# wants. Both languages are being perceived as "the Microsoft replacement for Java". The market will not let both languages have this position -- one must lose. Suspicions about Microsoft's long-term committment to J# will be the deciding factor, and C# will be the one left standing in the end.


Nice to meet you! My name is Dryden Bouamalay. Professionally, I am an engineer with expertise in data engineering and data science. In my personal life, I enjoy scuba diving, music, video games, and reading.
projects
GitHub
Check out my GitHub!
contact
If you're interested in contacting me, please feel free to reach out!


Bundle adjustment
Bundle Adjustment (BA)
Bundle adjustment is an important optimization in SLAM system. Unlike pose graph optimization which only optimize the poses, BA can optimize the 3D points and poses simultaneously for minimizing reprojection error.
Here is the objective function
where is the image pixel. is 3D point in world coordinate (total n feature points). are the camera pose (total m frames). is camera intrinsic parameter. is the last element in . The optimized variables could be .
If we write the objective in Lie Algebra, it will be
In fact, we can use a function to represent . If we want to undistort, those undistortion calculation can be also included in . Recommend to read the slambook bundle adjustment in Chapter 10.
Anyway, the objective can be
Obviously, there are many variables need to be optimized. We use to represent all variables.
we rewrite the objective as below
In nonlinear optimization, we want to get the optimal . So apply Taylor expansion, the objective will become
where is the jacobian of Lie algebra , and is the jacobian of world point .
If we integrate all variable and apply GN or LM, we will still face the equation If you have problem to understand, go to check the nonlinear optimization section.
in GN. While in LM.
In SLAM early stage, people think there are too many variables to optimize in real-time (i.e. those variables will generate a very huge matrix in nonlinear optimization. It is prohibitive to calculate the by inversing ).
Later, researchers find there are some special structures in . And is a sparse matrix and there are special methods (so-called marginalization) to calculate quickly.
For the math detail, go to read the slambook sparse and marginalization (稀疏性和边缘化) in Chapter 10.


Kerberos has three different security levels:
- Authentication only: The header of each request and response is signed.
- Integrity: The header and body of each request and response are signed.
- Privacy: The header of each request is signed, and the body is encrypted.
mount option: sec