package net.openhft.chronicle.salt; import jnr.ffi.LibraryLoader; import jnr.ffi.Platform; import jnr.ffi.annotations.In; import jnr.ffi.annotations.Out; import jnr.ffi.byref.LongLongByReference; import jnr.ffi.types.u_int64_t; import net.openhft.chronicle.bytes.Bytes; import net.openhft.chronicle.bytes.BytesStore; import net.openhft.chronicle.bytes.NativeBytesStore; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.xml.bind.DatatypeConverter; public interface Sodium { String STANDARD_GROUP_ELEMENT = "0900000000000000000000000000000000000000000000000000000000000000"; BytesStore<?, ?> SGE_BYTES = Init.fromHex(0, STANDARD_GROUP_ELEMENT); int ED25519_PUBLICKEY_BYTES = 32; int ED25519_PRIVATEKEY_BYTES = 32; int ED25519_SECRETKEY_BYTES = ED25519_PUBLICKEY_BYTES + ED25519_PRIVATEKEY_BYTES; Sodium SODIUM = Init.init(); int CRYPTO_BOX_CURVE25519XSALSA20POLY1305_PUBLICKEYBYTES = 32; int CRYPTO_BOX_CURVE25519XSALSA20POLY1305_SECRETKEYBYTES = 32; int SIZEOF_CRYPTO_HASH_SHA256_STATE = 128; // actual = 104. Add a little headroom int SIZEOF_CRYPTO_HASH_SHA512_STATE = 256; // actual = 208. Add a little headroom // --------------------------------------------------------------------- // Public-key cryptography: Sealed boxes int CRYPTO_BOX_CURVE25519XSALSA20POLY1305_ZEROBYTES = 32; int CRYPTO_BOX_CURVE25519XSALSA20POLY1305_BOXZEROBYTES = 16; int CRYPTO_BOX_CURVE25519XSALSA20POLY1305_MACBYTES = CRYPTO_BOX_CURVE25519XSALSA20POLY1305_ZEROBYTES - CRYPTO_BOX_CURVE25519XSALSA20POLY1305_BOXZEROBYTES; int CRYPTO_BOX_SEALBYTES = CRYPTO_BOX_CURVE25519XSALSA20POLY1305_PUBLICKEYBYTES + CRYPTO_BOX_CURVE25519XSALSA20POLY1305_MACBYTES; int CRYPTO_SCALARMULT_CURVE25519_SCALARBYTES = 32; int CRYPTO_BOX_PUBLICKEYBYTES = CRYPTO_BOX_CURVE25519XSALSA20POLY1305_PUBLICKEYBYTES; int CRYPTO_BOX_SECRETKEYBYTES = CRYPTO_BOX_CURVE25519XSALSA20POLY1305_SECRETKEYBYTES; int CRYPTO_BOX_MACBYTES = CRYPTO_BOX_CURVE25519XSALSA20POLY1305_MACBYTES; int CRYPTO_BOX_NONCEBYTES = 24; int CRYPTO_BOX_SEEDBYTES = 32; int RANDOMBYTES_SEEDBYTES = 32; int CRYPTO_BOX_BEFORENMBYTES = 32; int CRYPTO_SIGN_BYTES = 64; int CRYPTO_SIGN_SEEDBYTES = 32; int CRYPTO_SIGN_PUBLICKEYBYTES = 32; int CRYPTO_SIGN_SECRETKEYBYTES = 64; int SIZEOF_CRYPTO_SIGN_STATE = 256; // actual = 208. Add a little headroom static void checkValid(int status, String description) throws IllegalStateException { if (status != 0) { throw new IllegalStateException(description + ", status: " + status); } } int sodium_init(); // must be called only once, single threaded. String sodium_version_string(); void sodium_memzero(@In long address, @In @u_int64_t long size); void sodium_increment(@In long buffer, @In @u_int64_t int size); void randombytes(@In long buffer, @In @u_int64_t int size); void randombytes_buf(@In long buffer, @In @u_int64_t int size); void randombytes_buf_deterministic(@In long buffer, @In @u_int64_t int size, @In long seed); //// Methods for Ed25519 // key generation. int crypto_box_curve25519xsalsa20poly1305_keypair(@In long publicKey, @In long privateKey); // generate a public key from a private one int crypto_sign_ed25519_seed_keypair(@In long publicKey, @In long secretKey, @In long seed); // sign int crypto_sign_ed25519(@In long signature, @Out LongLongByReference sigLen, @In long message, @In @u_int64_t int msgLen, @In long secretKey); /// Easy Boxes int crypto_scalarmult_curve25519(@In long result, @In long intValue, @In long point); int crypto_hash_sha256(@In long buffer, @In long message, @In @u_int64_t int sizeof); int crypto_hash_sha256_init(@In long state); int crypto_hash_sha256_update(@In long state, @In long in, @In @u_int64_t long inlen); int crypto_hash_sha256_final(@In long state, @In long out); int crypto_hash_sha512(@In long buffer, @In long message, @In @u_int64_t int sizeof); int crypto_hash_sha512_init(@In long state); int crypto_hash_sha512_update(@In long state, @In long in, @In @u_int64_t long inlen); int crypto_hash_sha512_final(@In long state, @In long out); // verify int crypto_sign_ed25519_open(@In long buffer, @Out LongLongByReference bufferLen, @In long sigAndMsg, @In @u_int64_t int sigAndMsgLen, @In long publicKey); int crypto_box_seal(@In long ct, @In long message, @In @u_int64_t int length, @In long publicKey); int crypto_box_seal_open(@In long message, @In long c, @In @u_int64_t int length, @In long publicKey, @In long privateKey); void crypto_box_keypair(@In long publicKey, @In long secretKey); void crypto_box_seed_keypair(@In long publicKey, @In long secretKey, @In long seed); int crypto_box_beforenm(@In long shared, @In long publicKey, @In long secretKey); int crypto_box_easy(@In long c, @In long m, @In long mlen, @In long n, @In long pk, @In long sk); int crypto_box_easy_afternm(@In long c, @In long m, @In long mlen, @In long n, @In long sharedkey); int crypto_box_open_easy(@In long m, @In long c, @In long clen, @In long n, @In long pk, @In long sk); int crypto_box_open_easy_afternm(@In long c, @In long m, @In long mlen, @In long n, @In long sharedkey); int crypto_sign_keypair(@In long pl, @In long sk); int crypto_sign_seed_keypair(@In long pk, @In long sk, @In long seed); int crypto_sign(@In long sm, @In long smlen, @In long m, @In long mlen, @In long sk); int crypto_sign_open(@In long m, @In long mlen, @In long sm, @In long smlen, @In long pk); int crypto_sign_init(@In long state); int crypto_sign_update(@In long state, @In long m, @In long mlen); int crypto_sign_final_create(@In long state, @In long sig, @In long siglen, @In long sk); int crypto_sign_final_verify(@In long state, @In long sig, @In long pk); int crypto_sign_ed25519_sk_to_seed(@In long seed, @In long sk); int crypto_sign_ed25519_sk_to_pk(@In long pk, @In long sk); enum Init { ; static Sodium init() { String libraryName = "sodium"; if (Platform.getNativePlatform().getOS() == Platform.OS.WINDOWS) { libraryName = "libsodium"; } Sodium sodium = null; try { sodium = LibraryLoader.create(Sodium.class).search("lib").search("/usr/local/lib").search("/opt/local/lib").load(libraryName); } catch (Error e) { if (Platform.getNativePlatform().getOS() == Platform.OS.WINDOWS) System.err.println("Unable to load libsodium, make sure the Visual C++ Downloadable is installed\n" + "https://support.microsoft.com/en-gb/help/2977003/the-latest-supported-visual-c-downloads"); throw e; } checkValid(sodium.sodium_init(), "sodium_init()"); return sodium; } static Bytes<?> fromHex(int padding, String s) { byte[] byteArr = DatatypeConverter.parseHexBinary(s); Bytes<?> bytes = Bytes.allocateDirect(padding + byteArr.length); if (padding > 0) { bytes.zeroOut(0, padding); bytes.writePosition(padding); } bytes.write(byteArr); return bytes; } } enum Util { ; @NotNull public static BytesStore setSize(@Nullable BytesStore bs, long size) { if (bs == null) { return NativeBytesStore.nativeStoreWithFixedCapacity(size); } assert bs.refCount() > 0; if (bs instanceof Bytes) { Bytes b = (Bytes) bs; b.ensureCapacity(size); b.readPositionRemaining(0, size); return b; } else if (bs.capacity() == size) { return bs; } throw new IllegalArgumentException("Capacity expected " + size + " was " + bs.capacity()); } } }