(with ✨)
PCLMULQDQ
, AES-NI
, &c(on the JVM, for now)
Code → JNI call
⟿
JNI impl -> lib
public class NativeStuff { public static native long getpid(); // ^^^^^^ public static void main(String[] args) { getpid(); } static { System.load("/some/dir/nativestuff.dylib"); } }
javah
/* DO NOT EDIT THIS FILE - it is machine generated */ #include <jni.h> /* Header for class io_lvh_cljn_NativeStuff */ #ifndef _Included_io_lvh_cljn_NativeStuff #define _Included_io_lvh_cljn_NativeStuff #ifdef __cplusplus extern "C" { #endif /* * Class: io_lvh_cljn_NativeStuff * Method: getpid * Signature: ()J */ JNIEXPORT jlong JNICALL Java_io_lvh_cljn_NativeStuff_getpid (JNIEnv *, jclass); #ifdef __cplusplus } #endif #endif
#include "lvh_io_cljn_NativeStuff.h" jlong JNICALL Java_lvh_io_cljn_NativeStuff_getpid (JNIEnv *env, jclass c) { return getpid(); }
ᛠᛰᛜᛍᛥ ᚥᚮ‽
neanderthal → opencl → jocl
static native boolean initNativeLibrary(String fullName);
Great, if someone else does the compily bit
import com.sun.jna.Library; import com.sun.jna.Native; public class NativeStuff { public interface GetPid extends Library { long getpid(); } public static void main(String[] args) { GetPid getpid = (GetPid) Native .loadLibrary(GetPid.class); getpid.getpid(); } }
Code → JNR stub → JNI call
⟿
JNI impl -> libffi -> lib
JNA UX + JNI perf
jnr-ffi
public interface LibC { public int gettimeofday( @Out @Transient Timeval tv, Pointer unused ); }
public static final class Timeval extends Struct { public final time_t tv_sec = new time_t(); public final SignedLong tv_usec = new SignedLong(); }
fs, subprocesses, stat, tty/pty/fcntl, fast IO
jnr-posix
, jnr-enxio
, jnr-unixsocket
, …
jnr-constants
, jnr-x86asm
, …
(probably Java I guess?)
caesium
:: libsodium
$ wc -l **h
...
9166 total
😰
Mostly char *
Pointer, Buffer, String, [B, ByteBuffer…
encrypt-to-buf
, encrypt-to-array
, …void f(*int out, int x)
int f(int x)
Thousands of exposed syms
byte array → indirect ByteBuffer: fast!
indirect ByteBuffer → byte array: fast?
direct ByteBuffer ↔ byte array: slow!
-XX:+UnlockDiagnosticVMOptions
-XX:+PrintAssembly
Java HotSpot(TM) 64-Bit Server VM warning: PrintAssembly is enabled; turning on DebugNonSafepoints to gain additional output ... yada yada yada ...
Java HotSpot(TM) 64-Bit Server VM warning: PrintAssembly is enabled; turning on DebugNonSafepoints to gain additional output Could not load hsdis-amd64.dylib; library not loadable; PrintAssembly is disabled
0x00007fb8a181a2e0: mov DWORD PTR [rsp-0x14000],eax 0x00007fb8a181a2e7: push rbp 0x00007fb8a181a2e8: sub rsp,0x30 ;*aload_0 ; - clojure.lang.ASeq::size@0 (line 188) 0x00007fb8a181a2ec: nop 0x00007fb8a181a2ed: movabs rax,0xffffffffffffffff 0x00007fb8a181a2f7: call 0x00007fb8a1045f60 ; OopMap{off=60} ;*invokevirtual count ; - clojure.lang.ASeq::size@1 (line 188) ; {virtual_call} 0x00007fb8a181a2fc: add rsp,0x30 0x00007fb8a181a300: pop rbp 0x00007fb8a181a301: test DWORD PTR [rip+0x18527df9],eax
Mostly @Annotations
@IgnoreError
errno
@In
and @Out
@In
: only copy to native@Out
: only copy from native@Pinned
@Direct
and @Transient
Native backing memory
caesium
Look Ma, no Java!
Doesn't hide Java/JVM
definterface
(definterface LibC (^int gettimeofday [^Timeval ^{Out {} Transient {}} tv ^Pointer unused]))
(def ^:private raw-bound-fns '[[^int sodium_init []] [^String sodium_version_string []] [^long ^{size_t {}} crypto_secretbox_macbytes []] [^String crypto_secretbox_primitive []] [^int crypto_secretbox_easy [^bytes ^{Pinned {}} c ^bytes ^{Pinned {}} m ^long ^{LongLong {}} mlen ^bytes ^{Pinned {}} n ^bytes ^{Pinned {}} k]]] ;; ... )
(mapcat permuted-byte-types raw-bound-fns)
@IgnoreError
Just map a function over some values
defconsts
;; in caesium.crypto.secretbox (defconsts [keybytes noncebytes macbytes primitive]) ;; => (do (def keybytes "Constant returned by `crypto_secretbox_keybytes`. See libsodium docs." (.crypto_secretbox_keybytes caesium.binding/sodium)) ;;... )
;; in caesium.crypto.box (✨ open-easy m c n pk sk) ;; => (.crypto_box_open_easy m c (long (buflen c)) n pk sk)
(defmacro ✨ "Produces a form for calling named fn with lots of magic: * The fn-name is specified using its short name, which is resolved against the ns as per [[defconsts]]. * All bufs are annotated as ByteBuffers. * Buffer lengths are automatically added. The emoji name of this macro accurately reflects how easy I want it to be for third parties to call it." ;; ... )
Number used once
E(k, n, p) -> c
(not gonna talk about them now)
GCM was the good ciphersuite, right?!
… so just use TLS!
Encrypting a cookie or DB entry
Evidence in how often they…
Nope!
E(k, p) -> c
Fernet, modern crypto done right
total catastrophe
(decrypt, forge)
⬇
attacker can detect duplicates
(not decrypt, not forge)
(maybe mix with randomness)
Deterministic encryption
magicnonce
secretbox-rnd
secretbox-det
secretbox-nmr
BLAKE2b as a PRF → nonce XSalsa20 + Poly1305 (big nonce space)
Pretty good (but wait for the paper)
@lvh
https://latacora.com
{lvh,youagain}@latacora.com