o1c-dev / o1c Goto Github PK
View Code? Open in Web Editor NEWO(1) Cryptography is an easy to use, hard to misuse Java cryptographic library based on O(1) cryptographic algorithms
License: ISC License
O(1) Cryptography is an easy to use, hard to misuse Java cryptographic library based on O(1) cryptographic algorithms
License: ISC License
The key exchange SPI should expose low level functionality and use the standard implementation from RFC 7748. This should have at least two core implementations: one based on BouncyCastle, and the other based on Java 11.
As currently being standardized by the NIST LWC project, there are some very promising algorithms proposed, particularly ones that use a sponge function as popularized by FIPS 202/SHA-3/Keccak. These sponge functions offer extremely versatile cryptographic primitives as demonstrated by libhydrogen and its use of the Gimli permutation.
Based on the ECRYPT benchmarks for the NIST LWC submissions, I propose supporting the top three permutations along with their higher level primitives (AEAD/MAC, MD, PRF, KDF):
As these permutations and cryptographic schema are all fairly new, there doesn't seem to be much in the way of Java libraries supporting them already. Ascon has a Java reference implementation, but in order to support the algorithms, the C reference implementations should be ported to Java (along with fixing any non-constant-time checks in the reference implementations; the sample code seems to usually be lazy about this). At the very least, pure Java implementations should be offered. Linking to optimized C variants may be considered for alternatives, though it's also possible that there may be too much overhead from JNI.
This signature SPI should expose low level functionality and use the standard functionality from RFC 8032. This should have at least two core implementations: one based on BouncyCastle, and the other based on Java 15.
https://csrc.nist.gov/News/2021/lightweight-crypto-finalists-announced
Looks like Gimli got nixed as I thought it might. That can be removed now. ISAP made it to the final round as well, so perhaps that'd be a good replacement. Some other potential options to consider:
Other ciphers in the final round look interesting, but they only offer AEAD modes.
The primary feature a good cryptographic library provides for making things easy to use and hard to misuse is documentation; without documentation, the only users who can understand these types of libraries are cryptographers and security engineers who already know how to use the low level primitives and have little need for a library like this. In particular, various vocabulary must be defined, use cases explained (e.g., when do you need non-repudiation versus just authenticity, using context metadata/AAD for simulating type information, identities, and session state, how to handle key exchange, authentication, etc.), and examples provided. For the high level API, these should be both documented in javadoc (for more API-specific concerns) as well as in the wiki or future website with an appropriate narrative. Links to established standards (and perhaps even papers) are expected, but links are not sufficient for the documentation; make sure to summarize any important information.
Some established cryptography projects offer a lot of documentation. See libsodium docs and Themis docs for some decent examples of higher level documentation.
Lower level APIs (e.g., crypto primitives) can be documented via javadoc. While it may be nice to mention some of the math going on in the background (e.g., prime order groups and permutations), this may get overly technical which may also end up incorrect without accompanying proofs.
This SPI should the Argon2 (i or id; d is not too relevant here) key derivation function as standardized in PHC. There are some Java bindings on the main Argon2 PHC repo here: https://github.com/p-h-c/phc-winner-argon2
This cipher SPI should provide basic low level functionality that follows RFC 7539 for ChaCha20-Poly1305. This should have at least two core implementations: one based on BouncyCastle, and the other based on Java 11.
In order to support Java 8 environments, particularly ones that already add BouncyCastle as a dependency, SPI implementations for #1, #2, and #3 should be provided based on BouncyCastle.
The C implementation of the DRBG doesn't appear to mix in the gathered entropy, resulting in predictable output.
In the function below the entropy is collected in the local array 'seed', but this is never passed to the hasher.
static void drbg_ensure_init(void) {
if (!drbg.initialized) {
drbg.counter = 0;
uint8_t seed[BLAKE3_KEY_LEN];
drbg_entropy(seed, BLAKE3_KEY_LEN);
drbg_ratchet();
drbg.initialized = true;
}
}
I think a call to blake3_hasher_init_keyed()
would be needed, which I think is equivalent to what the Java version is doing.
Consider the design of Themis: https://docs.cossacklabs.com/themis/crypto-theory/cryptosystems/secure-session/
Another design to consider is MinimaLT: https://cr.yp.to/tcpip/minimalt-20131031.pdf
A larger survey of security network protocols: https://tools.ietf.org/html/draft-ietf-taps-transport-security-12
EdDSA provides a lot of tunable parameters, and when Ed25519 was initially created, it used SHA-512 with the note that the hash function could be updated to SHA-3 or other systems later on. Ed25519 still uses SHA-512 in standard contexts, but with the introduction of the Ristretto255 encoding as an alternative to splitting up keys into two algorithms (X25519 and Ed25519), we can provide a signature scheme to match the signcryption scheme that Ristretto support was initially introduced to enable. Instead of using SHA-3, we'll use Blake3, and improved version of Blake2s which was a finalist in SHA-3 anyways. As Blake3 provides 128-bit security, this matches fairly well with Curve25519.
In order to unify the key format used with EdDSA, this scheme will need to modify the previous simplicity assumed by using a scalar/element pair as with signcryption. Instead of using the scalar as the private key, a random 32-byte seed or secret is used as the private key as in EdDSA, then that key is hashed to get the scalar and a prefix key used for creating challenge hashes. In Ed25519, this works by taking the SHA-512 hash of the seed. In this scheme, we have two options: take the Blake3 hash of the seed and finalize its output to 64 bytes, or use the seed as the key for a keyed hash, then finalize 64 bytes of output. The plain hash method matches the EdDSA standard more exactly, though the availability of a keyed hash mode, if properly secure, can simplify the design here a little bit.
When calculating the (r, s) signature pair in an EdDSA scheme, s is still a scalar and is encoded in the usual way. However, r is now a Ristretto element rather than a normal extended Edwards coordinate in that the serialization algorithm should follow the Ristretto encoding instead of the traditional Edwards point compression.
It might be relevant to find out more about including a key id like in signcryption and whether it's useful here, too.
After working out some proof of concept code to try out https://github.com/mit-plv/fiat-crypto for elliptic curve stuff, it turns out to be fairly straightforward to build and include native variants of the algorithms being provided in the Java API through some fairly minimal JNI boilerplate. Since every crypto algorithm tends to have a reference C implementation, most of the symmetric algorithms can be easily imported that way rather than having to be ported again (the Java implementations are ported from C in the first place).
While the plain reference implementations are likely similar in performance to the Java ones, there are several assembly optimizations available for these algorithms and can be included for supported platforms (mostly for x86-64, though some may have additional platforms optimized).
As a sort of enterprise-style idea, it would be useful to have standards-compliant versions of the APIs that are a little less modern. For example, American standards like FIPS 140 (see also FIPS publications) use AES-GCM instead of ChaCha20-Poly1305, ECDSA instead of EdDSA, and ECDH instead of XDH; there are similar combinations of primitives. There are other country standards that can be looked at as well like CRYPTREC, NESSIE, and all sorts of processes. While these tend to be older (and arguably less secure in practice), they are also still widely used and in demand.
In order for the various SPIs to actually be pluggable, some service descriptor classes need to be made to describe the various algorithms. These can be located by ServiceLoader and filtered based on their properties. In doing this, it might be necessary to break up the API/SPI module into its own so that a particular implementation can be chosen at runtime based on the classpath, modulepath, or some other configuration mechanism.
Note, however, that configuration mechanisms should be fairly minimal to avoid introducing insecure ways to use things.
https://openjdk.java.net/jeps/338
This could be interesting to try out and compare with the assembly-optimized variants or if it can help improve any of the Java algorithms.
Since BouncyCastle is a large dependency, and as EdDSA is the only algorithm that was added to Java after 11, any program running in Java 11 through 14 can benefit from using the built-in providers from #9 combined with using a dedicated EdDSA library for a smaller dependency footprint.
Consider the design of Themis: https://docs.cossacklabs.com/themis/crypto-theory/cryptosystems/secure-cell/
Similarly, in NaCl and libsodium, this concept is exposed as a secretbox API for authenticated encryption, and the secretstream API is used as a higher level API for authenticated encryption of arbitrary length data streams (the lower level API should be limited to smaller, well tested data limits).
The high level API to develop here should address a similar use case to secretstream.
Note that password-based keys are out of scope for this issue and is covered in #7.
As discovered in the mini library over in https://github.com/o1c-dev/jcryptobox, it's pretty easy to enable a GitHub Pages site.
Consider the design of Themis: https://docs.cossacklabs.com/themis/crypto-theory/cryptosystems/secure-message/
And consider the NaCl and libsodium API, the box APIs for authenticated public-key encryption, and the sealed box APIs for anonymous public-key encryption.
Create an analogous API here using XChaCha20-Poly1305 and X25519. This should cover sending encrypted messages and signed messages.
Essentially, given Alice and Bob both have XDH keypairs, we can compute a shared secret to generate a symmetric key. Implementing a perfect-forward-secrecy variant involving ephemeral keypairs and signatures for authentication rather than the static XDH keys would be out of scope for messages at this level and is scoped in #6.
As a feasible option for a dependency-free modern hashing algorithm that's more widely supported than the more experimental lightweight cryptography, BLAKE3 support should be added. This will be particularly useful as an update/replacement for BLAKE2b (libsodium default for generic hashing).
As noted in this blog post, it seems as though most of the built-in KeyStore
providers are insecure. Using #7, a more secure implementation for KeyStore
can be made.
Alternatively, a similar SPI can be made inspired by the Tink key management APIs.
It'd be great to have a libsodium-compatibility mode that works with their box, sealed box, secretbox, etc., APIs.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.