Closed subes closed 1 year ago
we could implement our own pipeline for encryption similar to FragmentSynchronousWriter/FragmentSynchronousReader
Here the ticket where an application-side solution like this is discussed at aeron: https://github.com/real-logic/aeron/issues/203 And here a discussion at akka: https://github.com/akka/akka-meta/issues/16
AES implementation in java uses AES-NI nowadays and has acceleration for GCM: https://github.com/gerritjvv/crypto/tree/master/crypto-perf
(c code) https://github.com/kasbekarameya/AES-NI-Encryption
(could also use CTR mode, though GCM is supposed to be better) https://stackoverflow.com/questions/53706907/extremely-slow-built-in-aes-encryption-with-java
(GCM example) https://github.com/gerritjvv/crypto/blob/master/crypto-core/src/main/java/crypto/AES.java (though should use zero-copy and reuse objects)
(could also use google tink which supports key rotation, though I think key renegotiation is more interesting?) https://github.com/google/tink/blob/master/docs/JAVA-HOWTO.md
XChaCha20 with Poly1305 could be an alternative to AES256-CTR-HMAC256: https://crypto.stackexchange.com/questions/84081/how-to-choose-parameters-for-argon2-for-a-password-vault => nope, performance can not compete: https://www.bearssl.org/speed.html
We can encrypt any package using SSLEngine like this (we can then use tcnative openssl/boringssl and jdk impl):
(source https://stackoverflow.com/a/57512677)
More sources for DTLS: https://github.com/mobius-software-ltd/java-dtls https://github.com/snf4j/snf4j
commons-crypto seems to support a AES-NI binding via JNA nowadays: https://mvnrepository.com/artifact/org.apache.commons/commons-crypto/1.1.0
TODO:
HMAC-SHA256 signature is used by signal messenger to ensure messages are not corrupted: https://soatok.blog/2020/05/13/why-aes-gcm-sucks/
here how this could be added to a stream: https://www.javatips.net/api/conceal-master/benchmarks/src/com/facebook/crypto/benchmarks/mac/streams/MacLayeredInputStream.java
Akka also planned to use HMAC-SHA256: https://github.com/akka/akka-meta/issues/16
First verify mac, then work on the data: https://moxie.org/2011/12/13/the-cryptographic-doom-principle.html (mac the encrypted payload)
https://netnix.org/2015/04/19/aes-encryption-with-hmac-integrity-in-java/ https://stackoverflow.com/questions/7124735/hmac-sha256-algorithm-for-signature-calculation
Don't use the same key for AES and HMAC, instead derive two keys from the secret (which can also then be shorter than the required key length): https://crypto.stackexchange.com/questions/8081/using-the-same-secret-key-for-encryption-and-authentication-in-a-encrypt-then-ma https://crypto.stackexchange.com/questions/76588/multiple-aes-key-derivation-from-a-master-key
We can also expand an IV from this: https://stackoverflow.com/questions/45985661/is-hkdf-implemented-in-java-cryptography-architecture (we then send the counter instead of the whole IV)
HKDF impls:
Though HKDF can only be used with random enough keys. When using a password that is not strong/random enough, one should instead use bcrypt or PBKDF2 to strenghen/stretch the password. https://crypto.stackexchange.com/questions/46550/benchmark-differences-between-sha-512-and-bcrypt
Bcrypt could also be used with a salt before using HKDF: https://security.stackexchange.com/questions/71566/encryption-and-hmac-with-the-same-password
I guess the best approach would be to create a TLS connection using private/public keys, exchange a randomly generated key through that and then use HKDF to derive the other keys from that random key.
A less secure way to do this would be to SHA-256 a password and then use the first 128 bits and the last 128 bits is independent keys. (https://crypto.stackexchange.com/questions/8081/using-the-same-secret-key-for-encryption-and-authentication-in-a-encrypt-then-ma)
Confirms that a combination of Password+PBKDF2+HKDFexpands//Random+HKDFextract+HKDFexpands are they way to go: https://crypto.stackexchange.com/questions/20960/pbkdf-vs-hkdf-for-pretty-long-key We can derive AES-KEY, AES-IV, MAC-KEY from this.
Password+PBKDF2+HKDFexpands is also used by firefox sync: https://blog.mozilla.org/services/2014/04/30/firefox-syncs-new-security-model/ (the last paragraph)
Don't use the same salt for multiple keys: https://security.stackexchange.com/questions/48000/why-would-you-need-a-salt-for-aes-cbs-when-iv-is-already-randomly-generated-and
Bcrypt is better than Scrypt (until it is proven, which it is by now) and PBKDF2 (easily cracked by GPUs): https://medium.com/@mpreziuso/password-hashing-pbkdf2-scrypt-bcrypt-1ef4bb9c19b3 Argon2 is better than Scrypt or Bcrypt: https://medium.com/analytics-vidhya/password-hashing-pbkdf2-scrypt-bcrypt-and-argon2-e25aaf41598e
Native Argon2 has the benefit of support parallelization and using off-heap memory: https://github.com/phxql/argon2-jvm So we use that as the winner.
TODO:
HMAC256 is very slow. CMAC with AES would be a better option: https://crypto.stackexchange.com/questions/52009/fastest-algorithm-for-message-authentication https://stackoverflow.com/questions/60670117/cmac-aes-rfc-4493-calculation-in-java
A native SHA implementation: https://github.com/nayuki/Native-hashes-for-Java
Though better to use the amazon native provider: https://github.com/corretto/amazon-corretto-crypto-provider
(as discussed here: https://stackoverflow.com/a/59166873)
Should check if corretto is faster than commons-crypto, in that case use JCA in commons-crypto if corretto is enabled (only on linux, commons-crypto can then still be used on windows and mac).
Another alternative would be GMAC: https://stackoverflow.com/questions/48548394/how-to-verify-a-gmac Though no padding is required for AES/GCM mode: https://crypto.stackexchange.com/questions/42412/gcm-padding-or-not
Though should also implement CtrCryptoInput/OutputStream for AES/GCM, might be faster than AES/CTR+[H|C|G]MAC with amazon corretto provider.
https://github.com/wildfly-security/wildfly-openssl another native binding (only for SslEngine)
commons-crypto does not bind to openssl 3.0.2 and has no embedded version: https://issues.apache.org/jira/projects/CRYPTO/issues/CRYPTO-164
conscrypt also has many ciphers based on boringssl: https://github.com/google/conscrypt/blob/master/common/src/main/java/org/conscrypt/OpenSSLProvider.java Seems to have everything that commons-crypto has. Need to also check if SecureRandom implementation uses intel instructions.
done and working. performance tests and docs will be handled outside of the ticket
tcp transport with ssl encryption (ideally a native epoll socket) https://netty.io/wiki/forked-tomcat-native.html
maybe there is also a way to use this with nio sockets?