mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-14 19:59:05 +01:00
Add support for Ed25519 signatures.
This commit is contained in:
@@ -43,6 +43,7 @@ dependencyVerification {
|
|||||||
'com.madgag.spongycastle:core:1.58.0.0:core-1.58.0.0.jar:199617dd5698c5a9312b898c0a4cec7ce9dd8649d07f65d91629f58229d72728',
|
'com.madgag.spongycastle:core:1.58.0.0:core-1.58.0.0.jar:199617dd5698c5a9312b898c0a4cec7ce9dd8649d07f65d91629f58229d72728',
|
||||||
'javax.annotation:jsr250-api:1.0:jsr250-api-1.0.jar:a1a922d0d9b6d183ed3800dfac01d1e1eb159f0e8c6f94736931c1def54a941f',
|
'javax.annotation:jsr250-api:1.0:jsr250-api-1.0.jar:a1a922d0d9b6d183ed3800dfac01d1e1eb159f0e8c6f94736931c1def54a941f',
|
||||||
'javax.inject:javax.inject:1:javax.inject-1.jar:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff',
|
'javax.inject:javax.inject:1:javax.inject-1.jar:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff',
|
||||||
|
'net.i2p.crypto:eddsa:0.2.0:eddsa-0.2.0.jar:a7cb1b85c16e2f0730b9204106929a1d9aaae1df728adc7041a8b8b605692140',
|
||||||
'org.bitlet:weupnp:0.1.4:weupnp-0.1.4.jar:88df7e6504929d00bdb832863761385c68ab92af945b04f0770b126270a444fb',
|
'org.bitlet:weupnp:0.1.4:weupnp-0.1.4.jar:88df7e6504929d00bdb832863761385c68ab92af945b04f0770b126270a444fb',
|
||||||
'org.jacoco:org.jacoco.agent:0.7.4.201502262128:org.jacoco.agent-0.7.4.201502262128-runtime.jar:e357a0f1d573c2f702a273992b1b6cb661734f66311854efb3778a888515c5b5',
|
'org.jacoco:org.jacoco.agent:0.7.4.201502262128:org.jacoco.agent-0.7.4.201502262128-runtime.jar:e357a0f1d573c2f702a273992b1b6cb661734f66311854efb3778a888515c5b5',
|
||||||
'org.jacoco:org.jacoco.agent:0.7.4.201502262128:org.jacoco.agent-0.7.4.201502262128.jar:47b4bec6df11a1118da3953da8b9fa1e7079d6fec857faa1a3cf912e53a6fd4e',
|
'org.jacoco:org.jacoco.agent:0.7.4.201502262128:org.jacoco.agent-0.7.4.201502262128.jar:47b4bec6df11a1118da3953da8b9fa1e7079d6fec857faa1a3cf912e53a6fd4e',
|
||||||
|
|||||||
@@ -20,6 +20,10 @@ public interface CryptoComponent {
|
|||||||
|
|
||||||
KeyParser getSignatureKeyParser();
|
KeyParser getSignatureKeyParser();
|
||||||
|
|
||||||
|
KeyPair generateEdKeyPair();
|
||||||
|
|
||||||
|
KeyParser getEdKeyParser();
|
||||||
|
|
||||||
KeyParser getMessageKeyParser();
|
KeyParser getMessageKeyParser();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -61,7 +65,6 @@ public interface CryptoComponent {
|
|||||||
* @param ourKeyPair our ephemeral keypair
|
* @param ourKeyPair our ephemeral keypair
|
||||||
* @param alice true if ourKeyPair belongs to Alice
|
* @param alice true if ourKeyPair belongs to Alice
|
||||||
* @return the shared secret
|
* @return the shared secret
|
||||||
* @throws GeneralSecurityException
|
|
||||||
*/
|
*/
|
||||||
SecretKey deriveSharedSecret(byte[] theirPublicKey, KeyPair ourKeyPair,
|
SecretKey deriveSharedSecret(byte[] theirPublicKey, KeyPair ourKeyPair,
|
||||||
boolean alice) throws GeneralSecurityException;
|
boolean alice) throws GeneralSecurityException;
|
||||||
@@ -106,7 +109,6 @@ public interface CryptoComponent {
|
|||||||
* @param ourKeyPair our ephemeral keypair
|
* @param ourKeyPair our ephemeral keypair
|
||||||
* @param alice true if ourKeyPair belongs to Alice
|
* @param alice true if ourKeyPair belongs to Alice
|
||||||
* @return the shared secret
|
* @return the shared secret
|
||||||
* @throws GeneralSecurityException
|
|
||||||
*/
|
*/
|
||||||
SecretKey deriveMasterSecret(byte[] theirPublicKey, KeyPair ourKeyPair,
|
SecretKey deriveMasterSecret(byte[] theirPublicKey, KeyPair ourKeyPair,
|
||||||
boolean alice) throws GeneralSecurityException;
|
boolean alice) throws GeneralSecurityException;
|
||||||
@@ -130,7 +132,7 @@ public interface CryptoComponent {
|
|||||||
long streamNumber);
|
long streamNumber);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Signs the given byte[] with the given PrivateKey.
|
* Signs the given byte[] with the given ECDSA private key.
|
||||||
*
|
*
|
||||||
* @param label A label specific to this signature
|
* @param label A label specific to this signature
|
||||||
* to ensure that the signature cannot be repurposed
|
* to ensure that the signature cannot be repurposed
|
||||||
@@ -139,8 +141,17 @@ public interface CryptoComponent {
|
|||||||
throws GeneralSecurityException;
|
throws GeneralSecurityException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Verifies that the given signature is valid for the signedData
|
* Signs the given byte[] with the given Ed25519 private keu.
|
||||||
* and the given publicKey.
|
*
|
||||||
|
* @param label A label specific to this signature
|
||||||
|
* to ensure that the signature cannot be repurposed
|
||||||
|
*/
|
||||||
|
byte[] signEd(String label, byte[] toSign, byte[] privateKey)
|
||||||
|
throws GeneralSecurityException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verifies that the given signature is valid for the signed data
|
||||||
|
* and the given ECDSA public key.
|
||||||
*
|
*
|
||||||
* @param label A label that was specific to this signature
|
* @param label A label that was specific to this signature
|
||||||
* to ensure that the signature cannot be repurposed
|
* to ensure that the signature cannot be repurposed
|
||||||
@@ -149,6 +160,17 @@ public interface CryptoComponent {
|
|||||||
boolean verify(String label, byte[] signedData, byte[] publicKey,
|
boolean verify(String label, byte[] signedData, byte[] publicKey,
|
||||||
byte[] signature) throws GeneralSecurityException;
|
byte[] signature) throws GeneralSecurityException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verifies that the given signature is valid for the signed data
|
||||||
|
* and the given Ed25519 public key.
|
||||||
|
*
|
||||||
|
* @param label A label that was specific to this signature
|
||||||
|
* to ensure that the signature cannot be repurposed
|
||||||
|
* @return true if the signature was valid, false otherwise.
|
||||||
|
*/
|
||||||
|
boolean verifyEd(String label, byte[] signedData, byte[] publicKey,
|
||||||
|
byte[] signature) throws GeneralSecurityException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the hash of the given inputs. The inputs are unambiguously
|
* Returns the hash of the given inputs. The inputs are unambiguously
|
||||||
* combined by prefixing each input with its length.
|
* combined by prefixing each input with its length.
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ dependencies {
|
|||||||
implementation 'com.madgag.spongycastle:core:1.58.0.0'
|
implementation 'com.madgag.spongycastle:core:1.58.0.0'
|
||||||
implementation 'com.h2database:h2:1.4.192' // This is the last version that supports Java 1.6
|
implementation 'com.h2database:h2:1.4.192' // This is the last version that supports Java 1.6
|
||||||
implementation 'org.bitlet:weupnp:0.1.4'
|
implementation 'org.bitlet:weupnp:0.1.4'
|
||||||
|
implementation 'net.i2p.crypto:eddsa:0.2.0'
|
||||||
|
|
||||||
apt 'com.google.dagger:dagger-compiler:2.0.2'
|
apt 'com.google.dagger:dagger-compiler:2.0.2'
|
||||||
|
|
||||||
@@ -37,6 +38,7 @@ dependencyVerification {
|
|||||||
'com.madgag.spongycastle:core:1.58.0.0:core-1.58.0.0.jar:199617dd5698c5a9312b898c0a4cec7ce9dd8649d07f65d91629f58229d72728',
|
'com.madgag.spongycastle:core:1.58.0.0:core-1.58.0.0.jar:199617dd5698c5a9312b898c0a4cec7ce9dd8649d07f65d91629f58229d72728',
|
||||||
'javax.inject:javax.inject:1:javax.inject-1.jar:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff',
|
'javax.inject:javax.inject:1:javax.inject-1.jar:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff',
|
||||||
'junit:junit:4.12:junit-4.12.jar:59721f0805e223d84b90677887d9ff567dc534d7c502ca903c0c2b17f05c116a',
|
'junit:junit:4.12:junit-4.12.jar:59721f0805e223d84b90677887d9ff567dc534d7c502ca903c0c2b17f05c116a',
|
||||||
|
'net.i2p.crypto:eddsa:0.2.0:eddsa-0.2.0.jar:a7cb1b85c16e2f0730b9204106929a1d9aaae1df728adc7041a8b8b605692140',
|
||||||
'org.apache.ant:ant-launcher:1.9.4:ant-launcher-1.9.4.jar:7bccea20b41801ca17bcbc909a78c835d0f443f12d639c77bd6ae3d05861608d',
|
'org.apache.ant:ant-launcher:1.9.4:ant-launcher-1.9.4.jar:7bccea20b41801ca17bcbc909a78c835d0f443f12d639c77bd6ae3d05861608d',
|
||||||
'org.apache.ant:ant:1.9.4:ant-1.9.4.jar:649ae0730251de07b8913f49286d46bba7b92d47c5f332610aa426c4f02161d8',
|
'org.apache.ant:ant:1.9.4:ant-1.9.4.jar:649ae0730251de07b8913f49286d46bba7b92d47c5f332610aa426c4f02161d8',
|
||||||
'org.beanshell:bsh:1.3.0:bsh-1.3.0.jar:9b04edc75d19db54f1b4e8b5355e9364384c6cf71eb0a1b9724c159d779879f8',
|
'org.beanshell:bsh:1.3.0:bsh-1.3.0.jar:9b04edc75d19db54f1b4e8b5355e9364384c6cf71eb0a1b9724c159d779879f8',
|
||||||
|
|||||||
@@ -1,5 +1,9 @@
|
|||||||
package org.briarproject.bramble.crypto;
|
package org.briarproject.bramble.crypto;
|
||||||
|
|
||||||
|
import net.i2p.crypto.eddsa.EdDSAPrivateKey;
|
||||||
|
import net.i2p.crypto.eddsa.EdDSAPublicKey;
|
||||||
|
import net.i2p.crypto.eddsa.KeyPairGenerator;
|
||||||
|
|
||||||
import org.briarproject.bramble.api.crypto.CryptoComponent;
|
import org.briarproject.bramble.api.crypto.CryptoComponent;
|
||||||
import org.briarproject.bramble.api.crypto.KeyPair;
|
import org.briarproject.bramble.api.crypto.KeyPair;
|
||||||
import org.briarproject.bramble.api.crypto.KeyParser;
|
import org.briarproject.bramble.api.crypto.KeyParser;
|
||||||
@@ -56,6 +60,7 @@ class CryptoComponentImpl implements CryptoComponent {
|
|||||||
|
|
||||||
private static final int AGREEMENT_KEY_PAIR_BITS = 256;
|
private static final int AGREEMENT_KEY_PAIR_BITS = 256;
|
||||||
private static final int SIGNATURE_KEY_PAIR_BITS = 256;
|
private static final int SIGNATURE_KEY_PAIR_BITS = 256;
|
||||||
|
private static final int ED_KEY_PAIR_BITS = 256;
|
||||||
private static final int STORAGE_IV_BYTES = 24; // 196 bits
|
private static final int STORAGE_IV_BYTES = 24; // 196 bits
|
||||||
private static final int PBKDF_SALT_BYTES = 32; // 256 bits
|
private static final int PBKDF_SALT_BYTES = 32; // 256 bits
|
||||||
private static final int PBKDF_TARGET_MILLIS = 500;
|
private static final int PBKDF_TARGET_MILLIS = 500;
|
||||||
@@ -99,6 +104,8 @@ class CryptoComponentImpl implements CryptoComponent {
|
|||||||
private final ECKeyPairGenerator signatureKeyPairGenerator;
|
private final ECKeyPairGenerator signatureKeyPairGenerator;
|
||||||
private final KeyParser agreementKeyParser, signatureKeyParser;
|
private final KeyParser agreementKeyParser, signatureKeyParser;
|
||||||
private final MessageEncrypter messageEncrypter;
|
private final MessageEncrypter messageEncrypter;
|
||||||
|
private final KeyPairGenerator edKeyPairGenerator;
|
||||||
|
private final KeyParser edKeyParser;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
CryptoComponentImpl(SecureRandomProvider secureRandomProvider) {
|
CryptoComponentImpl(SecureRandomProvider secureRandomProvider) {
|
||||||
@@ -132,6 +139,9 @@ class CryptoComponentImpl implements CryptoComponent {
|
|||||||
signatureKeyParser = new Sec1KeyParser(PARAMETERS,
|
signatureKeyParser = new Sec1KeyParser(PARAMETERS,
|
||||||
SIGNATURE_KEY_PAIR_BITS);
|
SIGNATURE_KEY_PAIR_BITS);
|
||||||
messageEncrypter = new MessageEncrypter(secureRandom);
|
messageEncrypter = new MessageEncrypter(secureRandom);
|
||||||
|
edKeyPairGenerator = new KeyPairGenerator();
|
||||||
|
edKeyPairGenerator.initialize(ED_KEY_PAIR_BITS, secureRandom);
|
||||||
|
edKeyParser = new EdKeyParser();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Based on https://android-developers.googleblog.com/2013/08/some-securerandom-thoughts.html
|
// Based on https://android-developers.googleblog.com/2013/08/some-securerandom-thoughts.html
|
||||||
@@ -190,6 +200,21 @@ class CryptoComponentImpl implements CryptoComponent {
|
|||||||
return secret;
|
return secret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public KeyPair generateEdKeyPair() {
|
||||||
|
java.security.KeyPair keyPair = edKeyPairGenerator.generateKeyPair();
|
||||||
|
EdDSAPublicKey edPublicKey = (EdDSAPublicKey) keyPair.getPublic();
|
||||||
|
PublicKey publicKey = new EdPublicKey(edPublicKey.getAbyte());
|
||||||
|
EdDSAPrivateKey edPrivateKey = (EdDSAPrivateKey) keyPair.getPrivate();
|
||||||
|
PrivateKey privateKey = new EdPrivateKey(edPrivateKey.getSeed());
|
||||||
|
return new KeyPair(publicKey, privateKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public KeyParser getEdKeyParser() {
|
||||||
|
return edKeyParser;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public KeyPair generateAgreementKeyPair() {
|
public KeyPair generateAgreementKeyPair() {
|
||||||
AsymmetricCipherKeyPair keyPair =
|
AsymmetricCipherKeyPair keyPair =
|
||||||
@@ -416,19 +441,41 @@ class CryptoComponentImpl implements CryptoComponent {
|
|||||||
@Override
|
@Override
|
||||||
public byte[] sign(String label, byte[] toSign, byte[] privateKey)
|
public byte[] sign(String label, byte[] toSign, byte[] privateKey)
|
||||||
throws GeneralSecurityException {
|
throws GeneralSecurityException {
|
||||||
Signature signature = new SignatureImpl(secureRandom);
|
return sign(new SignatureImpl(secureRandom), signatureKeyParser, label,
|
||||||
KeyParser keyParser = getSignatureKeyParser();
|
toSign, privateKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte[] signEd(String label, byte[] toSign, byte[] privateKey)
|
||||||
|
throws GeneralSecurityException {
|
||||||
|
return sign(new EdSignature(), edKeyParser, label, toSign, privateKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
private byte[] sign(Signature sig, KeyParser keyParser, String label,
|
||||||
|
byte[] toSign, byte[] privateKey) throws GeneralSecurityException {
|
||||||
PrivateKey key = keyParser.parsePrivateKey(privateKey);
|
PrivateKey key = keyParser.parsePrivateKey(privateKey);
|
||||||
signature.initSign(key);
|
sig.initSign(key);
|
||||||
updateSignature(signature, label, toSign);
|
updateSignature(sig, label, toSign);
|
||||||
return signature.sign();
|
return sig.sign();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean verify(String label, byte[] signedData, byte[] publicKey,
|
public boolean verify(String label, byte[] signedData, byte[] publicKey,
|
||||||
byte[] signature) throws GeneralSecurityException {
|
byte[] signature) throws GeneralSecurityException {
|
||||||
Signature sig = new SignatureImpl(secureRandom);
|
return verify(new SignatureImpl(secureRandom), signatureKeyParser,
|
||||||
KeyParser keyParser = getSignatureKeyParser();
|
label, signedData, publicKey, signature);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean verifyEd(String label, byte[] signedData, byte[] publicKey,
|
||||||
|
byte[] signature) throws GeneralSecurityException {
|
||||||
|
return verify(new EdSignature(), edKeyParser, label, signedData,
|
||||||
|
publicKey, signature);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean verify(Signature sig, KeyParser keyParser, String label,
|
||||||
|
byte[] signedData, byte[] publicKey, byte[] signature)
|
||||||
|
throws GeneralSecurityException {
|
||||||
PublicKey key = keyParser.parsePublicKey(publicKey);
|
PublicKey key = keyParser.parsePublicKey(publicKey);
|
||||||
sig.initVerify(key);
|
sig.initVerify(key);
|
||||||
updateSignature(sig, label, signedData);
|
updateSignature(sig, label, signedData);
|
||||||
|
|||||||
@@ -0,0 +1,26 @@
|
|||||||
|
package org.briarproject.bramble.crypto;
|
||||||
|
|
||||||
|
import org.briarproject.bramble.api.crypto.KeyParser;
|
||||||
|
import org.briarproject.bramble.api.crypto.PrivateKey;
|
||||||
|
import org.briarproject.bramble.api.crypto.PublicKey;
|
||||||
|
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||||
|
|
||||||
|
import java.security.GeneralSecurityException;
|
||||||
|
|
||||||
|
@NotNullByDefault
|
||||||
|
class EdKeyParser implements KeyParser {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PublicKey parsePublicKey(byte[] encodedKey)
|
||||||
|
throws GeneralSecurityException {
|
||||||
|
if (encodedKey.length != 32) throw new GeneralSecurityException();
|
||||||
|
return new EdPublicKey(encodedKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PrivateKey parsePrivateKey(byte[] encodedKey)
|
||||||
|
throws GeneralSecurityException {
|
||||||
|
if (encodedKey.length != 32) throw new GeneralSecurityException();
|
||||||
|
return new EdPrivateKey(encodedKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
package org.briarproject.bramble.crypto;
|
||||||
|
|
||||||
|
import org.briarproject.bramble.api.Bytes;
|
||||||
|
import org.briarproject.bramble.api.crypto.PrivateKey;
|
||||||
|
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||||
|
|
||||||
|
@NotNullByDefault
|
||||||
|
class EdPrivateKey extends Bytes implements PrivateKey {
|
||||||
|
|
||||||
|
EdPrivateKey(byte[] bytes) {
|
||||||
|
super(bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte[] getEncoded() {
|
||||||
|
return getBytes();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
package org.briarproject.bramble.crypto;
|
||||||
|
|
||||||
|
import org.briarproject.bramble.api.Bytes;
|
||||||
|
import org.briarproject.bramble.api.crypto.PublicKey;
|
||||||
|
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||||
|
|
||||||
|
@NotNullByDefault
|
||||||
|
class EdPublicKey extends Bytes implements PublicKey {
|
||||||
|
|
||||||
|
EdPublicKey(byte[] bytes) {
|
||||||
|
super(bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte[] getEncoded() {
|
||||||
|
return getBytes();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,103 @@
|
|||||||
|
package org.briarproject.bramble.crypto;
|
||||||
|
|
||||||
|
import net.i2p.crypto.eddsa.EdDSAPrivateKey;
|
||||||
|
import net.i2p.crypto.eddsa.EdDSAPublicKey;
|
||||||
|
import net.i2p.crypto.eddsa.EdDSASecurityProvider;
|
||||||
|
import net.i2p.crypto.eddsa.spec.EdDSANamedCurveSpec;
|
||||||
|
import net.i2p.crypto.eddsa.spec.EdDSANamedCurveTable;
|
||||||
|
import net.i2p.crypto.eddsa.spec.EdDSAPrivateKeySpec;
|
||||||
|
import net.i2p.crypto.eddsa.spec.EdDSAPublicKeySpec;
|
||||||
|
|
||||||
|
import org.briarproject.bramble.api.crypto.PrivateKey;
|
||||||
|
import org.briarproject.bramble.api.crypto.PublicKey;
|
||||||
|
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||||
|
|
||||||
|
import java.security.GeneralSecurityException;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
import java.security.Provider;
|
||||||
|
import java.security.SignatureException;
|
||||||
|
|
||||||
|
import static net.i2p.crypto.eddsa.EdDSAEngine.SIGNATURE_ALGORITHM;
|
||||||
|
|
||||||
|
@NotNullByDefault
|
||||||
|
class EdSignature implements Signature {
|
||||||
|
|
||||||
|
private static final Provider PROVIDER = new EdDSASecurityProvider();
|
||||||
|
|
||||||
|
private static final EdDSANamedCurveSpec CURVE_SPEC =
|
||||||
|
EdDSANamedCurveTable.getByName("Ed25519");
|
||||||
|
|
||||||
|
private final java.security.Signature signature;
|
||||||
|
|
||||||
|
EdSignature() {
|
||||||
|
try {
|
||||||
|
signature = java.security.Signature
|
||||||
|
.getInstance(SIGNATURE_ALGORITHM, PROVIDER);
|
||||||
|
} catch (NoSuchAlgorithmException e) {
|
||||||
|
throw new AssertionError(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initSign(PrivateKey k) throws GeneralSecurityException {
|
||||||
|
if (!(k instanceof EdPrivateKey))
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
EdDSAPrivateKey privateKey = new EdDSAPrivateKey(
|
||||||
|
new EdDSAPrivateKeySpec(k.getEncoded(), CURVE_SPEC));
|
||||||
|
signature.initSign(privateKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initVerify(PublicKey k) throws GeneralSecurityException {
|
||||||
|
if (!(k instanceof EdPublicKey))
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
EdDSAPublicKey publicKey = new EdDSAPublicKey(
|
||||||
|
new EdDSAPublicKeySpec(k.getEncoded(), CURVE_SPEC));
|
||||||
|
signature.initVerify(publicKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void update(byte b) {
|
||||||
|
try {
|
||||||
|
signature.update(b);
|
||||||
|
} catch (SignatureException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void update(byte[] b) {
|
||||||
|
try {
|
||||||
|
signature.update(b);
|
||||||
|
} catch (SignatureException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void update(byte[] b, int off, int len) {
|
||||||
|
try {
|
||||||
|
signature.update(b, off, len);
|
||||||
|
} catch (SignatureException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte[] sign() {
|
||||||
|
try {
|
||||||
|
return signature.sign();
|
||||||
|
} catch (SignatureException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean verify(byte[] sig) {
|
||||||
|
try {
|
||||||
|
return signature.verify(sig);
|
||||||
|
} catch (SignatureException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
package org.briarproject.bramble.crypto;
|
||||||
|
|
||||||
|
import org.briarproject.bramble.api.crypto.KeyPair;
|
||||||
|
|
||||||
|
import java.security.GeneralSecurityException;
|
||||||
|
|
||||||
|
public class EcdsaSignatureTest extends SignatureTest {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected KeyPair generateKeyPair() {
|
||||||
|
return crypto.generateSignatureKeyPair();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected byte[] sign(String label, byte[] toSign, byte[] privateKey)
|
||||||
|
throws GeneralSecurityException {
|
||||||
|
return crypto.sign(label, toSign, privateKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean verify(String label, byte[] signedData, byte[] publicKey,
|
||||||
|
byte[] signature) throws GeneralSecurityException {
|
||||||
|
return crypto.verify(label, signedData, publicKey, signature);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
package org.briarproject.bramble.crypto;
|
||||||
|
|
||||||
|
import org.briarproject.bramble.api.crypto.KeyPair;
|
||||||
|
|
||||||
|
import java.security.GeneralSecurityException;
|
||||||
|
|
||||||
|
public class EdSignatureTest extends SignatureTest {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected KeyPair generateKeyPair() {
|
||||||
|
return crypto.generateEdKeyPair();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected byte[] sign(String label, byte[] toSign, byte[] privateKey)
|
||||||
|
throws GeneralSecurityException {
|
||||||
|
return crypto.signEd(label, toSign, privateKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean verify(String label, byte[] signedData, byte[] publicKey,
|
||||||
|
byte[] signature) throws GeneralSecurityException {
|
||||||
|
return crypto.verifyEd(label, signedData, publicKey, signature);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -8,23 +8,32 @@ import org.briarproject.bramble.test.TestUtils;
|
|||||||
import org.briarproject.bramble.util.StringUtils;
|
import org.briarproject.bramble.util.StringUtils;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.security.GeneralSecurityException;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
import static org.junit.Assert.assertArrayEquals;
|
import static org.junit.Assert.assertArrayEquals;
|
||||||
import static org.junit.Assert.assertFalse;
|
import static org.junit.Assert.assertFalse;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
public class SignatureTest extends BrambleTestCase {
|
public abstract class SignatureTest extends BrambleTestCase {
|
||||||
|
|
||||||
private final CryptoComponent crypto;
|
protected final CryptoComponent crypto;
|
||||||
|
|
||||||
private final byte[] publicKey, privateKey;
|
private final byte[] publicKey, privateKey;
|
||||||
private final String label = StringUtils.getRandomString(42);
|
private final String label = StringUtils.getRandomString(42);
|
||||||
private final byte[] inputBytes = TestUtils.getRandomBytes(123);
|
private final byte[] inputBytes = TestUtils.getRandomBytes(123);
|
||||||
|
|
||||||
public SignatureTest() {
|
protected abstract KeyPair generateKeyPair();
|
||||||
|
|
||||||
|
protected abstract byte[] sign(String label, byte[] toSign,
|
||||||
|
byte[] privateKey) throws GeneralSecurityException;
|
||||||
|
|
||||||
|
protected abstract boolean verify(String label, byte[] signedData,
|
||||||
|
byte[] publicKey, byte[] signature) throws GeneralSecurityException;
|
||||||
|
|
||||||
|
SignatureTest() {
|
||||||
crypto = new CryptoComponentImpl(new TestSecureRandomProvider());
|
crypto = new CryptoComponentImpl(new TestSecureRandomProvider());
|
||||||
KeyPair k = crypto.generateSignatureKeyPair();
|
KeyPair k = generateKeyPair();
|
||||||
publicKey = k.getPublic().getEncoded();
|
publicKey = k.getPublic().getEncoded();
|
||||||
privateKey = k.getPrivate().getEncoded();
|
privateKey = k.getPrivate().getEncoded();
|
||||||
}
|
}
|
||||||
@@ -33,19 +42,19 @@ public class SignatureTest extends BrambleTestCase {
|
|||||||
public void testIdenticalKeysAndInputsProduceIdenticalSignatures()
|
public void testIdenticalKeysAndInputsProduceIdenticalSignatures()
|
||||||
throws Exception {
|
throws Exception {
|
||||||
// Calculate the Signature twice - the results should be identical
|
// Calculate the Signature twice - the results should be identical
|
||||||
byte[] sig1 = crypto.sign(label, inputBytes, privateKey);
|
byte[] sig1 = sign(label, inputBytes, privateKey);
|
||||||
byte[] sig2 = crypto.sign(label, inputBytes, privateKey);
|
byte[] sig2 = sign(label, inputBytes, privateKey);
|
||||||
assertArrayEquals(sig1, sig2);
|
assertArrayEquals(sig1, sig2);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDifferentKeysProduceDifferentSignatures() throws Exception {
|
public void testDifferentKeysProduceDifferentSignatures() throws Exception {
|
||||||
// Generate second private key
|
// Generate second private key
|
||||||
KeyPair k2 = crypto.generateSignatureKeyPair();
|
KeyPair k2 = generateKeyPair();
|
||||||
byte[] privateKey2 = k2.getPrivate().getEncoded();
|
byte[] privateKey2 = k2.getPrivate().getEncoded();
|
||||||
// Calculate the signature with each key
|
// Calculate the signature with each key
|
||||||
byte[] sig1 = crypto.sign(label, inputBytes, privateKey);
|
byte[] sig1 = sign(label, inputBytes, privateKey);
|
||||||
byte[] sig2 = crypto.sign(label, inputBytes, privateKey2);
|
byte[] sig2 = sign(label, inputBytes, privateKey2);
|
||||||
assertFalse(Arrays.equals(sig1, sig2));
|
assertFalse(Arrays.equals(sig1, sig2));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -56,8 +65,8 @@ public class SignatureTest extends BrambleTestCase {
|
|||||||
byte[] inputBytes2 = TestUtils.getRandomBytes(123);
|
byte[] inputBytes2 = TestUtils.getRandomBytes(123);
|
||||||
// Calculate the signature with different inputs
|
// Calculate the signature with different inputs
|
||||||
// the results should be different
|
// the results should be different
|
||||||
byte[] sig1 = crypto.sign(label, inputBytes, privateKey);
|
byte[] sig1 = sign(label, inputBytes, privateKey);
|
||||||
byte[] sig2 = crypto.sign(label, inputBytes2, privateKey);
|
byte[] sig2 = sign(label, inputBytes2, privateKey);
|
||||||
assertFalse(Arrays.equals(sig1, sig2));
|
assertFalse(Arrays.equals(sig1, sig2));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -68,25 +77,25 @@ public class SignatureTest extends BrambleTestCase {
|
|||||||
String label2 = StringUtils.getRandomString(42);
|
String label2 = StringUtils.getRandomString(42);
|
||||||
// Calculate the signature with different inputs
|
// Calculate the signature with different inputs
|
||||||
// the results should be different
|
// the results should be different
|
||||||
byte[] sig1 = crypto.sign(label, inputBytes, privateKey);
|
byte[] sig1 = sign(label, inputBytes, privateKey);
|
||||||
byte[] sig2 = crypto.sign(label2, inputBytes, privateKey);
|
byte[] sig2 = sign(label2, inputBytes, privateKey);
|
||||||
assertFalse(Arrays.equals(sig1, sig2));
|
assertFalse(Arrays.equals(sig1, sig2));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSignatureVerification() throws Exception {
|
public void testSignatureVerification() throws Exception {
|
||||||
byte[] sig = crypto.sign(label, inputBytes, privateKey);
|
byte[] sig = sign(label, inputBytes, privateKey);
|
||||||
assertTrue(crypto.verify(label, inputBytes, publicKey, sig));
|
assertTrue(verify(label, inputBytes, publicKey, sig));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDifferentKeyFailsVerification() throws Exception {
|
public void testDifferentKeyFailsVerification() throws Exception {
|
||||||
// Generate second private key
|
// Generate second private key
|
||||||
KeyPair k2 = crypto.generateSignatureKeyPair();
|
KeyPair k2 = generateKeyPair();
|
||||||
byte[] privateKey2 = k2.getPrivate().getEncoded();
|
byte[] privateKey2 = k2.getPrivate().getEncoded();
|
||||||
// calculate the signature with different key, should fail to verify
|
// calculate the signature with different key, should fail to verify
|
||||||
byte[] sig = crypto.sign(label, inputBytes, privateKey2);
|
byte[] sig = sign(label, inputBytes, privateKey2);
|
||||||
assertFalse(crypto.verify(label, inputBytes, publicKey, sig));
|
assertFalse(verify(label, inputBytes, publicKey, sig));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -94,8 +103,8 @@ public class SignatureTest extends BrambleTestCase {
|
|||||||
// Generate a second input
|
// Generate a second input
|
||||||
byte[] inputBytes2 = TestUtils.getRandomBytes(123);
|
byte[] inputBytes2 = TestUtils.getRandomBytes(123);
|
||||||
// calculate the signature with different input, should fail to verify
|
// calculate the signature with different input, should fail to verify
|
||||||
byte[] sig = crypto.sign(label, inputBytes, privateKey);
|
byte[] sig = sign(label, inputBytes, privateKey);
|
||||||
assertFalse(crypto.verify(label, inputBytes2, publicKey, sig));
|
assertFalse(verify(label, inputBytes2, publicKey, sig));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -103,8 +112,8 @@ public class SignatureTest extends BrambleTestCase {
|
|||||||
// Generate a second label
|
// Generate a second label
|
||||||
String label2 = StringUtils.getRandomString(42);
|
String label2 = StringUtils.getRandomString(42);
|
||||||
// calculate the signature with different label, should fail to verify
|
// calculate the signature with different label, should fail to verify
|
||||||
byte[] sig = crypto.sign(label, inputBytes, privateKey);
|
byte[] sig = sign(label, inputBytes, privateKey);
|
||||||
assertFalse(crypto.verify(label2, inputBytes, publicKey, sig));
|
assertFalse(verify(label2, inputBytes, publicKey, sig));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ dependencyVerification {
|
|||||||
'com.madgag.spongycastle:core:1.58.0.0:core-1.58.0.0.jar:199617dd5698c5a9312b898c0a4cec7ce9dd8649d07f65d91629f58229d72728',
|
'com.madgag.spongycastle:core:1.58.0.0:core-1.58.0.0.jar:199617dd5698c5a9312b898c0a4cec7ce9dd8649d07f65d91629f58229d72728',
|
||||||
'javax.inject:javax.inject:1:javax.inject-1.jar:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff',
|
'javax.inject:javax.inject:1:javax.inject-1.jar:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff',
|
||||||
'junit:junit:4.12:junit-4.12.jar:59721f0805e223d84b90677887d9ff567dc534d7c502ca903c0c2b17f05c116a',
|
'junit:junit:4.12:junit-4.12.jar:59721f0805e223d84b90677887d9ff567dc534d7c502ca903c0c2b17f05c116a',
|
||||||
|
'net.i2p.crypto:eddsa:0.2.0:eddsa-0.2.0.jar:a7cb1b85c16e2f0730b9204106929a1d9aaae1df728adc7041a8b8b605692140',
|
||||||
'net.java.dev.jna:jna-platform:4.4.0:jna-platform-4.4.0.jar:e9dda9e884fc107eb6367710540789a12dfa8ad28be9326b22ca6e352e325499',
|
'net.java.dev.jna:jna-platform:4.4.0:jna-platform-4.4.0.jar:e9dda9e884fc107eb6367710540789a12dfa8ad28be9326b22ca6e352e325499',
|
||||||
'net.java.dev.jna:jna:4.4.0:jna-4.4.0.jar:c4dadeeecaa90c8847902082aee5eb107fcf59c5d0e63a17fcaf273c0e2d2bd1',
|
'net.java.dev.jna:jna:4.4.0:jna-4.4.0.jar:c4dadeeecaa90c8847902082aee5eb107fcf59c5d0e63a17fcaf273c0e2d2bd1',
|
||||||
'org.apache.ant:ant-launcher:1.9.4:ant-launcher-1.9.4.jar:7bccea20b41801ca17bcbc909a78c835d0f443f12d639c77bd6ae3d05861608d',
|
'org.apache.ant:ant-launcher:1.9.4:ant-launcher-1.9.4.jar:7bccea20b41801ca17bcbc909a78c835d0f443f12d639c77bd6ae3d05861608d',
|
||||||
|
|||||||
@@ -99,6 +99,7 @@ dependencyVerification {
|
|||||||
'nekohtml:xercesMinimal:1.9.6.2:xercesMinimal-1.9.6.2.jar:95b8b357d19f63797dd7d67622fd3f18374d64acbc6584faba1c7759a31e8438',
|
'nekohtml:xercesMinimal:1.9.6.2:xercesMinimal-1.9.6.2.jar:95b8b357d19f63797dd7d67622fd3f18374d64acbc6584faba1c7759a31e8438',
|
||||||
'net.bytebuddy:byte-buddy-agent:1.6.14:byte-buddy-agent-1.6.14.jar:c141a2d6809c3eeff4a43d25992826abccebdd4b793af3e7a5f346e88ae73a33',
|
'net.bytebuddy:byte-buddy-agent:1.6.14:byte-buddy-agent-1.6.14.jar:c141a2d6809c3eeff4a43d25992826abccebdd4b793af3e7a5f346e88ae73a33',
|
||||||
'net.bytebuddy:byte-buddy:1.6.14:byte-buddy-1.6.14.jar:917758b3c651e278a15a029ba1d42dbf802d8b0e1fe2aa4b81c5750c64f461c1',
|
'net.bytebuddy:byte-buddy:1.6.14:byte-buddy-1.6.14.jar:917758b3c651e278a15a029ba1d42dbf802d8b0e1fe2aa4b81c5750c64f461c1',
|
||||||
|
'net.i2p.crypto:eddsa:0.2.0:eddsa-0.2.0.jar:a7cb1b85c16e2f0730b9204106929a1d9aaae1df728adc7041a8b8b605692140',
|
||||||
'org.apache.ant:ant-launcher:1.9.4:ant-launcher-1.9.4.jar:7bccea20b41801ca17bcbc909a78c835d0f443f12d639c77bd6ae3d05861608d',
|
'org.apache.ant:ant-launcher:1.9.4:ant-launcher-1.9.4.jar:7bccea20b41801ca17bcbc909a78c835d0f443f12d639c77bd6ae3d05861608d',
|
||||||
'org.apache.ant:ant:1.9.4:ant-1.9.4.jar:649ae0730251de07b8913f49286d46bba7b92d47c5f332610aa426c4f02161d8',
|
'org.apache.ant:ant:1.9.4:ant-1.9.4.jar:649ae0730251de07b8913f49286d46bba7b92d47c5f332610aa426c4f02161d8',
|
||||||
'org.apache.maven.wagon:wagon-file:1.0-beta-6:wagon-file-1.0-beta-6.jar:7298feeb36ff14dd933c38e62585fb9973fea32fb3c4bc5379428cb1aac5dd3c',
|
'org.apache.maven.wagon:wagon-file:1.0-beta-6:wagon-file-1.0-beta-6.jar:7298feeb36ff14dd933c38e62585fb9973fea32fb3c4bc5379428cb1aac5dd3c',
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ dependencyVerification {
|
|||||||
'com.squareup.okio:okio:1.13.0:okio-1.13.0.jar:734269c3ebc5090e3b23566db558f421f0b4027277c79ad5d176b8ec168bb850',
|
'com.squareup.okio:okio:1.13.0:okio-1.13.0.jar:734269c3ebc5090e3b23566db558f421f0b4027277c79ad5d176b8ec168bb850',
|
||||||
'javax.inject:javax.inject:1:javax.inject-1.jar:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff',
|
'javax.inject:javax.inject:1:javax.inject-1.jar:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff',
|
||||||
'junit:junit:4.12:junit-4.12.jar:59721f0805e223d84b90677887d9ff567dc534d7c502ca903c0c2b17f05c116a',
|
'junit:junit:4.12:junit-4.12.jar:59721f0805e223d84b90677887d9ff567dc534d7c502ca903c0c2b17f05c116a',
|
||||||
|
'net.i2p.crypto:eddsa:0.2.0:eddsa-0.2.0.jar:a7cb1b85c16e2f0730b9204106929a1d9aaae1df728adc7041a8b8b605692140',
|
||||||
'net.jodah:concurrentunit:0.4.2:concurrentunit-0.4.2.jar:5583078e1acf91734939e985bc9e7ee947b0e93a8eef679da6bb07bbeb47ced3',
|
'net.jodah:concurrentunit:0.4.2:concurrentunit-0.4.2.jar:5583078e1acf91734939e985bc9e7ee947b0e93a8eef679da6bb07bbeb47ced3',
|
||||||
'org.apache.ant:ant-launcher:1.9.4:ant-launcher-1.9.4.jar:7bccea20b41801ca17bcbc909a78c835d0f443f12d639c77bd6ae3d05861608d',
|
'org.apache.ant:ant-launcher:1.9.4:ant-launcher-1.9.4.jar:7bccea20b41801ca17bcbc909a78c835d0f443f12d639c77bd6ae3d05861608d',
|
||||||
'org.apache.ant:ant:1.9.4:ant-1.9.4.jar:649ae0730251de07b8913f49286d46bba7b92d47c5f332610aa426c4f02161d8',
|
'org.apache.ant:ant:1.9.4:ant-1.9.4.jar:649ae0730251de07b8913f49286d46bba7b92d47c5f332610aa426c4f02161d8',
|
||||||
|
|||||||
Reference in New Issue
Block a user