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:
Torsten Grote
2016-11-17 16:36:51 -02:00
parent 9b09b64ad3
commit c86d971166
20 changed files with 158 additions and 107 deletions

View File

@@ -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 =

View File

@@ -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);
}

View File

@@ -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");
}
}

View File

@@ -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();

View File

@@ -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);

View File

@@ -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);
}

View File

@@ -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 =

View File

@@ -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);
}

View File

@@ -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

View File

@@ -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();
}