mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-19 22:29:53 +01:00
Separated key agreement algorithm from signature algorithm.
This commit is contained in:
@@ -23,9 +23,11 @@ public interface CryptoComponent {
|
|||||||
|
|
||||||
byte[] deriveNextSecret(byte[] secret, int index, long connection);
|
byte[] deriveNextSecret(byte[] secret, int index, long connection);
|
||||||
|
|
||||||
KeyPair generateKeyPair();
|
KeyPair generateAgreementKeyPair();
|
||||||
|
|
||||||
KeyParser getKeyParser();
|
KeyPair generateSignatureKeyPair();
|
||||||
|
|
||||||
|
KeyParser getSignatureKeyParser();
|
||||||
|
|
||||||
ErasableKey generateTestKey();
|
ErasableKey generateTestKey();
|
||||||
|
|
||||||
|
|||||||
@@ -30,14 +30,16 @@ import com.google.inject.Inject;
|
|||||||
class CryptoComponentImpl implements CryptoComponent {
|
class CryptoComponentImpl implements CryptoComponent {
|
||||||
|
|
||||||
private static final String PROVIDER = "BC";
|
private static final String PROVIDER = "BC";
|
||||||
private static final String KEY_PAIR_ALGO = "ECDSA";
|
private static final String AGREEMENT_KEY_PAIR_ALGO = "ECDH";
|
||||||
private static final int KEY_PAIR_BITS = 384;
|
private static final int AGREEMENT_KEY_PAIR_BITS = 384;
|
||||||
private static final String KEY_AGREEMENT_ALGO = "ECDHC";
|
private static final String AGREEMENT_ALGO = "ECDHC";
|
||||||
private static final String SECRET_KEY_ALGO = "AES";
|
private static final String SECRET_KEY_ALGO = "AES";
|
||||||
private static final int SECRET_KEY_BYTES = 32; // 256 bits
|
private static final int SECRET_KEY_BYTES = 32; // 256 bits
|
||||||
private static final int KEY_DERIVATION_IV_BYTES = 16; // 128 bits
|
private static final int KEY_DERIVATION_IV_BYTES = 16; // 128 bits
|
||||||
private static final String KEY_DERIVATION_ALGO = "AES/CTR/NoPadding";
|
private static final String KEY_DERIVATION_ALGO = "AES/CTR/NoPadding";
|
||||||
private static final String DIGEST_ALGO = "SHA-384";
|
private static final String DIGEST_ALGO = "SHA-384";
|
||||||
|
private static final String SIGNATURE_KEY_PAIR_ALGO = "ECDSA";
|
||||||
|
private static final int SIGNATURE_KEY_PAIR_BITS = 384;
|
||||||
private static final String SIGNATURE_ALGO = "ECDSA";
|
private static final String SIGNATURE_ALGO = "ECDSA";
|
||||||
private static final String TAG_CIPHER_ALGO = "AES/ECB/NoPadding";
|
private static final String TAG_CIPHER_ALGO = "AES/ECB/NoPadding";
|
||||||
private static final String FRAME_CIPHER_ALGO = "AES/CTR/NoPadding";
|
private static final String FRAME_CIPHER_ALGO = "AES/CTR/NoPadding";
|
||||||
@@ -59,18 +61,25 @@ class CryptoComponentImpl implements CryptoComponent {
|
|||||||
private static final byte[] KEY_DERIVATION_INPUT =
|
private static final byte[] KEY_DERIVATION_INPUT =
|
||||||
new byte[SECRET_KEY_BYTES];
|
new byte[SECRET_KEY_BYTES];
|
||||||
|
|
||||||
private final KeyParser keyParser;
|
private final KeyParser agreementKeyParser, signatureKeyParser;
|
||||||
private final KeyPairGenerator keyPairGenerator;
|
private final KeyPairGenerator agreementKeyPairGenerator;
|
||||||
|
private final KeyPairGenerator signatureKeyPairGenerator;
|
||||||
private final SecureRandom secureRandom;
|
private final SecureRandom secureRandom;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
CryptoComponentImpl() {
|
CryptoComponentImpl() {
|
||||||
Security.addProvider(new BouncyCastleProvider());
|
Security.addProvider(new BouncyCastleProvider());
|
||||||
try {
|
try {
|
||||||
keyParser = new KeyParserImpl(KEY_PAIR_ALGO, PROVIDER);
|
agreementKeyParser = new KeyParserImpl(AGREEMENT_KEY_PAIR_ALGO,
|
||||||
keyPairGenerator = KeyPairGenerator.getInstance(KEY_PAIR_ALGO,
|
|
||||||
PROVIDER);
|
PROVIDER);
|
||||||
keyPairGenerator.initialize(KEY_PAIR_BITS);
|
signatureKeyParser = new KeyParserImpl(SIGNATURE_KEY_PAIR_ALGO,
|
||||||
|
PROVIDER);
|
||||||
|
agreementKeyPairGenerator = KeyPairGenerator.getInstance(
|
||||||
|
AGREEMENT_KEY_PAIR_ALGO, PROVIDER);
|
||||||
|
agreementKeyPairGenerator.initialize(AGREEMENT_KEY_PAIR_BITS);
|
||||||
|
signatureKeyPairGenerator = KeyPairGenerator.getInstance(
|
||||||
|
SIGNATURE_KEY_PAIR_ALGO, PROVIDER);
|
||||||
|
signatureKeyPairGenerator.initialize(SIGNATURE_KEY_PAIR_BITS);
|
||||||
} catch(GeneralSecurityException e) {
|
} catch(GeneralSecurityException e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
@@ -130,7 +139,8 @@ class CryptoComponentImpl implements CryptoComponent {
|
|||||||
byte[] theirPublicKey, PrivateKey ourPrivateKey, int invitationCode,
|
byte[] theirPublicKey, PrivateKey ourPrivateKey, int invitationCode,
|
||||||
boolean initiator) {
|
boolean initiator) {
|
||||||
try {
|
try {
|
||||||
PublicKey theirPublic = keyParser.parsePublicKey(theirPublicKey);
|
PublicKey theirPublic = agreementKeyParser.parsePublicKey(
|
||||||
|
theirPublicKey);
|
||||||
MessageDigest messageDigest = getMessageDigest();
|
MessageDigest messageDigest = getMessageDigest();
|
||||||
byte[] ourHash = messageDigest.digest(ourPublicKey);
|
byte[] ourHash = messageDigest.digest(ourPublicKey);
|
||||||
byte[] theirHash = messageDigest.digest(theirPublicKey);
|
byte[] theirHash = messageDigest.digest(theirPublicKey);
|
||||||
@@ -147,8 +157,8 @@ class CryptoComponentImpl implements CryptoComponent {
|
|||||||
byte[] publicInfo = new byte[4];
|
byte[] publicInfo = new byte[4];
|
||||||
ByteUtils.writeUint32(invitationCode, publicInfo, 0);
|
ByteUtils.writeUint32(invitationCode, publicInfo, 0);
|
||||||
// The raw secret comes from the key agreement algorithm
|
// The raw secret comes from the key agreement algorithm
|
||||||
KeyAgreement keyAgreement = KeyAgreement.getInstance(
|
KeyAgreement keyAgreement = KeyAgreement.getInstance(AGREEMENT_ALGO,
|
||||||
KEY_AGREEMENT_ALGO, PROVIDER);
|
PROVIDER);
|
||||||
keyAgreement.init(ourPrivateKey);
|
keyAgreement.init(ourPrivateKey);
|
||||||
keyAgreement.doPhase(theirPublic, true);
|
keyAgreement.doPhase(theirPublic, true);
|
||||||
byte[] rawSecret = keyAgreement.generateSecret();
|
byte[] rawSecret = keyAgreement.generateSecret();
|
||||||
@@ -220,12 +230,16 @@ class CryptoComponentImpl implements CryptoComponent {
|
|||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
|
|
||||||
public KeyPair generateKeyPair() {
|
public KeyPair generateAgreementKeyPair() {
|
||||||
return keyPairGenerator.generateKeyPair();
|
return agreementKeyPairGenerator.generateKeyPair();
|
||||||
}
|
}
|
||||||
|
|
||||||
public KeyParser getKeyParser() {
|
public KeyPair generateSignatureKeyPair() {
|
||||||
return keyParser;
|
return signatureKeyPairGenerator.generateKeyPair();
|
||||||
|
}
|
||||||
|
|
||||||
|
public KeyParser getSignatureKeyParser() {
|
||||||
|
return signatureKeyParser;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ErasableKey generateTestKey() {
|
public ErasableKey generateTestKey() {
|
||||||
|
|||||||
@@ -106,7 +106,7 @@ class InvitationStarterImpl implements InvitationStarter {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Use an ephemeral key pair for key agreement
|
// Use an ephemeral key pair for key agreement
|
||||||
KeyPair ourKeyPair = crypto.generateKeyPair();
|
KeyPair ourKeyPair = crypto.generateAgreementKeyPair();
|
||||||
MessageDigest messageDigest = crypto.getMessageDigest();
|
MessageDigest messageDigest = crypto.getMessageDigest();
|
||||||
byte[] ourKey = ourKeyPair.getPublic().getEncoded();
|
byte[] ourKey = ourKeyPair.getPublic().getEncoded();
|
||||||
byte[] ourHash = messageDigest.digest(ourKey);
|
byte[] ourHash = messageDigest.digest(ourKey);
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ class UnverifiedBatchImpl implements UnverifiedBatch {
|
|||||||
// Verify the author's signature, if there is one
|
// Verify the author's signature, if there is one
|
||||||
Author author = m.getAuthor();
|
Author author = m.getAuthor();
|
||||||
if(author != null) {
|
if(author != null) {
|
||||||
if(keyParser == null) keyParser = crypto.getKeyParser();
|
if(keyParser == null) keyParser = crypto.getSignatureKeyParser();
|
||||||
PublicKey k = keyParser.parsePublicKey(author.getPublicKey());
|
PublicKey k = keyParser.parsePublicKey(author.getPublicKey());
|
||||||
if(signature == null) signature = crypto.getSignature();
|
if(signature == null) signature = crypto.getSignature();
|
||||||
signature.initVerify(k);
|
signature.initVerify(k);
|
||||||
@@ -68,7 +68,7 @@ class UnverifiedBatchImpl implements UnverifiedBatch {
|
|||||||
// Verify the group's signature, if there is one
|
// Verify the group's signature, if there is one
|
||||||
Group group = m.getGroup();
|
Group group = m.getGroup();
|
||||||
if(group != null && group.getPublicKey() != null) {
|
if(group != null && group.getPublicKey() != null) {
|
||||||
if(keyParser == null) keyParser = crypto.getKeyParser();
|
if(keyParser == null) keyParser = crypto.getSignatureKeyParser();
|
||||||
PublicKey k = keyParser.parsePublicKey(group.getPublicKey());
|
PublicKey k = keyParser.parsePublicKey(group.getPublicKey());
|
||||||
if(signature == null) signature = crypto.getSignature();
|
if(signature == null) signature = crypto.getSignature();
|
||||||
signature.initVerify(k);
|
signature.initVerify(k);
|
||||||
|
|||||||
@@ -100,12 +100,12 @@ public class ProtocolIntegrationTest extends BriarTestCase {
|
|||||||
// Create two groups: one restricted, one unrestricted
|
// Create two groups: one restricted, one unrestricted
|
||||||
GroupFactory groupFactory = i.getInstance(GroupFactory.class);
|
GroupFactory groupFactory = i.getInstance(GroupFactory.class);
|
||||||
group = groupFactory.createGroup("Unrestricted group", null);
|
group = groupFactory.createGroup("Unrestricted group", null);
|
||||||
KeyPair groupKeyPair = crypto.generateKeyPair();
|
KeyPair groupKeyPair = crypto.generateSignatureKeyPair();
|
||||||
group1 = groupFactory.createGroup("Restricted group",
|
group1 = groupFactory.createGroup("Restricted group",
|
||||||
groupKeyPair.getPublic().getEncoded());
|
groupKeyPair.getPublic().getEncoded());
|
||||||
// Create an author
|
// Create an author
|
||||||
AuthorFactory authorFactory = i.getInstance(AuthorFactory.class);
|
AuthorFactory authorFactory = i.getInstance(AuthorFactory.class);
|
||||||
KeyPair authorKeyPair = crypto.generateKeyPair();
|
KeyPair authorKeyPair = crypto.generateSignatureKeyPair();
|
||||||
author = authorFactory.createAuthor(authorName,
|
author = authorFactory.createAuthor(authorName,
|
||||||
authorKeyPair.getPublic().getEncoded());
|
authorKeyPair.getPublic().getEncoded());
|
||||||
// Create two messages to each group: one anonymous, one pseudonymous
|
// Create two messages to each group: one anonymous, one pseudonymous
|
||||||
|
|||||||
44
test/net/sf/briar/plugins/InvitationStarterImplTest.java
Normal file
44
test/net/sf/briar/plugins/InvitationStarterImplTest.java
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
package net.sf.briar.plugins;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertArrayEquals;
|
||||||
|
|
||||||
|
import java.security.KeyPair;
|
||||||
|
import java.security.PrivateKey;
|
||||||
|
|
||||||
|
import net.sf.briar.BriarTestCase;
|
||||||
|
import net.sf.briar.api.crypto.CryptoComponent;
|
||||||
|
import net.sf.briar.crypto.CryptoModule;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import com.google.inject.Guice;
|
||||||
|
import com.google.inject.Injector;
|
||||||
|
|
||||||
|
public class InvitationStarterImplTest extends BriarTestCase {
|
||||||
|
|
||||||
|
private final CryptoComponent crypto;
|
||||||
|
|
||||||
|
public InvitationStarterImplTest() {
|
||||||
|
super();
|
||||||
|
Injector i = Guice.createInjector(new CryptoModule());
|
||||||
|
crypto = i.getInstance(CryptoComponent.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testKeyAgreement() {
|
||||||
|
KeyPair a = crypto.generateAgreementKeyPair();
|
||||||
|
byte[] aPub = a.getPublic().getEncoded();
|
||||||
|
PrivateKey aPriv = a.getPrivate();
|
||||||
|
KeyPair b = crypto.generateAgreementKeyPair();
|
||||||
|
byte[] bPub = b.getPublic().getEncoded();
|
||||||
|
PrivateKey bPriv = b.getPrivate();
|
||||||
|
byte[][] aSecrets = crypto.deriveInitialSecrets(aPub, bPub, aPriv, 123,
|
||||||
|
true);
|
||||||
|
byte[][] bSecrets = crypto.deriveInitialSecrets(bPub, aPub, bPriv, 123,
|
||||||
|
false);
|
||||||
|
assertEquals(2, aSecrets.length);
|
||||||
|
assertEquals(2, bSecrets.length);
|
||||||
|
assertArrayEquals(aSecrets[0], bSecrets[0]);
|
||||||
|
assertArrayEquals(aSecrets[1], bSecrets[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -108,8 +108,8 @@ public class ConstantsTest extends BriarTestCase {
|
|||||||
byte[] authorPublic = new byte[MAX_PUBLIC_KEY_LENGTH];
|
byte[] authorPublic = new byte[MAX_PUBLIC_KEY_LENGTH];
|
||||||
Author author = authorFactory.createAuthor(authorName, authorPublic);
|
Author author = authorFactory.createAuthor(authorName, authorPublic);
|
||||||
// Create a maximum-length message
|
// Create a maximum-length message
|
||||||
PrivateKey groupPrivate = crypto.generateKeyPair().getPrivate();
|
PrivateKey groupPrivate = crypto.generateSignatureKeyPair().getPrivate();
|
||||||
PrivateKey authorPrivate = crypto.generateKeyPair().getPrivate();
|
PrivateKey authorPrivate = crypto.generateSignatureKeyPair().getPrivate();
|
||||||
String subject = createRandomString(MAX_SUBJECT_LENGTH);
|
String subject = createRandomString(MAX_SUBJECT_LENGTH);
|
||||||
byte[] body = new byte[MAX_BODY_LENGTH];
|
byte[] body = new byte[MAX_BODY_LENGTH];
|
||||||
Message message = messageFactory.createMessage(null, group,
|
Message message = messageFactory.createMessage(null, group,
|
||||||
|
|||||||
@@ -122,8 +122,8 @@ public class UnverifiedBatchImplTest extends BriarTestCase {
|
|||||||
@Test
|
@Test
|
||||||
public void testSignatures() throws Exception {
|
public void testSignatures() throws Exception {
|
||||||
final int signedByAuthor = 100, signedByGroup = 110;
|
final int signedByAuthor = 100, signedByGroup = 110;
|
||||||
final KeyPair authorKeyPair = crypto.generateKeyPair();
|
final KeyPair authorKeyPair = crypto.generateSignatureKeyPair();
|
||||||
final KeyPair groupKeyPair = crypto.generateKeyPair();
|
final KeyPair groupKeyPair = crypto.generateSignatureKeyPair();
|
||||||
Signature signature = crypto.getSignature();
|
Signature signature = crypto.getSignature();
|
||||||
// Calculate the expected author and group signatures
|
// Calculate the expected author and group signatures
|
||||||
signature.initSign(authorKeyPair.getPrivate());
|
signature.initSign(authorKeyPair.getPrivate());
|
||||||
@@ -202,7 +202,7 @@ public class UnverifiedBatchImplTest extends BriarTestCase {
|
|||||||
@Test
|
@Test
|
||||||
public void testExceptionThrownIfMessageIsModified() throws Exception {
|
public void testExceptionThrownIfMessageIsModified() throws Exception {
|
||||||
final int signedByAuthor = 100;
|
final int signedByAuthor = 100;
|
||||||
final KeyPair authorKeyPair = crypto.generateKeyPair();
|
final KeyPair authorKeyPair = crypto.generateSignatureKeyPair();
|
||||||
Signature signature = crypto.getSignature();
|
Signature signature = crypto.getSignature();
|
||||||
// Calculate the expected author signature
|
// Calculate the expected author signature
|
||||||
signature.initSign(authorKeyPair.getPrivate());
|
signature.initSign(authorKeyPair.getPrivate());
|
||||||
|
|||||||
Reference in New Issue
Block a user