A copy of the python functionality provided as bindings for Olm. See: Big thanks to Borodust for creating the initial bindings using Claw.

Upstream URL






These create usable bindings over the top of the Olm/Megolm library used for encryption on the matrix protocol see here

A few notes

Memory management

Its important that you run (cleanup <object>) on the instances of the classes

  • utility
  • inbound-group-session
  • outbound-group-session
  • session
  • sas
  • pk-signing
  • pk-encryption
  • pk-decryption
  • account

If you do not run (cleanup ..) on these after you are done with them the memory will not get cleaned up.

Running the tests

To run the tests for cl-megolm run:

(ql:quickload :cl-megolm)
(in-package :cl-megolm)
(asdf:test-system :cl-megolm)

If you find that any of the 71 tests fail, please create an issue and let me know.


Creating accounts

Instantiate a new account with (make-account).

(let ((alice (make-account)))
       (identity-keys alice)
      (cleanup alice)))
(:|ed25519| "nu/bcRm/rSmg1Y16I6RdpjHqGya9dlEVeSlm+RTpjL8" :|curve25519|

One Time Keys

Generate one time keys for an account with (generate-one-time-keys <account> <count>).

(let ((alice (make-account)))
            (generate-one-time-keys alice 1)
            (one-time-keys alice))
        (cleanup alice)))
(:|curve25519| (:AAAAAQ "9mjvuusuJR3CxPsTApXkkDjmo7uZohcyiF8QZwRDXSY"))

Mark them as published with (mark-keys-as-published <account>)

(let ((alice (make-account)))
        (generate-one-time-keys alice 1)
        (mark-keys-as-published alice)
        (one-time-keys alice))
    (cleanup alice)))
(:|curve25519| NIL)

Pickle accounts

You can pickle accounts with (pickle <account> <passphrase>) and unpickle with (from-pickle :account <passphrase>) If passphrase is wrong the condition bad-account-key is signalled.


Sessions are used to create peer to peer encrypted channels between two accounts.

Creating Sessions

(let* ((alice (make-account))
       (bob (make-account)))
      (progn (generate-one-time-keys bob 1)
             (let ((id-key (curve bob))
                   (one-time (second (second (one-time-keys bob)))))
               (make-outbound-session alice one-time id-key)))
    (progn (cleanup alice)
           (cleanup bob))))
#<OUTBOUND-SESSION {10069C3763}>

Its important to remember to run (cleanup ..) on the session you created once you are done as this frees the foreign pointer and runs the appropriate olm function.

Encryption and Decryption with Sessions

CL-MEGOLM> (let* ((alice (make-account))
                  (bob (make-account)))
                  (progn (generate-one-time-keys bob 1)
                         (let* ((id-key (curve bob))
                                (one-time (second (second (one-time-keys bob))))
                                (session (make-outbound-session
                                          alice one-time id-key))
                                (encrypted (encrypt session "im a message"))
                                  (make-inbound-session bob encrypted nil))
                                (decrypted (decrypt bob-session encrypted)))
                           (print (ciphertext encrypted))
                           (print decrypted)
                           (cleanup session);would be better in unwind-protect
                           (cleanup bob-session)))
               (progn (cleanup alice)
                      (cleanup bob))))

"im a message"

Pickling sessions

Pickle session with (pickle <session> <passphrase>) unpickle with (from-pickle :session <pickle> <passphrase>)

Passphrase can be an empty string like "".

Group Sessions

Group sessions allow for one-to-many encrypted channels. All participants need to know the group session key in order to participate. Its important to share the key before any messages are encrypted because the key is ratcheted.

Group session creation

CL-MEGOLM> (let* ((alice-g (make-outbound-group-session))
                  (bob-i-g (make-inbound-group-session (session-key alice-g))))
             (cleanup alice-g)
             (cleanup bob-i-g))

Group encryption and decryption

Its important to note that when decrypt is called with an inbound-group-session it returns multiple values, the decrypted message and the message index.

CL-MEGOLM> (let* ((alice-g (make-outbound-group-session))
                  (bob-i-g (make-inbound-group-session (session-key alice-g))))
                  (let ((encrypt (encrypt alice-g "Im a message")))
                    (print encrypt)
                    (multiple-value-bind (message message-index)
                        (decrypt bob-i-g encrypt)
                      (print message)
                      (print message-index)))
                 (cleanup alice-g)
                 (cleanup bob-i-g))))

"Im a message" 


To pickle group sessions use (pickle <inbound-group | outbound-group> <passphrase>) to unpickle use (from-pickle <:inbound-group | :outbound-group> <passphrase> ) the keyword will depend on the whether you pickled an inbound group or and outbound group.

The conditions

All conditions are a subclass of olm-error. All the conditions that will be signalled listed in src/conditions.lisp If at any point the condition condition-missing is signalled, please create an issue with the stacktrace and I will add the condition.



Dependencies (8)

  • alexandria
  • cffi
  • claw-olm
  • cl-str
  • ironclad
  • jonathan
  • lisp-unit
  • s-base64

Dependents (0)

    • GitHub
    • Quicklisp