The module io.github.mmm.crypto
(artifactId mmm-crypto
) allows more simple and secure usage of cryptography. JCA and JCE offer an extensible API to provide cryptographic algorithms for Java. However, this API is very low-level what often leads to programming mistakes and severe security frauds (missing parameters like nonce). Further, you need a lot of knowledge of the underlying cryptographic algorithms or you will end up with runtime errors. Also, changing things often requires refactorings of the code using the encryption or signature algorithms. Finally, the JCA and JCE are limited and for many things you need extensions like BouncyCastle. In some cases you need to create some cryptographic objects via BouncyCastle and others via the default provider and combine them properly to make things work. Again this opens pitfalls and requires a lot of knowledge.
This library allows you to get around all these problems and write your cryptogrphic code safe and easy.
This library addresses the following aspects of cryptography:
-
hashing
-
encryption and decryption
-
signing and verifying signatures
-
key creation and management
-
certificate creation and management
-
key store management
The special benefits of mmm-crypto
are:
-
Simple API to access and create cryptographic objects and algorithms.
-
API enforces all parameters required for secure usage.
-
Detailed JavaDocs assist you to make the correct choice.
-
Flexible composition of algorithms: combine any hash (e.g. 5 x SHA-256) with any signature algorithm (e.g. ECIES) to create and verify signatures.
-
Build in support to encrypt and decrypt binary streams on the fly with just one line of code.
-
Usable and extendable also for cryptographic algorithms not already considered in the current release (if Java or BouncyCastle ships with a new algorithm you can use it by creating your own config without the need to wait for an update of this library).
-
Extended support for bouncycastle.
-
Can be used with any other custom security provider.
Here is an example for asymmetric encryption with mmm-security-bc
:
Rsa access = Rsa.of4096(Sha256.SHA_256_X2);
AsymmetricKeyCreator keyCreator = access.newKeyCreator();
AsymmetricKeyPair keyPair = keyCreator.generateKeyPair();
PublicKey publicKey = keyPair.getPublicKey();
PrivateKey privateKey = keyPair.getPrivateKey();
// encryption + decryption
byte[] rawMessage = "Secret message".getBytes(StandardCharsets.UTF_8);
Encryptor encryptor = access.newEncryptorUnsafe(publicKey);
byte[] encryptedMessage = encryptor.crypt(rawMessage, true);
Decryptor decryptor = access.newDecryptorUnsafe(privateKey);
byte[] decryptedMessage = decryptor.crypt(encryptedMessage, true);
assertThat(decryptedMessage).isEqualTo(rawMessage);
// signing
SignatureBinary signature = access.newSignerUnsafe(privateKey).sign(rawMessage, true);
boolean signatureVerified = access.newVerifierUnsafe(publicKey).verifyUnsafe(rawMessage, signature);
assertThat(signatureVerified).as("signature verified").isTrue();
On the first view this might not look much simpler than plain JCA/JCE.
However, by only changing a single line you can change the encryption and key algorithms with all according settings.
If you replace the first line with the following it will use the Elliptic-Curve Secp256k1
with ECIES and ECDSA:
Secp256k1 access = Secp256k1.ofPlain(Sha256.SHA_256_X2);
You can see in the example some methods that end with Unsafe
.
Without this suffix the API is typesafe to prevent errors passing the wrong type of key or signature to a specific algorithm.
To make the code typesafe, you can use more specific types than PublicKey
, etc. and remove the Unsafe
suffix to use the type-safe methods.
If you still want to keep your code portable so that you can change the algorithms as simple as just shown, you can simply use Java10+ type inference syntax.
In the following example we use the algorithms used by BitCoin including a signature with recovery ID what is supported neither by JCA/JCE nor by BouncyCastle out of the box and requires some additional cryptograpic calculations.
var access = Secp256k1.ofRecoveryId(Sha256.SHA_256_X2);
var keyCreator = access.newKeyCreator();
var keyPair = keyCreator.generateKeyPair();
var publicKey = keyPair.getPublicKey();
var privateKey = keyPair.getPrivateKey();
// encryption + decryption
var rawMessage = "Secret message".getBytes(StandardCharsets.UTF_8);
var encryptor = access.newEncryptor(publicKey);
var encryptedMessage = encryptor.crypt(rawMessage, true);
var decryptor = access.newDecryptor(privateKey);
var decryptedMessage = decryptor.crypt(encryptedMessage, true);
assertThat(decryptedMessage).isEqualTo(rawMessage);
// signing
var signature = access.newSigner(privateKey).sign(rawMessage, true);
var signatureVerified = access.newVerifier(publicKey).verifyUnsafe(rawMessage, signature);
assertThat(signatureVerified).as("signature verified").isTrue();
var hash = access.newHashCreator().hash(rawMessage, true);
assertThat(signature.recoverPublicKey(hash)).isEqualTo(publicKey);
This is all just the beginning. There is even much more. Dealing with JCA/JCE directly is rather complex and error-prone what easily leads to runtime errors or security frauds and vulnerabilities. Using this library will make your life a lot more simple and safe.
Maven Dependency:
<dependency>
<groupId>io.github.m-m-m</groupId>
<artifactId>mmm-crypto</artifactId>
<version>${mmm.crypto.version}</version>
</dependency>
Module Dependency:
requires transitive io.github.mmm.crypto;
The module io.github.mmm.crypto.bc
(artifactId mmm-crypto-bc
) provides the extension and integration with bouncy-castle.