Chronicle Salt - Java binding to wrap libsodium which implements the NaCl crypto library
Based on
This library is a port of the Abstractj Kalium library to use Chronicle Bytes off heap instead of byte[] on heap.
Using off heap data directly improves performance and scalability.
Requirements
-
JDK 8 or higher
Installation
libsodium
For a more detailed explanation, please refer to RbNaCl’s documentation
Linux
Linux users can download the source tar for Linux
-
Download
libsodium
from https://download.libsodium.org/libsodium/releases/ -
Choose the version of
libsodium
you wish to use -
The archives follow the following pattern: libsodium-{version}.tar.gz
-
tar xzvf libsodium-{version}.tar.gz
-
cd libsodium-{version}
-
./configure
-
make
-
sudo make install
Windows
Windows users will need to provide the pre-build binaries from libsodium
.
-
Download
libsodium
from https://download.libsodium.org/libsodium/releases/ -
Choose the version of
libsodium
you wish to use -
The archives follow the following pattern: libsodium-{version}-msvc.zip
-
From the archive find the artifacts compiled for your architecture and then the MSVC tool set of your choice
-
For example:
v141 // these were compiled against the MSVC v141 (i.e. Visual Studio 2017)
-
Extract from the archive the
dll
library files into one of the following locations: -
into the
lib
at the root of the working directory directory of your project. -
into a location that is included in your
PATH
environment variable.
For example, on my Windows 10 machine with a x64 architecture:
{archive root}
└───x64
...
└───Release
...
└───v141
...
└───dynamic <- copy the library files from this locaiton.
Private (Secret) and Public Keys and Ed25519 Signatures
Private (Secret) Keys
-
One of two keys used in public key cryptography.
-
It is used to sign digital signatures and to decrypt data that was encoded using the recipient’s public key.
-
The private key is not visible to the public; it is only visible to the owner.
Public Keys
-
One of two keys used in public key cryptography.
-
The public key is used to encrypt the message receieved, and is assumed visibe to everyone.
Ed25519 Signatures
-
Elliptic-curve signatures.
-
Engineered at several levels of design and implementation to achieve very high speeds without compromising security.
Using Chronicle Salt
Generating Random Bytes
-
Random bytes are used to form a private key as it ensures they key is difficult to guess, therefore more secure.
Bytes rand = Ed25519.generateRandomBytes(32);
Generating a public and secret key from a seed
-
A public and secret key need to be generated as they are used to sign a message, making it secure and allowing the receiver authenticate the sender/message.
Bytes privateKey = Ed25519.generatePrivateKey();
Bytes publicKey = Bytes.allocateElasticDirect();
Bytes secretKey = Bytes.allocateElasticDirect();
Ed25519.privateToPublicAndSecret(publicKey, secretKey, privateKey);
Note
|
The secret key holds the private AND public key and is needed for some operations. |
Viewing keys as a hexadecimal dump
System.out.println(privateKey.toHexString());
System.out.println(publicKey.toHexString());
System.out.println(secretKey.toHexString());
Prints something like
00000000 54 c8 b8 05 5a df 56 9f 8a ae b4 72 2c 69 26 42 T···Z·V· ···r,i&B 00000010 99 c6 d4 36 13 4c cc 2b 83 04 da c5 71 75 b0 1a ···6·L·+ ····qu·· 00000000 95 65 db 8d 48 06 12 ae c4 fe 44 c1 d9 07 5f 19 ·e··H··· ··D···_· 00000010 19 de 6b 13 cc 24 67 27 3a bf 9b ce 25 c8 a1 33 ··k··$g' :···%··3 00000000 54 c8 b8 05 5a df 56 9f 8a ae b4 72 2c 69 26 42 T···Z·V· ···r,i&B 00000010 99 c6 d4 36 13 4c cc 2b 83 04 da c5 71 75 b0 1a ···6·L·+ ····qu·· 00000020 95 65 db 8d 48 06 12 ae c4 fe 44 c1 d9 07 5f 19 ·e··H··· ··D···_· 00000030 19 de 6b 13 cc 24 67 27 3a bf 9b ce 25 c8 a1 33 ··k··$g' :···%··3
Signing a message
After creating a message, it can be signed.
Note
|
The signatureAndMsg includes the signature and the messages as this is the way the underlying library is written.
|
Bytes signatureAndMsg = Bytes.allocateElasticDirect();
// OR
Bytes signatureAndMsg = Bytes.allocateDirect(Ed25519.SIGNATURE_LENGTH + message.readRemaining());
Ed25519.sign(signatureAndMsg, message, secretKey);
Note
|
The sign method appends, rather than overwrites the signatureAndMsg . If you want to overwrite, you need to call clear() first
|
Bytes signatureAndMsg = Bytes.allocateElasticDirect();
Ed25519.sign(signatureAndMsg, message, secretKey);
Ed25519.sign(signatureAndMsg, message2, secretKey); // (1)
-
signatureAndMsg now contains two messages
Bytes signatureAndMsg = Bytes.allocateElasticDirect();
Ed25519.sign(signatureAndMsg, message, secretKey); // (1)
client.write(signatureAndMsg);
signatureAndMsg.clear()
Ed25519.sign(signatureAndMsg, message2, secretKey); // (2)
client.write(signatureAndMsg);
-
first message signed
-
signatureAndMsg contains one message
Verifying a message
Once a message has been signed, you can verify it using the public key alone.
boolean verified = Ed25519.verify(signatureAndMsg, publicKey);
-
Verifying a message is a means of authenticating that a message is received from a certain sender.
-
The digital signature, put simply, is a hash of the data (message, file, etc.).
-
To validate a message, the receipient calculates the hash of the same data and will use the senders public key to decrypt the digital signature.
-
The two hash values are compared - if they match, the signature is considered valid. If they don’t match, it can mean that another signature was used to sign it, or the data was (intentionally or unintentionally) altered.
-
If the hash values do not match, the message will not be verified.
-
Using the public key to verify a message ensures you are receiving a genuine message from the sender, and that it hasn’t been altered in any way.
SHA-2 hashing
You can provide a message to hash and it will return the SHA-256 (32-byte) or SHA-512 (64-byte) hash of the data.
SHA-256 hash
BytesStore message = messageToHash();
Bytes hash256 = Bytes.allocateDirect(SHA2.HASH_SHA256_BYTES));
SHA2.sha256(hash256, message);
SHA-512 hash
BytesStore message = messageToHash();
Bytes hash512 = Bytes.allocateDirect(SHA2.HASH_SHA512_BYTES));
SHA2.sha512(hash512, message);
Benchmark
The library can be run in parallel to improve throughput
system |
sign |
verify |
i7-7700HQ 4 core |
64K/s |
26K/s |
i7-7820X 8 core |
206K/s |
87K/s |
E5-2650 v4 24 core |
306K/s |
154K/s |
E5-2650 v4 24 core, batch |
506K/s |
202K/s |
system |
sha256 of 55 bytes |
sha512 of 110 bytes |
i7-7820X 8 core |
21 M/s |
17 M/s |
E5-2650 v4 24 core |
39 M/s |
31 M/s |
Key Terms
- Chronicle Bytes
-
A similar purpose to Java NIO’s ByteBuffer, but with added extenstions. View Chronicle-Bytes here
- Cryptography
-
The practice of hiding information using a mix of mathematics, computer science and electrical engineering.
- Decrypt
-
Decoding a message using a public key.
- Digital Signature
-
A digital code attached to an electronically transmitted document to verify its contents and the senders identity.
- Ed25519 Signatures
-
A public key signature system
- Hash
-
A mathematical algorithm that maps data of arbitrary size, to a bit string of a fixed size (a hash). It is designed to be a one way function i.e. a function which is infeasible to revert.
Hexadecimal Dump - To be updated.
- Libsodium
-
A modern, easy-to-use software library for encryption, decryption, signatures, password hashing and more.
- Private Key
-
A variable used within an algorithm to encrypt and decrypt code. Mathematically linked to a public key.
- Public Key
-
A large numerical value used to encrypt data.
- Scalability
-
The capability of a system, network or process to handle large amounts of work, or its potential to be enlarged to accommodate growth.
- Seed
-
A number or other value that has been generated by software using one or more values.
- Throughput
-
The amount of data successfully moved from one place to another in a given timeframe.