Skip to content

Commit

Permalink
Used BoucnyCastle provider for ED25519 and SHA256DSA, since its faste…
Browse files Browse the repository at this point in the history
…r than the Java's native obe
  • Loading branch information
spoto committed May 22, 2024
1 parent 8bffa2c commit 3dcec40
Show file tree
Hide file tree
Showing 5 changed files with 100 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,8 @@ public class ED25519 extends AbstractSignatureAlgorithmImpl {
public ED25519() throws NoSuchAlgorithmException {
try {
ensureProvider();
this.signature = Signature.getInstance("Ed25519");
// the BC version of this algorithm is faster than the native Java version
this.signature = Signature.getInstance("Ed25519", "BC");
this.keyFactory = KeyFactory.getInstance("Ed25519", "BC");
this.keyPairGenerator = mkKeyPairGenerator(CryptoServicesRegistrar.getSecureRandom());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,8 @@ public class ED25519DET extends AbstractSignatureAlgorithmImpl {
public ED25519DET() throws NoSuchAlgorithmException {
try {
ensureProvider();
this.signature = Signature.getInstance("Ed25519");
// the BC version of this algorithm is faster than the native Java version
this.signature = Signature.getInstance("Ed25519", "BC");
this.keyFactory = KeyFactory.getInstance("Ed25519", "BC");
var random = SecureRandom.getInstance("SHA1PRNG");
random.setSeed("nel mezzo del cammin di nostra vita".getBytes(StandardCharsets.US_ASCII));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.Security;
import java.security.Signature;
import java.security.SignatureException;
import java.security.spec.InvalidKeySpecException;
Expand All @@ -37,6 +38,7 @@
import org.bouncycastle.crypto.digests.SHA512Digest;
import org.bouncycastle.crypto.generators.PKCS5S2ParametersGenerator;
import org.bouncycastle.crypto.params.KeyParameter;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

import io.hotmoka.crypto.api.BIP39Dictionary;

Expand All @@ -62,10 +64,10 @@ public class SHA256DSA extends AbstractSignatureAlgorithmImpl {
private final KeyFactory keyFactory;

public SHA256DSA() throws NoSuchAlgorithmException {
this.signature = Signature.getInstance("SHA256withDSA");
this.keyPairGenerator = mkKeyPairGenerator(CryptoServicesRegistrar.getSecureRandom());

try {
ensureProvider();
this.signature = Signature.getInstance("SHA256withDSA", "BC");
this.keyPairGenerator = mkKeyPairGenerator(CryptoServicesRegistrar.getSecureRandom());
this.keyFactory = KeyFactory.getInstance("DSA", "SUN");
}
catch (NoSuchProviderException e) {
Expand All @@ -74,8 +76,8 @@ public SHA256DSA() throws NoSuchAlgorithmException {
}

@Override
protected KeyPairGenerator mkKeyPairGenerator(SecureRandom random) throws NoSuchAlgorithmException {
var keyPairGenerator = KeyPairGenerator.getInstance("DSA");
protected KeyPairGenerator mkKeyPairGenerator(SecureRandom random) throws NoSuchAlgorithmException, NoSuchProviderException {
var keyPairGenerator = KeyPairGenerator.getInstance("DSA", "BC");
keyPairGenerator.initialize(2048, random);
return keyPairGenerator;
}
Expand Down Expand Up @@ -109,7 +111,7 @@ private byte[] mergeEntropyWithPassword() {
try {
return mkKeyPairGenerator(random).generateKeyPair();
}
catch (NoSuchAlgorithmException e) {
catch (NoSuchProviderException | NoSuchAlgorithmException e) {
throw new RuntimeException("Unexpected exception", e);
}
}
Expand Down Expand Up @@ -147,4 +149,9 @@ public PublicKey publicKeyFromEncoding(byte[] encoded) throws InvalidKeySpecExce
public PrivateKey privateKeyFromEncoding(byte[] encoded) throws InvalidKeySpecException {
return keyFactory.generatePrivate(new PKCS8EncodedKeySpec(encoded));
}

private static void ensureProvider() {
if (Security.getProvider(BouncyCastleProvider.PROVIDER_NAME) == null)
Security.addProvider(new BouncyCastleProvider());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
/*
Copyright 2021 Fausto Spoto
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package io.hotmoka.crypto.tests;

import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;

import java.security.InvalidKeyException;
import java.security.KeyPair;
import java.security.NoSuchAlgorithmException;
import java.security.PublicKey;
import java.security.SignatureException;
import java.security.spec.InvalidKeySpecException;

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import io.hotmoka.crypto.SignatureAlgorithms;
import io.hotmoka.crypto.api.Signer;
import io.hotmoka.crypto.api.Verifier;
import io.hotmoka.testing.AbstractLoggedTests;

public class SHA256DSA extends AbstractLoggedTests {
private final String data = "HELLO SHA256DSA";

@Test
@DisplayName("sign data with the sha256dsa signature")
void sign() throws NoSuchAlgorithmException, InvalidKeyException, SignatureException {
var sha256dsa = SignatureAlgorithms.sha256dsa();
KeyPair keyPair = sha256dsa.getKeyPair();
Signer<String> signer = sha256dsa.getSigner(keyPair.getPrivate(), String::getBytes);
Verifier<String> verifier = sha256dsa.getVerifier(keyPair.getPublic(), String::getBytes);
byte[] signed = signer.sign(data);

assertTrue(verifier.verify(data, signed), "data is not verified correctly");
assertFalse(verifier.verify(data + "corrupted", signed), "corrupted data is verified");
}

@Test
@DisplayName("sign, verify and create the public key from the encoded public key")
void testEncodedPublicKey() throws NoSuchAlgorithmException, InvalidKeyException, SignatureException, InvalidKeySpecException {
// create a signature algorithm
var sha256dsa = SignatureAlgorithms.sha256dsa();
// create a key pair (public, private) with that signature algorithm
KeyPair keyPair = sha256dsa.getKeyPair();
// create a signer and verifier of strings: strings are first transformed into their
// sequence of bytes and then signed with the private key and verified with the public key
Signer<String> signer = sha256dsa.getSigner(keyPair.getPrivate(), String::getBytes);
Verifier<String> verifier = sha256dsa.getVerifier(keyPair.getPublic(), String::getBytes);
// sign the data
byte[] signed = signer.sign(data);

// check that the signed data is correctly verified and that corrupted data is not verified
assertTrue(verifier.verify(data, signed), "data is not verified correctly");
assertFalse(verifier.verify(data + "corrupted", signed), "corrupted data is verified");

// transform the public key into an array of bytes and back into a public key: they should be equal
PublicKey publicKey = sha256dsa.publicKeyFromEncoding(sha256dsa.encodingOf(keyPair.getPublic()));
// create a verifier with the new public key
verifier = sha256dsa.getVerifier(publicKey, String::getBytes);
// if they are equal, the new public key should behave as the original public key
assertTrue(verifier.verify(data, signed), "data is not verified correctly with the encoded key");
assertFalse(verifier.verify(data + "corrupted", signed), "corrupted data is verified with the encoded key");

// explicitly check that the two public keys are equal
assertTrue(keyPair.getPublic().equals(publicKey), "the public keys do not match");
}
}
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ Note: submodules whose artifact must be deployed on Maven Central must activate
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.release>17</maven.compiler.release>
<io.hotmoka.crypto.version>1.4.1</io.hotmoka.crypto.version>
<io.hotmoka.crypto.version>1.4.2</io.hotmoka.crypto.version>
<io.hotmoka.testing.version>1.4.1</io.hotmoka.testing.version>
</properties>

Expand Down

0 comments on commit 3dcec40

Please sign in to comment.