mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-13 19:29:06 +01:00
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.
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.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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
|
||||
@@ -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);
|
||||
|
||||
}
|
||||
|
||||
@@ -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 =
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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 =
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}});
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()));
|
||||
}});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user