Skip to content

Commit

Permalink
Modularize signing and verification operations.
Browse files Browse the repository at this point in the history
Signed-off-by: Markus Sabadello <markus@danubetech.com>
  • Loading branch information
peacekeeper committed Jan 10, 2020
1 parent 4cbbb55 commit 923d070
Show file tree
Hide file tree
Showing 37 changed files with 597 additions and 391 deletions.
27 changes: 27 additions & 0 deletions src/main/java/info/weboftrust/ldsignatures/crypto/ByteSigner.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package info.weboftrust.ldsignatures.crypto;

import java.security.GeneralSecurityException;

public abstract class ByteSigner {

private final String algorithm;

protected ByteSigner(String algorithm) {

this.algorithm = algorithm;
}

public final byte[] sign(byte[] content, String algorithm) throws GeneralSecurityException {

if (! algorithm.equals(this.algorithm)) throw new GeneralSecurityException("Unexpected algorithm " + algorithm + " is different from " + this.algorithm);

return this.sign(content);
}

protected abstract byte[] sign(byte[] content) throws GeneralSecurityException;

public String getAlgorithm() {

return this.algorithm;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package info.weboftrust.ldsignatures.crypto;

import java.security.GeneralSecurityException;

public abstract class ByteVerifier {

private final String algorithm;

protected ByteVerifier(String algorithm) {

this.algorithm = algorithm;
}

public final boolean verify(byte[] content, byte[] signature, String algorithm) throws GeneralSecurityException {

if (! algorithm.equals(this.algorithm)) throw new GeneralSecurityException("Unexpected algorithm " + algorithm + " is different from " + this.algorithm);

return this.verify(content, signature);
}

protected abstract boolean verify(byte[] content, byte[] signature) throws GeneralSecurityException;

public String getAlgorithm() {

return this.algorithm;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package info.weboftrust.ldsignatures.crypto;

public abstract class PrivateKeySigner <T> extends ByteSigner {

private T privateKey;

protected PrivateKeySigner(T privateKey, String algorithm) {

super(algorithm);

this.privateKey = privateKey;
}

protected T getPrivateKey() {

return this.privateKey;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package info.weboftrust.ldsignatures.crypto;

import java.security.interfaces.RSAPrivateKey;

import org.bitcoinj.core.ECKey;

import com.nimbusds.jose.JOSEException;
import com.nimbusds.jose.JWSAlgorithm;
import com.nimbusds.jose.jwk.Curve;
import com.nimbusds.jose.jwk.KeyType;

import info.weboftrust.ldsignatures.crypto.impl.Ed25519_EdDSA_PrivateKeySigner;
import info.weboftrust.ldsignatures.crypto.impl.P256K_ES256K_PrivateKeySigner;
import info.weboftrust.ldsignatures.crypto.impl.RSA_PS256_PrivateKeySigner;
import info.weboftrust.ldsignatures.crypto.impl.RSA_RS256_PrivateKeySigner;

public class PrivateKeySignerFactory {

public static PrivateKeySigner<?> privateKeySignerForKey(String keyType, String algorithm, Object privateKey) throws JOSEException {

if (keyType == null) throw new NullPointerException("No key type provided.");
if (algorithm == null) throw new NullPointerException("No algorithm provided.");
if (privateKey == null) throw new NullPointerException("No private key provided.");

if (KeyType.RSA.getValue().equals(keyType)) {

if (JWSAlgorithm.RS256.getName().equals(algorithm)) return new RSA_RS256_PrivateKeySigner((RSAPrivateKey) privateKey);
if (JWSAlgorithm.PS256.getName().equals(algorithm)) return new RSA_PS256_PrivateKeySigner((RSAPrivateKey) privateKey);
} else if (Curve.P_256K.getName().equals(keyType)) {

if (JWSAlgorithm.ES256K.getName().equals(algorithm)) return new P256K_ES256K_PrivateKeySigner((ECKey) privateKey);
} else if (Curve.Ed25519.getName().equals(keyType)) {

if (JWSAlgorithm.EdDSA.getName().equals(algorithm)) return new Ed25519_EdDSA_PrivateKeySigner((byte[]) privateKey);
}

throw new IllegalArgumentException("Unsupported key " + keyType + " and/or algorithm " + algorithm);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package info.weboftrust.ldsignatures.crypto;

public abstract class PublicKeyVerifier <T> extends ByteVerifier {

private T publicKey;

protected PublicKeyVerifier(T publicKey, String algorithm) {

super(algorithm);

this.publicKey = publicKey;
}

protected T getPublicKey() {

return this.publicKey;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package info.weboftrust.ldsignatures.crypto;

import java.security.interfaces.RSAPublicKey;

import org.bitcoinj.core.ECKey;

import com.nimbusds.jose.JOSEException;
import com.nimbusds.jose.JWSAlgorithm;
import com.nimbusds.jose.jwk.Curve;
import com.nimbusds.jose.jwk.KeyType;

import info.weboftrust.ldsignatures.crypto.impl.Ed25519_EdDSA_PublicKeyVerifier;
import info.weboftrust.ldsignatures.crypto.impl.P256K_ES256K_PublicKeyVerifier;
import info.weboftrust.ldsignatures.crypto.impl.RSA_PS256_PublicKeyVerifier;
import info.weboftrust.ldsignatures.crypto.impl.RSA_RS256_PublicKeyVerifier;

public class PublicKeyVerifierFactory {

public static PublicKeyVerifier<?> publicKeyVerifierForKey(String keyType, String algorithm, Object publicKey) throws JOSEException {

if (keyType == null) throw new NullPointerException("No key type provided.");
if (algorithm == null) throw new NullPointerException("No algorithm provided.");
if (publicKey == null) throw new NullPointerException("No public key provided.");

if (KeyType.RSA.getValue().equals(keyType)) {

if (JWSAlgorithm.RS256.getName().equals(algorithm)) return new RSA_RS256_PublicKeyVerifier((RSAPublicKey) publicKey);
if (JWSAlgorithm.PS256.getName().equals(algorithm)) return new RSA_PS256_PublicKeyVerifier((RSAPublicKey) publicKey);
} else if (Curve.P_256K.getName().equals(keyType)) {

if (JWSAlgorithm.ES256K.getName().equals(algorithm)) return new P256K_ES256K_PublicKeyVerifier((ECKey) publicKey);
} else if (Curve.Ed25519.getName().equals(keyType)) {

if (JWSAlgorithm.EdDSA.getName().equals(algorithm)) return new Ed25519_EdDSA_PublicKeyVerifier((byte[]) publicKey);
}

throw new IllegalArgumentException("Unsupported key " + keyType + " and/or algorithm " + algorithm);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package info.weboftrust.ldsignatures.crypto.adapter;

import java.security.GeneralSecurityException;
import java.util.Collections;

import com.nimbusds.jose.JOSEException;
import com.nimbusds.jose.JWSAlgorithm;
import com.nimbusds.jose.JWSHeader;
import com.nimbusds.jose.JWSSigner;
import com.nimbusds.jose.crypto.impl.BaseJWSProvider;
import com.nimbusds.jose.util.Base64URL;

import info.weboftrust.ldsignatures.crypto.ByteSigner;

public class JWSSignerAdapter extends BaseJWSProvider implements JWSSigner {

private ByteSigner signer;

public JWSSignerAdapter(ByteSigner signer, JWSAlgorithm algorithm) {

super(Collections.singleton(algorithm));

this.signer = signer;
}

@Override
public Base64URL sign(final JWSHeader header, final byte[] signingInput) throws JOSEException {

if (! this.supportedJWSAlgorithms().contains(header.getAlgorithm())) throw new JOSEException("Unexpected algorithm: " + header.getAlgorithm());

try {

return Base64URL.encode(this.signer.sign(signingInput, header.getAlgorithm().getName()));
} catch (GeneralSecurityException ex) {

throw new JOSEException(ex.getMessage(), ex);
}
}

/*
* Getters and setters
*/

public ByteSigner getSigner() {

return this.signer;
}

public void setSigner(ByteSigner signer) {

this.signer = signer;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package info.weboftrust.ldsignatures.crypto.adapter;

import java.security.GeneralSecurityException;
import java.util.Collections;

import com.nimbusds.jose.JOSEException;
import com.nimbusds.jose.JWSAlgorithm;
import com.nimbusds.jose.JWSHeader;
import com.nimbusds.jose.JWSVerifier;
import com.nimbusds.jose.crypto.impl.BaseJWSProvider;
import com.nimbusds.jose.util.Base64URL;

import info.weboftrust.ldsignatures.crypto.ByteVerifier;

public class JWSVerifierAdapter extends BaseJWSProvider implements JWSVerifier {

private ByteVerifier verifier;

public JWSVerifierAdapter(ByteVerifier verifier, JWSAlgorithm algorithm) {

super(Collections.singleton(algorithm));

this.verifier = verifier;
}

@Override
public boolean verify(JWSHeader header, byte[] signingInput, Base64URL signature) throws JOSEException {

if (! this.supportedJWSAlgorithms().contains(header.getAlgorithm())) throw new JOSEException("Unexpected algorithm: " + header.getAlgorithm());

try {

return this.verifier.verify(signingInput, signature.decode(), header.getAlgorithm().getName());
} catch (GeneralSecurityException ex) {

throw new JOSEException(ex.getMessage(), ex);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package info.weboftrust.ldsignatures.crypto.impl;

import java.security.GeneralSecurityException;
import java.util.concurrent.ExecutionException;

import org.hyperledger.indy.sdk.IndyException;
import org.hyperledger.indy.sdk.crypto.Crypto;
import org.hyperledger.indy.sdk.wallet.Wallet;

import info.weboftrust.ldsignatures.crypto.ByteSigner;

public class Ed25519_EdDSA_LibIndySigner extends ByteSigner {

private Wallet wallet;
private String signerVk;

public Ed25519_EdDSA_LibIndySigner(byte[] privateKey, Wallet wallet, String signerVk) {

super("EdDSA");

this.wallet = wallet;
this.signerVk = signerVk;
}

@Override
public byte[] sign(byte[] content) throws GeneralSecurityException {

try {

return Crypto.cryptoSign(this.wallet, this.signerVk, content).get();
} catch (InterruptedException | ExecutionException | IndyException ex) {

throw new GeneralSecurityException(ex.getMessage(), ex);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package info.weboftrust.ldsignatures.crypto.impl;

import java.security.GeneralSecurityException;

import info.weboftrust.ldsignatures.crypto.PrivateKeySigner;
import info.weboftrust.ldsignatures.crypto.provider.EC25519Provider;

public class Ed25519_EdDSA_PrivateKeySigner extends PrivateKeySigner<byte[]> {

public Ed25519_EdDSA_PrivateKeySigner(byte[] privateKey) {

super(privateKey, "EdDSA");
}

@Override
public byte[] sign(byte[] content) throws GeneralSecurityException {

return EC25519Provider.get().sign(content, this.getPrivateKey());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package info.weboftrust.ldsignatures.crypto.impl;

import java.security.GeneralSecurityException;

import info.weboftrust.ldsignatures.crypto.PublicKeyVerifier;
import info.weboftrust.ldsignatures.crypto.provider.EC25519Provider;

public class Ed25519_EdDSA_PublicKeyVerifier extends PublicKeyVerifier<byte[]> {

public Ed25519_EdDSA_PublicKeyVerifier(byte[] publicKey) {

super(publicKey, "EdDSA");
}

@Override
public boolean verify(byte[] content, byte[] signature) throws GeneralSecurityException {

return EC25519Provider.get().verify(content, signature, this.getPublicKey());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package info.weboftrust.ldsignatures.crypto.impl;

import java.security.GeneralSecurityException;

import org.bitcoinj.core.ECKey;
import org.bitcoinj.core.Sha256Hash;

import info.weboftrust.ldsignatures.crypto.PrivateKeySigner;

public class P256K_ES256K_PrivateKeySigner extends PrivateKeySigner<ECKey> {

public P256K_ES256K_PrivateKeySigner(ECKey privateKey) {

super(privateKey, "ES256K");
}

@Override
public byte[] sign(byte[] content) throws GeneralSecurityException {

return this.getPrivateKey().sign(Sha256Hash.of(content)).encodeToDER();
}
}

0 comments on commit 923d070

Please sign in to comment.