From c86d971166215eb31f7e0a13cc9d7620b8f19123 Mon Sep 17 00:00:00 2001 From: Torsten Grote <t@grobox.de> Date: Thu, 17 Nov 2016 16:36:51 -0200 Subject: [PATCH] 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. --- .../briarproject/PrivateGroupManagerTest.java | 62 ++++++++----------- .../api/blogs/BlogPostFactory.java | 5 ++ .../api/clients/ClientHelper.java | 6 +- .../api/crypto/CryptoComponent.java | 20 ++++++ .../api/forum/ForumPostFactory.java | 4 ++ .../api/privategroup/GroupMessageFactory.java | 6 +- .../invitation/GroupInvitationFactory.java | 5 ++ .../blogs/BlogPostFactoryImpl.java | 6 +- .../briarproject/blogs/BlogPostValidator.java | 9 ++- .../clients/ClientHelperImpl.java | 17 ++--- .../crypto/CryptoComponentImpl.java | 22 +++++++ .../forum/ForumPostFactoryImpl.java | 3 +- .../forum/ForumPostValidator.java | 4 +- .../privategroup/GroupMessageFactoryImpl.java | 8 +-- .../privategroup/GroupMessageValidator.java | 13 ++-- .../GroupInvitationFactoryImpl.java | 3 +- .../invitation/GroupInvitationValidator.java | 5 +- .../blogs/BlogPostValidatorTest.java | 18 +++--- .../clients/ClientHelperImplTest.java | 28 +++------ .../forum/ForumPostValidatorTest.java | 21 ++++--- 20 files changed, 158 insertions(+), 107 deletions(-) diff --git a/briar-android-tests/src/test/java/org/briarproject/PrivateGroupManagerTest.java b/briar-android-tests/src/test/java/org/briarproject/PrivateGroupManagerTest.java index d7c9c051dc..ab8fa52cc1 100644 --- a/briar-android-tests/src/test/java/org/briarproject/PrivateGroupManagerTest.java +++ b/briar-android-tests/src/test/java/org/briarproject/PrivateGroupManagerTest.java @@ -5,6 +5,7 @@ import net.jodah.concurrentunit.Waiter; import org.briarproject.api.clients.ClientHelper; import org.briarproject.api.clients.ContactGroupFactory; import org.briarproject.api.clients.MessageTracker.GroupCount; +import org.briarproject.api.contact.Contact; import org.briarproject.api.contact.ContactId; import org.briarproject.api.contact.ContactManager; 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.PrivateGroupFactory; 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.MessageId; 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_US; 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.ValidationManager.State.DELIVERED; import static org.briarproject.api.sync.ValidationManager.State.INVALID; @@ -103,6 +104,8 @@ public class PrivateGroupManagerTest extends BriarIntegrationTest { PrivateGroupFactory privateGroupFactory; @Inject GroupMessageFactory groupMessageFactory; + @Inject + GroupInvitationFactory groupInvitationFactory; // objects accessed from background threads need to be volatile private volatile Waiter validationWaiter; @@ -358,13 +361,10 @@ public class PrivateGroupManagerTest extends BriarIntegrationTest { // author1 joins privateGroup0 with wrong timestamp joinTime = clock.currentTimeMillis(); long inviteTime = joinTime; - Group invitationGroup = contactGroupFactory - .createContactGroup(CLIENT_ID, author0.getId(), - author1.getId()); - BdfList toSign = BdfList.of(0, inviteTime, invitationGroup.getId(), - privateGroup0.getId()); - byte[] creatorSignature = - clientHelper.sign(toSign, author0.getPrivateKey()); + Contact c1 = contactManager0.getContact(contactId1); + byte[] creatorSignature = groupInvitationFactory + .signInvitation(c1, privateGroup0.getId(), inviteTime, + author0.getPrivateKey()); GroupMessage joinMsg1 = groupMessageFactory .createJoinMessage(privateGroup0.getId(), joinTime, author1, inviteTime, creatorSignature); @@ -402,13 +402,11 @@ public class PrivateGroupManagerTest extends BriarIntegrationTest { // author0 joins privateGroup0 with wrong member's join message long joinTime = clock.currentTimeMillis(); long inviteTime = joinTime - 1; - Group invitationGroup = contactGroupFactory - .createContactGroup(CLIENT_ID, author0.getId(), - author0.getId()); - BdfList toSign = BdfList.of(0, inviteTime, invitationGroup.getId(), - privateGroup0.getId()); - byte[] creatorSignature = - clientHelper.sign(toSign, author0.getPrivateKey()); + BdfList toSign = groupInvitationFactory + .createInviteToken(author0.getId(), author0.getId(), + privateGroup0.getId(), inviteTime); + byte[] creatorSignature = clientHelper + .sign(SIGNING_LABEL_INVITE, toSign, author0.getPrivateKey()); // join message should not include invite time and creator's signature GroupMessage joinMsg0 = groupMessageFactory .createJoinMessage(privateGroup0.getId(), joinTime, author0, @@ -426,13 +424,11 @@ public class PrivateGroupManagerTest extends BriarIntegrationTest { // author1 joins privateGroup0 with wrong signature in join message joinTime = clock.currentTimeMillis(); 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 - creatorSignature = clientHelper.sign(toSign, author1.getPrivateKey()); + Contact c1 = contactManager0.getContact(contactId1); + creatorSignature = groupInvitationFactory + .signInvitation(c1, privateGroup0.getId(), inviteTime, + author1.getPrivateKey()); GroupMessage joinMsg1 = groupMessageFactory .createJoinMessage(privateGroup0.getId(), joinTime, author1, inviteTime, creatorSignature); @@ -529,13 +525,10 @@ public class PrivateGroupManagerTest extends BriarIntegrationTest { // author2 joins privateGroup0 long joinTime = clock.currentTimeMillis(); long inviteTime = joinTime - 1; - Group invitationGroup = contactGroupFactory - .createContactGroup(CLIENT_ID, author0.getId(), - author2.getId()); - BdfList toSign = BdfList.of(0, inviteTime, invitationGroup.getId(), - privateGroup0.getId()); - byte[] creatorSignature = - clientHelper.sign(toSign, author0.getPrivateKey()); + Contact c2 = contactManager0.getContact(contactId2); + byte[] creatorSignature = groupInvitationFactory + .signInvitation(c2, privateGroup0.getId(), inviteTime, + author0.getPrivateKey()); GroupMessage joinMsg2 = groupMessageFactory .createJoinMessage(privateGroup0.getId(), joinTime, author2, inviteTime, creatorSignature); @@ -753,13 +746,10 @@ public class PrivateGroupManagerTest extends BriarIntegrationTest { // author1 joins privateGroup0 joinTime = clock.currentTimeMillis(); long inviteTime = joinTime - 1; - Group invitationGroup = contactGroupFactory - .createContactGroup(CLIENT_ID, author0.getId(), - author1.getId()); - BdfList toSign = BdfList.of(0, inviteTime, invitationGroup.getId(), - privateGroup0.getId()); - byte[] creatorSignature = - clientHelper.sign(toSign, author0.getPrivateKey()); + Contact c1 = contactManager0.getContact(contactId1); + byte[] creatorSignature = groupInvitationFactory + .signInvitation(c1, privateGroup0.getId(), inviteTime, + author0.getPrivateKey()); GroupMessage joinMsg1 = groupMessageFactory .createJoinMessage(privateGroup0.getId(), joinTime, author1, inviteTime, creatorSignature); diff --git a/briar-api/src/org/briarproject/api/blogs/BlogPostFactory.java b/briar-api/src/org/briarproject/api/blogs/BlogPostFactory.java index 7b05c0078e..4f8292720a 100644 --- a/briar-api/src/org/briarproject/api/blogs/BlogPostFactory.java +++ b/briar-api/src/org/briarproject/api/blogs/BlogPostFactory.java @@ -11,8 +11,13 @@ import org.jetbrains.annotations.Nullable; import java.security.GeneralSecurityException; +import static org.briarproject.api.blogs.BlogManager.CLIENT_ID; + public interface BlogPostFactory { + String SIGNING_LABEL_POST = CLIENT_ID + "/POST"; + String SIGNING_LABEL_COMMENT = CLIENT_ID + "/COMMENT"; + BlogPost createBlogPost(@NotNull GroupId groupId, long timestamp, @Nullable MessageId parent, @NotNull LocalAuthor author, @NotNull String body) diff --git a/briar-api/src/org/briarproject/api/clients/ClientHelper.java b/briar-api/src/org/briarproject/api/clients/ClientHelper.java index 7743f3ba5e..32af81f627 100644 --- a/briar-api/src/org/briarproject/api/clients/ClientHelper.java +++ b/briar-api/src/org/briarproject/api/clients/ClientHelper.java @@ -92,10 +92,10 @@ public interface ClientHelper { BdfList toList(Message m) throws FormatException; - byte[] sign(BdfList toSign, byte[] privateKey) + byte[] sign(String label, BdfList toSign, byte[] privateKey) throws FormatException, GeneralSecurityException; - void verifySignature(byte[] sig, byte[] publicKey, BdfList signed) - throws FormatException, GeneralSecurityException; + void verifySignature(String label, byte[] sig, byte[] publicKey, + BdfList signed) throws FormatException, GeneralSecurityException; } diff --git a/briar-api/src/org/briarproject/api/crypto/CryptoComponent.java b/briar-api/src/org/briarproject/api/crypto/CryptoComponent.java index 50a9c94d56..90830ac1d5 100644 --- a/briar-api/src/org/briarproject/api/crypto/CryptoComponent.java +++ b/briar-api/src/org/briarproject/api/crypto/CryptoComponent.java @@ -143,6 +143,26 @@ public interface CryptoComponent { /** Encodes the pseudo-random tag that is used to recognise a stream. */ 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, PrivateKey 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, PublicKey publicKey, + byte[] signature) throws GeneralSecurityException; + /** * Returns the hash of the given inputs. The inputs are unambiguously * combined by prefixing each input with its length. diff --git a/briar-api/src/org/briarproject/api/forum/ForumPostFactory.java b/briar-api/src/org/briarproject/api/forum/ForumPostFactory.java index 820a11acc2..d5b8d9b356 100644 --- a/briar-api/src/org/briarproject/api/forum/ForumPostFactory.java +++ b/briar-api/src/org/briarproject/api/forum/ForumPostFactory.java @@ -8,8 +8,12 @@ import org.briarproject.api.sync.MessageId; import java.security.GeneralSecurityException; +import static org.briarproject.api.forum.ForumManager.CLIENT_ID; + public interface ForumPostFactory { + String SIGNING_LABEL_POST = CLIENT_ID + "/POST"; + @CryptoExecutor ForumPost createPost(GroupId groupId, long timestamp, MessageId parent, LocalAuthor author, String body) diff --git a/briar-api/src/org/briarproject/api/privategroup/GroupMessageFactory.java b/briar-api/src/org/briarproject/api/privategroup/GroupMessageFactory.java index ff1b72e84f..220e958fc0 100644 --- a/briar-api/src/org/briarproject/api/privategroup/GroupMessageFactory.java +++ b/briar-api/src/org/briarproject/api/privategroup/GroupMessageFactory.java @@ -1,16 +1,20 @@ package org.briarproject.api.privategroup; import org.briarproject.api.crypto.CryptoExecutor; -import org.briarproject.api.identity.Author; import org.briarproject.api.identity.LocalAuthor; import org.briarproject.api.nullsafety.NotNullByDefault; import org.briarproject.api.sync.GroupId; import org.briarproject.api.sync.MessageId; import org.jetbrains.annotations.Nullable; +import static org.briarproject.api.privategroup.PrivateGroupManager.CLIENT_ID; + @NotNullByDefault 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. * diff --git a/briar-api/src/org/briarproject/api/privategroup/invitation/GroupInvitationFactory.java b/briar-api/src/org/briarproject/api/privategroup/invitation/GroupInvitationFactory.java index e5cf41adf7..fdde77abe3 100644 --- a/briar-api/src/org/briarproject/api/privategroup/invitation/GroupInvitationFactory.java +++ b/briar-api/src/org/briarproject/api/privategroup/invitation/GroupInvitationFactory.java @@ -6,8 +6,12 @@ import org.briarproject.api.data.BdfList; import org.briarproject.api.identity.AuthorId; import org.briarproject.api.sync.GroupId; +import static org.briarproject.api.privategroup.invitation.GroupInvitationManager.CLIENT_ID; + public interface GroupInvitationFactory { + String SIGNING_LABEL_INVITE = CLIENT_ID + "/INVITE"; + /** * Returns a signature to include when inviting a member to join a private * group. If the member accepts the invitation, the signature will be @@ -24,4 +28,5 @@ public interface GroupInvitationFactory { */ BdfList createInviteToken(AuthorId creatorId, AuthorId memberId, GroupId privateGroupId, long timestamp); + } diff --git a/briar-core/src/org/briarproject/blogs/BlogPostFactoryImpl.java b/briar-core/src/org/briarproject/blogs/BlogPostFactoryImpl.java index fdab87cac6..52cbc72a76 100644 --- a/briar-core/src/org/briarproject/blogs/BlogPostFactoryImpl.java +++ b/briar-core/src/org/briarproject/blogs/BlogPostFactoryImpl.java @@ -52,7 +52,8 @@ class BlogPostFactoryImpl implements BlogPostFactory { BdfList signed = BdfList.of(groupId, timestamp, body); // Generate the signature - byte[] sig = clientHelper.sign(signed, author.getPrivateKey()); + byte[] sig = clientHelper + .sign(SIGNING_LABEL_POST, signed, author.getPrivateKey()); // Serialise the signed message BdfList message = BdfList.of(POST.getInt(), body, sig); @@ -77,7 +78,8 @@ class BlogPostFactoryImpl implements BlogPostFactory { // Generate the signature BdfList signed = 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 BdfList message = diff --git a/briar-core/src/org/briarproject/blogs/BlogPostValidator.java b/briar-core/src/org/briarproject/blogs/BlogPostValidator.java index 088354fc16..4b7dd148e3 100644 --- a/briar-core/src/org/briarproject/blogs/BlogPostValidator.java +++ b/briar-core/src/org/briarproject/blogs/BlogPostValidator.java @@ -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.MAX_BLOG_COMMENT_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.POST; import static org.briarproject.api.identity.AuthorConstants.MAX_SIGNATURE_LENGTH; @@ -105,7 +107,9 @@ class BlogPostValidator extends BdfMessageValidator { Blog b = blogFactory.parseBlog(g); Author a = b.getAuthor(); try { - clientHelper.verifySignature(sig, a.getPublicKey(), signed); + clientHelper + .verifySignature(SIGNING_LABEL_POST, sig, a.getPublicKey(), + signed); } catch (GeneralSecurityException e) { throw new InvalidMessageException(e); } @@ -150,7 +154,8 @@ class BlogPostValidator extends BdfMessageValidator { Blog b = blogFactory.parseBlog(g); Author a = b.getAuthor(); try { - clientHelper.verifySignature(sig, a.getPublicKey(), signed); + clientHelper.verifySignature(SIGNING_LABEL_COMMENT, sig, + a.getPublicKey(), signed); } catch (GeneralSecurityException e) { throw new InvalidMessageException(e); } diff --git a/briar-core/src/org/briarproject/clients/ClientHelperImpl.java b/briar-core/src/org/briarproject/clients/ClientHelperImpl.java index 7356ca1d1c..77a3caad1f 100644 --- a/briar-core/src/org/briarproject/clients/ClientHelperImpl.java +++ b/briar-core/src/org/briarproject/clients/ClientHelperImpl.java @@ -6,7 +6,6 @@ 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.BdfList; import org.briarproject.api.data.BdfReader; @@ -346,27 +345,21 @@ class ClientHelperImpl implements ClientHelper { } @Override - public byte[] sign(BdfList toSign, byte[] privateKey) + public byte[] sign(String label, BdfList toSign, byte[] privateKey) throws FormatException, GeneralSecurityException { - Signature signature = crypto.getSignature(); KeyParser keyParser = crypto.getSignatureKeyParser(); PrivateKey key = keyParser.parsePrivateKey(privateKey); - signature.initSign(key); - signature.update(toByteArray(toSign)); - return signature.sign(); + return crypto.sign(label, toByteArray(toSign), key); } @Override - public void verifySignature(byte[] sig, byte[] publicKey, BdfList signed) - throws FormatException, GeneralSecurityException { + public void verifySignature(String label, byte[] sig, byte[] publicKey, + BdfList signed) throws FormatException, GeneralSecurityException { // Parse the public key 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)) { + if (!crypto.verify(label, toByteArray(signed), key, sig)) { throw new GeneralSecurityException("Invalid signature"); } } diff --git a/briar-core/src/org/briarproject/crypto/CryptoComponentImpl.java b/briar-core/src/org/briarproject/crypto/CryptoComponentImpl.java index 22698a22ff..3ce6e0e61a 100644 --- a/briar-core/src/org/briarproject/crypto/CryptoComponentImpl.java +++ b/briar-core/src/org/briarproject/crypto/CryptoComponentImpl.java @@ -1,5 +1,7 @@ package org.briarproject.crypto; +import com.google.common.primitives.Bytes; + import org.briarproject.api.TransportId; import org.briarproject.api.crypto.CryptoComponent; import org.briarproject.api.crypto.KeyPair; @@ -399,6 +401,26 @@ class CryptoComponentImpl implements CryptoComponent { System.arraycopy(mac, 0, tag, 0, TAG_LENGTH); } + @Override + public byte[] sign(String label, byte[] toSign, PrivateKey privateKey) + throws GeneralSecurityException { + Signature signature = getSignature(); + signature.initSign(privateKey); + toSign = Bytes.concat(StringUtils.toUtf8(label), toSign); + signature.update(toSign); + return signature.sign(); + } + + @Override + public boolean verify(String label, byte[] signedData, PublicKey publicKey, + byte[] signature) throws GeneralSecurityException { + Signature sig = getSignature(); + sig.initVerify(publicKey); + signedData = Bytes.concat(StringUtils.toUtf8(label), signedData); + sig.update(signedData); + return sig.verify(signature); + } + @Override public byte[] hash(byte[]... inputs) { MessageDigest digest = getMessageDigest(); diff --git a/briar-core/src/org/briarproject/forum/ForumPostFactoryImpl.java b/briar-core/src/org/briarproject/forum/ForumPostFactoryImpl.java index f4ddfad0f0..70a545e1f9 100644 --- a/briar-core/src/org/briarproject/forum/ForumPostFactoryImpl.java +++ b/briar-core/src/org/briarproject/forum/ForumPostFactoryImpl.java @@ -39,7 +39,8 @@ class ForumPostFactoryImpl implements ForumPostFactory { BdfList signed = BdfList.of(groupId, timestamp, parent, authorList, body); // Sign the data - byte[] sig = clientHelper.sign(signed, author.getPrivateKey()); + byte[] sig = clientHelper + .sign(SIGNING_LABEL_POST, signed, author.getPrivateKey()); // Serialise the signed message BdfList message = BdfList.of(parent, authorList, body, sig); Message m = clientHelper.createMessage(groupId, timestamp, message); diff --git a/briar-core/src/org/briarproject/forum/ForumPostValidator.java b/briar-core/src/org/briarproject/forum/ForumPostValidator.java index 19e62584c8..b7d2f70660 100644 --- a/briar-core/src/org/briarproject/forum/ForumPostValidator.java +++ b/briar-core/src/org/briarproject/forum/ForumPostValidator.java @@ -22,6 +22,7 @@ import java.util.Collection; import java.util.Collections; 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_PUBLIC_KEY_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, authorList, forumPostBody); try { - clientHelper.verifySignature(sig, author.getPublicKey(), signed); + clientHelper.verifySignature(SIGNING_LABEL_POST, sig, + author.getPublicKey(), signed); } catch (GeneralSecurityException e) { throw new InvalidMessageException(e); } diff --git a/briar-core/src/org/briarproject/privategroup/GroupMessageFactoryImpl.java b/briar-core/src/org/briarproject/privategroup/GroupMessageFactoryImpl.java index aeb478001b..71d6ebbeef 100644 --- a/briar-core/src/org/briarproject/privategroup/GroupMessageFactoryImpl.java +++ b/briar-core/src/org/briarproject/privategroup/GroupMessageFactoryImpl.java @@ -51,8 +51,8 @@ class GroupMessageFactoryImpl implements GroupMessageFactory { int type = JOIN.getInt(); BdfList toSign = BdfList.of(groupId, timestamp, type, member.getName(), member.getPublicKey(), invite); - byte[] memberSignature = - clientHelper.sign(toSign, member.getPrivateKey()); + byte[] memberSignature = clientHelper + .sign(SIGNING_LABEL_JOIN, toSign, member.getPrivateKey()); // Compose the message BdfList body = @@ -78,8 +78,8 @@ class GroupMessageFactoryImpl implements GroupMessageFactory { BdfList toSign = BdfList.of(groupId, timestamp, type, author.getName(), author.getPublicKey(), parentId, previousMsgId, content); - byte[] signature = - clientHelper.sign(toSign, author.getPrivateKey()); + byte[] signature = clientHelper + .sign(SIGNING_LABEL_POST, toSign, author.getPrivateKey()); // Compose the message BdfList body = diff --git a/briar-core/src/org/briarproject/privategroup/GroupMessageValidator.java b/briar-core/src/org/briarproject/privategroup/GroupMessageValidator.java index a80f1ce4b5..7e27d74685 100644 --- a/briar-core/src/org/briarproject/privategroup/GroupMessageValidator.java +++ b/briar-core/src/org/briarproject/privategroup/GroupMessageValidator.java @@ -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_PUBLIC_KEY_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.POST; 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_MEMBER_ID; import static org.briarproject.privategroup.GroupConstants.KEY_MEMBER_NAME; @@ -130,7 +133,7 @@ class GroupMessageValidator extends BdfMessageValidator { .createInviteToken(creator.getId(), member.getId(), pg.getId(), inviteTimestamp); try { - clientHelper.verifySignature(creatorSignature, + clientHelper.verifySignature(SIGNING_LABEL_INVITE, creatorSignature, creator.getPublicKey(), token); } catch (GeneralSecurityException e) { throw new InvalidMessageException(e); @@ -146,8 +149,8 @@ class GroupMessageValidator extends BdfMessageValidator { BdfList signed = BdfList.of(g.getId(), m.getTimestamp(), JOIN.getInt(), member.getName(), member.getPublicKey(), invite); try { - clientHelper.verifySignature(memberSignature, member.getPublicKey(), - signed); + clientHelper.verifySignature(SIGNING_LABEL_JOIN, memberSignature, + member.getPublicKey(), signed); } catch (GeneralSecurityException e) { throw new InvalidMessageException(e); } @@ -189,8 +192,8 @@ class GroupMessageValidator extends BdfMessageValidator { member.getName(), member.getPublicKey(), parentId, previousMessageId, content); try { - clientHelper - .verifySignature(signature, member.getPublicKey(), signed); + clientHelper.verifySignature(SIGNING_LABEL_POST, signature, + member.getPublicKey(), signed); } catch (GeneralSecurityException e) { throw new InvalidMessageException(e); } diff --git a/briar-core/src/org/briarproject/privategroup/invitation/GroupInvitationFactoryImpl.java b/briar-core/src/org/briarproject/privategroup/invitation/GroupInvitationFactoryImpl.java index 3e9b8c88c6..502d4f0761 100644 --- a/briar-core/src/org/briarproject/privategroup/invitation/GroupInvitationFactoryImpl.java +++ b/briar-core/src/org/briarproject/privategroup/invitation/GroupInvitationFactoryImpl.java @@ -36,7 +36,7 @@ class GroupInvitationFactoryImpl implements GroupInvitationFactory { BdfList token = createInviteToken(creatorId, memberId, privateGroupId, timestamp); try { - return clientHelper.sign(token, privateKey); + return clientHelper.sign(SIGNING_LABEL_INVITE, token, privateKey); } catch (GeneralSecurityException e) { throw new IllegalArgumentException(e); } catch (FormatException e) { @@ -50,7 +50,6 @@ class GroupInvitationFactoryImpl implements GroupInvitationFactory { Group contactGroup = contactGroupFactory.createContactGroup(CLIENT_ID, creatorId, memberId); return BdfList.of( - 0, // TODO: Replace with a namespaced string timestamp, contactGroup.getId(), privateGroupId diff --git a/briar-core/src/org/briarproject/privategroup/invitation/GroupInvitationValidator.java b/briar-core/src/org/briarproject/privategroup/invitation/GroupInvitationValidator.java index 15de431499..175a593c49 100644 --- a/briar-core/src/org/briarproject/privategroup/invitation/GroupInvitationValidator.java +++ b/briar-core/src/org/briarproject/privategroup/invitation/GroupInvitationValidator.java @@ -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.MAX_GROUP_INVITATION_MSG_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.INVITE; import static org.briarproject.privategroup.invitation.MessageType.JOIN; @@ -96,13 +97,13 @@ class GroupInvitationValidator extends BdfMessageValidator { groupName, creator, salt); // Verify the signature BdfList signed = BdfList.of( - INVITE.getValue(), m.getTimestamp(), m.getGroupId(), privateGroup.getId() ); try { - clientHelper.verifySignature(signature, creatorPublicKey, signed); + clientHelper.verifySignature(SIGNING_LABEL_INVITE, signature, + creatorPublicKey, signed); } catch (GeneralSecurityException e) { throw new FormatException(); } diff --git a/briar-tests/src/org/briarproject/blogs/BlogPostValidatorTest.java b/briar-tests/src/org/briarproject/blogs/BlogPostValidatorTest.java index 08943fc9f1..306b082a6b 100644 --- a/briar-tests/src/org/briarproject/blogs/BlogPostValidatorTest.java +++ b/briar-tests/src/org/briarproject/blogs/BlogPostValidatorTest.java @@ -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_PUBLIC_KEY; 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.POST; import static org.briarproject.api.blogs.MessageType.WRAPPED_COMMENT; @@ -101,7 +103,7 @@ public class BlogPostValidatorTest extends BriarTestCase { BdfList signed = BdfList.of(blog.getId(), message.getTimestamp(), body); - expectCrypto(signed, sigBytes); + expectCrypto(SIGNING_LABEL_POST, signed, sigBytes); final BdfDictionary result = validator.validateMessage(message, group, m).getDictionary(); @@ -143,7 +145,7 @@ public class BlogPostValidatorTest extends BriarTestCase { BdfList signed = BdfList.of(blog.getId(), message.getTimestamp(), comment, pOriginalId, currentId); - expectCrypto(signed, sigBytes); + expectCrypto(SIGNING_LABEL_COMMENT, signed, sigBytes); final BdfDictionary result = validator.validateMessage(message, group, m).getDictionary(); @@ -170,7 +172,7 @@ public class BlogPostValidatorTest extends BriarTestCase { BdfList signed = BdfList.of(blog.getId(), message.getTimestamp(), null, originalId, currentId); - expectCrypto(signed, sigBytes); + expectCrypto(SIGNING_LABEL_COMMENT, signed, sigBytes); final BdfDictionary result = validator.validateMessage(message, group, m).getDictionary(); @@ -189,7 +191,7 @@ public class BlogPostValidatorTest extends BriarTestCase { BdfList signed = 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 byte[] originalBody = TestUtils.getRandomBytes(42); @@ -228,7 +230,7 @@ public class BlogPostValidatorTest extends BriarTestCase { BdfList signed = BdfList.of(blog.getId(), message.getTimestamp(), comment, originalId, oldId); - expectCrypto(signed, sigBytes); + expectCrypto(SIGNING_LABEL_COMMENT, signed, sigBytes); final BdfList originalList = BdfList.of(COMMENT.getInt(), comment, originalId, oldId, sigBytes); @@ -256,13 +258,13 @@ public class BlogPostValidatorTest extends BriarTestCase { context.assertIsSatisfied(); } - private void expectCrypto(final BdfList signed, final byte[] sig) - throws IOException, GeneralSecurityException { + private void expectCrypto(final String label, final BdfList signed, + final byte[] sig) throws IOException, GeneralSecurityException { context.checking(new Expectations() {{ oneOf(blogFactory).parseBlog(group); will(returnValue(blog)); oneOf(clientHelper) - .verifySignature(sig, author.getPublicKey(), signed); + .verifySignature(label, sig, author.getPublicKey(), signed); }}); } diff --git a/briar-tests/src/org/briarproject/clients/ClientHelperImplTest.java b/briar-tests/src/org/briarproject/clients/ClientHelperImplTest.java index 73e17616a1..7c79464517 100644 --- a/briar-tests/src/org/briarproject/clients/ClientHelperImplTest.java +++ b/briar-tests/src/org/briarproject/clients/ClientHelperImplTest.java @@ -1,6 +1,7 @@ package org.briarproject.clients; import org.briarproject.BriarTestCase; +import org.briarproject.TestUtils; import org.briarproject.api.FormatException; import org.briarproject.api.clients.ClientHelper; import org.briarproject.api.crypto.CryptoComponent; @@ -70,6 +71,7 @@ public class ClientHelperImplTest extends BriarTestCase { new Message(messageId, groupId, timestamp, rawMessage); private final Metadata metadata = new Metadata(); private final BdfList list = BdfList.of("Sign this!", getRandomBytes(42)); + private final String label = TestUtils.getRandomString(5); public ClientHelperImplTest() { clientHelper = @@ -290,19 +292,16 @@ public class ClientHelperImplTest extends BriarTestCase { final byte[] bytes = expectToByteArray(list); context.checking(new Expectations() {{ - oneOf(cryptoComponent).getSignature(); - 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(); + oneOf(cryptoComponent).sign(label, bytes, privateKey); will(returnValue(signed)); }}); - assertArrayEquals(signed, clientHelper.sign(list, privateKeyBytes)); + assertArrayEquals(signed, + clientHelper.sign(label, list, privateKeyBytes)); context.assertIsSatisfied(); } @@ -317,15 +316,11 @@ public class ClientHelperImplTest extends BriarTestCase { 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); + oneOf(cryptoComponent).verify(label, bytes, publicKey, rawMessage); will(returnValue(true)); }}); - clientHelper.verifySignature(rawMessage, publicKeyBytes, list); + clientHelper.verifySignature(label, rawMessage, publicKeyBytes, list); context.assertIsSatisfied(); } @@ -340,16 +335,13 @@ public class ClientHelperImplTest extends BriarTestCase { 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); + oneOf(cryptoComponent).verify(label, bytes, publicKey, rawMessage); will(returnValue(false)); }}); try { - clientHelper.verifySignature(rawMessage, publicKeyBytes, list); + clientHelper + .verifySignature(label, rawMessage, publicKeyBytes, list); fail(); } catch (GeneralSecurityException e) { // expected diff --git a/briar-tests/src/org/briarproject/forum/ForumPostValidatorTest.java b/briar-tests/src/org/briarproject/forum/ForumPostValidatorTest.java index 17e5c1266d..af048f6f1a 100644 --- a/briar-tests/src/org/briarproject/forum/ForumPostValidatorTest.java +++ b/briar-tests/src/org/briarproject/forum/ForumPostValidatorTest.java @@ -19,6 +19,7 @@ import java.security.GeneralSecurityException; import java.util.Collection; 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_PUBLIC_KEY_LENGTH; import static org.briarproject.api.identity.AuthorConstants.MAX_SIGNATURE_LENGTH; @@ -70,8 +71,8 @@ public class ForumPostValidatorTest extends ValidatorTestCase { context.checking(new Expectations() {{ oneOf(authorFactory).createAuthor(authorName, authorPublicKey); will(returnValue(author)); - oneOf(clientHelper).verifySignature(signature, authorPublicKey, - signedWithoutParent); + oneOf(clientHelper).verifySignature(SIGNING_LABEL_POST, signature, + authorPublicKey, signedWithoutParent); }}); ForumPostValidator v = new ForumPostValidator(authorFactory, @@ -179,8 +180,8 @@ public class ForumPostValidatorTest extends ValidatorTestCase { context.checking(new Expectations() {{ oneOf(authorFactory).createAuthor(shortAuthorName, authorPublicKey); will(returnValue(shortNameAuthor)); - oneOf(clientHelper).verifySignature(signature, authorPublicKey, - signedWithShortNameAuthor); + oneOf(clientHelper).verifySignature(SIGNING_LABEL_POST, signature, + authorPublicKey, signedWithShortNameAuthor); }}); ForumPostValidator v = new ForumPostValidator(authorFactory, @@ -267,8 +268,8 @@ public class ForumPostValidatorTest extends ValidatorTestCase { context.checking(new Expectations() {{ oneOf(authorFactory).createAuthor(authorName, authorPublicKey); will(returnValue(author)); - oneOf(clientHelper).verifySignature(signature, authorPublicKey, - signedWithShortContent); + oneOf(clientHelper).verifySignature(SIGNING_LABEL_POST, signature, + authorPublicKey, signedWithShortContent); }}); ForumPostValidator v = new ForumPostValidator(authorFactory, @@ -342,8 +343,8 @@ public class ForumPostValidatorTest extends ValidatorTestCase { context.checking(new Expectations() {{ oneOf(authorFactory).createAuthor(authorName, authorPublicKey); will(returnValue(author)); - oneOf(clientHelper).verifySignature(signature, authorPublicKey, - signedWithParent); + oneOf(clientHelper).verifySignature(SIGNING_LABEL_POST, signature, + authorPublicKey, signedWithParent); will(throwException(new FormatException())); }}); @@ -359,8 +360,8 @@ public class ForumPostValidatorTest extends ValidatorTestCase { context.checking(new Expectations() {{ oneOf(authorFactory).createAuthor(authorName, authorPublicKey); will(returnValue(author)); - oneOf(clientHelper).verifySignature(signature, authorPublicKey, - signedWithParent); + oneOf(clientHelper).verifySignature(SIGNING_LABEL_POST, signature, + authorPublicKey, signedWithParent); will(throwException(new GeneralSecurityException())); }}); -- GitLab