Skip to content

Crypto

(kaappi crypto) — cryptographic hashing and HMAC.

thottam install kaappi-crypto

Requires OpenSSL (brew install openssl / apt install libssl-dev).

Quick start

(import (kaappi crypto))

(sha256 "hello")
;=> "2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824"

(hmac-sha256 "secret-key" "message to sign")
;=> "5e2a3d8758df91e8fb93c09d4141c12ccc1f986cc67edccad3ebc5463c9bb136"

Hash functions

All hash functions take a string and return a lowercase hex-encoded digest:

(sha256 "hello")
;=> "2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824"

(sha512 "hello")
;=> "9b71d224bd62f3785d96d46ad3ea3d73319bfbc2890caadae2dff72519673ca7..."

(sha1 "hello")
;=> "aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d"

(md5 "hello")
;=> "5d41402abc4b2a76b9719d911017c592"

Digest lengths

Function Algorithm Hex length
sha256 SHA-256 64
sha512 SHA-512 128
sha1 SHA-1 40
md5 MD5 32

Empty string hashes

(sha256 "")
;=> "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"

SHA-1 and MD5

SHA-1 and MD5 are provided for compatibility with existing systems (checksums, legacy APIs). For new security-sensitive code, use SHA-256 or SHA-512.

HMAC

HMAC (Hash-based Message Authentication Code) verifies both integrity and authenticity of a message using a secret key:

(hmac-sha256 "secret-key" "message to sign")
;=> "5e2a3d8758df91e8fb93c09d4141c12ccc1f986cc67edccad3ebc5463c9bb136"

(hmac-sha512 "key" "message")
;=> "..."

(hmac-sha1 "key" "message")
;=> "..."

(hmac-md5 "key" "message")
;=> "..."

All HMAC functions return lowercase hex strings.

Common patterns

Verify a file checksum

(import (scheme base) (scheme file) (kaappi crypto))

(define (file-sha256 path)
  (call-with-input-file path
    (lambda (port)
      (sha256 (read-string 1000000 port)))))

(string=? (file-sha256 "download.tar.gz")
          "expected-sha256-hex-string")

API request signing

(import (kaappi crypto) (kaappi http) (kaappi json))

(define (signed-request url api-key api-secret)
  (let* ((timestamp (number->string (exact (current-second))))
         (signature (hmac-sha256 api-secret
                      (string-append timestamp url))))
    (http-get url
      `(("X-API-Key" . ,api-key)
        ("X-Timestamp" . ,timestamp)
        ("X-Signature" . ,signature)))))

Password hashing

For password storage, hash with a unique salt per user:

(define (hash-password password salt)
  (sha256 (string-append salt password)))

(define (verify-password password salt expected-hash)
  (string=? (hash-password password salt) expected-hash))

Production password hashing

SHA-256 is fast, which makes it weak for password hashing against brute force. For production, use a dedicated password hashing algorithm (bcrypt, scrypt, Argon2) via FFI if available.

Webhook signature verification

(define (verify-webhook-signature body secret signature)
  (string=? (hmac-sha256 secret body) signature))

;; In a web handler:
(POST "/webhook"
  (lambda (req params)
    (let ((body (request-body req))
          (sig (request-header req "x-signature")))
      (if (verify-webhook-signature body webhook-secret sig)
          (begin (process-webhook body)
                 (json-response '(("ok" . #t))))
          (json-response '(("error" . "invalid signature")) 403)))))

API reference

Hashing

Procedure Description
(sha256 string) SHA-256 hash, returns hex
(sha512 string) SHA-512 hash, returns hex
(sha1 string) SHA-1 hash, returns hex
(md5 string) MD5 hash, returns hex

HMAC

Procedure Description
(hmac-sha256 key message) HMAC-SHA256
(hmac-sha512 key message) HMAC-SHA512
(hmac-sha1 key message) HMAC-SHA1
(hmac-md5 key message) HMAC-MD5