mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-21 07:09:56 +01:00
Removed salt from unrestricted groups: two unrestricted groups with
the same name will now be treated as the same group (this seems more intuitive than the alternative).
This commit is contained in:
@@ -1,7 +1,5 @@
|
|||||||
package net.sf.briar.api.protocol;
|
package net.sf.briar.api.protocol;
|
||||||
|
|
||||||
import java.security.PublicKey;
|
|
||||||
|
|
||||||
import net.sf.briar.api.serial.Writable;
|
import net.sf.briar.api.serial.Writable;
|
||||||
|
|
||||||
/** A group to which users may subscribe. */
|
/** A group to which users may subscribe. */
|
||||||
@@ -13,22 +11,9 @@ public interface Group extends Writable {
|
|||||||
/** Returns the group's name. */
|
/** Returns the group's name. */
|
||||||
String getName();
|
String getName();
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns true if messages sent to the group must be signed with a
|
|
||||||
* particular private key.
|
|
||||||
*/
|
|
||||||
boolean isRestricted();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* If the group is restricted, returns null. Otherwise returns a salt
|
|
||||||
* value that is combined with the group's name to generate its unique
|
|
||||||
* identifier.
|
|
||||||
*/
|
|
||||||
byte[] getSalt();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If the group is restricted, returns the public key that is used to
|
* If the group is restricted, returns the public key that is used to
|
||||||
* authorise all messages sent to the group. Otherwise returns null.
|
* authorise all messages sent to the group. Otherwise returns null.
|
||||||
*/
|
*/
|
||||||
PublicKey getPublicKey();
|
byte[] getPublicKey();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,5 @@ package net.sf.briar.api.protocol;
|
|||||||
|
|
||||||
public interface GroupFactory {
|
public interface GroupFactory {
|
||||||
|
|
||||||
Group createGroup(GroupId id, String name, boolean restricted,
|
Group createGroup(GroupId id, String name, byte[] publicKey);
|
||||||
byte[] saltOrKey);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,8 +40,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
"CREATE TABLE localSubscriptions"
|
"CREATE TABLE localSubscriptions"
|
||||||
+ " (groupId HASH NOT NULL,"
|
+ " (groupId HASH NOT NULL,"
|
||||||
+ " groupName VARCHAR NOT NULL,"
|
+ " groupName VARCHAR NOT NULL,"
|
||||||
+ " restricted BOOLEAN NOT NULL,"
|
+ " groupKey BINARY,"
|
||||||
+ " groupKey BINARY NOT NULL,"
|
|
||||||
+ " PRIMARY KEY (groupId))";
|
+ " PRIMARY KEY (groupId))";
|
||||||
|
|
||||||
private static final String CREATE_MESSAGES =
|
private static final String CREATE_MESSAGES =
|
||||||
@@ -90,8 +89,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
+ " (contactId INT NOT NULL,"
|
+ " (contactId INT NOT NULL,"
|
||||||
+ " groupId HASH NOT NULL,"
|
+ " groupId HASH NOT NULL,"
|
||||||
+ " groupName VARCHAR NOT NULL,"
|
+ " groupName VARCHAR NOT NULL,"
|
||||||
+ " restricted BOOLEAN NOT NULL,"
|
+ " groupKey BINARY,"
|
||||||
+ " groupKey BINARY NOT NULL,"
|
|
||||||
+ " PRIMARY KEY (contactId, groupId),"
|
+ " PRIMARY KEY (contactId, groupId),"
|
||||||
+ " FOREIGN KEY (contactId) REFERENCES contacts (contactId)"
|
+ " FOREIGN KEY (contactId) REFERENCES contacts (contactId)"
|
||||||
+ " ON DELETE CASCADE)";
|
+ " ON DELETE CASCADE)";
|
||||||
@@ -530,14 +528,12 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
PreparedStatement ps = null;
|
PreparedStatement ps = null;
|
||||||
try {
|
try {
|
||||||
String sql = "INSERT INTO localSubscriptions"
|
String sql = "INSERT INTO localSubscriptions"
|
||||||
+ " (groupId, groupName, restricted, groupKey)"
|
+ " (groupId, groupName, groupKey)"
|
||||||
+ " VALUES (?, ?, ?, ?)";
|
+ " VALUES (?, ?, ?)";
|
||||||
ps = txn.prepareStatement(sql);
|
ps = txn.prepareStatement(sql);
|
||||||
ps.setBytes(1, g.getId().getBytes());
|
ps.setBytes(1, g.getId().getBytes());
|
||||||
ps.setString(2, g.getName());
|
ps.setString(2, g.getName());
|
||||||
ps.setBoolean(3, g.isRestricted());
|
ps.setBytes(3, g.getPublicKey());
|
||||||
if(g.isRestricted()) ps.setBytes(4, g.getPublicKey().getEncoded());
|
|
||||||
else ps.setBytes(4, g.getSalt());
|
|
||||||
int rowsAffected = ps.executeUpdate();
|
int rowsAffected = ps.executeUpdate();
|
||||||
assert rowsAffected == 1;
|
assert rowsAffected == 1;
|
||||||
ps.close();
|
ps.close();
|
||||||
@@ -989,7 +985,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
PreparedStatement ps = null;
|
PreparedStatement ps = null;
|
||||||
ResultSet rs = null;
|
ResultSet rs = null;
|
||||||
try {
|
try {
|
||||||
String sql = "SELECT groupId, groupName, restricted, groupKey"
|
String sql = "SELECT groupId, groupName, groupKey"
|
||||||
+ " FROM localSubscriptions";
|
+ " FROM localSubscriptions";
|
||||||
ps = txn.prepareStatement(sql);
|
ps = txn.prepareStatement(sql);
|
||||||
rs = ps.executeQuery();
|
rs = ps.executeQuery();
|
||||||
@@ -997,9 +993,8 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
while(rs.next()) {
|
while(rs.next()) {
|
||||||
GroupId id = new GroupId(rs.getBytes(1));
|
GroupId id = new GroupId(rs.getBytes(1));
|
||||||
String name = rs.getString(2);
|
String name = rs.getString(2);
|
||||||
boolean restricted = rs.getBoolean(3);
|
byte[] publicKey = rs.getBytes(3);
|
||||||
byte[] key = rs.getBytes(4);
|
subs.add(groupFactory.createGroup(id, name, publicKey));
|
||||||
subs.add(groupFactory.createGroup(id, name, restricted, key));
|
|
||||||
}
|
}
|
||||||
rs.close();
|
rs.close();
|
||||||
ps.close();
|
ps.close();
|
||||||
@@ -1017,7 +1012,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
PreparedStatement ps = null;
|
PreparedStatement ps = null;
|
||||||
ResultSet rs = null;
|
ResultSet rs = null;
|
||||||
try {
|
try {
|
||||||
String sql = "SELECT groupId, groupName, restricted, groupKey"
|
String sql = "SELECT groupId, groupName, groupKey"
|
||||||
+ " FROM contactSubscriptions"
|
+ " FROM contactSubscriptions"
|
||||||
+ " WHERE contactId = ?";
|
+ " WHERE contactId = ?";
|
||||||
ps = txn.prepareStatement(sql);
|
ps = txn.prepareStatement(sql);
|
||||||
@@ -1027,9 +1022,8 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
while(rs.next()) {
|
while(rs.next()) {
|
||||||
GroupId id = new GroupId(rs.getBytes(1));
|
GroupId id = new GroupId(rs.getBytes(1));
|
||||||
String name = rs.getString(2);
|
String name = rs.getString(2);
|
||||||
boolean restricted = rs.getBoolean(3);
|
byte[] publicKey = rs.getBytes(3);
|
||||||
byte[] key = rs.getBytes(4);
|
subs.add(groupFactory.createGroup(id, name, publicKey));
|
||||||
subs.add(groupFactory.createGroup(id, name, restricted, key));
|
|
||||||
}
|
}
|
||||||
rs.close();
|
rs.close();
|
||||||
ps.close();
|
ps.close();
|
||||||
@@ -1389,17 +1383,14 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
ps.close();
|
ps.close();
|
||||||
// Store the new subscriptions
|
// Store the new subscriptions
|
||||||
sql = "INSERT INTO contactSubscriptions"
|
sql = "INSERT INTO contactSubscriptions"
|
||||||
+ "(contactId, groupId, groupName, restricted, groupKey)"
|
+ " (contactId, groupId, groupName, groupKey)"
|
||||||
+ " VALUES (?, ?, ?, ?, ?)";
|
+ " VALUES (?, ?, ?, ?)";
|
||||||
ps = txn.prepareStatement(sql);
|
ps = txn.prepareStatement(sql);
|
||||||
ps.setInt(1, c.getInt());
|
ps.setInt(1, c.getInt());
|
||||||
for(Group g : subs) {
|
for(Group g : subs) {
|
||||||
ps.setBytes(2, g.getId().getBytes());
|
ps.setBytes(2, g.getId().getBytes());
|
||||||
ps.setString(3, g.getName());
|
ps.setString(3, g.getName());
|
||||||
ps.setBoolean(4, g.isRestricted());
|
ps.setBytes(4, g.getPublicKey());
|
||||||
if(g.isRestricted())
|
|
||||||
ps.setBytes(5, g.getPublicKey().getEncoded());
|
|
||||||
else ps.setBytes(5, g.getSalt());
|
|
||||||
ps.addBatch();
|
ps.addBatch();
|
||||||
}
|
}
|
||||||
int[] rowsAffectedArray = ps.executeBatch();
|
int[] rowsAffectedArray = ps.executeBatch();
|
||||||
|
|||||||
@@ -1,34 +1,12 @@
|
|||||||
package net.sf.briar.protocol;
|
package net.sf.briar.protocol;
|
||||||
|
|
||||||
import java.security.PublicKey;
|
|
||||||
import java.security.spec.InvalidKeySpecException;
|
|
||||||
|
|
||||||
import net.sf.briar.api.crypto.CryptoComponent;
|
|
||||||
import net.sf.briar.api.crypto.KeyParser;
|
|
||||||
import net.sf.briar.api.protocol.Group;
|
import net.sf.briar.api.protocol.Group;
|
||||||
import net.sf.briar.api.protocol.GroupFactory;
|
import net.sf.briar.api.protocol.GroupFactory;
|
||||||
import net.sf.briar.api.protocol.GroupId;
|
import net.sf.briar.api.protocol.GroupId;
|
||||||
|
|
||||||
import com.google.inject.Inject;
|
|
||||||
|
|
||||||
class GroupFactoryImpl implements GroupFactory {
|
class GroupFactoryImpl implements GroupFactory {
|
||||||
|
|
||||||
private final KeyParser keyParser;
|
public Group createGroup(GroupId id, String name, byte[] publicKey) {
|
||||||
|
return new GroupImpl(id, name, publicKey);
|
||||||
@Inject
|
|
||||||
GroupFactoryImpl(CryptoComponent crypto) {
|
|
||||||
keyParser = crypto.getKeyParser();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Group createGroup(GroupId id, String name, boolean restricted,
|
|
||||||
byte[] saltOrKey) {
|
|
||||||
if(restricted) {
|
|
||||||
try {
|
|
||||||
PublicKey key = keyParser.parsePublicKey(saltOrKey);
|
|
||||||
return new GroupImpl(id, name, key);
|
|
||||||
} catch(InvalidKeySpecException e) {
|
|
||||||
throw new IllegalArgumentException(e);
|
|
||||||
}
|
|
||||||
} else return new GroupImpl(id, name, saltOrKey);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package net.sf.briar.protocol;
|
package net.sf.briar.protocol;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.security.PublicKey;
|
|
||||||
|
|
||||||
import net.sf.briar.api.protocol.Group;
|
import net.sf.briar.api.protocol.Group;
|
||||||
import net.sf.briar.api.protocol.GroupId;
|
import net.sf.briar.api.protocol.GroupId;
|
||||||
@@ -12,21 +11,12 @@ class GroupImpl implements Group {
|
|||||||
|
|
||||||
private final GroupId id;
|
private final GroupId id;
|
||||||
private final String name;
|
private final String name;
|
||||||
private final byte[] salt;
|
private final byte[] publicKey;
|
||||||
private final PublicKey publicKey;
|
|
||||||
|
|
||||||
GroupImpl(GroupId id, String name, byte[] salt) {
|
GroupImpl(GroupId id, String name, byte[] publicKey) {
|
||||||
this.id = id;
|
|
||||||
this.name = name;
|
|
||||||
this.salt = salt;
|
|
||||||
publicKey = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
GroupImpl(GroupId id, String name, PublicKey publicKey) {
|
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.publicKey = publicKey;
|
this.publicKey = publicKey;
|
||||||
salt = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public GroupId getId() {
|
public GroupId getId() {
|
||||||
@@ -37,24 +27,15 @@ class GroupImpl implements Group {
|
|||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isRestricted() {
|
public byte[] getPublicKey() {
|
||||||
return salt == null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte[] getSalt() {
|
|
||||||
return salt;
|
|
||||||
}
|
|
||||||
|
|
||||||
public PublicKey getPublicKey() {
|
|
||||||
return publicKey;
|
return publicKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void writeTo(Writer w) throws IOException {
|
public void writeTo(Writer w) throws IOException {
|
||||||
w.writeUserDefinedTag(Tags.GROUP);
|
w.writeUserDefinedTag(Tags.GROUP);
|
||||||
w.writeString(name);
|
w.writeString(name);
|
||||||
w.writeBoolean(isRestricted());
|
if(publicKey == null) w.writeNull();
|
||||||
if(salt == null) w.writeBytes(publicKey.getEncoded());
|
else w.writeBytes(publicKey);
|
||||||
else w.writeBytes(salt);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -28,11 +28,12 @@ class GroupReader implements ObjectReader<Group> {
|
|||||||
r.addConsumer(digesting);
|
r.addConsumer(digesting);
|
||||||
r.readUserDefinedTag(Tags.GROUP);
|
r.readUserDefinedTag(Tags.GROUP);
|
||||||
String name = r.readString();
|
String name = r.readString();
|
||||||
boolean restricted = r.readBoolean();
|
byte[] publicKey = null;
|
||||||
byte[] saltOrKey = r.readBytes();
|
if(r.hasNull()) r.readNull();
|
||||||
|
else publicKey = r.readBytes();
|
||||||
r.removeConsumer(digesting);
|
r.removeConsumer(digesting);
|
||||||
// Build and return the group
|
// Build and return the group
|
||||||
GroupId id = new GroupId(messageDigest.digest());
|
GroupId id = new GroupId(messageDigest.digest());
|
||||||
return groupFactory.createGroup(id, name, restricted, saltOrKey);
|
return groupFactory.createGroup(id, name, publicKey);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -77,8 +77,7 @@ public class H2DatabaseTest extends TestCase {
|
|||||||
random.nextBytes(raw);
|
random.nextBytes(raw);
|
||||||
message = new TestMessage(messageId, MessageId.NONE, groupId, authorId,
|
message = new TestMessage(messageId, MessageId.NONE, groupId, authorId,
|
||||||
timestamp, raw);
|
timestamp, raw);
|
||||||
group = groupFactory.createGroup(groupId, "Group name", false,
|
group = groupFactory.createGroup(groupId, "Group name", null);
|
||||||
TestUtils.getRandomId());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
@@ -534,7 +533,7 @@ public class H2DatabaseTest extends TestCase {
|
|||||||
MessageId childId3 = new MessageId(TestUtils.getRandomId());
|
MessageId childId3 = new MessageId(TestUtils.getRandomId());
|
||||||
GroupId groupId1 = new GroupId(TestUtils.getRandomId());
|
GroupId groupId1 = new GroupId(TestUtils.getRandomId());
|
||||||
Group group1 = groupFactory.createGroup(groupId1, "Another group name",
|
Group group1 = groupFactory.createGroup(groupId1, "Another group name",
|
||||||
false, TestUtils.getRandomId());
|
null);
|
||||||
Message child1 = new TestMessage(childId1, messageId, groupId,
|
Message child1 = new TestMessage(childId1, messageId, groupId,
|
||||||
authorId, timestamp, raw);
|
authorId, timestamp, raw);
|
||||||
Message child2 = new TestMessage(childId2, messageId, groupId,
|
Message child2 = new TestMessage(childId2, messageId, groupId,
|
||||||
@@ -759,7 +758,7 @@ public class H2DatabaseTest extends TestCase {
|
|||||||
public void testUpdateSubscriptions() throws DbException {
|
public void testUpdateSubscriptions() throws DbException {
|
||||||
GroupId groupId1 = new GroupId(TestUtils.getRandomId());
|
GroupId groupId1 = new GroupId(TestUtils.getRandomId());
|
||||||
Group group1 = groupFactory.createGroup(groupId1, "Another group name",
|
Group group1 = groupFactory.createGroup(groupId1, "Another group name",
|
||||||
false, TestUtils.getRandomId());
|
null);
|
||||||
Database<Connection> db = open(false);
|
Database<Connection> db = open(false);
|
||||||
Connection txn = db.startTransaction();
|
Connection txn = db.startTransaction();
|
||||||
|
|
||||||
@@ -784,7 +783,7 @@ public class H2DatabaseTest extends TestCase {
|
|||||||
throws DbException {
|
throws DbException {
|
||||||
GroupId groupId1 = new GroupId(TestUtils.getRandomId());
|
GroupId groupId1 = new GroupId(TestUtils.getRandomId());
|
||||||
Group group1 = groupFactory.createGroup(groupId1, "Another group name",
|
Group group1 = groupFactory.createGroup(groupId1, "Another group name",
|
||||||
false, TestUtils.getRandomId());
|
null);
|
||||||
Database<Connection> db = open(false);
|
Database<Connection> db = open(false);
|
||||||
Connection txn = db.startTransaction();
|
Connection txn = db.startTransaction();
|
||||||
|
|
||||||
|
|||||||
@@ -64,7 +64,6 @@ public class FileReadWriteTest extends TestCase {
|
|||||||
private final ReaderFactory readerFactory;
|
private final ReaderFactory readerFactory;
|
||||||
private final WriterFactory writerFactory;
|
private final WriterFactory writerFactory;
|
||||||
private final PacketWriterFactory packetWriterFactory;
|
private final PacketWriterFactory packetWriterFactory;
|
||||||
private final CryptoComponent crypto;
|
|
||||||
private final Signature signature;
|
private final Signature signature;
|
||||||
private final MessageDigest messageDigest, batchDigest;
|
private final MessageDigest messageDigest, batchDigest;
|
||||||
private final KeyParser keyParser;
|
private final KeyParser keyParser;
|
||||||
@@ -79,7 +78,7 @@ public class FileReadWriteTest extends TestCase {
|
|||||||
readerFactory = i.getInstance(ReaderFactory.class);
|
readerFactory = i.getInstance(ReaderFactory.class);
|
||||||
writerFactory = i.getInstance(WriterFactory.class);
|
writerFactory = i.getInstance(WriterFactory.class);
|
||||||
packetWriterFactory = i.getInstance(PacketWriterFactory.class);
|
packetWriterFactory = i.getInstance(PacketWriterFactory.class);
|
||||||
crypto = i.getInstance(CryptoComponent.class);
|
CryptoComponent crypto = i.getInstance(CryptoComponent.class);
|
||||||
keyParser = crypto.getKeyParser();
|
keyParser = crypto.getKeyParser();
|
||||||
signature = crypto.getSignature();
|
signature = crypto.getSignature();
|
||||||
messageDigest = crypto.getMessageDigest();
|
messageDigest = crypto.getMessageDigest();
|
||||||
@@ -94,8 +93,7 @@ public class FileReadWriteTest extends TestCase {
|
|||||||
// Create a test group, then write and read it to calculate its ID
|
// Create a test group, then write and read it to calculate its ID
|
||||||
GroupFactory groupFactory = i.getInstance(GroupFactory.class);
|
GroupFactory groupFactory = i.getInstance(GroupFactory.class);
|
||||||
Group noId = groupFactory.createGroup(
|
Group noId = groupFactory.createGroup(
|
||||||
new GroupId(new byte[UniqueId.LENGTH]), "Group name", false,
|
new GroupId(new byte[UniqueId.LENGTH]), "Group name", null);
|
||||||
TestUtils.getRandomId());
|
|
||||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||||
Writer w = writerFactory.createWriter(out);
|
Writer w = writerFactory.createWriter(out);
|
||||||
noId.writeTo(w);
|
noId.writeTo(w);
|
||||||
@@ -147,7 +145,7 @@ public class FileReadWriteTest extends TestCase {
|
|||||||
ObjectReader<Batch> batchReader = new BatchReader(batchDigest,
|
ObjectReader<Batch> batchReader = new BatchReader(batchDigest,
|
||||||
messageReader, new BatchFactoryImpl());
|
messageReader, new BatchFactoryImpl());
|
||||||
ObjectReader<Group> groupReader = new GroupReader(batchDigest,
|
ObjectReader<Group> groupReader = new GroupReader(batchDigest,
|
||||||
new GroupFactoryImpl(crypto));
|
new GroupFactoryImpl());
|
||||||
ObjectReader<Subscriptions> subscriptionReader =
|
ObjectReader<Subscriptions> subscriptionReader =
|
||||||
new SubscriptionReader(groupReader, new SubscriptionFactoryImpl());
|
new SubscriptionReader(groupReader, new SubscriptionFactoryImpl());
|
||||||
ObjectReader<Transports> transportReader =
|
ObjectReader<Transports> transportReader =
|
||||||
|
|||||||
Reference in New Issue
Block a user