mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-13 03:09:04 +01:00
Replaced SHA-256 with SHAd-256 to prevent length extension attacks.
This commit is contained in:
@@ -1,7 +1,6 @@
|
||||
package net.sf.briar.api.crypto;
|
||||
|
||||
import java.security.KeyPair;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.SecureRandom;
|
||||
import java.security.Signature;
|
||||
|
||||
|
||||
29
api/net/sf/briar/api/crypto/MessageDigest.java
Normal file
29
api/net/sf/briar/api/crypto/MessageDigest.java
Normal file
@@ -0,0 +1,29 @@
|
||||
package net.sf.briar.api.crypto;
|
||||
|
||||
/** An interface that allows a java.security.MessageDigest to be wrapped. */
|
||||
public interface MessageDigest {
|
||||
|
||||
/** @see {@link java.security.MessageDigest#digest()} */
|
||||
byte[] digest();
|
||||
|
||||
/** @see {@link java.security.MessageDigest#digest(byte[])} */
|
||||
byte[] digest(byte[] input);
|
||||
|
||||
/** @see {@link java.security.MessageDigest#digest(byte[], int, int)} */
|
||||
int digest(byte[] buf, int offset, int len);
|
||||
|
||||
/** @see {@link java.security.MessageDigest#getDigestLength()} */
|
||||
int getDigestLength();
|
||||
|
||||
/** @see {@link java.security.MessageDigest#reset()} */
|
||||
void reset();
|
||||
|
||||
/** @see {@link java.security.MessageDigest#update(byte)} */
|
||||
void update(byte input);
|
||||
|
||||
/** @see {@link java.security.MessageDigest#update(byte[])} */
|
||||
void update(byte[] input);
|
||||
|
||||
/** @see {@link java.security.MessageDigest#update(byte[], int, int)} */
|
||||
void update(byte[] input, int offset, int len);
|
||||
}
|
||||
@@ -1,16 +1,14 @@
|
||||
package net.sf.briar.protocol;
|
||||
package net.sf.briar.api.serial;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import net.sf.briar.api.serial.Consumer;
|
||||
|
||||
/** A consumer that makes a copy of the bytes consumed. */
|
||||
class CopyingConsumer implements Consumer {
|
||||
public class CopyingConsumer implements Consumer {
|
||||
|
||||
private final ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
|
||||
byte[] getCopy() {
|
||||
public byte[] getCopy() {
|
||||
return out.toByteArray();
|
||||
}
|
||||
|
||||
@@ -1,24 +1,23 @@
|
||||
package net.sf.briar.protocol;
|
||||
package net.sf.briar.api.serial;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import net.sf.briar.api.FormatException;
|
||||
import net.sf.briar.api.serial.Consumer;
|
||||
|
||||
/**
|
||||
* A consumer that counts the number of bytes consumed and throws a
|
||||
* FormatException if the count exceeds a given limit.
|
||||
*/
|
||||
class CountingConsumer implements Consumer {
|
||||
public class CountingConsumer implements Consumer {
|
||||
|
||||
private final long limit;
|
||||
private long count = 0L;
|
||||
|
||||
CountingConsumer(long limit) {
|
||||
public CountingConsumer(long limit) {
|
||||
this.limit = limit;
|
||||
}
|
||||
|
||||
long getCount() {
|
||||
public long getCount() {
|
||||
return count;
|
||||
}
|
||||
|
||||
@@ -1,15 +1,13 @@
|
||||
package net.sf.briar.protocol;
|
||||
package net.sf.briar.api.serial;
|
||||
|
||||
import java.security.MessageDigest;
|
||||
|
||||
import net.sf.briar.api.serial.Consumer;
|
||||
import net.sf.briar.api.crypto.MessageDigest;
|
||||
|
||||
/** A consumer that passes its input through a message digest. */
|
||||
class DigestingConsumer implements Consumer {
|
||||
public class DigestingConsumer implements Consumer {
|
||||
|
||||
private final MessageDigest messageDigest;
|
||||
|
||||
DigestingConsumer(MessageDigest messageDigest) {
|
||||
public DigestingConsumer(MessageDigest messageDigest) {
|
||||
this.messageDigest = messageDigest;
|
||||
}
|
||||
|
||||
@@ -1,17 +1,15 @@
|
||||
package net.sf.briar.protocol;
|
||||
package net.sf.briar.api.serial;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.security.Signature;
|
||||
import java.security.SignatureException;
|
||||
|
||||
import net.sf.briar.api.serial.Consumer;
|
||||
|
||||
/** A consumer that passes its input through a signature. */
|
||||
class SigningConsumer implements Consumer {
|
||||
public class SigningConsumer implements Consumer {
|
||||
|
||||
private final Signature signature;
|
||||
|
||||
SigningConsumer(Signature signature) {
|
||||
public SigningConsumer(Signature signature) {
|
||||
this.signature = signature;
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@ import java.security.InvalidAlgorithmParameterException;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.KeyPair;
|
||||
import java.security.KeyPairGenerator;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.NoSuchProviderException;
|
||||
import java.security.SecureRandom;
|
||||
@@ -25,6 +24,7 @@ import javax.crypto.spec.SecretKeySpec;
|
||||
|
||||
import net.sf.briar.api.crypto.CryptoComponent;
|
||||
import net.sf.briar.api.crypto.KeyParser;
|
||||
import net.sf.briar.api.crypto.MessageDigest;
|
||||
import net.sf.briar.api.crypto.SecretStorageKey;
|
||||
|
||||
import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
||||
@@ -198,7 +198,8 @@ class CryptoComponentImpl implements CryptoComponent {
|
||||
|
||||
public MessageDigest getMessageDigest() {
|
||||
try {
|
||||
return MessageDigest.getInstance(DIGEST_ALGO, PROVIDER);
|
||||
return new DoubleDigest(java.security.MessageDigest.getInstance(
|
||||
DIGEST_ALGO, PROVIDER));
|
||||
} catch(NoSuchAlgorithmException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch(NoSuchProviderException e) {
|
||||
|
||||
59
components/net/sf/briar/crypto/DoubleDigest.java
Normal file
59
components/net/sf/briar/crypto/DoubleDigest.java
Normal file
@@ -0,0 +1,59 @@
|
||||
package net.sf.briar.crypto;
|
||||
|
||||
import net.sf.briar.api.crypto.MessageDigest;
|
||||
|
||||
/**
|
||||
* A message digest that prevents length extension attacks - see Ferguson and
|
||||
* Schneier, <i>Practical Cryptography</i>, chapter 6.
|
||||
* <p>
|
||||
* "Let h be an interative hash function. The hash function h<sub>d</sub> is
|
||||
* defined by h<sub>d</sub> := h(h(m)), and has a claimed security level of
|
||||
* min(k, n/2) where k is the security level of h and n is the size of the hash
|
||||
* result."
|
||||
*/
|
||||
class DoubleDigest implements MessageDigest {
|
||||
|
||||
private final java.security.MessageDigest delegate;
|
||||
|
||||
DoubleDigest(java.security.MessageDigest delegate) {
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
public byte[] digest() {
|
||||
byte[] digest = delegate.digest(); // h(m)
|
||||
delegate.update(digest);
|
||||
return delegate.digest(); // h(h(m))
|
||||
}
|
||||
|
||||
public byte[] digest(byte[] input) {
|
||||
delegate.update(input);
|
||||
return digest();
|
||||
}
|
||||
|
||||
public int digest(byte[] buf, int offset, int len) {
|
||||
byte[] digest = digest();
|
||||
len = Math.min(len, digest.length);
|
||||
System.arraycopy(digest, 0, buf, offset, len);
|
||||
return len;
|
||||
}
|
||||
|
||||
public int getDigestLength() {
|
||||
return delegate.getDigestLength();
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
delegate.reset();
|
||||
}
|
||||
|
||||
public void update(byte input) {
|
||||
delegate.update(input);
|
||||
}
|
||||
|
||||
public void update(byte[] input) {
|
||||
delegate.update(input);
|
||||
}
|
||||
|
||||
public void update(byte[] input, int offset, int len) {
|
||||
delegate.update(input, offset, len);
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,7 @@ import net.sf.briar.api.protocol.BatchId;
|
||||
import net.sf.briar.api.protocol.ProtocolConstants;
|
||||
import net.sf.briar.api.protocol.Types;
|
||||
import net.sf.briar.api.serial.Consumer;
|
||||
import net.sf.briar.api.serial.CountingConsumer;
|
||||
import net.sf.briar.api.serial.ObjectReader;
|
||||
import net.sf.briar.api.serial.Reader;
|
||||
|
||||
|
||||
@@ -2,9 +2,9 @@ package net.sf.briar.protocol;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.security.MessageDigest;
|
||||
|
||||
import net.sf.briar.api.crypto.CryptoComponent;
|
||||
import net.sf.briar.api.crypto.MessageDigest;
|
||||
import net.sf.briar.api.protocol.Author;
|
||||
import net.sf.briar.api.protocol.AuthorFactory;
|
||||
import net.sf.briar.api.protocol.AuthorId;
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
package net.sf.briar.protocol;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.security.MessageDigest;
|
||||
|
||||
import net.sf.briar.api.crypto.CryptoComponent;
|
||||
import net.sf.briar.api.crypto.MessageDigest;
|
||||
import net.sf.briar.api.protocol.Author;
|
||||
import net.sf.briar.api.protocol.AuthorFactory;
|
||||
import net.sf.briar.api.protocol.AuthorId;
|
||||
import net.sf.briar.api.protocol.ProtocolConstants;
|
||||
import net.sf.briar.api.protocol.Types;
|
||||
import net.sf.briar.api.serial.DigestingConsumer;
|
||||
import net.sf.briar.api.serial.ObjectReader;
|
||||
import net.sf.briar.api.serial.Reader;
|
||||
|
||||
|
||||
@@ -1,16 +1,18 @@
|
||||
package net.sf.briar.protocol;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.security.MessageDigest;
|
||||
import java.util.List;
|
||||
|
||||
import net.sf.briar.api.crypto.CryptoComponent;
|
||||
import net.sf.briar.api.crypto.MessageDigest;
|
||||
import net.sf.briar.api.protocol.Batch;
|
||||
import net.sf.briar.api.protocol.BatchId;
|
||||
import net.sf.briar.api.protocol.Message;
|
||||
import net.sf.briar.api.protocol.ProtocolConstants;
|
||||
import net.sf.briar.api.protocol.Types;
|
||||
import net.sf.briar.api.serial.Consumer;
|
||||
import net.sf.briar.api.serial.CountingConsumer;
|
||||
import net.sf.briar.api.serial.DigestingConsumer;
|
||||
import net.sf.briar.api.serial.ObjectReader;
|
||||
import net.sf.briar.api.serial.Reader;
|
||||
|
||||
|
||||
@@ -2,9 +2,9 @@ package net.sf.briar.protocol;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.security.MessageDigest;
|
||||
|
||||
import net.sf.briar.api.crypto.CryptoComponent;
|
||||
import net.sf.briar.api.crypto.MessageDigest;
|
||||
import net.sf.briar.api.protocol.Group;
|
||||
import net.sf.briar.api.protocol.GroupFactory;
|
||||
import net.sf.briar.api.protocol.GroupId;
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
package net.sf.briar.protocol;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.security.MessageDigest;
|
||||
|
||||
import net.sf.briar.api.crypto.CryptoComponent;
|
||||
import net.sf.briar.api.crypto.MessageDigest;
|
||||
import net.sf.briar.api.protocol.Group;
|
||||
import net.sf.briar.api.protocol.GroupFactory;
|
||||
import net.sf.briar.api.protocol.GroupId;
|
||||
import net.sf.briar.api.protocol.ProtocolConstants;
|
||||
import net.sf.briar.api.protocol.Types;
|
||||
import net.sf.briar.api.serial.DigestingConsumer;
|
||||
import net.sf.briar.api.serial.ObjectReader;
|
||||
import net.sf.briar.api.serial.Reader;
|
||||
|
||||
|
||||
@@ -3,12 +3,12 @@ package net.sf.briar.protocol;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.SecureRandom;
|
||||
import java.security.Signature;
|
||||
|
||||
import net.sf.briar.api.crypto.CryptoComponent;
|
||||
import net.sf.briar.api.crypto.MessageDigest;
|
||||
import net.sf.briar.api.protocol.Author;
|
||||
import net.sf.briar.api.protocol.AuthorId;
|
||||
import net.sf.briar.api.protocol.Group;
|
||||
@@ -19,6 +19,9 @@ import net.sf.briar.api.protocol.MessageId;
|
||||
import net.sf.briar.api.protocol.ProtocolConstants;
|
||||
import net.sf.briar.api.protocol.Types;
|
||||
import net.sf.briar.api.serial.Consumer;
|
||||
import net.sf.briar.api.serial.CountingConsumer;
|
||||
import net.sf.briar.api.serial.DigestingConsumer;
|
||||
import net.sf.briar.api.serial.SigningConsumer;
|
||||
import net.sf.briar.api.serial.Writer;
|
||||
import net.sf.briar.api.serial.WriterFactory;
|
||||
|
||||
|
||||
@@ -2,13 +2,13 @@ package net.sf.briar.protocol;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.PublicKey;
|
||||
import java.security.Signature;
|
||||
|
||||
import net.sf.briar.api.FormatException;
|
||||
import net.sf.briar.api.crypto.CryptoComponent;
|
||||
import net.sf.briar.api.crypto.KeyParser;
|
||||
import net.sf.briar.api.crypto.MessageDigest;
|
||||
import net.sf.briar.api.protocol.Author;
|
||||
import net.sf.briar.api.protocol.AuthorId;
|
||||
import net.sf.briar.api.protocol.Group;
|
||||
@@ -17,6 +17,8 @@ import net.sf.briar.api.protocol.Message;
|
||||
import net.sf.briar.api.protocol.MessageId;
|
||||
import net.sf.briar.api.protocol.ProtocolConstants;
|
||||
import net.sf.briar.api.protocol.Types;
|
||||
import net.sf.briar.api.serial.CopyingConsumer;
|
||||
import net.sf.briar.api.serial.CountingConsumer;
|
||||
import net.sf.briar.api.serial.ObjectReader;
|
||||
import net.sf.briar.api.serial.Reader;
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ import net.sf.briar.api.protocol.Offer;
|
||||
import net.sf.briar.api.protocol.ProtocolConstants;
|
||||
import net.sf.briar.api.protocol.Types;
|
||||
import net.sf.briar.api.serial.Consumer;
|
||||
import net.sf.briar.api.serial.CountingConsumer;
|
||||
import net.sf.briar.api.serial.ObjectReader;
|
||||
import net.sf.briar.api.serial.Reader;
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ import net.sf.briar.api.protocol.ProtocolConstants;
|
||||
import net.sf.briar.api.protocol.Request;
|
||||
import net.sf.briar.api.protocol.Types;
|
||||
import net.sf.briar.api.serial.Consumer;
|
||||
import net.sf.briar.api.serial.CountingConsumer;
|
||||
import net.sf.briar.api.serial.ObjectReader;
|
||||
import net.sf.briar.api.serial.Reader;
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ import net.sf.briar.api.protocol.ProtocolConstants;
|
||||
import net.sf.briar.api.protocol.SubscriptionUpdate;
|
||||
import net.sf.briar.api.protocol.Types;
|
||||
import net.sf.briar.api.serial.Consumer;
|
||||
import net.sf.briar.api.serial.CountingConsumer;
|
||||
import net.sf.briar.api.serial.ObjectReader;
|
||||
import net.sf.briar.api.serial.Reader;
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@ import net.sf.briar.api.protocol.TransportUpdate;
|
||||
import net.sf.briar.api.protocol.Types;
|
||||
import net.sf.briar.api.protocol.UniqueId;
|
||||
import net.sf.briar.api.serial.Consumer;
|
||||
import net.sf.briar.api.serial.CountingConsumer;
|
||||
import net.sf.briar.api.serial.ObjectReader;
|
||||
import net.sf.briar.api.serial.Reader;
|
||||
|
||||
|
||||
@@ -2,23 +2,24 @@ package net.sf.briar.protocol.writers;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.security.DigestOutputStream;
|
||||
import java.security.MessageDigest;
|
||||
|
||||
import net.sf.briar.api.crypto.MessageDigest;
|
||||
import net.sf.briar.api.protocol.BatchId;
|
||||
import net.sf.briar.api.protocol.ProtocolConstants;
|
||||
import net.sf.briar.api.protocol.Types;
|
||||
import net.sf.briar.api.protocol.writers.BatchWriter;
|
||||
import net.sf.briar.api.serial.DigestingConsumer;
|
||||
import net.sf.briar.api.serial.SerialComponent;
|
||||
import net.sf.briar.api.serial.Writer;
|
||||
import net.sf.briar.api.serial.WriterFactory;
|
||||
|
||||
class BatchWriterImpl implements BatchWriter {
|
||||
|
||||
private final DigestOutputStream out;
|
||||
private final OutputStream out;
|
||||
private final int headerLength, footerLength;
|
||||
private final Writer w;
|
||||
private final MessageDigest messageDigest;
|
||||
private final DigestingConsumer digestingConsumer;
|
||||
|
||||
private boolean started = false;
|
||||
private int capacity = ProtocolConstants.MAX_PACKET_LENGTH;
|
||||
@@ -26,12 +27,13 @@ class BatchWriterImpl implements BatchWriter {
|
||||
|
||||
BatchWriterImpl(OutputStream out, SerialComponent serial,
|
||||
WriterFactory writerFactory, MessageDigest messageDigest) {
|
||||
this.out = new DigestOutputStream(out, messageDigest);
|
||||
this.out = out;
|
||||
headerLength = serial.getSerialisedUserDefinedIdLength(Types.BATCH)
|
||||
+ serial.getSerialisedListStartLength();
|
||||
footerLength = serial.getSerialisedListEndLength();
|
||||
w = writerFactory.createWriter(this.out);
|
||||
this.messageDigest = messageDigest;
|
||||
digestingConsumer = new DigestingConsumer(messageDigest);
|
||||
}
|
||||
|
||||
public int getCapacity() {
|
||||
@@ -58,6 +60,7 @@ class BatchWriterImpl implements BatchWriter {
|
||||
public BatchId finish() throws IOException {
|
||||
if(!started) start();
|
||||
w.writeListEnd();
|
||||
w.removeConsumer(digestingConsumer);
|
||||
out.flush();
|
||||
remaining = capacity = ProtocolConstants.MAX_PACKET_LENGTH;
|
||||
started = false;
|
||||
@@ -66,6 +69,7 @@ class BatchWriterImpl implements BatchWriter {
|
||||
|
||||
private void start() throws IOException {
|
||||
messageDigest.reset();
|
||||
w.addConsumer(digestingConsumer);
|
||||
w.writeUserDefinedId(Types.BATCH);
|
||||
w.writeListStart();
|
||||
remaining -= headerLength;
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
package net.sf.briar.protocol.writers;
|
||||
|
||||
import java.io.OutputStream;
|
||||
import java.security.MessageDigest;
|
||||
|
||||
import net.sf.briar.api.crypto.CryptoComponent;
|
||||
import net.sf.briar.api.crypto.MessageDigest;
|
||||
import net.sf.briar.api.protocol.writers.AckWriter;
|
||||
import net.sf.briar.api.protocol.writers.BatchWriter;
|
||||
import net.sf.briar.api.protocol.writers.OfferWriter;
|
||||
|
||||
@@ -3,12 +3,12 @@ package net.sf.briar.protocol;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.security.MessageDigest;
|
||||
import java.util.Collections;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
import net.sf.briar.api.FormatException;
|
||||
import net.sf.briar.api.crypto.CryptoComponent;
|
||||
import net.sf.briar.api.crypto.MessageDigest;
|
||||
import net.sf.briar.api.protocol.Batch;
|
||||
import net.sf.briar.api.protocol.BatchId;
|
||||
import net.sf.briar.api.protocol.Message;
|
||||
|
||||
@@ -2,12 +2,15 @@ package net.sf.briar.protocol;
|
||||
|
||||
import static org.junit.Assert.assertArrayEquals;
|
||||
|
||||
import java.security.MessageDigest;
|
||||
import java.util.Random;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
import net.sf.briar.api.FormatException;
|
||||
import net.sf.briar.api.crypto.CryptoComponent;
|
||||
import net.sf.briar.api.crypto.MessageDigest;
|
||||
import net.sf.briar.api.serial.CopyingConsumer;
|
||||
import net.sf.briar.api.serial.CountingConsumer;
|
||||
import net.sf.briar.api.serial.DigestingConsumer;
|
||||
import net.sf.briar.crypto.CryptoModule;
|
||||
|
||||
import org.junit.Before;
|
||||
|
||||
Reference in New Issue
Block a user