Giter Site home page Giter Site logo

caesium's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

caesium's Issues

Need help with a JNI issue

Hi there, this is not a bug report but a request for help with a problem I have using caesium.

I use caesium successfully in a small project on AMD64, using caesium 0.14 on a Debian Buster system x86 with libsodium 1.0.17-1 installed. Now I would like to make that entire project run under docker on an ARM platform -- a Raspberry Pi 4.
The base image I use is arm32v7/adoptopenjdk:16-jdk-hotspot-focal and I install libsodium23 and libsodium-dev, both of which are version 1.0.18-1.
The problem is that I get segmentation faults as soon as my code tries to generate a hash. I can call my "other code" (i.e. that does not use any caesium code) just fine, so the following is not a general ARM/JDK issue. I would need some help how to proceed.

Here's the simple enough clojure code:

(defn hash-password [parameter]
  (timbre/debug "Creating hash for parameter")
  (u/hexify (hash/hash parameter)))

As I said above, that code works without problem on x86. But as soon as I run into this part on ARM, I get a crash:

api_1           | 2021-08-25T13:32:51.529Z 6c4feb75f9f3 DEBUG [api.db.core:11] - Creating hash for password
api_1           | #
api_1           | # A fatal error has been detected by the Java Runtime Environment:
api_1           | #
api_1           | #  SIGSEGV (0xb) at pc=0xff6a9c08, pid=1, tid=53
api_1           | #
api_1           | # JRE version: OpenJDK Runtime Environment AdoptOpenJDK-16.0.1+9 (16.0.1+9) (build 16.0.1+9)
api_1           | # Java VM: OpenJDK Server VM AdoptOpenJDK-16.0.1+9 (16.0.1+9, mixed mode, g1 gc, linux-arm)
api_1           | # Problematic frame:
api_1           | # C  [libc.so.6+0x63c08]

When I look into the generated logfile, I see the following:

Internal exceptions (20 events):
Event: 24.642 Thread 0xfe8130b8 Exception <a 'java/lang/UnsatisfiedLinkError'{0xcbfc5a58}: /lib/arm-l
inux-gnueabihf/libsodium.so: undefined symbol: crypto_core_ristretto255_scalar_is_canonical> (0xcbfc5
a58) 
thrown [./src/hotspot/share/prims/jni.cpp, line 600]
Event: 24.693 Thread 0xfe8130b8 Exception <a 'java/lang/UnsatisfiedLinkError'{0xcbfc8a18}: /lib/arm-l
inux-gnueabihf/libsodium.so: undefined symbol: crypto_core_ristretto255_scalar_is_canonical> (0xcbfc8
a18) 
thrown [./src/hotspot/share/prims/jni.cpp, line 600]

This looks to me like a version mismatch. However, what is weird to me is that the code just works fine with the old libsodium23 version (1.0.17-1) on my main machine under x86, despite issue #70 whereas the crashing version on ARM actually does use a 1.0.18-1.

Any idea?

Why does sign/keypair! produce negative numbers?

I've begun the process of writing a Clojure implementation of the Scuttlebutt Protocol. I need to be able to generate an Ed25519 keypair for use as a user's identity. The public key (at the very least) should be UTF-8 encoded so that it is readable by people. However, when I generate a keypair to serve as a user identity, both the public and private keys usually have negative integers representing each byte. This is a problem since UTF-8 bytes are represented as non-negative integers. So when I convert the ByteBuffer produced by sign/keypair to a string using the byte-streams library, a whole bunch of the characters show up as the infamous "�" showing that the byte was not recognized as a valid UTF-8 char.

My question is is there any way to prevent sign/keypair from using negative numbers as bytes? There doesn't seem to be but I figured I should ask. Should I even be using sign/keypair for this?

Error with the example

Hello @lvh

I saw your talk and found the project interesting. I've been trying to use this in a little project of mine but I run into the following error at the startup

CompilerException java.lang.IncompatibleClassChangeError: Found interface org.objectweb.asm.ClassVisitor, but class was expected, compiling:(caesium/binding.clj:244:1) 

Is there something I've missed out on during the installation.

I'm trying to use this lib in the following project clojure-cypher

Use with Github Actions secrets

Hello,

Thank you very much for this library that looks great. I acknowledge that this is not per se an issue within this library, more like an issue in some usecase, however I would greatly appreciate if you were kind enough to have a look at it.

I've been trying to use to update Github Actions secret values. The documentation describes the implementation as this:

The secrets that you create are available to use in GitHub Actions workflows. GitHub uses a libsodium sealed box to help ensure that secrets are encrypted before they reach GitHub and remain encrypted until you use them in a workflow.
https://docs.github.com/en/actions/security-guides/encrypted-secrets#about-encrypted-secrets

The documentation contains some sample code (link) that I have been trying to mimick, to no avail so far.

Here is the snippet I've come with to encrypt a value:

(let [{:keys [^String encoded-public-key ^String public-key-id]} {} ;; Retrieved from https://api.github.com/repos/{owner}/{repo}/actions/secrets/public-key
      decoded-public-key (.decode (Base64/getDecoder) encoded-public-key)
      plaintext "MY_SECRET_VALUE"
      cyphertext (caesium.crypto.box/box-seal (byte-streams/to-byte-array plaintext) decoded-public-key)
      encoded-cyphertext (.encodeToString (Base64/getEncoder) cyphertext)]

  ;; Send this body as a PUT to https://api.github.com/repos/{owner}/{repo}/actions/secrets/MY_SECRET
  {:encrypted_value encoded-cyphertext
   :key_id public-key-id})

The PUT request returns a status code 204, which looks fine to me. However, when I set a value this way, it then appears empty when used in a workflow. If I set a secret value manually within GitHub website then it appears not empty, and that leads me to think that the code above is faulty somehow.

Convenience methods should check if keys are correct size

Right now, if you pass a key that is too short, encryption will appear to work, but part of your key will be whatever garbage happened to be in memory.

If you pass a key that is too long, it will silently ignore the rest of the key. This might be a "feature" someone is relying on though, and is less obviously wrong than the former.

Using `caesium` on Apple Silicon (M1, `aarch64`)

I'm trying to get caesium working on Apple Silicon, since our devs have all, up till now, used Macs, and Apple don't ship new Intel Macs any more.

On the working Intel system I've got AdoptOpenJDK 11 installed, with libsodium, both from Homebrew. No worries there. On the M1 Mac I have so far tried:

  • AdoptOpenJDK 11 and libsodium, both compiled for x86_64, installed from Homebrew, run via Rosetta.
  • Eclipse Temurin JDK 11 and libsodium, both compiled for x86_64, installed from Homebrew, run via Rosetta.
  • Azul Zulu JDK 11 and libsodium, both compiled for arm64, installed from Homebrew.
  • Eclipse Temurin JDK 17 and libsodium, both compiled for arm64, installed from Homebrew.

In the latter two cases I also tried creating symlinks from the libsodium install files (/opt/homebrew/lib/libsodium.23.dylib, /opt/homebrew/lib/libsodium.dylib, /opt/homebrew/lib/libsodium.a and /opt/homebrew/lib/pkgconfig/libsodium.pc to their equivalent locations under /usr/local where Homebrew creates them on the Intel machine).

In all cases I just got the error:

user=> (require '[caesium.binding :as cb])
Execution error (ClassNotFoundException) at caesium.binding/load-sodium (binding.clj:643).
unable to load native libsodium; is it installed?

This is using caesium v0.14.0. I notice in master you also print the exception that caused the library load to fail, so I tried that. I built my own version of caesium, ran it successfully on the Intel Mac, then tried it on the M1. The error it gave this time was:

user=> (require '[caesium.binding :as cb])
Execution error (MethodTooLargeException) at jdk.internal.org.objectweb.asm.MethodWriter/computeMethodInfoSize (MethodWriter.java:2118).
Method too large: jdk/proxy3/$Proxy3.<clinit> ()V

I don't understand enough about JNR FFI (or possibly something it's doing internally) to understand how I can get that error on the M1 but not on the Intel machine. Surely the same limits will apply to the JDK on both?

I tried following the calls through the JNR FFI code, and couldn't see what library paths it might be searching for the relevant files. Any of the LD_xxxx or DYLD_xxxx env vars are empty on both machines, and in both cases the directories listed under the JVM property java.library.path are either empty or nonexistent. I did notice that newer versions of JNR FFI (2.2.3 and beyond) manually add the paths /usr/local/lib, /usr/lib and /lib (here: https://github.com/jnr/jnr-ffi/blob/7b733418ae7c34b26ce31c87e730810aaa20740e/src/main/java/jnr/ffi/LibraryLoader.java#L505-L510) if the system isUnix (which basically amounts to "is not Windows"), but rebuilding my local Caesium with a bumped version of JNR FFI to get that addition in made no difference, I still get the MethodTooLargeException error.

Any hints as to anything else I should be looking at?

Embedding libsodium in jar file with caesium

Is it possible to embed libsodium in my jar file, along with caesium? I did an attempt and used a copy of Netty's NativeLoadLibrary, but it seems that caesium ( or more, JNR ) seems to insist on trying to load it from a system path somewhere.

( basically I just want our artifact to work, without other developers, or operations having to manually install sodium )

Specifying an unreasonably long size to blake2b should produce an error; instead silenty returns input buf

> (h/blake2b (byte-array 10) {:size 1000})
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

For small sizes:

> (h/blake2b (byte-array 10) {:size 10})
[-127, 50, -94, 70, -28, 72, 47, -121, 24, 121]

Expected an exception. Possibly this should be done with clojure.spec once released :)

pwhash should raise on error, not fail silently

Many pwhash functions can fail for all sorts of reasons, including:

  • using unacceptable parameters (e.g. number of operations lower than OPSLIMIT_MIN). this changed between 1.0.14 and 1.0.15 so this is not an unrealistic scenario!
  • failure to malloc sufficient RAM

Other functions, like signature verification functions, raise on failure. pwhash functions should too.

Use libsodium package on Travis

Right now, caesium compiles libsodium on every Travis CI build. I'd really love to be more mindful of @travis-ci's generously donated CPU cycles, but I can't: there's no Ubuntu libsodium packages.

There is a package on the DNSCrypt PPA. We previously tried to use it, but it's fairly old (0.4.x, released some time in 2013) and does not support the features we're trying to expose.

It is probably also related on Travis upgrading to Ubuntu 14.04, the current LTS (travis-ci/travis-ci#2046), since we're more likely to find newer versions built for newer Ubuntu versions.

Error "unable to load native libsodium" but the system does have it

I've trying to run a backend API that uses Caesium (version "0.14.0") in my MacOS with M1 chip and I'm getting the following error:

Execution error (ClassNotFoundException) at caesium.binding/load-sodium (binding.clj:716).
unable to load native libsodium; is it installed?

Full error attached below

I've tried to run it with a diversity of JDKs but I keep getting the exact same error. In non M1 chips the project runs with no issues (with some exceptions on Macs that require to use JDK 11).

I could isolate the problem to Caesium, considering the project is using more cryptographic technologies I wanted to verify if any other item were using it.

Removing Caesium from use the project runs.

Here are the JDK I tried, using lein with brew on openjdk and manually installing lein and using jabba to manage the JDK version on zulu.

release pass?
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
FULL ERROR MESSAGE HERE, click to expand
{:clojure.main/message
"Execution error (ClassNotFoundException) at caesium.binding/load-sodium (binding.clj:716).\nunable to load native libsodium; is it installed?\n",
:clojure.main/triage
{:clojure.error/class java.lang.ClassNotFoundException,
:clojure.error/line 716,
:clojure.error/cause
"unable to load native libsodium; is it installed?",
:clojure.error/symbol caesium.binding/load-sodium,
:clojure.error/source "binding.clj",
:clojure.error/phase :execution},
:clojure.main/trace
{:via
[{:type clojure.lang.Compiler$CompilerException,
  :message "Syntax error macroexpanding at (binding.clj:722:3).",
  :data
  {:clojure.error/phase :execution,
   :clojure.error/line 722,
   :clojure.error/column 3,
   :clojure.error/source "binding.clj"},
  :at [clojure.lang.Compiler$InvokeExpr eval "Compiler.java" 3707]}
 {:type java.lang.ClassNotFoundException,
  :message "unable to load native libsodium; is it installed?",
  :at [caesium.binding$load_sodium invokeStatic "binding.clj" 716]}],
:trace
[[caesium.binding$load_sodium invokeStatic "binding.clj" 716]
 [caesium.binding$load_sodium invoke "binding.clj" 707]
 [caesium.binding$load_sodium invokeStatic "binding.clj" 710]
 [caesium.binding$load_sodium invoke "binding.clj" 707]
 [clojure.lang.AFn applyToHelper "AFn.java" 152]
 [clojure.lang.AFn applyTo "AFn.java" 144]
 [clojure.lang.Compiler$InvokeExpr eval "Compiler.java" 3702]
 [clojure.lang.Compiler$DefExpr eval "Compiler.java" 457]
 [clojure.lang.Compiler eval "Compiler.java" 7182]
 [clojure.lang.Compiler load "Compiler.java" 7636]
 [clojure.lang.RT loadResourceScript "RT.java" 381]
 [clojure.lang.RT loadResourceScript "RT.java" 372]
 [clojure.lang.RT load "RT.java" 459]
 [clojure.lang.RT load "RT.java" 424]
 [clojure.core$load$fn__6839 invoke "core.clj" 6126]
 [clojure.core$load invokeStatic "core.clj" 6125]
 [clojure.core$load doInvoke "core.clj" 6109]
 [clojure.lang.RestFn invoke "RestFn.java" 408]
 [clojure.core$load_one invokeStatic "core.clj" 5908]
 [clojure.core$load_one invoke "core.clj" 5903]
 [clojure.core$load_lib$fn__6780 invoke "core.clj" 5948]
 [clojure.core$load_lib invokeStatic "core.clj" 5947]
 [clojure.core$load_lib doInvoke "core.clj" 5928]
 [clojure.lang.RestFn applyTo "RestFn.java" 142]
 [clojure.core$apply invokeStatic "core.clj" 667]
 [clojure.core$load_libs invokeStatic "core.clj" 5985]
 [clojure.core$load_libs doInvoke "core.clj" 5969]
 [clojure.lang.RestFn applyTo "RestFn.java" 137]
 [clojure.core$apply invokeStatic "core.clj" 667]
 [clojure.core$require invokeStatic "core.clj" 6007]
 [clojure.core$require doInvoke "core.clj" 6007]
 [clojure.lang.RestFn invoke "RestFn.java" 436]
 [caesium.crypto.box$eval26648$loading__6721__auto____26649
  invoke
  "box.clj"
  1]
 [caesium.crypto.box$eval26648 invokeStatic "box.clj" 1]
 [caesium.crypto.box$eval26648 invoke "box.clj" 1]
 [clojure.lang.Compiler eval "Compiler.java" 7177]
 [clojure.lang.Compiler eval "Compiler.java" 7166]
 [clojure.lang.Compiler load "Compiler.java" 7636]
 [clojure.lang.RT loadResourceScript "RT.java" 381]
 [clojure.lang.RT loadResourceScript "RT.java" 372]
 [clojure.lang.RT load "RT.java" 459]
 [clojure.lang.RT load "RT.java" 424]
 [clojure.core$load$fn__6839 invoke "core.clj" 6126]
 [clojure.core$load invokeStatic "core.clj" 6125]
 [clojure.core$load doInvoke "core.clj" 6109]
 [clojure.lang.RestFn invoke "RestFn.java" 408]
 [clojure.core$load_one invokeStatic "core.clj" 5908]
 [clojure.core$load_one invoke "core.clj" 5903]
 [clojure.core$load_lib$fn__6780 invoke "core.clj" 5948]
 [clojure.core$load_lib invokeStatic "core.clj" 5947]
 [clojure.core$load_lib doInvoke "core.clj" 5928]
 [clojure.lang.RestFn applyTo "RestFn.java" 142]
 [clojure.core$apply invokeStatic "core.clj" 667]
 [clojure.core$load_libs invokeStatic "core.clj" 5985]
 [clojure.core$load_libs doInvoke "core.clj" 5969]
 [clojure.lang.RestFn applyTo "RestFn.java" 137]
 [clojure.core$apply invokeStatic "core.clj" 667]
 [clojure.core$require invokeStatic "core.clj" 6007]
 [clojure.core$require doInvoke "core.clj" 6007]
 [clojure.lang.RestFn invoke "RestFn.java" 482]
 [security.crypto$eval26640$loading__6721__auto____26641
  invoke
  "crypto.clj"
  1]
 [security.crypto$eval26640 invokeStatic "crypto.clj" 1]
 [security.crypto$eval26640 invoke "crypto.clj" 1]
 [clojure.lang.Compiler eval "Compiler.java" 7177]
 [clojure.lang.Compiler eval "Compiler.java" 7166]
 [clojure.lang.Compiler load "Compiler.java" 7636]
 [clojure.lang.RT loadResourceScript "RT.java" 381]
 [clojure.lang.RT loadResourceScript "RT.java" 372]
 [clojure.lang.RT load "RT.java" 459]
 [clojure.lang.RT load "RT.java" 424]
 [clojure.core$load$fn__6839 invoke "core.clj" 6126]
 [clojure.core$load invokeStatic "core.clj" 6125]
 [clojure.core$load doInvoke "core.clj" 6109]
 [clojure.lang.RestFn invoke "RestFn.java" 408]
 [clojure.core$load_one invokeStatic "core.clj" 5908]
 [clojure.core$load_one invoke "core.clj" 5903]
 [clojure.core$load_lib$fn__6780 invoke "core.clj" 5948]
 [clojure.core$load_lib invokeStatic "core.clj" 5947]
 [clojure.core$load_lib doInvoke "core.clj" 5928]
 [clojure.lang.RestFn applyTo "RestFn.java" 142]
 [clojure.core$apply invokeStatic "core.clj" 667]
 [clojure.core$load_libs invokeStatic "core.clj" 5985]
 [clojure.core$load_libs doInvoke "core.clj" 5969]
 [clojure.lang.RestFn applyTo "RestFn.java" 137]
 [clojure.core$apply invokeStatic "core.clj" 667]
 [clojure.core$require invokeStatic "core.clj" 6007]
 [clojure.core$require doInvoke "core.clj" 6007]
 [clojure.lang.RestFn invoke "RestFn.java" 703]
 [security.login.login$eval17253$loading__6721__auto____17254
  invoke
  "login.clj"
  1]
 [security.login.login$eval17253 invokeStatic "login.clj" 1]
 [security.login.login$eval17253 invoke "login.clj" 1]
 [clojure.lang.Compiler eval "Compiler.java" 7177]
 [clojure.lang.Compiler eval "Compiler.java" 7166]
 [clojure.lang.Compiler load "Compiler.java" 7636]
 [clojure.lang.RT loadResourceScript "RT.java" 381]
 [clojure.lang.RT loadResourceScript "RT.java" 372]
 [clojure.lang.RT load "RT.java" 459]
 [clojure.lang.RT load "RT.java" 424]
 [clojure.core$load$fn__6839 invoke "core.clj" 6126]
 [clojure.core$load invokeStatic "core.clj" 6125]
 [clojure.core$load doInvoke "core.clj" 6109]
 [clojure.lang.RestFn invoke "RestFn.java" 408]
 [clojure.core$load_one invokeStatic "core.clj" 5908]
 [clojure.core$load_one invoke "core.clj" 5903]
 [clojure.core$load_lib$fn__6780 invoke "core.clj" 5948]
 [clojure.core$load_lib invokeStatic "core.clj" 5947]
 [clojure.core$load_lib doInvoke "core.clj" 5928]
 [clojure.lang.RestFn applyTo "RestFn.java" 142]
 [clojure.core$apply invokeStatic "core.clj" 667]
 [clojure.core$load_libs invokeStatic "core.clj" 5985]
 [clojure.core$load_libs doInvoke "core.clj" 5969]
 [clojure.lang.RestFn applyTo "RestFn.java" 137]
 [clojure.core$apply invokeStatic "core.clj" 667]
 [clojure.core$require invokeStatic "core.clj" 6007]
 [clojure.core$require doInvoke "core.clj" 6007]
 [clojure.lang.RestFn invoke "RestFn.java" 457]
 [security.login.interceptor$eval17247$loading__6721__auto____17248
  invoke
  "interceptor.clj"
  1]
 [security.login.interceptor$eval17247
  invokeStatic
  "interceptor.clj"
  1]
 [security.login.interceptor$eval17247 invoke "interceptor.clj" 1]
 [clojure.lang.Compiler eval "Compiler.java" 7177]
 [clojure.lang.Compiler eval "Compiler.java" 7166]
 [clojure.lang.Compiler load "Compiler.java" 7636]
 [clojure.lang.RT loadResourceScript "RT.java" 381]
 [clojure.lang.RT loadResourceScript "RT.java" 372]
 [clojure.lang.RT load "RT.java" 459]
 [clojure.lang.RT load "RT.java" 424]
 [clojure.core$load$fn__6839 invoke "core.clj" 6126]
 [clojure.core$load invokeStatic "core.clj" 6125]
 [clojure.core$load doInvoke "core.clj" 6109]
 [clojure.lang.RestFn invoke "RestFn.java" 408]
 [clojure.core$load_one invokeStatic "core.clj" 5908]
 [clojure.core$load_one invoke "core.clj" 5903]
 [clojure.core$load_lib$fn__6780 invoke "core.clj" 5948]
 [clojure.core$load_lib invokeStatic "core.clj" 5947]
 [clojure.core$load_lib doInvoke "core.clj" 5928]
 [clojure.lang.RestFn applyTo "RestFn.java" 142]
 [clojure.core$apply invokeStatic "core.clj" 667]
 [clojure.core$load_libs invokeStatic "core.clj" 5985]
 [clojure.core$load_libs doInvoke "core.clj" 5969]
 [clojure.lang.RestFn applyTo "RestFn.java" 137]
 [clojure.core$apply invokeStatic "core.clj" 667]
 [clojure.core$require invokeStatic "core.clj" 6007]
 [clojure.core$require doInvoke "core.clj" 6007]
 [clojure.lang.RestFn invoke "RestFn.java" 930]
 [http.routes$eval16978$loading__6721__auto____16979
  invoke
  "routes.clj"
  1]
 [http.routes$eval16978 invokeStatic "routes.clj" 1]
 [http.routes$eval16978 invoke "routes.clj" 1]
 [clojure.lang.Compiler eval "Compiler.java" 7177]
 [clojure.lang.Compiler eval "Compiler.java" 7166]
 [clojure.lang.Compiler load "Compiler.java" 7636]
 [clojure.lang.RT loadResourceScript "RT.java" 381]
 [clojure.lang.RT loadResourceScript "RT.java" 372]
 [clojure.lang.RT load "RT.java" 459]
 [clojure.lang.RT load "RT.java" 424]
 [clojure.core$load$fn__6839 invoke "core.clj" 6126]
 [clojure.core$load invokeStatic "core.clj" 6125]
 [clojure.core$load doInvoke "core.clj" 6109]
 [clojure.lang.RestFn invoke "RestFn.java" 408]
 [clojure.core$load_one invokeStatic "core.clj" 5908]
 [clojure.core$load_one invoke "core.clj" 5903]
 [clojure.core$load_lib$fn__6780 invoke "core.clj" 5948]
 [clojure.core$load_lib invokeStatic "core.clj" 5947]
 [clojure.core$load_lib doInvoke "core.clj" 5928]
 [clojure.lang.RestFn applyTo "RestFn.java" 142]
 [clojure.core$apply invokeStatic "core.clj" 667]
 [clojure.core$load_libs invokeStatic "core.clj" 5985]
 [clojure.core$load_libs doInvoke "core.clj" 5969]
 [clojure.lang.RestFn applyTo "RestFn.java" 137]
 [clojure.core$apply invokeStatic "core.clj" 667]
 [clojure.core$require invokeStatic "core.clj" 6007]
 [clojure.core$require doInvoke "core.clj" 6007]
 [clojure.lang.RestFn invoke "RestFn.java" 482]
 [http.server$eval157$loading__6721__auto____158
  invoke
  "server.clj"
  1]
 [http.server$eval157 invokeStatic "server.clj" 1]
 [http.server$eval157 invoke "server.clj" 1]
 [clojure.lang.Compiler eval "Compiler.java" 7177]
 [clojure.lang.Compiler eval "Compiler.java" 7166]
 [clojure.lang.Compiler load "Compiler.java" 7636]
 [clojure.lang.RT loadResourceScript "RT.java" 381]
 [clojure.lang.RT loadResourceScript "RT.java" 372]
 [clojure.lang.RT load "RT.java" 459]
 [clojure.lang.RT load "RT.java" 424]
 [clojure.core$load$fn__6839 invoke "core.clj" 6126]
 [clojure.core$load invokeStatic "core.clj" 6125]
 [clojure.core$load doInvoke "core.clj" 6109]
 [clojure.lang.RestFn invoke "RestFn.java" 408]
 [clojure.core$load_one invokeStatic "core.clj" 5908]
 [clojure.core$load_one invoke "core.clj" 5903]
 [clojure.core$load_lib$fn__6780 invoke "core.clj" 5948]
 [clojure.core$load_lib invokeStatic "core.clj" 5947]
 [clojure.core$load_lib doInvoke "core.clj" 5928]
 [clojure.lang.RestFn applyTo "RestFn.java" 142]
 [clojure.core$apply invokeStatic "core.clj" 667]
 [clojure.core$load_libs invokeStatic "core.clj" 5985]
 [clojure.core$load_libs doInvoke "core.clj" 5969]
 [clojure.lang.RestFn applyTo "RestFn.java" 137]
 [clojure.core$apply invokeStatic "core.clj" 667]
 [clojure.core$require invokeStatic "core.clj" 6007]
 [clojure.core$require doInvoke "core.clj" 6007]
 [clojure.lang.RestFn invoke "RestFn.java" 408]
 [user$eval140$fn__144 invoke "form-init10770987251725177174.clj" 1]
 [user$eval140 invokeStatic "form-init10770987251725177174.clj" 1]
 [user$eval140 invoke "form-init10770987251725177174.clj" 1]
 [clojure.lang.Compiler eval "Compiler.java" 7177]
 [clojure.lang.Compiler eval "Compiler.java" 7167]
 [clojure.lang.Compiler load "Compiler.java" 7636]
 [clojure.lang.Compiler loadFile "Compiler.java" 7574]
 [clojure.main$load_script invokeStatic "main.clj" 475]
 [clojure.main$init_opt invokeStatic "main.clj" 477]
 [clojure.main$init_opt invoke "main.clj" 477]
 [clojure.main$initialize invokeStatic "main.clj" 508]
 [clojure.main$null_opt invokeStatic "main.clj" 542]
 [clojure.main$null_opt invoke "main.clj" 539]
 [clojure.main$main invokeStatic "main.clj" 664]
 [clojure.main$main doInvoke "main.clj" 616]
 [clojure.lang.RestFn applyTo "RestFn.java" 137]
 [clojure.lang.Var applyTo "Var.java" 705]
 [clojure.main main "main.java" 40]],
:cause "unable to load native libsodium; is it installed?",
:phase :execution}}

If anyone have a solution or workaround to run the project locally in my machine I would really appreciate it. Thanks

Make tests work on both 1.0.14 and 1.0.15

In #33 I tried to run the tests on a fedora26 machine. Fedora 26 ships 1.0.14, not 1.0.15. Between those two versions, the default pwhash algorithm and some of its parameters changed.

AOT fails on some JDKs

MacOS 11.2.3

AOT'ing fails on some JDKs but not others.

minimal reproduction, using the table below:

clj --report stderr -e "(do (compile 'caesium.sodium))"

release pass?
openjdk version 1.8.0_222
adoptopenjdk 11.0.6
adoptopenjdk 12.0.2
adoptopenjdk 13.0.2
adoptopenjdk 14.0.2
zulu 11.0.10

The compilation appears to produce the same .class file on all JDKs, indicating the problem is during loading, not generation.

The JDK has a method size limit of 64k. I believe the offending function is caesium.binding/bound-fns. A quick inspection of the classes/caesium/sodium/Sodium.class file shows that it is 181kB long, and the last 60% of it consists solely of annotations. Replacing (mapcat permuted-byte-types raw-bound-fns) with just bound-fns drops the size down to 15k, and allows the file to load. (Not suggesting that is good or correct, just the source of the classfile size)

pwhash tests fail under cloverage

While working on #71 I noticed the cloverage step fails. It appears there's some trouble in calling some of the crypto_pwhash_* bindings.

STR:
lein with-profile +test cloverage --codecov -t caesium.crypto.pwhash-test

The log output follows:

Instrumented namespaces.

Testing caesium.crypto.pwhash-test

ERROR in (pwhash-str-alg-argon2i13-and-verify-test-equal) (Reflector.java:154)
Uncaught exception, not in assertion.
expected: nil
  actual: java.lang.IllegalArgumentException: No matching method crypto_pwhash_str_alg found taking 6 args for class caesium.binding.Sodium$jnr$ffi$0
 at clojure.lang.Reflector.invokeMatchingMethod (Reflector.java:154)
    clojure.lang.Reflector.invokeInstanceMethod (Reflector.java:102)
    caesium.crypto.pwhash$pwhash_str_alg_to_buf_BANG_.invokeStatic (caesium/crypto/pwhash.clj:1)
    caesium.crypto.pwhash$pwhash_str_alg_to_buf_BANG_.invoke (caesium/crypto/pwhash.clj:1)
    caesium.crypto.pwhash$pwhash_str_alg.invokeStatic (caesium/crypto/pwhash.clj:123)
    caesium.crypto.pwhash$pwhash_str_alg.invoke (caesium/crypto/pwhash.clj:1)
    caesium.crypto.pwhash_test$fn__10870.invokeStatic (pwhash_test.clj:109)
    caesium.crypto.pwhash_test/fn (pwhash_test.clj:108)
    clojure.test$test_var$fn__9737.invoke (test.clj:717)
    clojure.test$test_var.invokeStatic (test.clj:717)
    clojure.test$test_var.invoke (test.clj:708)
    clojure.test$test_vars$fn__9763$fn__9768.invoke (test.clj:735)
    clojure.test$default_fixture.invokeStatic (test.clj:687)
    clojure.test$default_fixture.invoke (test.clj:683)
    clojure.test$test_vars$fn__9763.invoke (test.clj:735)
    clojure.test$default_fixture.invokeStatic (test.clj:687)
    clojure.test$default_fixture.invoke (test.clj:683)
    clojure.test$test_vars.invokeStatic (test.clj:731)
    clojure.test$test_all_vars.invokeStatic (test.clj:737)
    clojure.test$test_ns.invokeStatic (test.clj:758)
    clojure.test$test_ns.invoke (test.clj:743)
    clojure.core$map$fn__5866.invoke (core.clj:2755)
    clojure.lang.LazySeq.sval (LazySeq.java:42)
    clojure.lang.LazySeq.seq (LazySeq.java:51)
    clojure.lang.Cons.next (Cons.java:39)
    clojure.lang.RT.boundedLength (RT.java:1792)
    clojure.lang.RestFn.applyTo (RestFn.java:130)
    clojure.core$apply.invokeStatic (core.clj:667)
    clojure.test$run_tests.invokeStatic (test.clj:768)
    clojure.test$run_tests.doInvoke (test.clj:768)
    clojure.lang.RestFn.applyTo (RestFn.java:137)
    clojure.core$apply.invokeStatic (core.clj:665)
    clojure.core$apply.invoke (core.clj:660)
    cloverage.coverage$eval4113$fn__4115$fn__4117$run_tests__4118.invoke (coverage.clj:187)
    cloverage.coverage$eval4113$fn__4115$fn__4117.invoke (coverage.clj:193)
    cloverage.coverage$run_tests$fn__4136.invoke (coverage.clj:211)
    cloverage.coverage$form_for_suppressing_unselected_tests.invokeStatic (coverage.clj:54)
    cloverage.coverage$form_for_suppressing_unselected_tests.invoke (coverage.clj:32)
    cloverage.coverage$run_tests.invokeStatic (coverage.clj:209)
    cloverage.coverage$run_tests.invoke (coverage.clj:199)
    cloverage.coverage$run_main.invokeStatic (coverage.clj:261)
    cloverage.coverage$run_main.invoke (coverage.clj:253)
    cloverage.coverage$run_project.invokeStatic (coverage.clj:277)
    cloverage.coverage$run_project.doInvoke (coverage.clj:273)
    clojure.lang.RestFn.invoke (RestFn.java:460)
    user$eval4238.invokeStatic (form-init582277943802464326.clj:1)
    user$eval4238.invoke (form-init582277943802464326.clj:1)
    clojure.lang.Compiler.eval (Compiler.java:7177)
    clojure.lang.Compiler.eval (Compiler.java:7167)
    clojure.lang.Compiler.load (Compiler.java:7636)
    clojure.lang.Compiler.loadFile (Compiler.java:7574)
    clojure.main$load_script.invokeStatic (main.clj:475)
    clojure.main$init_opt.invokeStatic (main.clj:477)
    clojure.main$init_opt.invoke (main.clj:477)
    clojure.main$initialize.invokeStatic (main.clj:508)
    clojure.main$null_opt.invokeStatic (main.clj:542)
    clojure.main$null_opt.invoke (main.clj:539)
    clojure.main$main.invokeStatic (main.clj:664)
    clojure.main$main.doInvoke (main.clj:616)
    clojure.lang.RestFn.applyTo (RestFn.java:137)
    clojure.lang.Var.applyTo (Var.java:705)
    clojure.main.main (main.java:40)

ERROR in (pwhash-argon2i-alg-argon2i13-test) (Reflector.java:154)
expected: (= "75a10fdb4db0836498f824f1f0cc9ab9d3bb194d41b8dd66bd1ca6f0cf686810" (u/hexify (p/argon2i 32 "password" salt p/argon2i-opslimit-min p/argon2i-memlimit-interactive p/argon2i-alg-argon2i13)))
  actual: java.lang.IllegalArgumentException: No matching method crypto_pwhash_argon2i found taking 8 args for class caesium.binding.Sodium$jnr$ffi$0
 at clojure.lang.Reflector.invokeMatchingMethod (Reflector.java:154)
    clojure.lang.Reflector.invokeInstanceMethod (Reflector.java:102)
    caesium.crypto.pwhash$pwhash_argon2i_to_buf_BANG_.invokeStatic (caesium/crypto/pwhash.clj:1)
    caesium.crypto.pwhash$pwhash_argon2i_to_buf_BANG_.invoke (caesium/crypto/pwhash.clj:1)
    caesium.crypto.pwhash$argon2i.invokeStatic (caesium/crypto/pwhash.clj:154)
    caesium.crypto.pwhash$argon2i.invoke (caesium/crypto/pwhash.clj:1)
    caesium.crypto.pwhash_test$fn__10880.invokeStatic (pwhash_test.clj:122)
    caesium.crypto.pwhash_test/fn (pwhash_test.clj:120)
    clojure.test$test_var$fn__9737.invoke (test.clj:717)
    clojure.test$test_var.invokeStatic (test.clj:717)
    clojure.test$test_var.invoke (test.clj:708)
    clojure.test$test_vars$fn__9763$fn__9768.invoke (test.clj:735)
    clojure.test$default_fixture.invokeStatic (test.clj:687)
    clojure.test$default_fixture.invoke (test.clj:683)
    clojure.test$test_vars$fn__9763.invoke (test.clj:735)
    clojure.test$default_fixture.invokeStatic (test.clj:687)
    clojure.test$default_fixture.invoke (test.clj:683)
    clojure.test$test_vars.invokeStatic (test.clj:731)
    clojure.test$test_all_vars.invokeStatic (test.clj:737)
    clojure.test$test_ns.invokeStatic (test.clj:758)
    clojure.test$test_ns.invoke (test.clj:743)
    clojure.core$map$fn__5866.invoke (core.clj:2755)
    clojure.lang.LazySeq.sval (LazySeq.java:42)
    clojure.lang.LazySeq.seq (LazySeq.java:51)
    clojure.lang.Cons.next (Cons.java:39)
    clojure.lang.RT.boundedLength (RT.java:1792)
    clojure.lang.RestFn.applyTo (RestFn.java:130)
    clojure.core$apply.invokeStatic (core.clj:667)
    clojure.test$run_tests.invokeStatic (test.clj:768)
    clojure.test$run_tests.doInvoke (test.clj:768)
    clojure.lang.RestFn.applyTo (RestFn.java:137)
    clojure.core$apply.invokeStatic (core.clj:665)
    clojure.core$apply.invoke (core.clj:660)
    cloverage.coverage$eval4113$fn__4115$fn__4117$run_tests__4118.invoke (coverage.clj:187)
    cloverage.coverage$eval4113$fn__4115$fn__4117.invoke (coverage.clj:193)
    cloverage.coverage$run_tests$fn__4136.invoke (coverage.clj:211)
    cloverage.coverage$form_for_suppressing_unselected_tests.invokeStatic (coverage.clj:54)
    cloverage.coverage$form_for_suppressing_unselected_tests.invoke (coverage.clj:32)
    cloverage.coverage$run_tests.invokeStatic (coverage.clj:209)
    cloverage.coverage$run_tests.invoke (coverage.clj:199)
    cloverage.coverage$run_main.invokeStatic (coverage.clj:261)
    cloverage.coverage$run_main.invoke (coverage.clj:253)
    cloverage.coverage$run_project.invokeStatic (coverage.clj:277)
    cloverage.coverage$run_project.doInvoke (coverage.clj:273)
    clojure.lang.RestFn.invoke (RestFn.java:460)
    user$eval4238.invokeStatic (form-init582277943802464326.clj:1)
    user$eval4238.invoke (form-init582277943802464326.clj:1)
    clojure.lang.Compiler.eval (Compiler.java:7177)
    clojure.lang.Compiler.eval (Compiler.java:7167)
    clojure.lang.Compiler.load (Compiler.java:7636)
    clojure.lang.Compiler.loadFile (Compiler.java:7574)
    clojure.main$load_script.invokeStatic (main.clj:475)
    clojure.main$init_opt.invokeStatic (main.clj:477)
    clojure.main$init_opt.invoke (main.clj:477)
    clojure.main$initialize.invokeStatic (main.clj:508)
    clojure.main$null_opt.invokeStatic (main.clj:542)
    clojure.main$null_opt.invoke (main.clj:539)
    clojure.main$main.invokeStatic (main.clj:664)
    clojure.main$main.doInvoke (main.clj:616)
    clojure.lang.RestFn.applyTo (RestFn.java:137)
    clojure.lang.Var.applyTo (Var.java:705)
    clojure.main.main (main.java:40)

ERROR in (argon2i-str-needs-rehash-test) (Reflector.java:154)
Uncaught exception, not in assertion.
expected: nil
  actual: java.lang.IllegalArgumentException: No matching method crypto_pwhash_str_alg found taking 6 args for class caesium.binding.Sodium$jnr$ffi$0
 at clojure.lang.Reflector.invokeMatchingMethod (Reflector.java:154)
    clojure.lang.Reflector.invokeInstanceMethod (Reflector.java:102)
    caesium.crypto.pwhash$pwhash_str_alg_to_buf_BANG_.invokeStatic (caesium/crypto/pwhash.clj:1)
    caesium.crypto.pwhash$pwhash_str_alg_to_buf_BANG_.invoke (caesium/crypto/pwhash.clj:1)
    caesium.crypto.pwhash$pwhash_str_alg.invokeStatic (caesium/crypto/pwhash.clj:123)
    caesium.crypto.pwhash$pwhash_str_alg.invoke (caesium/crypto/pwhash.clj:1)
    caesium.crypto.pwhash_test$fn__10895.invokeStatic (pwhash_test.clj:135)
    caesium.crypto.pwhash_test/fn (pwhash_test.clj:134)
    clojure.test$test_var$fn__9737.invoke (test.clj:717)
    clojure.test$test_var.invokeStatic (test.clj:717)
    clojure.test$test_var.invoke (test.clj:708)
    clojure.test$test_vars$fn__9763$fn__9768.invoke (test.clj:735)
    clojure.test$default_fixture.invokeStatic (test.clj:687)
    clojure.test$default_fixture.invoke (test.clj:683)
    clojure.test$test_vars$fn__9763.invoke (test.clj:735)
    clojure.test$default_fixture.invokeStatic (test.clj:687)
    clojure.test$default_fixture.invoke (test.clj:683)
    clojure.test$test_vars.invokeStatic (test.clj:731)
    clojure.test$test_all_vars.invokeStatic (test.clj:737)
    clojure.test$test_ns.invokeStatic (test.clj:758)
    clojure.test$test_ns.invoke (test.clj:743)
    clojure.core$map$fn__5866.invoke (core.clj:2755)
    clojure.lang.LazySeq.sval (LazySeq.java:42)
    clojure.lang.LazySeq.seq (LazySeq.java:51)
    clojure.lang.Cons.next (Cons.java:39)
    clojure.lang.RT.boundedLength (RT.java:1792)
    clojure.lang.RestFn.applyTo (RestFn.java:130)
    clojure.core$apply.invokeStatic (core.clj:667)
    clojure.test$run_tests.invokeStatic (test.clj:768)
    clojure.test$run_tests.doInvoke (test.clj:768)
    clojure.lang.RestFn.applyTo (RestFn.java:137)
    clojure.core$apply.invokeStatic (core.clj:665)
    clojure.core$apply.invoke (core.clj:660)
    cloverage.coverage$eval4113$fn__4115$fn__4117$run_tests__4118.invoke (coverage.clj:187)
    cloverage.coverage$eval4113$fn__4115$fn__4117.invoke (coverage.clj:193)
    cloverage.coverage$run_tests$fn__4136.invoke (coverage.clj:211)
    cloverage.coverage$form_for_suppressing_unselected_tests.invokeStatic (coverage.clj:54)
    cloverage.coverage$form_for_suppressing_unselected_tests.invoke (coverage.clj:32)
    cloverage.coverage$run_tests.invokeStatic (coverage.clj:209)
    cloverage.coverage$run_tests.invoke (coverage.clj:199)
    cloverage.coverage$run_main.invokeStatic (coverage.clj:261)
    cloverage.coverage$run_main.invoke (coverage.clj:253)
    cloverage.coverage$run_project.invokeStatic (coverage.clj:277)
    cloverage.coverage$run_project.doInvoke (coverage.clj:273)
    clojure.lang.RestFn.invoke (RestFn.java:460)
    user$eval4238.invokeStatic (form-init582277943802464326.clj:1)
    user$eval4238.invoke (form-init582277943802464326.clj:1)
    clojure.lang.Compiler.eval (Compiler.java:7177)
    clojure.lang.Compiler.eval (Compiler.java:7167)
    clojure.lang.Compiler.load (Compiler.java:7636)
    clojure.lang.Compiler.loadFile (Compiler.java:7574)
    clojure.main$load_script.invokeStatic (main.clj:475)
    clojure.main$init_opt.invokeStatic (main.clj:477)
    clojure.main$init_opt.invoke (main.clj:477)
    clojure.main$initialize.invokeStatic (main.clj:508)
    clojure.main$null_opt.invokeStatic (main.clj:542)
    clojure.main$null_opt.invoke (main.clj:539)
    clojure.main$main.invokeStatic (main.clj:664)
    clojure.main$main.doInvoke (main.clj:616)
    clojure.lang.RestFn.applyTo (RestFn.java:137)
    clojure.lang.Var.applyTo (Var.java:705)
    clojure.main.main (main.java:40)

ERROR in (argon2id-str-needs-rehash-test) (Reflector.java:154)
Uncaught exception, not in assertion.
expected: nil
  actual: java.lang.IllegalArgumentException: No matching method crypto_pwhash_str_alg found taking 6 args for class caesium.binding.Sodium$jnr$ffi$0
 at clojure.lang.Reflector.invokeMatchingMethod (Reflector.java:154)
    clojure.lang.Reflector.invokeInstanceMethod (Reflector.java:102)
    caesium.crypto.pwhash$pwhash_str_alg_to_buf_BANG_.invokeStatic (caesium/crypto/pwhash.clj:1)
    caesium.crypto.pwhash$pwhash_str_alg_to_buf_BANG_.invoke (caesium/crypto/pwhash.clj:1)
    caesium.crypto.pwhash$pwhash_str_alg.invokeStatic (caesium/crypto/pwhash.clj:123)
    caesium.crypto.pwhash$pwhash_str_alg.invoke (caesium/crypto/pwhash.clj:1)
    caesium.crypto.pwhash_test$fn__10910.invokeStatic (pwhash_test.clj:151)
    caesium.crypto.pwhash_test/fn (pwhash_test.clj:150)
    clojure.test$test_var$fn__9737.invoke (test.clj:717)
    clojure.test$test_var.invokeStatic (test.clj:717)
    clojure.test$test_var.invoke (test.clj:708)
    clojure.test$test_vars$fn__9763$fn__9768.invoke (test.clj:735)
    clojure.test$default_fixture.invokeStatic (test.clj:687)
    clojure.test$default_fixture.invoke (test.clj:683)
    clojure.test$test_vars$fn__9763.invoke (test.clj:735)
    clojure.test$default_fixture.invokeStatic (test.clj:687)
    clojure.test$default_fixture.invoke (test.clj:683)
    clojure.test$test_vars.invokeStatic (test.clj:731)
    clojure.test$test_all_vars.invokeStatic (test.clj:737)
    clojure.test$test_ns.invokeStatic (test.clj:758)
    clojure.test$test_ns.invoke (test.clj:743)
    clojure.core$map$fn__5866.invoke (core.clj:2755)
    clojure.lang.LazySeq.sval (LazySeq.java:42)
    clojure.lang.LazySeq.seq (LazySeq.java:51)
    clojure.lang.Cons.next (Cons.java:39)
    clojure.lang.RT.boundedLength (RT.java:1792)
    clojure.lang.RestFn.applyTo (RestFn.java:130)
    clojure.core$apply.invokeStatic (core.clj:667)
    clojure.test$run_tests.invokeStatic (test.clj:768)
    clojure.test$run_tests.doInvoke (test.clj:768)
    clojure.lang.RestFn.applyTo (RestFn.java:137)
    clojure.core$apply.invokeStatic (core.clj:665)
    clojure.core$apply.invoke (core.clj:660)
    cloverage.coverage$eval4113$fn__4115$fn__4117$run_tests__4118.invoke (coverage.clj:187)
    cloverage.coverage$eval4113$fn__4115$fn__4117.invoke (coverage.clj:193)
    cloverage.coverage$run_tests$fn__4136.invoke (coverage.clj:211)
    cloverage.coverage$form_for_suppressing_unselected_tests.invokeStatic (coverage.clj:54)
    cloverage.coverage$form_for_suppressing_unselected_tests.invoke (coverage.clj:32)
    cloverage.coverage$run_tests.invokeStatic (coverage.clj:209)
    cloverage.coverage$run_tests.invoke (coverage.clj:199)
    cloverage.coverage$run_main.invokeStatic (coverage.clj:261)
    cloverage.coverage$run_main.invoke (coverage.clj:253)
    cloverage.coverage$run_project.invokeStatic (coverage.clj:277)
    cloverage.coverage$run_project.doInvoke (coverage.clj:273)
    clojure.lang.RestFn.invoke (RestFn.java:460)
    user$eval4238.invokeStatic (form-init582277943802464326.clj:1)
    user$eval4238.invoke (form-init582277943802464326.clj:1)
    clojure.lang.Compiler.eval (Compiler.java:7177)
    clojure.lang.Compiler.eval (Compiler.java:7167)
    clojure.lang.Compiler.load (Compiler.java:7636)
    clojure.lang.Compiler.loadFile (Compiler.java:7574)
    clojure.main$load_script.invokeStatic (main.clj:475)
    clojure.main$init_opt.invokeStatic (main.clj:477)
    clojure.main$init_opt.invoke (main.clj:477)
    clojure.main$initialize.invokeStatic (main.clj:508)
    clojure.main$null_opt.invokeStatic (main.clj:542)
    clojure.main$null_opt.invoke (main.clj:539)
    clojure.main$main.invokeStatic (main.clj:664)
    clojure.main$main.doInvoke (main.clj:616)
    clojure.lang.RestFn.applyTo (RestFn.java:137)
    clojure.lang.Var.applyTo (Var.java:705)
    clojure.main.main (main.java:40)

ERROR in (pwhash-alg-default-test) (Reflector.java:154)
expected: (= "86b902e6577791ff5e1aaa73a57d21ee7a8822ed8e183940af4fa1ba6ab9803c" (u/hexify (p/pwhash 32 "password" salt p/opslimit-min p/memlimit-min p/alg-default)))
  actual: java.lang.IllegalArgumentException: No matching method crypto_pwhash found taking 8 args for class caesium.binding.Sodium$jnr$ffi$0
 at clojure.lang.Reflector.invokeMatchingMethod (Reflector.java:154)
    clojure.lang.Reflector.invokeInstanceMethod (Reflector.java:102)
    caesium.crypto.pwhash$pwhash_to_buf_BANG_.invokeStatic (caesium/crypto/pwhash.clj:1)
    caesium.crypto.pwhash$pwhash_to_buf_BANG_.invoke (caesium/crypto/pwhash.clj:1)
    caesium.crypto.pwhash$pwhash.invokeStatic (caesium/crypto/pwhash.clj:93)
    caesium.crypto.pwhash$pwhash.invoke (caesium/crypto/pwhash.clj:1)
    caesium.crypto.pwhash_test$fn__10845.invokeStatic (pwhash_test.clj:85)
    caesium.crypto.pwhash_test/fn (pwhash_test.clj:83)
    clojure.test$test_var$fn__9737.invoke (test.clj:717)
    clojure.test$test_var.invokeStatic (test.clj:717)
    clojure.test$test_var.invoke (test.clj:708)
    clojure.test$test_vars$fn__9763$fn__9768.invoke (test.clj:735)
    clojure.test$default_fixture.invokeStatic (test.clj:687)
    clojure.test$default_fixture.invoke (test.clj:683)
    clojure.test$test_vars$fn__9763.invoke (test.clj:735)
    clojure.test$default_fixture.invokeStatic (test.clj:687)
    clojure.test$default_fixture.invoke (test.clj:683)
    clojure.test$test_vars.invokeStatic (test.clj:731)
    clojure.test$test_all_vars.invokeStatic (test.clj:737)
    clojure.test$test_ns.invokeStatic (test.clj:758)
    clojure.test$test_ns.invoke (test.clj:743)
    clojure.core$map$fn__5866.invoke (core.clj:2755)
    clojure.lang.LazySeq.sval (LazySeq.java:42)
    clojure.lang.LazySeq.seq (LazySeq.java:51)
    clojure.lang.Cons.next (Cons.java:39)
    clojure.lang.RT.boundedLength (RT.java:1792)
    clojure.lang.RestFn.applyTo (RestFn.java:130)
    clojure.core$apply.invokeStatic (core.clj:667)
    clojure.test$run_tests.invokeStatic (test.clj:768)
    clojure.test$run_tests.doInvoke (test.clj:768)
    clojure.lang.RestFn.applyTo (RestFn.java:137)
    clojure.core$apply.invokeStatic (core.clj:665)
    clojure.core$apply.invoke (core.clj:660)
    cloverage.coverage$eval4113$fn__4115$fn__4117$run_tests__4118.invoke (coverage.clj:187)
    cloverage.coverage$eval4113$fn__4115$fn__4117.invoke (coverage.clj:193)
    cloverage.coverage$run_tests$fn__4136.invoke (coverage.clj:211)
    cloverage.coverage$form_for_suppressing_unselected_tests.invokeStatic (coverage.clj:54)
    cloverage.coverage$form_for_suppressing_unselected_tests.invoke (coverage.clj:32)
    cloverage.coverage$run_tests.invokeStatic (coverage.clj:209)
    cloverage.coverage$run_tests.invoke (coverage.clj:199)
    cloverage.coverage$run_main.invokeStatic (coverage.clj:261)
    cloverage.coverage$run_main.invoke (coverage.clj:253)
    cloverage.coverage$run_project.invokeStatic (coverage.clj:277)
    cloverage.coverage$run_project.doInvoke (coverage.clj:273)
    clojure.lang.RestFn.invoke (RestFn.java:460)
    user$eval4238.invokeStatic (form-init582277943802464326.clj:1)
    user$eval4238.invoke (form-init582277943802464326.clj:1)
    clojure.lang.Compiler.eval (Compiler.java:7177)
    clojure.lang.Compiler.eval (Compiler.java:7167)
    clojure.lang.Compiler.load (Compiler.java:7636)
    clojure.lang.Compiler.loadFile (Compiler.java:7574)
    clojure.main$load_script.invokeStatic (main.clj:475)
    clojure.main$init_opt.invokeStatic (main.clj:477)
    clojure.main$init_opt.invoke (main.clj:477)
    clojure.main$initialize.invokeStatic (main.clj:508)
    clojure.main$null_opt.invokeStatic (main.clj:542)
    clojure.main$null_opt.invoke (main.clj:539)
    clojure.main$main.invokeStatic (main.clj:664)
    clojure.main$main.doInvoke (main.clj:616)
    clojure.lang.RestFn.applyTo (RestFn.java:137)
    clojure.lang.Var.applyTo (Var.java:705)
    clojure.main.main (main.java:40)

ERROR in (str-needs-rehash-test) (Reflector.java:154)
Uncaught exception, not in assertion.
expected: nil
  actual: java.lang.IllegalArgumentException: No matching method crypto_pwhash_str_alg found taking 6 args for class caesium.binding.Sodium$jnr$ffi$0
 at clojure.lang.Reflector.invokeMatchingMethod (Reflector.java:154)
    clojure.lang.Reflector.invokeInstanceMethod (Reflector.java:102)
    caesium.crypto.pwhash$pwhash_str_alg_to_buf_BANG_.invokeStatic (caesium/crypto/pwhash.clj:1)
    caesium.crypto.pwhash$pwhash_str_alg_to_buf_BANG_.invoke (caesium/crypto/pwhash.clj:1)
    caesium.crypto.pwhash$pwhash_str_alg.invokeStatic (caesium/crypto/pwhash.clj:123)
    caesium.crypto.pwhash$pwhash_str_alg.invoke (caesium/crypto/pwhash.clj:1)
    caesium.crypto.pwhash_test$fn__10875.invokeStatic (pwhash_test.clj:114)
    caesium.crypto.pwhash_test/fn (pwhash_test.clj:113)
    clojure.test$test_var$fn__9737.invoke (test.clj:717)
    clojure.test$test_var.invokeStatic (test.clj:717)
    clojure.test$test_var.invoke (test.clj:708)
    clojure.test$test_vars$fn__9763$fn__9768.invoke (test.clj:735)
    clojure.test$default_fixture.invokeStatic (test.clj:687)
    clojure.test$default_fixture.invoke (test.clj:683)
    clojure.test$test_vars$fn__9763.invoke (test.clj:735)
    clojure.test$default_fixture.invokeStatic (test.clj:687)
    clojure.test$default_fixture.invoke (test.clj:683)
    clojure.test$test_vars.invokeStatic (test.clj:731)
    clojure.test$test_all_vars.invokeStatic (test.clj:737)
    clojure.test$test_ns.invokeStatic (test.clj:758)
    clojure.test$test_ns.invoke (test.clj:743)
    clojure.core$map$fn__5866.invoke (core.clj:2755)
    clojure.lang.LazySeq.sval (LazySeq.java:42)
    clojure.lang.LazySeq.seq (LazySeq.java:51)
    clojure.lang.Cons.next (Cons.java:39)
    clojure.lang.RT.boundedLength (RT.java:1792)
    clojure.lang.RestFn.applyTo (RestFn.java:130)
    clojure.core$apply.invokeStatic (core.clj:667)
    clojure.test$run_tests.invokeStatic (test.clj:768)
    clojure.test$run_tests.doInvoke (test.clj:768)
    clojure.lang.RestFn.applyTo (RestFn.java:137)
    clojure.core$apply.invokeStatic (core.clj:665)
    clojure.core$apply.invoke (core.clj:660)
    cloverage.coverage$eval4113$fn__4115$fn__4117$run_tests__4118.invoke (coverage.clj:187)
    cloverage.coverage$eval4113$fn__4115$fn__4117.invoke (coverage.clj:193)
    cloverage.coverage$run_tests$fn__4136.invoke (coverage.clj:211)
    cloverage.coverage$form_for_suppressing_unselected_tests.invokeStatic (coverage.clj:54)
    cloverage.coverage$form_for_suppressing_unselected_tests.invoke (coverage.clj:32)
    cloverage.coverage$run_tests.invokeStatic (coverage.clj:209)
    cloverage.coverage$run_tests.invoke (coverage.clj:199)
    cloverage.coverage$run_main.invokeStatic (coverage.clj:261)
    cloverage.coverage$run_main.invoke (coverage.clj:253)
    cloverage.coverage$run_project.invokeStatic (coverage.clj:277)
    cloverage.coverage$run_project.doInvoke (coverage.clj:273)
    clojure.lang.RestFn.invoke (RestFn.java:460)
    user$eval4238.invokeStatic (form-init582277943802464326.clj:1)
    user$eval4238.invoke (form-init582277943802464326.clj:1)
    clojure.lang.Compiler.eval (Compiler.java:7177)
    clojure.lang.Compiler.eval (Compiler.java:7167)
    clojure.lang.Compiler.load (Compiler.java:7636)
    clojure.lang.Compiler.loadFile (Compiler.java:7574)
    clojure.main$load_script.invokeStatic (main.clj:475)
    clojure.main$init_opt.invokeStatic (main.clj:477)
    clojure.main$init_opt.invoke (main.clj:477)
    clojure.main$initialize.invokeStatic (main.clj:508)
    clojure.main$null_opt.invokeStatic (main.clj:542)
    clojure.main$null_opt.invoke (main.clj:539)
    clojure.main$main.invokeStatic (main.clj:664)
    clojure.main$main.doInvoke (main.clj:616)
    clojure.lang.RestFn.applyTo (RestFn.java:137)
    clojure.lang.Var.applyTo (Var.java:705)
    clojure.main.main (main.java:40)

ERROR in (pwhash-argon2id-alg-argon2id13-test) (Reflector.java:154)
expected: (= "86b902e6577791ff5e1aaa73a57d21ee7a8822ed8e183940af4fa1ba6ab9803c" (u/hexify (p/argon2id 32 "password" salt p/argon2id-opslimit-min p/argon2id-memlimit-min p/argon2id-alg-argon2id13)))
  actual: java.lang.IllegalArgumentException: No matching method crypto_pwhash_argon2id found taking 8 args for class caesium.binding.Sodium$jnr$ffi$0
 at clojure.lang.Reflector.invokeMatchingMethod (Reflector.java:154)
    clojure.lang.Reflector.invokeInstanceMethod (Reflector.java:102)
    caesium.crypto.pwhash$argon2id_to_buf_BANG_.invokeStatic (caesium/crypto/pwhash.clj:1)
    caesium.crypto.pwhash$argon2id_to_buf_BANG_.invoke (caesium/crypto/pwhash.clj:1)
    caesium.crypto.pwhash$argon2id.invokeStatic (caesium/crypto/pwhash.clj:190)
    caesium.crypto.pwhash$argon2id.invoke (caesium/crypto/pwhash.clj:1)
    caesium.crypto.pwhash_test$fn__10900.invokeStatic (pwhash_test.clj:143)
    caesium.crypto.pwhash_test/fn (pwhash_test.clj:141)
    clojure.test$test_var$fn__9737.invoke (test.clj:717)
    clojure.test$test_var.invokeStatic (test.clj:717)
    clojure.test$test_var.invoke (test.clj:708)
    clojure.test$test_vars$fn__9763$fn__9768.invoke (test.clj:735)
    clojure.test$default_fixture.invokeStatic (test.clj:687)
    clojure.test$default_fixture.invoke (test.clj:683)
    clojure.test$test_vars$fn__9763.invoke (test.clj:735)
    clojure.test$default_fixture.invokeStatic (test.clj:687)
    clojure.test$default_fixture.invoke (test.clj:683)
    clojure.test$test_vars.invokeStatic (test.clj:731)
    clojure.test$test_all_vars.invokeStatic (test.clj:737)
    clojure.test$test_ns.invokeStatic (test.clj:758)
    clojure.test$test_ns.invoke (test.clj:743)
    clojure.core$map$fn__5866.invoke (core.clj:2755)
    clojure.lang.LazySeq.sval (LazySeq.java:42)
    clojure.lang.LazySeq.seq (LazySeq.java:51)
    clojure.lang.Cons.next (Cons.java:39)
    clojure.lang.RT.boundedLength (RT.java:1792)
    clojure.lang.RestFn.applyTo (RestFn.java:130)
    clojure.core$apply.invokeStatic (core.clj:667)
    clojure.test$run_tests.invokeStatic (test.clj:768)
    clojure.test$run_tests.doInvoke (test.clj:768)
    clojure.lang.RestFn.applyTo (RestFn.java:137)
    clojure.core$apply.invokeStatic (core.clj:665)
    clojure.core$apply.invoke (core.clj:660)
    cloverage.coverage$eval4113$fn__4115$fn__4117$run_tests__4118.invoke (coverage.clj:187)
    cloverage.coverage$eval4113$fn__4115$fn__4117.invoke (coverage.clj:193)
    cloverage.coverage$run_tests$fn__4136.invoke (coverage.clj:211)
    cloverage.coverage$form_for_suppressing_unselected_tests.invokeStatic (coverage.clj:54)
    cloverage.coverage$form_for_suppressing_unselected_tests.invoke (coverage.clj:32)
    cloverage.coverage$run_tests.invokeStatic (coverage.clj:209)
    cloverage.coverage$run_tests.invoke (coverage.clj:199)
    cloverage.coverage$run_main.invokeStatic (coverage.clj:261)
    cloverage.coverage$run_main.invoke (coverage.clj:253)
    cloverage.coverage$run_project.invokeStatic (coverage.clj:277)
    cloverage.coverage$run_project.doInvoke (coverage.clj:273)
    clojure.lang.RestFn.invoke (RestFn.java:460)
    user$eval4238.invokeStatic (form-init582277943802464326.clj:1)
    user$eval4238.invoke (form-init582277943802464326.clj:1)
    clojure.lang.Compiler.eval (Compiler.java:7177)
    clojure.lang.Compiler.eval (Compiler.java:7167)
    clojure.lang.Compiler.load (Compiler.java:7636)
    clojure.lang.Compiler.loadFile (Compiler.java:7574)
    clojure.main$load_script.invokeStatic (main.clj:475)
    clojure.main$init_opt.invokeStatic (main.clj:477)
    clojure.main$init_opt.invoke (main.clj:477)
    clojure.main$initialize.invokeStatic (main.clj:508)
    clojure.main$null_opt.invokeStatic (main.clj:542)
    clojure.main$null_opt.invoke (main.clj:539)
    clojure.main$main.invokeStatic (main.clj:664)
    clojure.main$main.doInvoke (main.clj:616)
    clojure.lang.RestFn.applyTo (RestFn.java:137)
    clojure.lang.Var.applyTo (Var.java:705)
    clojure.main.main (main.java:40)

ERROR in (pwhash-str-alg-and-verify-test-equal) (Reflector.java:154)
Uncaught exception, not in assertion.
expected: nil
  actual: java.lang.IllegalArgumentException: No matching method crypto_pwhash_str_alg found taking 6 args for class caesium.binding.Sodium$jnr$ffi$0
 at clojure.lang.Reflector.invokeMatchingMethod (Reflector.java:154)
    clojure.lang.Reflector.invokeInstanceMethod (Reflector.java:102)
    caesium.crypto.pwhash$pwhash_str_alg_to_buf_BANG_.invokeStatic (caesium/crypto/pwhash.clj:1)
    caesium.crypto.pwhash$pwhash_str_alg_to_buf_BANG_.invoke (caesium/crypto/pwhash.clj:1)
    caesium.crypto.pwhash$pwhash_str_alg.invokeStatic (caesium/crypto/pwhash.clj:123)
    caesium.crypto.pwhash$pwhash_str_alg.invoke (caesium/crypto/pwhash.clj:1)
    caesium.crypto.pwhash_test$fn__10865.invokeStatic (pwhash_test.clj:104)
    caesium.crypto.pwhash_test/fn (pwhash_test.clj:103)
    clojure.test$test_var$fn__9737.invoke (test.clj:717)
    clojure.test$test_var.invokeStatic (test.clj:717)
    clojure.test$test_var.invoke (test.clj:708)
    clojure.test$test_vars$fn__9763$fn__9768.invoke (test.clj:735)
    clojure.test$default_fixture.invokeStatic (test.clj:687)
    clojure.test$default_fixture.invoke (test.clj:683)
    clojure.test$test_vars$fn__9763.invoke (test.clj:735)
    clojure.test$default_fixture.invokeStatic (test.clj:687)
    clojure.test$default_fixture.invoke (test.clj:683)
    clojure.test$test_vars.invokeStatic (test.clj:731)
    clojure.test$test_all_vars.invokeStatic (test.clj:737)
    clojure.test$test_ns.invokeStatic (test.clj:758)
    clojure.test$test_ns.invoke (test.clj:743)
    clojure.core$map$fn__5866.invoke (core.clj:2755)
    clojure.lang.LazySeq.sval (LazySeq.java:42)
    clojure.lang.LazySeq.seq (LazySeq.java:51)
    clojure.lang.Cons.next (Cons.java:39)
    clojure.lang.RT.boundedLength (RT.java:1792)
    clojure.lang.RestFn.applyTo (RestFn.java:130)
    clojure.core$apply.invokeStatic (core.clj:667)
    clojure.test$run_tests.invokeStatic (test.clj:768)
    clojure.test$run_tests.doInvoke (test.clj:768)
    clojure.lang.RestFn.applyTo (RestFn.java:137)
    clojure.core$apply.invokeStatic (core.clj:665)
    clojure.core$apply.invoke (core.clj:660)
    cloverage.coverage$eval4113$fn__4115$fn__4117$run_tests__4118.invoke (coverage.clj:187)
    cloverage.coverage$eval4113$fn__4115$fn__4117.invoke (coverage.clj:193)
    cloverage.coverage$run_tests$fn__4136.invoke (coverage.clj:211)
    cloverage.coverage$form_for_suppressing_unselected_tests.invokeStatic (coverage.clj:54)
    cloverage.coverage$form_for_suppressing_unselected_tests.invoke (coverage.clj:32)
    cloverage.coverage$run_tests.invokeStatic (coverage.clj:209)
    cloverage.coverage$run_tests.invoke (coverage.clj:199)
    cloverage.coverage$run_main.invokeStatic (coverage.clj:261)
    cloverage.coverage$run_main.invoke (coverage.clj:253)
    cloverage.coverage$run_project.invokeStatic (coverage.clj:277)
    cloverage.coverage$run_project.doInvoke (coverage.clj:273)
    clojure.lang.RestFn.invoke (RestFn.java:460)
    user$eval4238.invokeStatic (form-init582277943802464326.clj:1)
    user$eval4238.invoke (form-init582277943802464326.clj:1)
    clojure.lang.Compiler.eval (Compiler.java:7177)
    clojure.lang.Compiler.eval (Compiler.java:7167)
    clojure.lang.Compiler.load (Compiler.java:7636)
    clojure.lang.Compiler.loadFile (Compiler.java:7574)
    clojure.main$load_script.invokeStatic (main.clj:475)
    clojure.main$init_opt.invokeStatic (main.clj:477)
    clojure.main$init_opt.invoke (main.clj:477)
    clojure.main$initialize.invokeStatic (main.clj:508)
    clojure.main$null_opt.invokeStatic (main.clj:542)
    clojure.main$null_opt.invoke (main.clj:539)
    clojure.main$main.invokeStatic (main.clj:664)
    clojure.main$main.doInvoke (main.clj:616)
    clojure.lang.RestFn.applyTo (RestFn.java:137)
    clojure.lang.Var.applyTo (Var.java:705)
    clojure.main.main (main.java:40)

ERROR in (pwhash-alg-argon2i-test) (Reflector.java:154)
expected: (= "75a10fdb4db0836498f824f1f0cc9ab9d3bb194d41b8dd66bd1ca6f0cf686810" (u/hexify (p/pwhash 32 "password" salt p/argon2i-opslimit-min p/argon2i-memlimit-interactive p/alg-argon2i13)))
  actual: java.lang.IllegalArgumentException: No matching method crypto_pwhash found taking 8 args for class caesium.binding.Sodium$jnr$ffi$0
 at clojure.lang.Reflector.invokeMatchingMethod (Reflector.java:154)
    clojure.lang.Reflector.invokeInstanceMethod (Reflector.java:102)
    caesium.crypto.pwhash$pwhash_to_buf_BANG_.invokeStatic (caesium/crypto/pwhash.clj:1)
    caesium.crypto.pwhash$pwhash_to_buf_BANG_.invoke (caesium/crypto/pwhash.clj:1)
    caesium.crypto.pwhash$pwhash.invokeStatic (caesium/crypto/pwhash.clj:93)
    caesium.crypto.pwhash$pwhash.invoke (caesium/crypto/pwhash.clj:1)
    caesium.crypto.pwhash_test$fn__10850.invokeStatic (pwhash_test.clj:91)
    caesium.crypto.pwhash_test/fn (pwhash_test.clj:89)
    clojure.test$test_var$fn__9737.invoke (test.clj:717)
    clojure.test$test_var.invokeStatic (test.clj:717)
    clojure.test$test_var.invoke (test.clj:708)
    clojure.test$test_vars$fn__9763$fn__9768.invoke (test.clj:735)
    clojure.test$default_fixture.invokeStatic (test.clj:687)
    clojure.test$default_fixture.invoke (test.clj:683)
    clojure.test$test_vars$fn__9763.invoke (test.clj:735)
    clojure.test$default_fixture.invokeStatic (test.clj:687)
    clojure.test$default_fixture.invoke (test.clj:683)
    clojure.test$test_vars.invokeStatic (test.clj:731)
    clojure.test$test_all_vars.invokeStatic (test.clj:737)
    clojure.test$test_ns.invokeStatic (test.clj:758)
    clojure.test$test_ns.invoke (test.clj:743)
    clojure.core$map$fn__5866.invoke (core.clj:2755)
    clojure.lang.LazySeq.sval (LazySeq.java:42)
    clojure.lang.LazySeq.seq (LazySeq.java:51)
    clojure.lang.Cons.next (Cons.java:39)
    clojure.lang.RT.boundedLength (RT.java:1792)
    clojure.lang.RestFn.applyTo (RestFn.java:130)
    clojure.core$apply.invokeStatic (core.clj:667)
    clojure.test$run_tests.invokeStatic (test.clj:768)
    clojure.test$run_tests.doInvoke (test.clj:768)
    clojure.lang.RestFn.applyTo (RestFn.java:137)
    clojure.core$apply.invokeStatic (core.clj:665)
    clojure.core$apply.invoke (core.clj:660)
    cloverage.coverage$eval4113$fn__4115$fn__4117$run_tests__4118.invoke (coverage.clj:187)
    cloverage.coverage$eval4113$fn__4115$fn__4117.invoke (coverage.clj:193)
    cloverage.coverage$run_tests$fn__4136.invoke (coverage.clj:211)
    cloverage.coverage$form_for_suppressing_unselected_tests.invokeStatic (coverage.clj:54)
    cloverage.coverage$form_for_suppressing_unselected_tests.invoke (coverage.clj:32)
    cloverage.coverage$run_tests.invokeStatic (coverage.clj:209)
    cloverage.coverage$run_tests.invoke (coverage.clj:199)
    cloverage.coverage$run_main.invokeStatic (coverage.clj:261)
    cloverage.coverage$run_main.invoke (coverage.clj:253)
    cloverage.coverage$run_project.invokeStatic (coverage.clj:277)
    cloverage.coverage$run_project.doInvoke (coverage.clj:273)
    clojure.lang.RestFn.invoke (RestFn.java:460)
    user$eval4238.invokeStatic (form-init582277943802464326.clj:1)
    user$eval4238.invoke (form-init582277943802464326.clj:1)
    clojure.lang.Compiler.eval (Compiler.java:7177)
    clojure.lang.Compiler.eval (Compiler.java:7167)
    clojure.lang.Compiler.load (Compiler.java:7636)
    clojure.lang.Compiler.loadFile (Compiler.java:7574)
    clojure.main$load_script.invokeStatic (main.clj:475)
    clojure.main$init_opt.invokeStatic (main.clj:477)
    clojure.main$init_opt.invoke (main.clj:477)
    clojure.main$initialize.invokeStatic (main.clj:508)
    clojure.main$null_opt.invokeStatic (main.clj:542)
    clojure.main$null_opt.invoke (main.clj:539)
    clojure.main$main.invokeStatic (main.clj:664)
    clojure.main$main.doInvoke (main.clj:616)
    clojure.lang.RestFn.applyTo (RestFn.java:137)
    clojure.lang.Var.applyTo (Var.java:705)
    clojure.main.main (main.java:40)

Ran 19 tests containing 150 assertions.
0 failures, 9 errors.
Ran tests.

AuthN & AuthZ ?

Hi first thanks for Caesium, we're using it at http://smxemail.com in email security products.

Any thoughts on Caesium for authn and authz? Can't see much out there. I guess the low hanging fruit is as a buddy backend - though I have some reservations on buddy.

Something based on Clara Rules would be cool.

cheers
Colin

Side-effect, loading Sodium too early

Hello! Thanks very much for this great work. For some project I've been trying to setup CI jobs that runs on GitHub Actions, and I believe that caesium trying to load sodium when loading ns makes the job fails. See an example for caesium itself analysed by cljdoc (link).

What would you think about putting these forms in a function that gets called on runtime startup, and not at compile time? https://github.com/lvh/caesium/blob/master/src/caesium/binding.clj#L720-L725

Cheers,
Piotr

Make tests run on 1.0.16 as well

We currently test against 1.0.15 but 1.0.16 is out. #37 should be resolved first: that ticket will give us the infrastructure for testing against multiple versions on Travis.

Inscrutable errors when libsodium is not installed

I attempted to use caesium when libsodium was not yet installed. I ran (require 'caesium.crypto.pwhash) and got an error "code size limit exceeded". An error like "libsodium is not installed" would have saved me a whole lot of searching and debugging.

Ristretto255 API is available in libsodium 1.0.18+ only

While trying to fix linter errors on CI in #69 I happened to come upon the following in the CI logs:

== Linting caesium.crypto.core.ristretto255 ==
Exception thrown during phase :analyze+eval of linting namespace caesium.crypto.core.ristretto255
...
Caused by:
UnsatisfiedLinkError unknown
	jnr.ffi.provider.jffi.AsmRuntime.newUnsatisifiedLinkError (AsmRuntime.java:40)
	caesium.binding.Sodium$jnr$ffi$0.crypto_core_ristretto255_bytes (:-1)

Source: https://travis-ci.com/github/eploko/caesium/jobs/383426457

The API was just recently added to libsodium and thus is not present in the 1.0.16 version that is being targeted by the CI builds. What can/should we do about it?

An obvious solution would be to bump the target version on CI, but I'm not sure it's along the way this project was heading before the change. There are build steps for older versions of libsodium as well, which stumble on the unsatisfied linking issue too. What are your thoughts on a proper way to approach it all?

Unable to decrypt strings encrypted with `secretbox-nmr` across JVM restarts on MacOS

Thanks for the great library.

We're hitting an issue on MacOS where a string that is encrypted with caesium.magicnonce.secretbox/secretbox-nmr without a nonce (just a key and string as arguments) produces a byte array that cannot be decrypted after a JVM restart.

(require '[byte-streams :as bs])
(require '[caesium.magicnonce.secretbox :refer [secretbox-nmr] :as sb])
(org.apache.commons.codec.binary.Hex/encodeHexString (-> "secret" bs/to-byte-array (secretbox-nmr "asdf")))
<long hex string is printed>
(String. (-> (org.apache.commons.codec.binary.Hex/decodeHex (.toCharArray *1)) bs/to-byte-array (sb/open "asdf")))
"secret"

then following a JVM restart

(require '[byte-streams :as bs])
(require '[caesium.magicnonce.secretbox :refer [secretbox-nmr] :as sb])
(String. (-> (org.apache.commons.codec.binary.Hex/decodeHex (.toCharArray <long hex string>)) bs/to-byte-array (sb/open "asdf")))
Execution error at caesium.crypto.secretbox/secretbox-open-easy-to-buf! (secretbox.clj:50).
Ciphertext verification failed

libsodium is 1.0.18 on java 11, commons-codec 1.6 and caesium 0.10 but bumping the library versions didn't help here.

Are there any known issues with libsodium + caesium on MacOS? Is there something that needs to be initialized to make decryption work across reloads? Thanks!

Release version v0.11

We've started to use caesium (which is great) and wanted to use some of the pwhash functions. What's the ETA on the next release?

Thanks!

Error on binding.clj

Hi @lvh,

Here is the error message I'm getting with deps.edn and clojure 1.10.0 when I try and evaluate the namespace:

2. Unhandled clojure.lang.Compiler$CompilerException
   Error compiling binding.clj at (614:4)
   #:clojure.error{:phase :compile-syntax-check,
                   :line 614,
                   :column 4,
                   :source "binding.clj"}

             Compiler.java: 1560  clojure.lang.Compiler$InstanceMethodExpr/eval
             Compiler.java:  457  clojure.lang.Compiler$DefExpr/eval
             Compiler.java: 7181  clojure.lang.Compiler/eval
             Compiler.java: 7635  clojure.lang.Compiler/load
                   RT.java:  381  clojure.lang.RT/loadResourceScript
                   RT.java:  372  clojure.lang.RT/loadResourceScript
                   RT.java:  463  clojure.lang.RT/load
                   RT.java:  428  clojure.lang.RT/load
                  core.clj: 6126  clojure.core/load/fn
                  core.clj: 6125  clojure.core/load
                  core.clj: 6109  clojure.core/load
               RestFn.java:  408  clojure.lang.RestFn/invoke
                  core.clj: 5908  clojure.core/load-one
                  core.clj: 5903  clojure.core/load-one
                  core.clj: 5948  clojure.core/load-lib/fn
                  core.clj: 5947  clojure.core/load-lib
                  core.clj: 5928  clojure.core/load-lib
               RestFn.java:  142  clojure.lang.RestFn/applyTo
                  core.clj:  667  clojure.core/apply
                  core.clj: 5985  clojure.core/load-libs
                  core.clj: 5969  clojure.core/load-libs
               RestFn.java:  137  clojure.lang.RestFn/applyTo
                  core.clj:  667  clojure.core/apply
                  core.clj: 6007  clojure.core/require
                  core.clj: 6007  clojure.core/require
               RestFn.java:  421  clojure.lang.RestFn/invoke
                  sign.clj:    1  caesium.crypto.sign/eval15482/loading--auto--
                  sign.clj:    1  caesium.crypto.sign/eval15482
                  sign.clj:    1  caesium.crypto.sign/eval15482
             Compiler.java: 7176  clojure.lang.Compiler/eval
             Compiler.java: 7165  clojure.lang.Compiler/eval
             Compiler.java: 7635  clojure.lang.Compiler/load
                   RT.java:  381  clojure.lang.RT/loadResourceScript
                   RT.java:  372  clojure.lang.RT/loadResourceScript
                   RT.java:  463  clojure.lang.RT/load
                   RT.java:  428  clojure.lang.RT/load
                  core.clj: 6126  clojure.core/load/fn
                  core.clj: 6125  clojure.core/load
                  core.clj: 6109  clojure.core/load
               RestFn.java:  408  clojure.lang.RestFn/invoke
                  core.clj: 5908  clojure.core/load-one
                  core.clj: 5903  clojure.core/load-one
                  core.clj: 5948  clojure.core/load-lib/fn
                  core.clj: 5947  clojure.core/load-lib
                  core.clj: 5928  clojure.core/load-lib
               RestFn.java:  142  clojure.lang.RestFn/applyTo
                  core.clj:  667  clojure.core/apply
                  core.clj: 5985  clojure.core/load-libs
                  core.clj: 5969  clojure.core/load-libs
               RestFn.java:  137  clojure.lang.RestFn/applyTo
                  core.clj:  667  clojure.core/apply
                  core.clj: 6007  clojure.core/require
                  core.clj: 6007  clojure.core/require
               RestFn.java:  408  clojure.lang.RestFn/invoke
                      REPL:    1  apeni.crypto.identity/eval15476/loading--auto--
                      REPL:    1  apeni.crypto.identity/eval15476
                      REPL:    1  apeni.crypto.identity/eval15476
             Compiler.java: 7176  clojure.lang.Compiler/eval
             Compiler.java: 7165  clojure.lang.Compiler/eval
             Compiler.java: 7131  clojure.lang.Compiler/eval
                  core.clj: 3214  clojure.core/eval
                  core.clj: 3210  clojure.core/eval
                  main.clj:  414  clojure.main/repl/read-eval-print/fn
                  main.clj:  414  clojure.main/repl/read-eval-print
                  main.clj:  435  clojure.main/repl/fn
                  main.clj:  435  clojure.main/repl
                  main.clj:  345  clojure.main/repl
               RestFn.java:  137  clojure.lang.RestFn/applyTo
                  core.clj:  665  clojure.core/apply
                  core.clj:  660  clojure.core/apply
                regrow.clj:   18  refactor-nrepl.ns.slam.hound.regrow/wrap-clojure-repl/fn
               RestFn.java: 1523  clojure.lang.RestFn/invoke
    interruptible_eval.clj:   83  nrepl.middleware.interruptible-eval/evaluate/fn
                  AFn.java:  152  clojure.lang.AFn/applyToHelper
                  AFn.java:  144  clojure.lang.AFn/applyTo
                  core.clj:  665  clojure.core/apply
                  core.clj: 1973  clojure.core/with-bindings*
                  core.clj: 1973  clojure.core/with-bindings*
               RestFn.java:  425  clojure.lang.RestFn/invoke
    interruptible_eval.clj:   81  nrepl.middleware.interruptible-eval/evaluate
    interruptible_eval.clj:   50  nrepl.middleware.interruptible-eval/evaluate
    interruptible_eval.clj:  221  nrepl.middleware.interruptible-eval/interruptible-eval/fn/fn
    interruptible_eval.clj:  189  nrepl.middleware.interruptible-eval/run-next/fn
                  AFn.java:   22  clojure.lang.AFn/run
   ThreadPoolExecutor.java: 1149  java.util.concurrent.ThreadPoolExecutor/runWorker
   ThreadPoolExecutor.java:  624  java.util.concurrent.ThreadPoolExecutor$Worker/run
               Thread.java:  748  java.lang.Thread/run

1. Caused by java.lang.IllegalArgumentException
   code size limit exceeded

       ProxyGenerator.java: 1261  sun.misc.ProxyGenerator/generateStaticInitializer
       ProxyGenerator.java:  484  sun.misc.ProxyGenerator/generateClassFile
       ProxyGenerator.java:  339  sun.misc.ProxyGenerator/generateProxyClass
                Proxy.java:  639  java.lang.reflect.Proxy$ProxyClassFactory/apply
                Proxy.java:  557  java.lang.reflect.Proxy$ProxyClassFactory/apply
            WeakCache.java:  230  java.lang.reflect.WeakCache$Factory/get
            WeakCache.java:  127  java.lang.reflect.WeakCache/get
                Proxy.java:  419  java.lang.reflect.Proxy/getProxyClass0
                Proxy.java:  719  java.lang.reflect.Proxy/newProxyInstance
        LibraryLoader.java:  341  jnr.ffi.LibraryLoader/createErrorProxy
        LibraryLoader.java:  330  jnr.ffi.LibraryLoader/load
        LibraryLoader.java:  304  jnr.ffi.LibraryLoader/load
NativeMethodAccessorImpl.java:   -2  sun.reflect.NativeMethodAccessorImpl/invoke0
NativeMethodAccessorImpl.java:   62  sun.reflect.NativeMethodAccessorImpl/invoke
DelegatingMethodAccessorImpl.java:   43  sun.reflect.DelegatingMethodAccessorImpl/invoke
               Method.java:  498  java.lang.reflect.Method/invoke
            Reflector.java:  167  clojure.lang.Reflector/invokeMatchingMethod
             Compiler.java: 1553  clojure.lang.Compiler$InstanceMethodExpr/eval
             Compiler.java:  457  clojure.lang.Compiler$DefExpr/eval
             Compiler.java: 7181  clojure.lang.Compiler/eval
             Compiler.java: 7635  clojure.lang.Compiler/load
                   RT.java:  381  clojure.lang.RT/loadResourceScript
                   RT.java:  372  clojure.lang.RT/loadResourceScript
                   RT.java:  463  clojure.lang.RT/load
                   RT.java:  428  clojure.lang.RT/load
                  core.clj: 6126  clojure.core/load/fn
                  core.clj: 6125  clojure.core/load
                  core.clj: 6109  clojure.core/load
               RestFn.java:  408  clojure.lang.RestFn/invoke
                  core.clj: 5908  clojure.core/load-one
                  core.clj: 5903  clojure.core/load-one
                  core.clj: 5948  clojure.core/load-lib/fn
                  core.clj: 5947  clojure.core/load-lib
                  core.clj: 5928  clojure.core/load-lib
               RestFn.java:  142  clojure.lang.RestFn/applyTo
                  core.clj:  667  clojure.core/apply
                  core.clj: 5985  clojure.core/load-libs
                  core.clj: 5969  clojure.core/load-libs
               RestFn.java:  137  clojure.lang.RestFn/applyTo
                  core.clj:  667  clojure.core/apply
                  core.clj: 6007  clojure.core/require
                  core.clj: 6007  clojure.core/require
               RestFn.java:  421  clojure.lang.RestFn/invoke
                  sign.clj:    1  caesium.crypto.sign/eval15482/loading--auto--
                  sign.clj:    1  caesium.crypto.sign/eval15482
                  sign.clj:    1  caesium.crypto.sign/eval15482
             Compiler.java: 7176  clojure.lang.Compiler/eval
             Compiler.java: 7165  clojure.lang.Compiler/eval
             Compiler.java: 7635  clojure.lang.Compiler/load
                   RT.java:  381  clojure.lang.RT/loadResourceScript
                   RT.java:  372  clojure.lang.RT/loadResourceScript
                   RT.java:  463  clojure.lang.RT/load
                   RT.java:  428  clojure.lang.RT/load
                  core.clj: 6126  clojure.core/load/fn
                  core.clj: 6125  clojure.core/load
                  core.clj: 6109  clojure.core/load
               RestFn.java:  408  clojure.lang.RestFn/invoke
                  core.clj: 5908  clojure.core/load-one
                  core.clj: 5903  clojure.core/load-one
                  core.clj: 5948  clojure.core/load-lib/fn
                  core.clj: 5947  clojure.core/load-lib
                  core.clj: 5928  clojure.core/load-lib
               RestFn.java:  142  clojure.lang.RestFn/applyTo
                  core.clj:  667  clojure.core/apply
                  core.clj: 5985  clojure.core/load-libs
                  core.clj: 5969  clojure.core/load-libs
               RestFn.java:  137  clojure.lang.RestFn/applyTo
                  core.clj:  667  clojure.core/apply
                  core.clj: 6007  clojure.core/require
                  core.clj: 6007  clojure.core/require
               RestFn.java:  408  clojure.lang.RestFn/invoke
                      REPL:    1  apeni.crypto.identity/eval15476/loading--auto--
                      REPL:    1  apeni.crypto.identity/eval15476
                      REPL:    1  apeni.crypto.identity/eval15476
             Compiler.java: 7176  clojure.lang.Compiler/eval
             Compiler.java: 7165  clojure.lang.Compiler/eval
             Compiler.java: 7131  clojure.lang.Compiler/eval
                  core.clj: 3214  clojure.core/eval
                  core.clj: 3210  clojure.core/eval
                  main.clj:  414  clojure.main/repl/read-eval-print/fn
                  main.clj:  414  clojure.main/repl/read-eval-print
                  main.clj:  435  clojure.main/repl/fn
                  main.clj:  435  clojure.main/repl
                  main.clj:  345  clojure.main/repl
               RestFn.java:  137  clojure.lang.RestFn/applyTo
                  core.clj:  665  clojure.core/apply
                  core.clj:  660  clojure.core/apply
                regrow.clj:   18  refactor-nrepl.ns.slam.hound.regrow/wrap-clojure-repl/fn
               RestFn.java: 1523  clojure.lang.RestFn/invoke
    interruptible_eval.clj:   83  nrepl.middleware.interruptible-eval/evaluate/fn
                  AFn.java:  152  clojure.lang.AFn/applyToHelper
                  AFn.java:  144  clojure.lang.AFn/applyTo
                  core.clj:  665  clojure.core/apply
                  core.clj: 1973  clojure.core/with-bindings*
                  core.clj: 1973  clojure.core/with-bindings*
               RestFn.java:  425  clojure.lang.RestFn/invoke
    interruptible_eval.clj:   81  nrepl.middleware.interruptible-eval/evaluate
    interruptible_eval.clj:   50  nrepl.middleware.interruptible-eval/evaluate
    interruptible_eval.clj:  221  nrepl.middleware.interruptible-eval/interruptible-eval/fn/fn
    interruptible_eval.clj:  189  nrepl.middleware.interruptible-eval/run-next/fn
                  AFn.java:   22  clojure.lang.AFn/run
   ThreadPoolExecutor.java: 1149  java.util.concurrent.ThreadPoolExecutor/runWorker
   ThreadPoolExecutor.java:  624  java.util.concurrent.ThreadPoolExecutor$Worker/run
               Thread.java:  748  java.lang.Thread/run

Here is the file:

(ns apeni.crypto.identity
  (:require [caesium.crypto.sign :as sign]))

(defn foo
  "I don't do a whole lot."
  [x]
  (println x "Hello, World!"))

Bindings for Ed25519 to Curve25519

I was going to add bindings for the ed25519 to curve25519 key conversion functions (https://download.libsodium.org/doc/advanced/ed25519-curve25519.html). Is that something you'd be happy to take a pull request for?

If so maybe you can help me with an error I'm getting:

clojure.lang.Compiler$CompilerException: java.lang.IllegalArgumentException: More than one matching method found: crypto_sign_ed25519_pk_to_curve25519, compiling:(.../caesium/src/caesium/crypto/sign/ed25519.clj:16:5)

in binding.clj I've added:

    [^int crypto_sign_ed25519_pk_to_curve25519
     [^bytes ^{Pinned {}} curve25519_pk
      ^bytes ^{Pinned {}} ed25519_pk]]

then to call it

    (b/call! crypto_sign_ed25519_pk_to_curve25519
             (bb/->indirect-byte-buf curve_pk)
             (bb/->indirect-byte-buf pk))

Any idea what I'm doing wrong?

Any help needed?

The current SNAPSHOT version works fine, but I'm a tad worried some of the old tests fail, the build doesn't pass on CI, and the dependencies are marked as not up-to-date.

I'd like to spend some time to polish the things out and would like to know what'd be a proper direction of tackling this. @lvh, what are your thoughts on all of this?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.