mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-15 20:29:52 +01:00
Merge branch '549-require-a-label-for-signing' into 'master'
Require a label for signing This adds a sign() and a verify() method to the CryptoComponent that take a mandatory label argument to ensure that signatures can't be repurposed. Closes #549 See merge request !419
This commit is contained in:
@@ -5,6 +5,7 @@ import net.jodah.concurrentunit.Waiter;
|
|||||||
import org.briarproject.api.clients.ClientHelper;
|
import org.briarproject.api.clients.ClientHelper;
|
||||||
import org.briarproject.api.clients.ContactGroupFactory;
|
import org.briarproject.api.clients.ContactGroupFactory;
|
||||||
import org.briarproject.api.clients.MessageTracker.GroupCount;
|
import org.briarproject.api.clients.MessageTracker.GroupCount;
|
||||||
|
import org.briarproject.api.contact.Contact;
|
||||||
import org.briarproject.api.contact.ContactId;
|
import org.briarproject.api.contact.ContactId;
|
||||||
import org.briarproject.api.contact.ContactManager;
|
import org.briarproject.api.contact.ContactManager;
|
||||||
import org.briarproject.api.crypto.CryptoComponent;
|
import org.briarproject.api.crypto.CryptoComponent;
|
||||||
@@ -29,7 +30,7 @@ import org.briarproject.api.privategroup.JoinMessageHeader;
|
|||||||
import org.briarproject.api.privategroup.PrivateGroup;
|
import org.briarproject.api.privategroup.PrivateGroup;
|
||||||
import org.briarproject.api.privategroup.PrivateGroupFactory;
|
import org.briarproject.api.privategroup.PrivateGroupFactory;
|
||||||
import org.briarproject.api.privategroup.PrivateGroupManager;
|
import org.briarproject.api.privategroup.PrivateGroupManager;
|
||||||
import org.briarproject.api.sync.Group;
|
import org.briarproject.api.privategroup.invitation.GroupInvitationFactory;
|
||||||
import org.briarproject.api.sync.GroupId;
|
import org.briarproject.api.sync.GroupId;
|
||||||
import org.briarproject.api.sync.MessageId;
|
import org.briarproject.api.sync.MessageId;
|
||||||
import org.briarproject.api.sync.SyncSession;
|
import org.briarproject.api.sync.SyncSession;
|
||||||
@@ -65,7 +66,7 @@ import static org.briarproject.api.privategroup.Visibility.INVISIBLE;
|
|||||||
import static org.briarproject.api.privategroup.Visibility.REVEALED_BY_CONTACT;
|
import static org.briarproject.api.privategroup.Visibility.REVEALED_BY_CONTACT;
|
||||||
import static org.briarproject.api.privategroup.Visibility.REVEALED_BY_US;
|
import static org.briarproject.api.privategroup.Visibility.REVEALED_BY_US;
|
||||||
import static org.briarproject.api.privategroup.Visibility.VISIBLE;
|
import static org.briarproject.api.privategroup.Visibility.VISIBLE;
|
||||||
import static org.briarproject.api.privategroup.invitation.GroupInvitationManager.CLIENT_ID;
|
import static org.briarproject.api.privategroup.invitation.GroupInvitationFactory.SIGNING_LABEL_INVITE;
|
||||||
import static org.briarproject.api.sync.Group.Visibility.SHARED;
|
import static org.briarproject.api.sync.Group.Visibility.SHARED;
|
||||||
import static org.briarproject.api.sync.ValidationManager.State.DELIVERED;
|
import static org.briarproject.api.sync.ValidationManager.State.DELIVERED;
|
||||||
import static org.briarproject.api.sync.ValidationManager.State.INVALID;
|
import static org.briarproject.api.sync.ValidationManager.State.INVALID;
|
||||||
@@ -103,6 +104,8 @@ public class PrivateGroupManagerTest extends BriarIntegrationTest {
|
|||||||
PrivateGroupFactory privateGroupFactory;
|
PrivateGroupFactory privateGroupFactory;
|
||||||
@Inject
|
@Inject
|
||||||
GroupMessageFactory groupMessageFactory;
|
GroupMessageFactory groupMessageFactory;
|
||||||
|
@Inject
|
||||||
|
GroupInvitationFactory groupInvitationFactory;
|
||||||
|
|
||||||
// objects accessed from background threads need to be volatile
|
// objects accessed from background threads need to be volatile
|
||||||
private volatile Waiter validationWaiter;
|
private volatile Waiter validationWaiter;
|
||||||
@@ -358,13 +361,10 @@ public class PrivateGroupManagerTest extends BriarIntegrationTest {
|
|||||||
// author1 joins privateGroup0 with wrong timestamp
|
// author1 joins privateGroup0 with wrong timestamp
|
||||||
joinTime = clock.currentTimeMillis();
|
joinTime = clock.currentTimeMillis();
|
||||||
long inviteTime = joinTime;
|
long inviteTime = joinTime;
|
||||||
Group invitationGroup = contactGroupFactory
|
Contact c1 = contactManager0.getContact(contactId1);
|
||||||
.createContactGroup(CLIENT_ID, author0.getId(),
|
byte[] creatorSignature = groupInvitationFactory
|
||||||
author1.getId());
|
.signInvitation(c1, privateGroup0.getId(), inviteTime,
|
||||||
BdfList toSign = BdfList.of(0, inviteTime, invitationGroup.getId(),
|
author0.getPrivateKey());
|
||||||
privateGroup0.getId());
|
|
||||||
byte[] creatorSignature =
|
|
||||||
clientHelper.sign(toSign, author0.getPrivateKey());
|
|
||||||
GroupMessage joinMsg1 = groupMessageFactory
|
GroupMessage joinMsg1 = groupMessageFactory
|
||||||
.createJoinMessage(privateGroup0.getId(), joinTime, author1,
|
.createJoinMessage(privateGroup0.getId(), joinTime, author1,
|
||||||
inviteTime, creatorSignature);
|
inviteTime, creatorSignature);
|
||||||
@@ -402,13 +402,11 @@ public class PrivateGroupManagerTest extends BriarIntegrationTest {
|
|||||||
// author0 joins privateGroup0 with wrong member's join message
|
// author0 joins privateGroup0 with wrong member's join message
|
||||||
long joinTime = clock.currentTimeMillis();
|
long joinTime = clock.currentTimeMillis();
|
||||||
long inviteTime = joinTime - 1;
|
long inviteTime = joinTime - 1;
|
||||||
Group invitationGroup = contactGroupFactory
|
BdfList toSign = groupInvitationFactory
|
||||||
.createContactGroup(CLIENT_ID, author0.getId(),
|
.createInviteToken(author0.getId(), author0.getId(),
|
||||||
author0.getId());
|
privateGroup0.getId(), inviteTime);
|
||||||
BdfList toSign = BdfList.of(0, inviteTime, invitationGroup.getId(),
|
byte[] creatorSignature = clientHelper
|
||||||
privateGroup0.getId());
|
.sign(SIGNING_LABEL_INVITE, toSign, author0.getPrivateKey());
|
||||||
byte[] creatorSignature =
|
|
||||||
clientHelper.sign(toSign, author0.getPrivateKey());
|
|
||||||
// join message should not include invite time and creator's signature
|
// join message should not include invite time and creator's signature
|
||||||
GroupMessage joinMsg0 = groupMessageFactory
|
GroupMessage joinMsg0 = groupMessageFactory
|
||||||
.createJoinMessage(privateGroup0.getId(), joinTime, author0,
|
.createJoinMessage(privateGroup0.getId(), joinTime, author0,
|
||||||
@@ -426,13 +424,11 @@ public class PrivateGroupManagerTest extends BriarIntegrationTest {
|
|||||||
// author1 joins privateGroup0 with wrong signature in join message
|
// author1 joins privateGroup0 with wrong signature in join message
|
||||||
joinTime = clock.currentTimeMillis();
|
joinTime = clock.currentTimeMillis();
|
||||||
inviteTime = joinTime - 1;
|
inviteTime = joinTime - 1;
|
||||||
invitationGroup = contactGroupFactory
|
|
||||||
.createContactGroup(CLIENT_ID, author0.getId(),
|
|
||||||
author1.getId());
|
|
||||||
toSign = BdfList.of(0, inviteTime, invitationGroup.getId(),
|
|
||||||
privateGroup0.getId());
|
|
||||||
// signature uses joiner's key, not creator's key
|
// signature uses joiner's key, not creator's key
|
||||||
creatorSignature = clientHelper.sign(toSign, author1.getPrivateKey());
|
Contact c1 = contactManager0.getContact(contactId1);
|
||||||
|
creatorSignature = groupInvitationFactory
|
||||||
|
.signInvitation(c1, privateGroup0.getId(), inviteTime,
|
||||||
|
author1.getPrivateKey());
|
||||||
GroupMessage joinMsg1 = groupMessageFactory
|
GroupMessage joinMsg1 = groupMessageFactory
|
||||||
.createJoinMessage(privateGroup0.getId(), joinTime, author1,
|
.createJoinMessage(privateGroup0.getId(), joinTime, author1,
|
||||||
inviteTime, creatorSignature);
|
inviteTime, creatorSignature);
|
||||||
@@ -529,13 +525,10 @@ public class PrivateGroupManagerTest extends BriarIntegrationTest {
|
|||||||
// author2 joins privateGroup0
|
// author2 joins privateGroup0
|
||||||
long joinTime = clock.currentTimeMillis();
|
long joinTime = clock.currentTimeMillis();
|
||||||
long inviteTime = joinTime - 1;
|
long inviteTime = joinTime - 1;
|
||||||
Group invitationGroup = contactGroupFactory
|
Contact c2 = contactManager0.getContact(contactId2);
|
||||||
.createContactGroup(CLIENT_ID, author0.getId(),
|
byte[] creatorSignature = groupInvitationFactory
|
||||||
author2.getId());
|
.signInvitation(c2, privateGroup0.getId(), inviteTime,
|
||||||
BdfList toSign = BdfList.of(0, inviteTime, invitationGroup.getId(),
|
author0.getPrivateKey());
|
||||||
privateGroup0.getId());
|
|
||||||
byte[] creatorSignature =
|
|
||||||
clientHelper.sign(toSign, author0.getPrivateKey());
|
|
||||||
GroupMessage joinMsg2 = groupMessageFactory
|
GroupMessage joinMsg2 = groupMessageFactory
|
||||||
.createJoinMessage(privateGroup0.getId(), joinTime, author2,
|
.createJoinMessage(privateGroup0.getId(), joinTime, author2,
|
||||||
inviteTime, creatorSignature);
|
inviteTime, creatorSignature);
|
||||||
@@ -753,13 +746,10 @@ public class PrivateGroupManagerTest extends BriarIntegrationTest {
|
|||||||
// author1 joins privateGroup0
|
// author1 joins privateGroup0
|
||||||
joinTime = clock.currentTimeMillis();
|
joinTime = clock.currentTimeMillis();
|
||||||
long inviteTime = joinTime - 1;
|
long inviteTime = joinTime - 1;
|
||||||
Group invitationGroup = contactGroupFactory
|
Contact c1 = contactManager0.getContact(contactId1);
|
||||||
.createContactGroup(CLIENT_ID, author0.getId(),
|
byte[] creatorSignature = groupInvitationFactory
|
||||||
author1.getId());
|
.signInvitation(c1, privateGroup0.getId(), inviteTime,
|
||||||
BdfList toSign = BdfList.of(0, inviteTime, invitationGroup.getId(),
|
author0.getPrivateKey());
|
||||||
privateGroup0.getId());
|
|
||||||
byte[] creatorSignature =
|
|
||||||
clientHelper.sign(toSign, author0.getPrivateKey());
|
|
||||||
GroupMessage joinMsg1 = groupMessageFactory
|
GroupMessage joinMsg1 = groupMessageFactory
|
||||||
.createJoinMessage(privateGroup0.getId(), joinTime, author1,
|
.createJoinMessage(privateGroup0.getId(), joinTime, author1,
|
||||||
inviteTime, creatorSignature);
|
inviteTime, creatorSignature);
|
||||||
|
|||||||
@@ -17,7 +17,6 @@ import org.briarproject.api.contact.ContactManager;
|
|||||||
import org.briarproject.api.crypto.CryptoComponent;
|
import org.briarproject.api.crypto.CryptoComponent;
|
||||||
import org.briarproject.api.crypto.KeyPair;
|
import org.briarproject.api.crypto.KeyPair;
|
||||||
import org.briarproject.api.crypto.SecretKey;
|
import org.briarproject.api.crypto.SecretKey;
|
||||||
import org.briarproject.api.crypto.Signature;
|
|
||||||
import org.briarproject.api.data.BdfDictionary;
|
import org.briarproject.api.data.BdfDictionary;
|
||||||
import org.briarproject.api.data.BdfEntry;
|
import org.briarproject.api.data.BdfEntry;
|
||||||
import org.briarproject.api.data.BdfList;
|
import org.briarproject.api.data.BdfList;
|
||||||
@@ -95,6 +94,7 @@ import static org.briarproject.api.introduction.IntroductionConstants.TYPE_REQUE
|
|||||||
import static org.briarproject.api.introduction.IntroductionConstants.TYPE_RESPONSE;
|
import static org.briarproject.api.introduction.IntroductionConstants.TYPE_RESPONSE;
|
||||||
import static org.briarproject.api.sync.ValidationManager.State.DELIVERED;
|
import static org.briarproject.api.sync.ValidationManager.State.DELIVERED;
|
||||||
import static org.briarproject.api.sync.ValidationManager.State.INVALID;
|
import static org.briarproject.api.sync.ValidationManager.State.INVALID;
|
||||||
|
import static org.briarproject.introduction.IntroduceeManager.SIGNING_LABEL_RESPONSE;
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertFalse;
|
import static org.junit.Assert.assertFalse;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
@@ -922,10 +922,8 @@ public class IntroductionIntegrationTest extends BriarIntegrationTest {
|
|||||||
byte[] nonce1 = crypto.deriveSignatureNonce(secretKey, true);
|
byte[] nonce1 = crypto.deriveSignatureNonce(secretKey, true);
|
||||||
|
|
||||||
// Signature 1
|
// Signature 1
|
||||||
Signature signature = crypto.getSignature();
|
byte[] sig1 = crypto.sign(SIGNING_LABEL_RESPONSE, nonce1,
|
||||||
signature.initSign(keyPair1.getPrivate());
|
keyPair1.getPrivate().getEncoded());
|
||||||
signature.update(nonce1);
|
|
||||||
byte[] sig1 = signature.sign();
|
|
||||||
|
|
||||||
// MAC 1
|
// MAC 1
|
||||||
SecretKey macKey1 = crypto.deriveMacKey(secretKey, true);
|
SecretKey macKey1 = crypto.deriveMacKey(secretKey, true);
|
||||||
|
|||||||
@@ -11,8 +11,13 @@ import org.jetbrains.annotations.Nullable;
|
|||||||
|
|
||||||
import java.security.GeneralSecurityException;
|
import java.security.GeneralSecurityException;
|
||||||
|
|
||||||
|
import static org.briarproject.api.blogs.BlogManager.CLIENT_ID;
|
||||||
|
|
||||||
public interface BlogPostFactory {
|
public interface BlogPostFactory {
|
||||||
|
|
||||||
|
String SIGNING_LABEL_POST = CLIENT_ID + "/POST";
|
||||||
|
String SIGNING_LABEL_COMMENT = CLIENT_ID + "/COMMENT";
|
||||||
|
|
||||||
BlogPost createBlogPost(@NotNull GroupId groupId, long timestamp,
|
BlogPost createBlogPost(@NotNull GroupId groupId, long timestamp,
|
||||||
@Nullable MessageId parent, @NotNull LocalAuthor author,
|
@Nullable MessageId parent, @NotNull LocalAuthor author,
|
||||||
@NotNull String body)
|
@NotNull String body)
|
||||||
|
|||||||
@@ -92,10 +92,10 @@ public interface ClientHelper {
|
|||||||
|
|
||||||
BdfList toList(Message m) throws FormatException;
|
BdfList toList(Message m) throws FormatException;
|
||||||
|
|
||||||
byte[] sign(BdfList toSign, byte[] privateKey)
|
byte[] sign(String label, BdfList toSign, byte[] privateKey)
|
||||||
throws FormatException, GeneralSecurityException;
|
throws FormatException, GeneralSecurityException;
|
||||||
|
|
||||||
void verifySignature(byte[] sig, byte[] publicKey, BdfList signed)
|
void verifySignature(String label, byte[] sig, byte[] publicKey,
|
||||||
throws FormatException, GeneralSecurityException;
|
BdfList signed) throws FormatException, GeneralSecurityException;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,8 +16,6 @@ public interface CryptoComponent {
|
|||||||
|
|
||||||
SecureRandom getSecureRandom();
|
SecureRandom getSecureRandom();
|
||||||
|
|
||||||
Signature getSignature();
|
|
||||||
|
|
||||||
KeyPair generateAgreementKeyPair();
|
KeyPair generateAgreementKeyPair();
|
||||||
|
|
||||||
KeyParser getAgreementKeyParser();
|
KeyParser getAgreementKeyParser();
|
||||||
@@ -143,6 +141,26 @@ public interface CryptoComponent {
|
|||||||
/** Encodes the pseudo-random tag that is used to recognise a stream. */
|
/** Encodes the pseudo-random tag that is used to recognise a stream. */
|
||||||
void encodeTag(byte[] tag, SecretKey tagKey, long streamNumber);
|
void encodeTag(byte[] tag, SecretKey tagKey, long streamNumber);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Signs the given byte[] with the given PrivateKey.
|
||||||
|
*
|
||||||
|
* @param label A label specific to this signature
|
||||||
|
* to ensure that the signature cannot be repurposed
|
||||||
|
*/
|
||||||
|
byte[] sign(String label, byte[] toSign, byte[] privateKey)
|
||||||
|
throws GeneralSecurityException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verifies that the given signature is valid for the signedData
|
||||||
|
* and the given publicKey.
|
||||||
|
*
|
||||||
|
* @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 verify(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.
|
||||||
|
|||||||
@@ -8,8 +8,12 @@ import org.briarproject.api.sync.MessageId;
|
|||||||
|
|
||||||
import java.security.GeneralSecurityException;
|
import java.security.GeneralSecurityException;
|
||||||
|
|
||||||
|
import static org.briarproject.api.forum.ForumManager.CLIENT_ID;
|
||||||
|
|
||||||
public interface ForumPostFactory {
|
public interface ForumPostFactory {
|
||||||
|
|
||||||
|
String SIGNING_LABEL_POST = CLIENT_ID + "/POST";
|
||||||
|
|
||||||
@CryptoExecutor
|
@CryptoExecutor
|
||||||
ForumPost createPost(GroupId groupId, long timestamp, MessageId parent,
|
ForumPost createPost(GroupId groupId, long timestamp, MessageId parent,
|
||||||
LocalAuthor author, String body)
|
LocalAuthor author, String body)
|
||||||
|
|||||||
@@ -1,16 +1,20 @@
|
|||||||
package org.briarproject.api.privategroup;
|
package org.briarproject.api.privategroup;
|
||||||
|
|
||||||
import org.briarproject.api.crypto.CryptoExecutor;
|
import org.briarproject.api.crypto.CryptoExecutor;
|
||||||
import org.briarproject.api.identity.Author;
|
|
||||||
import org.briarproject.api.identity.LocalAuthor;
|
import org.briarproject.api.identity.LocalAuthor;
|
||||||
import org.briarproject.api.nullsafety.NotNullByDefault;
|
import org.briarproject.api.nullsafety.NotNullByDefault;
|
||||||
import org.briarproject.api.sync.GroupId;
|
import org.briarproject.api.sync.GroupId;
|
||||||
import org.briarproject.api.sync.MessageId;
|
import org.briarproject.api.sync.MessageId;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import static org.briarproject.api.privategroup.PrivateGroupManager.CLIENT_ID;
|
||||||
|
|
||||||
@NotNullByDefault
|
@NotNullByDefault
|
||||||
public interface GroupMessageFactory {
|
public interface GroupMessageFactory {
|
||||||
|
|
||||||
|
String SIGNING_LABEL_JOIN = CLIENT_ID + "/JOIN";
|
||||||
|
String SIGNING_LABEL_POST = CLIENT_ID + "/POST";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a join announcement message for the creator of a group.
|
* Creates a join announcement message for the creator of a group.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -6,8 +6,12 @@ import org.briarproject.api.data.BdfList;
|
|||||||
import org.briarproject.api.identity.AuthorId;
|
import org.briarproject.api.identity.AuthorId;
|
||||||
import org.briarproject.api.sync.GroupId;
|
import org.briarproject.api.sync.GroupId;
|
||||||
|
|
||||||
|
import static org.briarproject.api.privategroup.invitation.GroupInvitationManager.CLIENT_ID;
|
||||||
|
|
||||||
public interface GroupInvitationFactory {
|
public interface GroupInvitationFactory {
|
||||||
|
|
||||||
|
String SIGNING_LABEL_INVITE = CLIENT_ID + "/INVITE";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a signature to include when inviting a member to join a private
|
* Returns a signature to include when inviting a member to join a private
|
||||||
* group. If the member accepts the invitation, the signature will be
|
* group. If the member accepts the invitation, the signature will be
|
||||||
@@ -24,4 +28,5 @@ public interface GroupInvitationFactory {
|
|||||||
*/
|
*/
|
||||||
BdfList createInviteToken(AuthorId creatorId, AuthorId memberId,
|
BdfList createInviteToken(AuthorId creatorId, AuthorId memberId,
|
||||||
GroupId privateGroupId, long timestamp);
|
GroupId privateGroupId, long timestamp);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,7 +52,8 @@ class BlogPostFactoryImpl implements BlogPostFactory {
|
|||||||
BdfList signed = BdfList.of(groupId, timestamp, body);
|
BdfList signed = BdfList.of(groupId, timestamp, body);
|
||||||
|
|
||||||
// Generate the signature
|
// Generate the signature
|
||||||
byte[] sig = clientHelper.sign(signed, author.getPrivateKey());
|
byte[] sig = clientHelper
|
||||||
|
.sign(SIGNING_LABEL_POST, signed, author.getPrivateKey());
|
||||||
|
|
||||||
// Serialise the signed message
|
// Serialise the signed message
|
||||||
BdfList message = BdfList.of(POST.getInt(), body, sig);
|
BdfList message = BdfList.of(POST.getInt(), body, sig);
|
||||||
@@ -77,7 +78,8 @@ class BlogPostFactoryImpl implements BlogPostFactory {
|
|||||||
// Generate the signature
|
// Generate the signature
|
||||||
BdfList signed =
|
BdfList signed =
|
||||||
BdfList.of(groupId, timestamp, comment, pOriginalId, parentId);
|
BdfList.of(groupId, timestamp, comment, pOriginalId, parentId);
|
||||||
byte[] sig = clientHelper.sign(signed, author.getPrivateKey());
|
byte[] sig = clientHelper
|
||||||
|
.sign(SIGNING_LABEL_COMMENT, signed, author.getPrivateKey());
|
||||||
|
|
||||||
// Serialise the signed message
|
// Serialise the signed message
|
||||||
BdfList message =
|
BdfList message =
|
||||||
|
|||||||
@@ -39,6 +39,8 @@ import static org.briarproject.api.blogs.BlogConstants.KEY_TIME_RECEIVED;
|
|||||||
import static org.briarproject.api.blogs.BlogConstants.KEY_TYPE;
|
import static org.briarproject.api.blogs.BlogConstants.KEY_TYPE;
|
||||||
import static org.briarproject.api.blogs.BlogConstants.MAX_BLOG_COMMENT_LENGTH;
|
import static org.briarproject.api.blogs.BlogConstants.MAX_BLOG_COMMENT_LENGTH;
|
||||||
import static org.briarproject.api.blogs.BlogConstants.MAX_BLOG_POST_BODY_LENGTH;
|
import static org.briarproject.api.blogs.BlogConstants.MAX_BLOG_POST_BODY_LENGTH;
|
||||||
|
import static org.briarproject.api.blogs.BlogPostFactory.SIGNING_LABEL_COMMENT;
|
||||||
|
import static org.briarproject.api.blogs.BlogPostFactory.SIGNING_LABEL_POST;
|
||||||
import static org.briarproject.api.blogs.MessageType.COMMENT;
|
import static org.briarproject.api.blogs.MessageType.COMMENT;
|
||||||
import static org.briarproject.api.blogs.MessageType.POST;
|
import static org.briarproject.api.blogs.MessageType.POST;
|
||||||
import static org.briarproject.api.identity.AuthorConstants.MAX_SIGNATURE_LENGTH;
|
import static org.briarproject.api.identity.AuthorConstants.MAX_SIGNATURE_LENGTH;
|
||||||
@@ -105,7 +107,9 @@ class BlogPostValidator extends BdfMessageValidator {
|
|||||||
Blog b = blogFactory.parseBlog(g);
|
Blog b = blogFactory.parseBlog(g);
|
||||||
Author a = b.getAuthor();
|
Author a = b.getAuthor();
|
||||||
try {
|
try {
|
||||||
clientHelper.verifySignature(sig, a.getPublicKey(), signed);
|
clientHelper
|
||||||
|
.verifySignature(SIGNING_LABEL_POST, sig, a.getPublicKey(),
|
||||||
|
signed);
|
||||||
} catch (GeneralSecurityException e) {
|
} catch (GeneralSecurityException e) {
|
||||||
throw new InvalidMessageException(e);
|
throw new InvalidMessageException(e);
|
||||||
}
|
}
|
||||||
@@ -150,7 +154,8 @@ class BlogPostValidator extends BdfMessageValidator {
|
|||||||
Blog b = blogFactory.parseBlog(g);
|
Blog b = blogFactory.parseBlog(g);
|
||||||
Author a = b.getAuthor();
|
Author a = b.getAuthor();
|
||||||
try {
|
try {
|
||||||
clientHelper.verifySignature(sig, a.getPublicKey(), signed);
|
clientHelper.verifySignature(SIGNING_LABEL_COMMENT, sig,
|
||||||
|
a.getPublicKey(), signed);
|
||||||
} catch (GeneralSecurityException e) {
|
} catch (GeneralSecurityException e) {
|
||||||
throw new InvalidMessageException(e);
|
throw new InvalidMessageException(e);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,10 +3,6 @@ package org.briarproject.clients;
|
|||||||
import org.briarproject.api.FormatException;
|
import org.briarproject.api.FormatException;
|
||||||
import org.briarproject.api.clients.ClientHelper;
|
import org.briarproject.api.clients.ClientHelper;
|
||||||
import org.briarproject.api.crypto.CryptoComponent;
|
import org.briarproject.api.crypto.CryptoComponent;
|
||||||
import org.briarproject.api.crypto.KeyParser;
|
|
||||||
import org.briarproject.api.crypto.PrivateKey;
|
|
||||||
import org.briarproject.api.crypto.PublicKey;
|
|
||||||
import org.briarproject.api.crypto.Signature;
|
|
||||||
import org.briarproject.api.data.BdfDictionary;
|
import org.briarproject.api.data.BdfDictionary;
|
||||||
import org.briarproject.api.data.BdfList;
|
import org.briarproject.api.data.BdfList;
|
||||||
import org.briarproject.api.data.BdfReader;
|
import org.briarproject.api.data.BdfReader;
|
||||||
@@ -346,27 +342,15 @@ class ClientHelperImpl implements ClientHelper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public byte[] sign(BdfList toSign, byte[] privateKey)
|
public byte[] sign(String label, BdfList toSign, byte[] privateKey)
|
||||||
throws FormatException, GeneralSecurityException {
|
throws FormatException, GeneralSecurityException {
|
||||||
Signature signature = crypto.getSignature();
|
return crypto.sign(label, toByteArray(toSign), privateKey);
|
||||||
KeyParser keyParser = crypto.getSignatureKeyParser();
|
|
||||||
PrivateKey key = keyParser.parsePrivateKey(privateKey);
|
|
||||||
signature.initSign(key);
|
|
||||||
signature.update(toByteArray(toSign));
|
|
||||||
return signature.sign();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void verifySignature(byte[] sig, byte[] publicKey, BdfList signed)
|
public void verifySignature(String label, byte[] sig, byte[] publicKey,
|
||||||
throws FormatException, GeneralSecurityException {
|
BdfList signed) throws FormatException, GeneralSecurityException {
|
||||||
// Parse the public key
|
if (!crypto.verify(label, toByteArray(signed), publicKey, sig)) {
|
||||||
KeyParser keyParser = crypto.getSignatureKeyParser();
|
|
||||||
PublicKey key = keyParser.parsePublicKey(publicKey);
|
|
||||||
// Verify the signature
|
|
||||||
Signature signature = crypto.getSignature();
|
|
||||||
signature.initVerify(key);
|
|
||||||
signature.update(toByteArray(signed));
|
|
||||||
if (!signature.verify(sig)) {
|
|
||||||
throw new GeneralSecurityException("Invalid signature");
|
throw new GeneralSecurityException("Invalid signature");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,9 +7,7 @@ import org.briarproject.api.contact.ContactExchangeTask;
|
|||||||
import org.briarproject.api.contact.ContactId;
|
import org.briarproject.api.contact.ContactId;
|
||||||
import org.briarproject.api.contact.ContactManager;
|
import org.briarproject.api.contact.ContactManager;
|
||||||
import org.briarproject.api.crypto.CryptoComponent;
|
import org.briarproject.api.crypto.CryptoComponent;
|
||||||
import org.briarproject.api.crypto.KeyParser;
|
|
||||||
import org.briarproject.api.crypto.SecretKey;
|
import org.briarproject.api.crypto.SecretKey;
|
||||||
import org.briarproject.api.crypto.Signature;
|
|
||||||
import org.briarproject.api.data.BdfList;
|
import org.briarproject.api.data.BdfList;
|
||||||
import org.briarproject.api.data.BdfReader;
|
import org.briarproject.api.data.BdfReader;
|
||||||
import org.briarproject.api.data.BdfReaderFactory;
|
import org.briarproject.api.data.BdfReaderFactory;
|
||||||
@@ -55,6 +53,8 @@ public class ContactExchangeTaskImpl extends Thread
|
|||||||
|
|
||||||
private static final Logger LOG =
|
private static final Logger LOG =
|
||||||
Logger.getLogger(ContactExchangeTaskImpl.class.getName());
|
Logger.getLogger(ContactExchangeTaskImpl.class.getName());
|
||||||
|
private static final String SIGNING_LABEL_EXCHANGE =
|
||||||
|
"org.briarproject.briar.contact/EXCHANGE";
|
||||||
|
|
||||||
private final DatabaseComponent db;
|
private final DatabaseComponent db;
|
||||||
private final AuthorFactory authorFactory;
|
private final AuthorFactory authorFactory;
|
||||||
@@ -219,12 +219,9 @@ public class ContactExchangeTaskImpl extends Thread
|
|||||||
private void sendPseudonym(BdfWriter w, byte[] nonce)
|
private void sendPseudonym(BdfWriter w, byte[] nonce)
|
||||||
throws GeneralSecurityException, IOException {
|
throws GeneralSecurityException, IOException {
|
||||||
// Sign the nonce
|
// Sign the nonce
|
||||||
Signature signature = crypto.getSignature();
|
|
||||||
KeyParser keyParser = crypto.getSignatureKeyParser();
|
|
||||||
byte[] privateKey = localAuthor.getPrivateKey();
|
byte[] privateKey = localAuthor.getPrivateKey();
|
||||||
signature.initSign(keyParser.parsePrivateKey(privateKey));
|
byte[] sig = crypto.sign(SIGNING_LABEL_EXCHANGE, nonce, privateKey);
|
||||||
signature.update(nonce);
|
|
||||||
byte[] sig = signature.sign();
|
|
||||||
// Write the name, public key and signature
|
// Write the name, public key and signature
|
||||||
w.writeListStart();
|
w.writeListStart();
|
||||||
w.writeString(localAuthor.getName());
|
w.writeString(localAuthor.getName());
|
||||||
@@ -244,11 +241,7 @@ public class ContactExchangeTaskImpl extends Thread
|
|||||||
r.readListEnd();
|
r.readListEnd();
|
||||||
LOG.info("Received pseudonym");
|
LOG.info("Received pseudonym");
|
||||||
// Verify the signature
|
// Verify the signature
|
||||||
Signature signature = crypto.getSignature();
|
if (!crypto.verify(SIGNING_LABEL_EXCHANGE, nonce, publicKey, sig)) {
|
||||||
KeyParser keyParser = crypto.getSignatureKeyParser();
|
|
||||||
signature.initVerify(keyParser.parsePublicKey(publicKey));
|
|
||||||
signature.update(nonce);
|
|
||||||
if (!signature.verify(sig)) {
|
|
||||||
if (LOG.isLoggable(INFO))
|
if (LOG.isLoggable(INFO))
|
||||||
LOG.info("Invalid signature");
|
LOG.info("Invalid signature");
|
||||||
throw new GeneralSecurityException();
|
throw new GeneralSecurityException();
|
||||||
|
|||||||
@@ -164,11 +164,6 @@ class CryptoComponentImpl implements CryptoComponent {
|
|||||||
return secret;
|
return secret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public Signature getSignature() {
|
|
||||||
return new SignatureImpl(secureRandom);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public KeyPair generateAgreementKeyPair() {
|
public KeyPair generateAgreementKeyPair() {
|
||||||
AsymmetricCipherKeyPair keyPair =
|
AsymmetricCipherKeyPair keyPair =
|
||||||
@@ -399,6 +394,40 @@ class CryptoComponentImpl implements CryptoComponent {
|
|||||||
System.arraycopy(mac, 0, tag, 0, TAG_LENGTH);
|
System.arraycopy(mac, 0, tag, 0, TAG_LENGTH);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte[] sign(String label, byte[] toSign, byte[] privateKey)
|
||||||
|
throws GeneralSecurityException {
|
||||||
|
Signature signature = new SignatureImpl(secureRandom);
|
||||||
|
KeyParser keyParser = getSignatureKeyParser();
|
||||||
|
PrivateKey key = keyParser.parsePrivateKey(privateKey);
|
||||||
|
signature.initSign(key);
|
||||||
|
updateSignature(signature, label, toSign);
|
||||||
|
return signature.sign();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean verify(String label, byte[] signedData, byte[] publicKey,
|
||||||
|
byte[] signature) throws GeneralSecurityException {
|
||||||
|
Signature sig = new SignatureImpl(secureRandom);
|
||||||
|
KeyParser keyParser = getSignatureKeyParser();
|
||||||
|
PublicKey key = keyParser.parsePublicKey(publicKey);
|
||||||
|
sig.initVerify(key);
|
||||||
|
updateSignature(sig, label, signedData);
|
||||||
|
return sig.verify(signature);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateSignature(Signature signature, String label,
|
||||||
|
byte[] toSign) {
|
||||||
|
byte[] labelBytes = StringUtils.toUtf8(label);
|
||||||
|
byte[] length = new byte[INT_32_BYTES];
|
||||||
|
ByteUtils.writeUint32(labelBytes.length, length, 0);
|
||||||
|
signature.update(length);
|
||||||
|
signature.update(labelBytes);
|
||||||
|
ByteUtils.writeUint32(toSign.length, length, 0);
|
||||||
|
signature.update(length);
|
||||||
|
signature.update(toSign);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public byte[] hash(byte[]... inputs) {
|
public byte[] hash(byte[]... inputs) {
|
||||||
MessageDigest digest = getMessageDigest();
|
MessageDigest digest = getMessageDigest();
|
||||||
|
|||||||
@@ -39,7 +39,8 @@ class ForumPostFactoryImpl implements ForumPostFactory {
|
|||||||
BdfList signed = BdfList.of(groupId, timestamp, parent, authorList,
|
BdfList signed = BdfList.of(groupId, timestamp, parent, authorList,
|
||||||
body);
|
body);
|
||||||
// Sign the data
|
// Sign the data
|
||||||
byte[] sig = clientHelper.sign(signed, author.getPrivateKey());
|
byte[] sig = clientHelper
|
||||||
|
.sign(SIGNING_LABEL_POST, signed, author.getPrivateKey());
|
||||||
// Serialise the signed message
|
// Serialise the signed message
|
||||||
BdfList message = BdfList.of(parent, authorList, body, sig);
|
BdfList message = BdfList.of(parent, authorList, body, sig);
|
||||||
Message m = clientHelper.createMessage(groupId, timestamp, message);
|
Message m = clientHelper.createMessage(groupId, timestamp, message);
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import java.util.Collection;
|
|||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
|
||||||
import static org.briarproject.api.forum.ForumConstants.MAX_FORUM_POST_BODY_LENGTH;
|
import static org.briarproject.api.forum.ForumConstants.MAX_FORUM_POST_BODY_LENGTH;
|
||||||
|
import static org.briarproject.api.forum.ForumPostFactory.SIGNING_LABEL_POST;
|
||||||
import static org.briarproject.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH;
|
import static org.briarproject.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH;
|
||||||
import static org.briarproject.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
|
import static org.briarproject.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
|
||||||
import static org.briarproject.api.identity.AuthorConstants.MAX_SIGNATURE_LENGTH;
|
import static org.briarproject.api.identity.AuthorConstants.MAX_SIGNATURE_LENGTH;
|
||||||
@@ -68,7 +69,8 @@ class ForumPostValidator extends BdfMessageValidator {
|
|||||||
BdfList signed = BdfList.of(g.getId(), m.getTimestamp(), parent,
|
BdfList signed = BdfList.of(g.getId(), m.getTimestamp(), parent,
|
||||||
authorList, forumPostBody);
|
authorList, forumPostBody);
|
||||||
try {
|
try {
|
||||||
clientHelper.verifySignature(sig, author.getPublicKey(), signed);
|
clientHelper.verifySignature(SIGNING_LABEL_POST, sig,
|
||||||
|
author.getPublicKey(), signed);
|
||||||
} catch (GeneralSecurityException e) {
|
} catch (GeneralSecurityException e) {
|
||||||
throw new InvalidMessageException(e);
|
throw new InvalidMessageException(e);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ import org.briarproject.api.crypto.KeyParser;
|
|||||||
import org.briarproject.api.crypto.PrivateKey;
|
import org.briarproject.api.crypto.PrivateKey;
|
||||||
import org.briarproject.api.crypto.PublicKey;
|
import org.briarproject.api.crypto.PublicKey;
|
||||||
import org.briarproject.api.crypto.SecretKey;
|
import org.briarproject.api.crypto.SecretKey;
|
||||||
import org.briarproject.api.crypto.Signature;
|
|
||||||
import org.briarproject.api.data.BdfDictionary;
|
import org.briarproject.api.data.BdfDictionary;
|
||||||
import org.briarproject.api.data.BdfList;
|
import org.briarproject.api.data.BdfList;
|
||||||
import org.briarproject.api.db.DatabaseComponent;
|
import org.briarproject.api.db.DatabaseComponent;
|
||||||
@@ -88,11 +87,13 @@ import static org.briarproject.api.introduction.IntroductionConstants.TYPE;
|
|||||||
import static org.briarproject.api.introduction.IntroductionConstants.TYPE_ABORT;
|
import static org.briarproject.api.introduction.IntroductionConstants.TYPE_ABORT;
|
||||||
import static org.briarproject.api.introduction.IntroductionConstants.TYPE_ACK;
|
import static org.briarproject.api.introduction.IntroductionConstants.TYPE_ACK;
|
||||||
import static org.briarproject.api.introduction.IntroductionConstants.TYPE_RESPONSE;
|
import static org.briarproject.api.introduction.IntroductionConstants.TYPE_RESPONSE;
|
||||||
|
import static org.briarproject.api.introduction.IntroductionManager.CLIENT_ID;
|
||||||
|
|
||||||
class IntroduceeManager {
|
class IntroduceeManager {
|
||||||
|
|
||||||
private static final Logger LOG =
|
private static final Logger LOG =
|
||||||
Logger.getLogger(IntroduceeManager.class.getName());
|
Logger.getLogger(IntroduceeManager.class.getName());
|
||||||
|
static final String SIGNING_LABEL_RESPONSE = CLIENT_ID + "/RESPONSE";
|
||||||
|
|
||||||
private final MessageSender messageSender;
|
private final MessageSender messageSender;
|
||||||
private final DatabaseComponent db;
|
private final DatabaseComponent db;
|
||||||
@@ -453,12 +454,8 @@ class IntroduceeManager {
|
|||||||
localState.put(MAC_KEY, theirMacKey.getBytes());
|
localState.put(MAC_KEY, theirMacKey.getBytes());
|
||||||
|
|
||||||
// Sign our nonce with our long-term identity public key
|
// Sign our nonce with our long-term identity public key
|
||||||
Signature signature = cryptoComponent.getSignature();
|
byte[] sig = cryptoComponent
|
||||||
KeyParser sigParser = cryptoComponent.getSignatureKeyParser();
|
.sign(SIGNING_LABEL_RESPONSE, ourNonce, author.getPrivateKey());
|
||||||
PrivateKey privKey = sigParser.parsePrivateKey(author.getPrivateKey());
|
|
||||||
signature.initSign(privKey);
|
|
||||||
signature.update(ourNonce);
|
|
||||||
byte[] sig = signature.sign();
|
|
||||||
|
|
||||||
// Calculate a MAC over identity public key, ephemeral public key,
|
// Calculate a MAC over identity public key, ephemeral public key,
|
||||||
// transport properties and timestamp.
|
// transport properties and timestamp.
|
||||||
@@ -479,16 +476,10 @@ class IntroduceeManager {
|
|||||||
throws FormatException, GeneralSecurityException {
|
throws FormatException, GeneralSecurityException {
|
||||||
byte[] nonce = localState.getRaw(NONCE);
|
byte[] nonce = localState.getRaw(NONCE);
|
||||||
byte[] sig = localState.getRaw(SIGNATURE);
|
byte[] sig = localState.getRaw(SIGNATURE);
|
||||||
byte[] keyBytes = localState.getRaw(PUBLIC_KEY);
|
byte[] key = localState.getRaw(PUBLIC_KEY);
|
||||||
|
|
||||||
// Parse the public key
|
|
||||||
KeyParser keyParser = cryptoComponent.getSignatureKeyParser();
|
|
||||||
PublicKey key = keyParser.parsePublicKey(keyBytes);
|
|
||||||
// Verify the signature
|
// Verify the signature
|
||||||
Signature signature = cryptoComponent.getSignature();
|
if (!cryptoComponent.verify(SIGNING_LABEL_RESPONSE, nonce, key, sig)) {
|
||||||
signature.initVerify(key);
|
|
||||||
signature.update(nonce);
|
|
||||||
if (!signature.verify(sig)) {
|
|
||||||
LOG.warning("Invalid nonce signature in ACK");
|
LOG.warning("Invalid nonce signature in ACK");
|
||||||
throw new GeneralSecurityException();
|
throw new GeneralSecurityException();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,8 +51,8 @@ class GroupMessageFactoryImpl implements GroupMessageFactory {
|
|||||||
int type = JOIN.getInt();
|
int type = JOIN.getInt();
|
||||||
BdfList toSign = BdfList.of(groupId, timestamp, type,
|
BdfList toSign = BdfList.of(groupId, timestamp, type,
|
||||||
member.getName(), member.getPublicKey(), invite);
|
member.getName(), member.getPublicKey(), invite);
|
||||||
byte[] memberSignature =
|
byte[] memberSignature = clientHelper
|
||||||
clientHelper.sign(toSign, member.getPrivateKey());
|
.sign(SIGNING_LABEL_JOIN, toSign, member.getPrivateKey());
|
||||||
|
|
||||||
// Compose the message
|
// Compose the message
|
||||||
BdfList body =
|
BdfList body =
|
||||||
@@ -78,8 +78,8 @@ class GroupMessageFactoryImpl implements GroupMessageFactory {
|
|||||||
BdfList toSign = BdfList.of(groupId, timestamp, type,
|
BdfList toSign = BdfList.of(groupId, timestamp, type,
|
||||||
author.getName(), author.getPublicKey(), parentId,
|
author.getName(), author.getPublicKey(), parentId,
|
||||||
previousMsgId, content);
|
previousMsgId, content);
|
||||||
byte[] signature =
|
byte[] signature = clientHelper
|
||||||
clientHelper.sign(toSign, author.getPrivateKey());
|
.sign(SIGNING_LABEL_POST, toSign, author.getPrivateKey());
|
||||||
|
|
||||||
// Compose the message
|
// Compose the message
|
||||||
BdfList body =
|
BdfList body =
|
||||||
|
|||||||
@@ -27,9 +27,12 @@ import java.util.Collection;
|
|||||||
import static org.briarproject.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH;
|
import static org.briarproject.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH;
|
||||||
import static org.briarproject.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
|
import static org.briarproject.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
|
||||||
import static org.briarproject.api.identity.AuthorConstants.MAX_SIGNATURE_LENGTH;
|
import static org.briarproject.api.identity.AuthorConstants.MAX_SIGNATURE_LENGTH;
|
||||||
|
import static org.briarproject.api.privategroup.GroupMessageFactory.SIGNING_LABEL_JOIN;
|
||||||
|
import static org.briarproject.api.privategroup.GroupMessageFactory.SIGNING_LABEL_POST;
|
||||||
import static org.briarproject.api.privategroup.MessageType.JOIN;
|
import static org.briarproject.api.privategroup.MessageType.JOIN;
|
||||||
import static org.briarproject.api.privategroup.MessageType.POST;
|
import static org.briarproject.api.privategroup.MessageType.POST;
|
||||||
import static org.briarproject.api.privategroup.PrivateGroupConstants.MAX_GROUP_POST_BODY_LENGTH;
|
import static org.briarproject.api.privategroup.PrivateGroupConstants.MAX_GROUP_POST_BODY_LENGTH;
|
||||||
|
import static org.briarproject.api.privategroup.invitation.GroupInvitationFactory.SIGNING_LABEL_INVITE;
|
||||||
import static org.briarproject.privategroup.GroupConstants.KEY_INITIAL_JOIN_MSG;
|
import static org.briarproject.privategroup.GroupConstants.KEY_INITIAL_JOIN_MSG;
|
||||||
import static org.briarproject.privategroup.GroupConstants.KEY_MEMBER_ID;
|
import static org.briarproject.privategroup.GroupConstants.KEY_MEMBER_ID;
|
||||||
import static org.briarproject.privategroup.GroupConstants.KEY_MEMBER_NAME;
|
import static org.briarproject.privategroup.GroupConstants.KEY_MEMBER_NAME;
|
||||||
@@ -130,7 +133,7 @@ class GroupMessageValidator extends BdfMessageValidator {
|
|||||||
.createInviteToken(creator.getId(), member.getId(),
|
.createInviteToken(creator.getId(), member.getId(),
|
||||||
pg.getId(), inviteTimestamp);
|
pg.getId(), inviteTimestamp);
|
||||||
try {
|
try {
|
||||||
clientHelper.verifySignature(creatorSignature,
|
clientHelper.verifySignature(SIGNING_LABEL_INVITE, creatorSignature,
|
||||||
creator.getPublicKey(), token);
|
creator.getPublicKey(), token);
|
||||||
} catch (GeneralSecurityException e) {
|
} catch (GeneralSecurityException e) {
|
||||||
throw new InvalidMessageException(e);
|
throw new InvalidMessageException(e);
|
||||||
@@ -146,8 +149,8 @@ class GroupMessageValidator extends BdfMessageValidator {
|
|||||||
BdfList signed = BdfList.of(g.getId(), m.getTimestamp(), JOIN.getInt(),
|
BdfList signed = BdfList.of(g.getId(), m.getTimestamp(), JOIN.getInt(),
|
||||||
member.getName(), member.getPublicKey(), invite);
|
member.getName(), member.getPublicKey(), invite);
|
||||||
try {
|
try {
|
||||||
clientHelper.verifySignature(memberSignature, member.getPublicKey(),
|
clientHelper.verifySignature(SIGNING_LABEL_JOIN, memberSignature,
|
||||||
signed);
|
member.getPublicKey(), signed);
|
||||||
} catch (GeneralSecurityException e) {
|
} catch (GeneralSecurityException e) {
|
||||||
throw new InvalidMessageException(e);
|
throw new InvalidMessageException(e);
|
||||||
}
|
}
|
||||||
@@ -189,8 +192,8 @@ class GroupMessageValidator extends BdfMessageValidator {
|
|||||||
member.getName(), member.getPublicKey(), parentId,
|
member.getName(), member.getPublicKey(), parentId,
|
||||||
previousMessageId, content);
|
previousMessageId, content);
|
||||||
try {
|
try {
|
||||||
clientHelper
|
clientHelper.verifySignature(SIGNING_LABEL_POST, signature,
|
||||||
.verifySignature(signature, member.getPublicKey(), signed);
|
member.getPublicKey(), signed);
|
||||||
} catch (GeneralSecurityException e) {
|
} catch (GeneralSecurityException e) {
|
||||||
throw new InvalidMessageException(e);
|
throw new InvalidMessageException(e);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ class GroupInvitationFactoryImpl implements GroupInvitationFactory {
|
|||||||
BdfList token = createInviteToken(creatorId, memberId, privateGroupId,
|
BdfList token = createInviteToken(creatorId, memberId, privateGroupId,
|
||||||
timestamp);
|
timestamp);
|
||||||
try {
|
try {
|
||||||
return clientHelper.sign(token, privateKey);
|
return clientHelper.sign(SIGNING_LABEL_INVITE, token, privateKey);
|
||||||
} catch (GeneralSecurityException e) {
|
} catch (GeneralSecurityException e) {
|
||||||
throw new IllegalArgumentException(e);
|
throw new IllegalArgumentException(e);
|
||||||
} catch (FormatException e) {
|
} catch (FormatException e) {
|
||||||
@@ -50,7 +50,6 @@ class GroupInvitationFactoryImpl implements GroupInvitationFactory {
|
|||||||
Group contactGroup = contactGroupFactory.createContactGroup(CLIENT_ID,
|
Group contactGroup = contactGroupFactory.createContactGroup(CLIENT_ID,
|
||||||
creatorId, memberId);
|
creatorId, memberId);
|
||||||
return BdfList.of(
|
return BdfList.of(
|
||||||
0, // TODO: Replace with a namespaced string
|
|
||||||
timestamp,
|
timestamp,
|
||||||
contactGroup.getId(),
|
contactGroup.getId(),
|
||||||
privateGroupId
|
privateGroupId
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ import static org.briarproject.api.identity.AuthorConstants.MAX_SIGNATURE_LENGTH
|
|||||||
import static org.briarproject.api.privategroup.PrivateGroupConstants.GROUP_SALT_LENGTH;
|
import static org.briarproject.api.privategroup.PrivateGroupConstants.GROUP_SALT_LENGTH;
|
||||||
import static org.briarproject.api.privategroup.PrivateGroupConstants.MAX_GROUP_INVITATION_MSG_LENGTH;
|
import static org.briarproject.api.privategroup.PrivateGroupConstants.MAX_GROUP_INVITATION_MSG_LENGTH;
|
||||||
import static org.briarproject.api.privategroup.PrivateGroupConstants.MAX_GROUP_NAME_LENGTH;
|
import static org.briarproject.api.privategroup.PrivateGroupConstants.MAX_GROUP_NAME_LENGTH;
|
||||||
|
import static org.briarproject.api.privategroup.invitation.GroupInvitationFactory.SIGNING_LABEL_INVITE;
|
||||||
import static org.briarproject.privategroup.invitation.MessageType.ABORT;
|
import static org.briarproject.privategroup.invitation.MessageType.ABORT;
|
||||||
import static org.briarproject.privategroup.invitation.MessageType.INVITE;
|
import static org.briarproject.privategroup.invitation.MessageType.INVITE;
|
||||||
import static org.briarproject.privategroup.invitation.MessageType.JOIN;
|
import static org.briarproject.privategroup.invitation.MessageType.JOIN;
|
||||||
@@ -96,13 +97,13 @@ class GroupInvitationValidator extends BdfMessageValidator {
|
|||||||
groupName, creator, salt);
|
groupName, creator, salt);
|
||||||
// Verify the signature
|
// Verify the signature
|
||||||
BdfList signed = BdfList.of(
|
BdfList signed = BdfList.of(
|
||||||
INVITE.getValue(),
|
|
||||||
m.getTimestamp(),
|
m.getTimestamp(),
|
||||||
m.getGroupId(),
|
m.getGroupId(),
|
||||||
privateGroup.getId()
|
privateGroup.getId()
|
||||||
);
|
);
|
||||||
try {
|
try {
|
||||||
clientHelper.verifySignature(signature, creatorPublicKey, signed);
|
clientHelper.verifySignature(SIGNING_LABEL_INVITE, signature,
|
||||||
|
creatorPublicKey, signed);
|
||||||
} catch (GeneralSecurityException e) {
|
} catch (GeneralSecurityException e) {
|
||||||
throw new FormatException();
|
throw new FormatException();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,6 +38,8 @@ import static org.briarproject.api.blogs.BlogConstants.KEY_ORIGINAL_PARENT_MSG_I
|
|||||||
import static org.briarproject.api.blogs.BlogConstants.KEY_PARENT_MSG_ID;
|
import static org.briarproject.api.blogs.BlogConstants.KEY_PARENT_MSG_ID;
|
||||||
import static org.briarproject.api.blogs.BlogConstants.KEY_PUBLIC_KEY;
|
import static org.briarproject.api.blogs.BlogConstants.KEY_PUBLIC_KEY;
|
||||||
import static org.briarproject.api.blogs.BlogConstants.KEY_READ;
|
import static org.briarproject.api.blogs.BlogConstants.KEY_READ;
|
||||||
|
import static org.briarproject.api.blogs.BlogPostFactory.SIGNING_LABEL_COMMENT;
|
||||||
|
import static org.briarproject.api.blogs.BlogPostFactory.SIGNING_LABEL_POST;
|
||||||
import static org.briarproject.api.blogs.MessageType.COMMENT;
|
import static org.briarproject.api.blogs.MessageType.COMMENT;
|
||||||
import static org.briarproject.api.blogs.MessageType.POST;
|
import static org.briarproject.api.blogs.MessageType.POST;
|
||||||
import static org.briarproject.api.blogs.MessageType.WRAPPED_COMMENT;
|
import static org.briarproject.api.blogs.MessageType.WRAPPED_COMMENT;
|
||||||
@@ -101,7 +103,7 @@ public class BlogPostValidatorTest extends BriarTestCase {
|
|||||||
|
|
||||||
BdfList signed =
|
BdfList signed =
|
||||||
BdfList.of(blog.getId(), message.getTimestamp(), body);
|
BdfList.of(blog.getId(), message.getTimestamp(), body);
|
||||||
expectCrypto(signed, sigBytes);
|
expectCrypto(SIGNING_LABEL_POST, signed, sigBytes);
|
||||||
final BdfDictionary result =
|
final BdfDictionary result =
|
||||||
validator.validateMessage(message, group, m).getDictionary();
|
validator.validateMessage(message, group, m).getDictionary();
|
||||||
|
|
||||||
@@ -143,7 +145,7 @@ public class BlogPostValidatorTest extends BriarTestCase {
|
|||||||
BdfList signed =
|
BdfList signed =
|
||||||
BdfList.of(blog.getId(), message.getTimestamp(), comment,
|
BdfList.of(blog.getId(), message.getTimestamp(), comment,
|
||||||
pOriginalId, currentId);
|
pOriginalId, currentId);
|
||||||
expectCrypto(signed, sigBytes);
|
expectCrypto(SIGNING_LABEL_COMMENT, signed, sigBytes);
|
||||||
final BdfDictionary result =
|
final BdfDictionary result =
|
||||||
validator.validateMessage(message, group, m).getDictionary();
|
validator.validateMessage(message, group, m).getDictionary();
|
||||||
|
|
||||||
@@ -170,7 +172,7 @@ public class BlogPostValidatorTest extends BriarTestCase {
|
|||||||
BdfList signed =
|
BdfList signed =
|
||||||
BdfList.of(blog.getId(), message.getTimestamp(), null,
|
BdfList.of(blog.getId(), message.getTimestamp(), null,
|
||||||
originalId, currentId);
|
originalId, currentId);
|
||||||
expectCrypto(signed, sigBytes);
|
expectCrypto(SIGNING_LABEL_COMMENT, signed, sigBytes);
|
||||||
final BdfDictionary result =
|
final BdfDictionary result =
|
||||||
validator.validateMessage(message, group, m).getDictionary();
|
validator.validateMessage(message, group, m).getDictionary();
|
||||||
|
|
||||||
@@ -189,7 +191,7 @@ public class BlogPostValidatorTest extends BriarTestCase {
|
|||||||
|
|
||||||
BdfList signed =
|
BdfList signed =
|
||||||
BdfList.of(blog.getId(), message.getTimestamp(), body);
|
BdfList.of(blog.getId(), message.getTimestamp(), body);
|
||||||
expectCrypto(signed, sigBytes);
|
expectCrypto(SIGNING_LABEL_POST, signed, sigBytes);
|
||||||
|
|
||||||
final BdfList originalList = BdfList.of(POST.getInt(), body, sigBytes);
|
final BdfList originalList = BdfList.of(POST.getInt(), body, sigBytes);
|
||||||
final byte[] originalBody = TestUtils.getRandomBytes(42);
|
final byte[] originalBody = TestUtils.getRandomBytes(42);
|
||||||
@@ -228,7 +230,7 @@ public class BlogPostValidatorTest extends BriarTestCase {
|
|||||||
|
|
||||||
BdfList signed = BdfList.of(blog.getId(), message.getTimestamp(),
|
BdfList signed = BdfList.of(blog.getId(), message.getTimestamp(),
|
||||||
comment, originalId, oldId);
|
comment, originalId, oldId);
|
||||||
expectCrypto(signed, sigBytes);
|
expectCrypto(SIGNING_LABEL_COMMENT, signed, sigBytes);
|
||||||
|
|
||||||
final BdfList originalList = BdfList.of(COMMENT.getInt(), comment,
|
final BdfList originalList = BdfList.of(COMMENT.getInt(), comment,
|
||||||
originalId, oldId, sigBytes);
|
originalId, oldId, sigBytes);
|
||||||
@@ -256,13 +258,13 @@ public class BlogPostValidatorTest extends BriarTestCase {
|
|||||||
context.assertIsSatisfied();
|
context.assertIsSatisfied();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void expectCrypto(final BdfList signed, final byte[] sig)
|
private void expectCrypto(final String label, final BdfList signed,
|
||||||
throws IOException, GeneralSecurityException {
|
final byte[] sig) throws IOException, GeneralSecurityException {
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
oneOf(blogFactory).parseBlog(group);
|
oneOf(blogFactory).parseBlog(group);
|
||||||
will(returnValue(blog));
|
will(returnValue(blog));
|
||||||
oneOf(clientHelper)
|
oneOf(clientHelper)
|
||||||
.verifySignature(sig, author.getPublicKey(), signed);
|
.verifySignature(label, sig, author.getPublicKey(), signed);
|
||||||
}});
|
}});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,13 +1,10 @@
|
|||||||
package org.briarproject.clients;
|
package org.briarproject.clients;
|
||||||
|
|
||||||
import org.briarproject.BriarTestCase;
|
import org.briarproject.BriarTestCase;
|
||||||
|
import org.briarproject.TestUtils;
|
||||||
import org.briarproject.api.FormatException;
|
import org.briarproject.api.FormatException;
|
||||||
import org.briarproject.api.clients.ClientHelper;
|
import org.briarproject.api.clients.ClientHelper;
|
||||||
import org.briarproject.api.crypto.CryptoComponent;
|
import org.briarproject.api.crypto.CryptoComponent;
|
||||||
import org.briarproject.api.crypto.KeyParser;
|
|
||||||
import org.briarproject.api.crypto.PrivateKey;
|
|
||||||
import org.briarproject.api.crypto.PublicKey;
|
|
||||||
import org.briarproject.api.crypto.Signature;
|
|
||||||
import org.briarproject.api.data.BdfDictionary;
|
import org.briarproject.api.data.BdfDictionary;
|
||||||
import org.briarproject.api.data.BdfEntry;
|
import org.briarproject.api.data.BdfEntry;
|
||||||
import org.briarproject.api.data.BdfList;
|
import org.briarproject.api.data.BdfList;
|
||||||
@@ -57,8 +54,6 @@ public class ClientHelperImplTest extends BriarTestCase {
|
|||||||
context.mock(MetadataEncoder.class);
|
context.mock(MetadataEncoder.class);
|
||||||
private final CryptoComponent cryptoComponent =
|
private final CryptoComponent cryptoComponent =
|
||||||
context.mock(CryptoComponent.class);
|
context.mock(CryptoComponent.class);
|
||||||
private final KeyParser keyParser = context.mock(KeyParser.class);
|
|
||||||
private final Signature signature = context.mock(Signature.class);
|
|
||||||
private final ClientHelper clientHelper;
|
private final ClientHelper clientHelper;
|
||||||
|
|
||||||
private final GroupId groupId = new GroupId(getRandomId());
|
private final GroupId groupId = new GroupId(getRandomId());
|
||||||
@@ -70,6 +65,7 @@ public class ClientHelperImplTest extends BriarTestCase {
|
|||||||
new Message(messageId, groupId, timestamp, rawMessage);
|
new Message(messageId, groupId, timestamp, rawMessage);
|
||||||
private final Metadata metadata = new Metadata();
|
private final Metadata metadata = new Metadata();
|
||||||
private final BdfList list = BdfList.of("Sign this!", getRandomBytes(42));
|
private final BdfList list = BdfList.of("Sign this!", getRandomBytes(42));
|
||||||
|
private final String label = TestUtils.getRandomString(5);
|
||||||
|
|
||||||
public ClientHelperImplTest() {
|
public ClientHelperImplTest() {
|
||||||
clientHelper =
|
clientHelper =
|
||||||
@@ -284,72 +280,46 @@ public class ClientHelperImplTest extends BriarTestCase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSign() throws Exception {
|
public void testSign() throws Exception {
|
||||||
final byte[] privateKeyBytes = getRandomBytes(42);
|
final byte[] privateKey = getRandomBytes(42);
|
||||||
final PrivateKey privateKey = context.mock(PrivateKey.class);
|
|
||||||
final byte[] signed = getRandomBytes(42);
|
final byte[] signed = getRandomBytes(42);
|
||||||
|
|
||||||
final byte[] bytes = expectToByteArray(list);
|
final byte[] bytes = expectToByteArray(list);
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
oneOf(cryptoComponent).getSignature();
|
oneOf(cryptoComponent).sign(label, bytes, privateKey);
|
||||||
will(returnValue(signature));
|
|
||||||
oneOf(cryptoComponent).getSignatureKeyParser();
|
|
||||||
will(returnValue(keyParser));
|
|
||||||
oneOf(keyParser).parsePrivateKey(privateKeyBytes);
|
|
||||||
will(returnValue(privateKey));
|
|
||||||
oneOf(signature).initSign(privateKey);
|
|
||||||
oneOf(signature).update(bytes);
|
|
||||||
oneOf(signature).sign();
|
|
||||||
will(returnValue(signed));
|
will(returnValue(signed));
|
||||||
}});
|
}});
|
||||||
|
|
||||||
assertArrayEquals(signed, clientHelper.sign(list, privateKeyBytes));
|
assertArrayEquals(signed, clientHelper.sign(label, list, privateKey));
|
||||||
context.assertIsSatisfied();
|
context.assertIsSatisfied();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testVerifySignature() throws Exception {
|
public void testVerifySignature() throws Exception {
|
||||||
final PublicKey publicKey = context.mock(PublicKey.class);
|
final byte[] publicKey = getRandomBytes(42);
|
||||||
final byte[] publicKeyBytes = getRandomBytes(42);
|
|
||||||
|
|
||||||
final byte[] bytes = expectToByteArray(list);
|
final byte[] bytes = expectToByteArray(list);
|
||||||
|
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
oneOf(cryptoComponent).getSignatureKeyParser();
|
oneOf(cryptoComponent).verify(label, bytes, publicKey, rawMessage);
|
||||||
will(returnValue(keyParser));
|
|
||||||
oneOf(keyParser).parsePublicKey(publicKeyBytes);
|
|
||||||
will(returnValue(publicKey));
|
|
||||||
oneOf(cryptoComponent).getSignature();
|
|
||||||
will(returnValue(signature));
|
|
||||||
oneOf(signature).initVerify(publicKey);
|
|
||||||
oneOf(signature).update(bytes);
|
|
||||||
oneOf(signature).verify(rawMessage);
|
|
||||||
will(returnValue(true));
|
will(returnValue(true));
|
||||||
}});
|
}});
|
||||||
|
|
||||||
clientHelper.verifySignature(rawMessage, publicKeyBytes, list);
|
clientHelper.verifySignature(label, rawMessage, publicKey, list);
|
||||||
context.assertIsSatisfied();
|
context.assertIsSatisfied();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testVerifyWrongSignature() throws Exception {
|
public void testVerifyWrongSignature() throws Exception {
|
||||||
final PublicKey publicKey = context.mock(PublicKey.class);
|
final byte[] publicKey = getRandomBytes(42);
|
||||||
final byte[] publicKeyBytes = getRandomBytes(42);
|
|
||||||
|
|
||||||
final byte[] bytes = expectToByteArray(list);
|
final byte[] bytes = expectToByteArray(list);
|
||||||
|
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
oneOf(cryptoComponent).getSignatureKeyParser();
|
oneOf(cryptoComponent).verify(label, bytes, publicKey, rawMessage);
|
||||||
will(returnValue(keyParser));
|
|
||||||
oneOf(keyParser).parsePublicKey(publicKeyBytes);
|
|
||||||
will(returnValue(publicKey));
|
|
||||||
oneOf(cryptoComponent).getSignature();
|
|
||||||
will(returnValue(signature));
|
|
||||||
oneOf(signature).initVerify(publicKey);
|
|
||||||
oneOf(signature).update(bytes);
|
|
||||||
oneOf(signature).verify(rawMessage);
|
|
||||||
will(returnValue(false));
|
will(returnValue(false));
|
||||||
}});
|
}});
|
||||||
|
|
||||||
try {
|
try {
|
||||||
clientHelper.verifySignature(rawMessage, publicKeyBytes, list);
|
clientHelper
|
||||||
|
.verifySignature(label, rawMessage, publicKey, list);
|
||||||
fail();
|
fail();
|
||||||
} catch (GeneralSecurityException e) {
|
} catch (GeneralSecurityException e) {
|
||||||
// expected
|
// expected
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import org.briarproject.api.crypto.KeyPair;
|
|||||||
import org.briarproject.api.crypto.KeyParser;
|
import org.briarproject.api.crypto.KeyParser;
|
||||||
import org.briarproject.api.crypto.PrivateKey;
|
import org.briarproject.api.crypto.PrivateKey;
|
||||||
import org.briarproject.api.crypto.PublicKey;
|
import org.briarproject.api.crypto.PublicKey;
|
||||||
import org.briarproject.api.crypto.Signature;
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import java.security.GeneralSecurityException;
|
import java.security.GeneralSecurityException;
|
||||||
@@ -102,15 +101,13 @@ public class KeyEncodingAndParsingTest extends BriarTestCase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSignatureLength() throws Exception {
|
public void testSignatureLength() throws Exception {
|
||||||
Signature sig = crypto.getSignature();
|
|
||||||
// Generate 10 signature key pairs
|
// Generate 10 signature key pairs
|
||||||
for (int i = 0; i < 10; i++) {
|
for (int i = 0; i < 10; i++) {
|
||||||
KeyPair keyPair = crypto.generateSignatureKeyPair();
|
KeyPair keyPair = crypto.generateSignatureKeyPair();
|
||||||
|
byte[] key = keyPair.getPrivate().getEncoded();
|
||||||
// Sign some random data and check the length of the signature
|
// Sign some random data and check the length of the signature
|
||||||
byte[] toBeSigned = TestUtils.getRandomBytes(1234);
|
byte[] toBeSigned = TestUtils.getRandomBytes(1234);
|
||||||
sig.initSign(keyPair.getPrivate());
|
byte[] signature = crypto.sign("label", toBeSigned, key);
|
||||||
sig.update(toBeSigned);
|
|
||||||
byte[] signature = sig.sign();
|
|
||||||
assertTrue(signature.length <= MAX_SIGNATURE_LENGTH);
|
assertTrue(signature.length <= MAX_SIGNATURE_LENGTH);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,18 +16,17 @@ public class MacTest extends BriarTestCase {
|
|||||||
|
|
||||||
private final CryptoComponent crypto;
|
private final CryptoComponent crypto;
|
||||||
|
|
||||||
|
private final SecretKey k = TestUtils.getSecretKey();
|
||||||
|
private final byte[] inputBytes = TestUtils.getRandomBytes(123);
|
||||||
|
private final byte[] inputBytes1 = TestUtils.getRandomBytes(234);
|
||||||
|
private final byte[] inputBytes2 = new byte[0];
|
||||||
|
|
||||||
public MacTest() {
|
public MacTest() {
|
||||||
crypto = new CryptoComponentImpl(new TestSeedProvider());
|
crypto = new CryptoComponentImpl(new TestSeedProvider());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testIdenticalKeysAndInputsProduceIdenticalMacs() {
|
public void testIdenticalKeysAndInputsProduceIdenticalMacs() {
|
||||||
// Generate a random key and some random input
|
|
||||||
byte[] keyBytes = TestUtils.getRandomBytes(SecretKey.LENGTH);
|
|
||||||
SecretKey k = new SecretKey(keyBytes);
|
|
||||||
byte[] inputBytes = TestUtils.getRandomBytes(123);
|
|
||||||
byte[] inputBytes1 = TestUtils.getRandomBytes(234);
|
|
||||||
byte[] inputBytes2 = new byte[0];
|
|
||||||
// Calculate the MAC twice - the results should be identical
|
// Calculate the MAC twice - the results should be identical
|
||||||
byte[] mac = crypto.mac(k, inputBytes, inputBytes1, inputBytes2);
|
byte[] mac = crypto.mac(k, inputBytes, inputBytes1, inputBytes2);
|
||||||
byte[] mac1 = crypto.mac(k, inputBytes, inputBytes1, inputBytes2);
|
byte[] mac1 = crypto.mac(k, inputBytes, inputBytes1, inputBytes2);
|
||||||
@@ -36,14 +35,8 @@ public class MacTest extends BriarTestCase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDifferentKeysProduceDifferentMacs() {
|
public void testDifferentKeysProduceDifferentMacs() {
|
||||||
// Generate two random keys and some random input
|
// Generate second random key
|
||||||
byte[] keyBytes = TestUtils.getRandomBytes(SecretKey.LENGTH);
|
SecretKey k1 = TestUtils.getSecretKey();
|
||||||
SecretKey k = new SecretKey(keyBytes);
|
|
||||||
byte[] keyBytes1 = TestUtils.getRandomBytes(SecretKey.LENGTH);
|
|
||||||
SecretKey k1 = new SecretKey(keyBytes1);
|
|
||||||
byte[] inputBytes = TestUtils.getRandomBytes(123);
|
|
||||||
byte[] inputBytes1 = TestUtils.getRandomBytes(234);
|
|
||||||
byte[] inputBytes2 = new byte[0];
|
|
||||||
// Calculate the MAC with each key - the results should be different
|
// Calculate the MAC with each key - the results should be different
|
||||||
byte[] mac = crypto.mac(k, inputBytes, inputBytes1, inputBytes2);
|
byte[] mac = crypto.mac(k, inputBytes, inputBytes1, inputBytes2);
|
||||||
byte[] mac1 = crypto.mac(k1, inputBytes, inputBytes1, inputBytes2);
|
byte[] mac1 = crypto.mac(k1, inputBytes, inputBytes1, inputBytes2);
|
||||||
@@ -52,16 +45,11 @@ public class MacTest extends BriarTestCase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDifferentInputsProduceDifferentMacs() {
|
public void testDifferentInputsProduceDifferentMacs() {
|
||||||
// Generate a random key and some random input
|
|
||||||
byte[] keyBytes = TestUtils.getRandomBytes(SecretKey.LENGTH);
|
|
||||||
SecretKey k = new SecretKey(keyBytes);
|
|
||||||
byte[] inputBytes = TestUtils.getRandomBytes(123);
|
|
||||||
byte[] inputBytes1 = TestUtils.getRandomBytes(234);
|
|
||||||
byte[] inputBytes2 = new byte[0];
|
|
||||||
// Calculate the MAC with the inputs in different orders - the results
|
// Calculate the MAC with the inputs in different orders - the results
|
||||||
// should be different
|
// should be different
|
||||||
byte[] mac = crypto.mac(k, inputBytes, inputBytes1, inputBytes2);
|
byte[] mac = crypto.mac(k, inputBytes, inputBytes1, inputBytes2);
|
||||||
byte[] mac1 = crypto.mac(k, inputBytes2, inputBytes1, inputBytes);
|
byte[] mac1 = crypto.mac(k, inputBytes2, inputBytes1, inputBytes);
|
||||||
assertFalse(Arrays.equals(mac, mac1));
|
assertFalse(Arrays.equals(mac, mac1));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
109
briar-tests/src/org/briarproject/crypto/SignatureTest.java
Normal file
109
briar-tests/src/org/briarproject/crypto/SignatureTest.java
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
package org.briarproject.crypto;
|
||||||
|
|
||||||
|
import org.briarproject.BriarTestCase;
|
||||||
|
import org.briarproject.TestSeedProvider;
|
||||||
|
import org.briarproject.TestUtils;
|
||||||
|
import org.briarproject.api.crypto.CryptoComponent;
|
||||||
|
import org.briarproject.api.crypto.KeyPair;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertArrayEquals;
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
|
public class SignatureTest extends BriarTestCase {
|
||||||
|
|
||||||
|
private final CryptoComponent crypto;
|
||||||
|
|
||||||
|
private final byte[] publicKey, privateKey;
|
||||||
|
private final String label = TestUtils.getRandomString(42);
|
||||||
|
private final byte[] inputBytes = TestUtils.getRandomBytes(123);
|
||||||
|
|
||||||
|
public SignatureTest() {
|
||||||
|
crypto = new CryptoComponentImpl(new TestSeedProvider());
|
||||||
|
KeyPair k = crypto.generateSignatureKeyPair();
|
||||||
|
publicKey = k.getPublic().getEncoded();
|
||||||
|
privateKey = k.getPrivate().getEncoded();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testIdenticalKeysAndInputsProduceIdenticalSignatures()
|
||||||
|
throws Exception {
|
||||||
|
// Calculate the Signature twice - the results should be identical
|
||||||
|
byte[] sig1 = crypto.sign(label, inputBytes, privateKey);
|
||||||
|
byte[] sig2 = crypto.sign(label, inputBytes, privateKey);
|
||||||
|
assertArrayEquals(sig1, sig2);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDifferentKeysProduceDifferentSignatures() throws Exception {
|
||||||
|
// Generate second private key
|
||||||
|
KeyPair k2 = crypto.generateSignatureKeyPair();
|
||||||
|
byte[] privateKey2 = k2.getPrivate().getEncoded();
|
||||||
|
// Calculate the signature with each key
|
||||||
|
byte[] sig1 = crypto.sign(label, inputBytes, privateKey);
|
||||||
|
byte[] sig2 = crypto.sign(label, inputBytes, privateKey2);
|
||||||
|
assertFalse(Arrays.equals(sig1, sig2));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDifferentInputsProduceDifferentSignatures()
|
||||||
|
throws Exception {
|
||||||
|
// Generate a second input
|
||||||
|
byte[] inputBytes2 = TestUtils.getRandomBytes(123);
|
||||||
|
// Calculate the signature with different inputs
|
||||||
|
// the results should be different
|
||||||
|
byte[] sig1 = crypto.sign(label, inputBytes, privateKey);
|
||||||
|
byte[] sig2 = crypto.sign(label, inputBytes2, privateKey);
|
||||||
|
assertFalse(Arrays.equals(sig1, sig2));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDifferentLabelsProduceDifferentSignatures()
|
||||||
|
throws Exception {
|
||||||
|
// Generate a second label
|
||||||
|
String label2 = TestUtils.getRandomString(42);
|
||||||
|
// Calculate the signature with different inputs
|
||||||
|
// the results should be different
|
||||||
|
byte[] sig1 = crypto.sign(label, inputBytes, privateKey);
|
||||||
|
byte[] sig2 = crypto.sign(label2, inputBytes, privateKey);
|
||||||
|
assertFalse(Arrays.equals(sig1, sig2));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSignatureVerification() throws Exception {
|
||||||
|
byte[] sig = crypto.sign(label, inputBytes, privateKey);
|
||||||
|
assertTrue(crypto.verify(label, inputBytes, publicKey, sig));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDifferentKeyFailsVerification() throws Exception {
|
||||||
|
// Generate second private key
|
||||||
|
KeyPair k2 = crypto.generateSignatureKeyPair();
|
||||||
|
byte[] privateKey2 = k2.getPrivate().getEncoded();
|
||||||
|
// calculate the signature with different key, should fail to verify
|
||||||
|
byte[] sig = crypto.sign(label, inputBytes, privateKey2);
|
||||||
|
assertFalse(crypto.verify(label, inputBytes, publicKey, sig));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDifferentInputFailsVerification() throws Exception {
|
||||||
|
// Generate a second input
|
||||||
|
byte[] inputBytes2 = TestUtils.getRandomBytes(123);
|
||||||
|
// calculate the signature with different input, should fail to verify
|
||||||
|
byte[] sig = crypto.sign(label, inputBytes, privateKey);
|
||||||
|
assertFalse(crypto.verify(label, inputBytes2, publicKey, sig));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDifferentLabelFailsVerification() throws Exception {
|
||||||
|
// Generate a second label
|
||||||
|
String label2 = TestUtils.getRandomString(42);
|
||||||
|
// calculate the signature with different label, should fail to verify
|
||||||
|
byte[] sig = crypto.sign(label, inputBytes, privateKey);
|
||||||
|
assertFalse(crypto.verify(label2, inputBytes, publicKey, sig));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -19,6 +19,7 @@ import java.security.GeneralSecurityException;
|
|||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|
||||||
import static org.briarproject.api.forum.ForumConstants.MAX_FORUM_POST_BODY_LENGTH;
|
import static org.briarproject.api.forum.ForumConstants.MAX_FORUM_POST_BODY_LENGTH;
|
||||||
|
import static org.briarproject.api.forum.ForumPostFactory.SIGNING_LABEL_POST;
|
||||||
import static org.briarproject.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH;
|
import static org.briarproject.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH;
|
||||||
import static org.briarproject.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
|
import static org.briarproject.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
|
||||||
import static org.briarproject.api.identity.AuthorConstants.MAX_SIGNATURE_LENGTH;
|
import static org.briarproject.api.identity.AuthorConstants.MAX_SIGNATURE_LENGTH;
|
||||||
@@ -70,8 +71,8 @@ public class ForumPostValidatorTest extends ValidatorTestCase {
|
|||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
oneOf(authorFactory).createAuthor(authorName, authorPublicKey);
|
oneOf(authorFactory).createAuthor(authorName, authorPublicKey);
|
||||||
will(returnValue(author));
|
will(returnValue(author));
|
||||||
oneOf(clientHelper).verifySignature(signature, authorPublicKey,
|
oneOf(clientHelper).verifySignature(SIGNING_LABEL_POST, signature,
|
||||||
signedWithoutParent);
|
authorPublicKey, signedWithoutParent);
|
||||||
}});
|
}});
|
||||||
|
|
||||||
ForumPostValidator v = new ForumPostValidator(authorFactory,
|
ForumPostValidator v = new ForumPostValidator(authorFactory,
|
||||||
@@ -179,8 +180,8 @@ public class ForumPostValidatorTest extends ValidatorTestCase {
|
|||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
oneOf(authorFactory).createAuthor(shortAuthorName, authorPublicKey);
|
oneOf(authorFactory).createAuthor(shortAuthorName, authorPublicKey);
|
||||||
will(returnValue(shortNameAuthor));
|
will(returnValue(shortNameAuthor));
|
||||||
oneOf(clientHelper).verifySignature(signature, authorPublicKey,
|
oneOf(clientHelper).verifySignature(SIGNING_LABEL_POST, signature,
|
||||||
signedWithShortNameAuthor);
|
authorPublicKey, signedWithShortNameAuthor);
|
||||||
}});
|
}});
|
||||||
|
|
||||||
ForumPostValidator v = new ForumPostValidator(authorFactory,
|
ForumPostValidator v = new ForumPostValidator(authorFactory,
|
||||||
@@ -267,8 +268,8 @@ public class ForumPostValidatorTest extends ValidatorTestCase {
|
|||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
oneOf(authorFactory).createAuthor(authorName, authorPublicKey);
|
oneOf(authorFactory).createAuthor(authorName, authorPublicKey);
|
||||||
will(returnValue(author));
|
will(returnValue(author));
|
||||||
oneOf(clientHelper).verifySignature(signature, authorPublicKey,
|
oneOf(clientHelper).verifySignature(SIGNING_LABEL_POST, signature,
|
||||||
signedWithShortContent);
|
authorPublicKey, signedWithShortContent);
|
||||||
}});
|
}});
|
||||||
|
|
||||||
ForumPostValidator v = new ForumPostValidator(authorFactory,
|
ForumPostValidator v = new ForumPostValidator(authorFactory,
|
||||||
@@ -342,8 +343,8 @@ public class ForumPostValidatorTest extends ValidatorTestCase {
|
|||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
oneOf(authorFactory).createAuthor(authorName, authorPublicKey);
|
oneOf(authorFactory).createAuthor(authorName, authorPublicKey);
|
||||||
will(returnValue(author));
|
will(returnValue(author));
|
||||||
oneOf(clientHelper).verifySignature(signature, authorPublicKey,
|
oneOf(clientHelper).verifySignature(SIGNING_LABEL_POST, signature,
|
||||||
signedWithParent);
|
authorPublicKey, signedWithParent);
|
||||||
will(throwException(new FormatException()));
|
will(throwException(new FormatException()));
|
||||||
}});
|
}});
|
||||||
|
|
||||||
@@ -359,8 +360,8 @@ public class ForumPostValidatorTest extends ValidatorTestCase {
|
|||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
oneOf(authorFactory).createAuthor(authorName, authorPublicKey);
|
oneOf(authorFactory).createAuthor(authorName, authorPublicKey);
|
||||||
will(returnValue(author));
|
will(returnValue(author));
|
||||||
oneOf(clientHelper).verifySignature(signature, authorPublicKey,
|
oneOf(clientHelper).verifySignature(SIGNING_LABEL_POST, signature,
|
||||||
signedWithParent);
|
authorPublicKey, signedWithParent);
|
||||||
will(throwException(new GeneralSecurityException()));
|
will(throwException(new GeneralSecurityException()));
|
||||||
}});
|
}});
|
||||||
|
|
||||||
|
|||||||
@@ -10,10 +10,7 @@ import org.briarproject.api.contact.Contact;
|
|||||||
import org.briarproject.api.contact.ContactId;
|
import org.briarproject.api.contact.ContactId;
|
||||||
import org.briarproject.api.contact.ContactManager;
|
import org.briarproject.api.contact.ContactManager;
|
||||||
import org.briarproject.api.crypto.CryptoComponent;
|
import org.briarproject.api.crypto.CryptoComponent;
|
||||||
import org.briarproject.api.crypto.KeyParser;
|
|
||||||
import org.briarproject.api.crypto.PublicKey;
|
|
||||||
import org.briarproject.api.crypto.SecretKey;
|
import org.briarproject.api.crypto.SecretKey;
|
||||||
import org.briarproject.api.crypto.Signature;
|
|
||||||
import org.briarproject.api.data.BdfDictionary;
|
import org.briarproject.api.data.BdfDictionary;
|
||||||
import org.briarproject.api.data.BdfEntry;
|
import org.briarproject.api.data.BdfEntry;
|
||||||
import org.briarproject.api.data.BdfList;
|
import org.briarproject.api.data.BdfList;
|
||||||
@@ -77,6 +74,7 @@ import static org.briarproject.api.introduction.IntroductionConstants.TYPE_ACK;
|
|||||||
import static org.briarproject.api.introduction.IntroductionConstants.TYPE_REQUEST;
|
import static org.briarproject.api.introduction.IntroductionConstants.TYPE_REQUEST;
|
||||||
import static org.briarproject.api.introduction.IntroductionConstants.TYPE_RESPONSE;
|
import static org.briarproject.api.introduction.IntroductionConstants.TYPE_RESPONSE;
|
||||||
import static org.briarproject.api.sync.SyncConstants.MESSAGE_HEADER_LENGTH;
|
import static org.briarproject.api.sync.SyncConstants.MESSAGE_HEADER_LENGTH;
|
||||||
|
import static org.briarproject.introduction.IntroduceeManager.SIGNING_LABEL_RESPONSE;
|
||||||
import static org.hamcrest.Matchers.array;
|
import static org.hamcrest.Matchers.array;
|
||||||
import static org.hamcrest.Matchers.samePropertyValuesAs;
|
import static org.hamcrest.Matchers.samePropertyValuesAs;
|
||||||
import static org.junit.Assert.assertFalse;
|
import static org.junit.Assert.assertFalse;
|
||||||
@@ -91,11 +89,8 @@ public class IntroduceeManagerTest extends BriarTestCase {
|
|||||||
private final CryptoComponent cryptoComponent;
|
private final CryptoComponent cryptoComponent;
|
||||||
private final ClientHelper clientHelper;
|
private final ClientHelper clientHelper;
|
||||||
private final IntroductionGroupFactory introductionGroupFactory;
|
private final IntroductionGroupFactory introductionGroupFactory;
|
||||||
private final MessageSender messageSender;
|
|
||||||
private final TransportPropertyManager transportPropertyManager;
|
|
||||||
private final AuthorFactory authorFactory;
|
private final AuthorFactory authorFactory;
|
||||||
private final ContactManager contactManager;
|
private final ContactManager contactManager;
|
||||||
private final IdentityManager identityManager;
|
|
||||||
private final Clock clock;
|
private final Clock clock;
|
||||||
private final Contact introducer;
|
private final Contact introducer;
|
||||||
private final Contact introducee1;
|
private final Contact introducee1;
|
||||||
@@ -105,24 +100,24 @@ public class IntroduceeManagerTest extends BriarTestCase {
|
|||||||
private final Transaction txn;
|
private final Transaction txn;
|
||||||
private final long time = 42L;
|
private final long time = 42L;
|
||||||
private final Message localStateMessage;
|
private final Message localStateMessage;
|
||||||
private final ClientId clientId;
|
|
||||||
private final SessionId sessionId;
|
private final SessionId sessionId;
|
||||||
private final Message message1;
|
private final Message message1;
|
||||||
|
|
||||||
public IntroduceeManagerTest() {
|
public IntroduceeManagerTest() {
|
||||||
context = new Mockery();
|
context = new Mockery();
|
||||||
context.setImposteriser(ClassImposteriser.INSTANCE);
|
context.setImposteriser(ClassImposteriser.INSTANCE);
|
||||||
messageSender = context.mock(MessageSender.class);
|
MessageSender messageSender = context.mock(MessageSender.class);
|
||||||
db = context.mock(DatabaseComponent.class);
|
db = context.mock(DatabaseComponent.class);
|
||||||
cryptoComponent = context.mock(CryptoComponent.class);
|
cryptoComponent = context.mock(CryptoComponent.class);
|
||||||
clientHelper = context.mock(ClientHelper.class);
|
clientHelper = context.mock(ClientHelper.class);
|
||||||
clock = context.mock(Clock.class);
|
clock = context.mock(Clock.class);
|
||||||
introductionGroupFactory =
|
introductionGroupFactory =
|
||||||
context.mock(IntroductionGroupFactory.class);
|
context.mock(IntroductionGroupFactory.class);
|
||||||
transportPropertyManager = context.mock(TransportPropertyManager.class);
|
TransportPropertyManager transportPropertyManager =
|
||||||
|
context.mock(TransportPropertyManager.class);
|
||||||
authorFactory = context.mock(AuthorFactory.class);
|
authorFactory = context.mock(AuthorFactory.class);
|
||||||
contactManager = context.mock(ContactManager.class);
|
contactManager = context.mock(ContactManager.class);
|
||||||
identityManager = context.mock(IdentityManager.class);
|
IdentityManager identityManager = context.mock(IdentityManager.class);
|
||||||
|
|
||||||
introduceeManager = new IntroduceeManager(messageSender, db,
|
introduceeManager = new IntroduceeManager(messageSender, db,
|
||||||
clientHelper, clock, cryptoComponent, transportPropertyManager,
|
clientHelper, clock, cryptoComponent, transportPropertyManager,
|
||||||
@@ -152,7 +147,7 @@ public class IntroduceeManagerTest extends BriarTestCase {
|
|||||||
introducee2 =
|
introducee2 =
|
||||||
new Contact(contactId2, author2, localAuthorId, true, true);
|
new Contact(contactId2, author2, localAuthorId, true, true);
|
||||||
|
|
||||||
clientId = IntroductionManagerImpl.CLIENT_ID;
|
ClientId clientId = IntroductionManagerImpl.CLIENT_ID;
|
||||||
localGroup1 = new Group(new GroupId(TestUtils.getRandomId()),
|
localGroup1 = new Group(new GroupId(TestUtils.getRandomId()),
|
||||||
clientId, new byte[0]);
|
clientId, new byte[0]);
|
||||||
introductionGroup1 = new Group(new GroupId(TestUtils.getRandomId()),
|
introductionGroup1 = new Group(new GroupId(TestUtils.getRandomId()),
|
||||||
@@ -270,20 +265,9 @@ public class IntroduceeManagerTest extends BriarTestCase {
|
|||||||
new BdfEntry(SIGNATURE, sig)
|
new BdfEntry(SIGNATURE, sig)
|
||||||
);
|
);
|
||||||
|
|
||||||
final KeyParser keyParser = context.mock(KeyParser.class);
|
|
||||||
final PublicKey publicKey = context.mock(PublicKey.class);
|
|
||||||
final Signature signature = context.mock(Signature.class);
|
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
oneOf(cryptoComponent).getSignatureKeyParser();
|
oneOf(cryptoComponent).verify(SIGNING_LABEL_RESPONSE, nonce,
|
||||||
will(returnValue(keyParser));
|
introducee2.getAuthor().getPublicKey(), sig);
|
||||||
oneOf(keyParser)
|
|
||||||
.parsePublicKey(introducee2.getAuthor().getPublicKey());
|
|
||||||
will(returnValue(publicKey));
|
|
||||||
oneOf(cryptoComponent).getSignature();
|
|
||||||
will(returnValue(signature));
|
|
||||||
oneOf(signature).initVerify(publicKey);
|
|
||||||
oneOf(signature).update(nonce);
|
|
||||||
oneOf(signature).verify(sig);
|
|
||||||
will(returnValue(false));
|
will(returnValue(false));
|
||||||
}});
|
}});
|
||||||
|
|
||||||
@@ -311,19 +295,9 @@ public class IntroduceeManagerTest extends BriarTestCase {
|
|||||||
state.put(NONCE, nonce);
|
state.put(NONCE, nonce);
|
||||||
state.put(SIGNATURE, sig);
|
state.put(SIGNATURE, sig);
|
||||||
|
|
||||||
final KeyParser keyParser = context.mock(KeyParser.class);
|
|
||||||
final Signature signature = context.mock(Signature.class);
|
|
||||||
final PublicKey publicKey = context.mock(PublicKey.class);
|
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
oneOf(cryptoComponent).getSignatureKeyParser();
|
oneOf(cryptoComponent).verify(SIGNING_LABEL_RESPONSE, nonce,
|
||||||
will(returnValue(keyParser));
|
publicKeyBytes, sig);
|
||||||
oneOf(keyParser).parsePublicKey(publicKeyBytes);
|
|
||||||
will(returnValue(publicKey));
|
|
||||||
oneOf(cryptoComponent).getSignature();
|
|
||||||
will(returnValue(signature));
|
|
||||||
oneOf(signature).initVerify(publicKey);
|
|
||||||
oneOf(signature).update(nonce);
|
|
||||||
oneOf(signature).verify(sig);
|
|
||||||
will(returnValue(true));
|
will(returnValue(true));
|
||||||
}});
|
}});
|
||||||
introduceeManager.verifySignature(state);
|
introduceeManager.verifySignature(state);
|
||||||
|
|||||||
Reference in New Issue
Block a user