mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-12 02:39:05 +01:00
Added accessors for the amount of raw data read and written by readers and writers - this fixes a fixme in MessageParserImpl.
This commit is contained in:
@@ -1,9 +1,9 @@
|
||||
package net.sf.briar.api.crypto;
|
||||
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.security.PublicKey;
|
||||
import java.security.spec.InvalidKeySpecException;
|
||||
|
||||
public interface KeyParser {
|
||||
|
||||
PublicKey parsePublicKey(byte[] encodedKey) throws GeneralSecurityException;
|
||||
PublicKey parsePublicKey(byte[] encodedKey) throws InvalidKeySpecException;
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ public interface Reader {
|
||||
boolean eof() throws IOException;
|
||||
void setReadLimit(long limit);
|
||||
void resetReadLimit();
|
||||
long getRawBytesRead();
|
||||
void close() throws IOException;
|
||||
|
||||
boolean hasBoolean() throws IOException;
|
||||
|
||||
@@ -6,6 +6,7 @@ import java.util.Map;
|
||||
|
||||
public interface Writer {
|
||||
|
||||
long getRawBytesWritten();
|
||||
void close() throws IOException;
|
||||
|
||||
void writeBoolean(boolean b) throws IOException;
|
||||
|
||||
@@ -7,6 +7,7 @@ import java.security.MessageDigest;
|
||||
import java.security.PublicKey;
|
||||
import java.security.Signature;
|
||||
import java.security.SignatureException;
|
||||
import java.security.spec.InvalidKeySpecException;
|
||||
|
||||
import net.sf.briar.api.crypto.KeyParser;
|
||||
import net.sf.briar.api.protocol.AuthorId;
|
||||
@@ -52,7 +53,6 @@ class MessageParserImpl implements MessageParser {
|
||||
// Hash the author's nick and public key to get the author ID
|
||||
String nick = r.readUtf8();
|
||||
byte[] encodedKey = r.readRaw();
|
||||
PublicKey publicKey = keyParser.parsePublicKey(encodedKey);
|
||||
messageDigest.reset();
|
||||
messageDigest.update(nick.getBytes("UTF-8"));
|
||||
messageDigest.update((byte) 0); // Null separator
|
||||
@@ -60,12 +60,17 @@ class MessageParserImpl implements MessageParser {
|
||||
AuthorId author = new AuthorId(messageDigest.digest());
|
||||
// Skip the message body
|
||||
r.readRaw();
|
||||
// Read the signature and work out how long the signed message is
|
||||
byte[] sig = r.readRaw();
|
||||
int length = raw.length - sig.length - bytesToEncode(sig.length);
|
||||
// Verify the signature
|
||||
int messageLength = (int) r.getRawBytesRead();
|
||||
byte[] sig = r.readRaw();
|
||||
PublicKey publicKey;
|
||||
try {
|
||||
publicKey = keyParser.parsePublicKey(encodedKey);
|
||||
} catch(InvalidKeySpecException e) {
|
||||
throw new FormatException();
|
||||
}
|
||||
signature.initVerify(publicKey);
|
||||
signature.update(raw, 0, length);
|
||||
signature.update(raw, 0, messageLength);
|
||||
if(!signature.verify(sig)) throw new SignatureException();
|
||||
// Hash the message, including the signature, to get the message ID
|
||||
messageDigest.reset();
|
||||
@@ -73,12 +78,4 @@ class MessageParserImpl implements MessageParser {
|
||||
MessageId id = new MessageId(messageDigest.digest());
|
||||
return new MessageImpl(id, parent, group, author, timestamp, raw);
|
||||
}
|
||||
|
||||
// FIXME: Work out a better way of doing this
|
||||
private int bytesToEncode(int i) {
|
||||
if(i >= 0 && i <= Byte.MAX_VALUE) return 2;
|
||||
if(i >= Byte.MIN_VALUE && i <= Byte.MAX_VALUE) return 3;
|
||||
if(i >= Short.MIN_VALUE && i <= Short.MAX_VALUE) return 4;
|
||||
return 6;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ class ReaderImpl implements Reader {
|
||||
private final InputStream in;
|
||||
private boolean started = false, eof = false, readLimited = false;
|
||||
private byte next;
|
||||
private long readLimit = 0L;
|
||||
private long rawBytesRead = 0L, readLimit = 0L;
|
||||
private byte[] buf = null;
|
||||
|
||||
ReaderImpl(InputStream in) {
|
||||
@@ -31,12 +31,12 @@ class ReaderImpl implements Reader {
|
||||
}
|
||||
|
||||
private byte readNext(boolean eofAcceptable) throws IOException {
|
||||
started = true;
|
||||
int i = in.read();
|
||||
if(i == -1) {
|
||||
eof = true;
|
||||
if(!eofAcceptable) throw new FormatException();
|
||||
}
|
||||
} else rawBytesRead++;
|
||||
started = true;
|
||||
if(i > 127) i -= 256;
|
||||
next = (byte) i;
|
||||
return next;
|
||||
@@ -53,6 +53,12 @@ class ReaderImpl implements Reader {
|
||||
readLimit = 0L;
|
||||
}
|
||||
|
||||
public long getRawBytesRead() {
|
||||
if(eof) return rawBytesRead;
|
||||
else if(started) return rawBytesRead - 1L; // Exclude lookahead byte
|
||||
else return 0L;
|
||||
}
|
||||
|
||||
public void close() throws IOException {
|
||||
in.close();
|
||||
}
|
||||
@@ -134,9 +140,11 @@ class ReaderImpl implements Reader {
|
||||
if(buf == null || buf.length < length) buf = new byte[length];
|
||||
buf[0] = next;
|
||||
int offset = 1, read = 0;
|
||||
while(offset < length && read != -1) {
|
||||
while(offset < length) {
|
||||
read = in.read(buf, offset, length - offset);
|
||||
if(read != -1) offset += read;
|
||||
if(read == -1) break;
|
||||
offset += read;
|
||||
rawBytesRead += read;
|
||||
}
|
||||
if(offset < length) throw new FormatException();
|
||||
readNext(true);
|
||||
@@ -307,7 +315,7 @@ class ReaderImpl implements Reader {
|
||||
readNull();
|
||||
return null;
|
||||
}
|
||||
throw new IllegalStateException();
|
||||
throw new FormatException();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
|
||||
@@ -13,11 +13,16 @@ import net.sf.briar.api.serial.Writer;
|
||||
class WriterImpl implements Writer {
|
||||
|
||||
private final OutputStream out;
|
||||
private long rawBytesWritten = 0L;
|
||||
|
||||
WriterImpl(OutputStream out) {
|
||||
this.out = out;
|
||||
}
|
||||
|
||||
public long getRawBytesWritten() {
|
||||
return rawBytesWritten;
|
||||
}
|
||||
|
||||
public void close() throws IOException {
|
||||
out.flush();
|
||||
out.close();
|
||||
@@ -26,27 +31,32 @@ class WriterImpl implements Writer {
|
||||
public void writeBoolean(boolean b) throws IOException {
|
||||
if(b) out.write(Tag.TRUE);
|
||||
else out.write(Tag.FALSE);
|
||||
rawBytesWritten++;
|
||||
}
|
||||
|
||||
public void writeUint7(byte b) throws IOException {
|
||||
if(b < 0) throw new IllegalArgumentException();
|
||||
out.write(b);
|
||||
rawBytesWritten++;
|
||||
}
|
||||
|
||||
public void writeInt8(byte b) throws IOException {
|
||||
out.write(Tag.INT8);
|
||||
out.write(b);
|
||||
rawBytesWritten += 2;
|
||||
}
|
||||
|
||||
public void writeInt16(short s) throws IOException {
|
||||
out.write(Tag.INT16);
|
||||
out.write((byte) (s >> 8));
|
||||
out.write((byte) ((s << 8) >> 8));
|
||||
rawBytesWritten += 3;
|
||||
}
|
||||
|
||||
public void writeInt32(int i) throws IOException {
|
||||
out.write(Tag.INT32);
|
||||
writeInt32Bits(i);
|
||||
rawBytesWritten += 5;
|
||||
}
|
||||
|
||||
private void writeInt32Bits(int i) throws IOException {
|
||||
@@ -59,6 +69,7 @@ class WriterImpl implements Writer {
|
||||
public void writeInt64(long l) throws IOException {
|
||||
out.write(Tag.INT64);
|
||||
writeInt64Bits(l);
|
||||
rawBytesWritten += 9;
|
||||
}
|
||||
|
||||
private void writeInt64Bits(long l) throws IOException {
|
||||
@@ -87,11 +98,13 @@ class WriterImpl implements Writer {
|
||||
public void writeFloat32(float f) throws IOException {
|
||||
out.write(Tag.FLOAT32);
|
||||
writeInt32Bits(Float.floatToRawIntBits(f));
|
||||
rawBytesWritten += 5;
|
||||
}
|
||||
|
||||
public void writeFloat64(double d) throws IOException {
|
||||
out.write(Tag.FLOAT64);
|
||||
writeInt64Bits(Double.doubleToRawLongBits(d));
|
||||
rawBytesWritten += 9;
|
||||
}
|
||||
|
||||
public void writeUtf8(String s) throws IOException {
|
||||
@@ -99,12 +112,14 @@ class WriterImpl implements Writer {
|
||||
byte[] b = s.getBytes("UTF-8");
|
||||
writeIntAny(b.length);
|
||||
out.write(b);
|
||||
rawBytesWritten += b.length + 1;
|
||||
}
|
||||
|
||||
public void writeRaw(byte[] b) throws IOException {
|
||||
out.write(Tag.RAW);
|
||||
writeIntAny(b.length);
|
||||
out.write(b);
|
||||
rawBytesWritten += b.length + 1;
|
||||
}
|
||||
|
||||
public void writeRaw(Raw r) throws IOException {
|
||||
@@ -113,6 +128,7 @@ class WriterImpl implements Writer {
|
||||
|
||||
public void writeList(List<?> l) throws IOException {
|
||||
out.write(Tag.LIST_DEF);
|
||||
rawBytesWritten++;
|
||||
writeIntAny(l.size());
|
||||
for(Object o : l) writeObject(o);
|
||||
}
|
||||
@@ -135,14 +151,17 @@ class WriterImpl implements Writer {
|
||||
|
||||
public void writeListStart() throws IOException {
|
||||
out.write(Tag.LIST_INDEF);
|
||||
rawBytesWritten++;
|
||||
}
|
||||
|
||||
public void writeListEnd() throws IOException {
|
||||
out.write(Tag.END);
|
||||
rawBytesWritten++;
|
||||
}
|
||||
|
||||
public void writeMap(Map<?, ?> m) throws IOException {
|
||||
out.write(Tag.MAP_DEF);
|
||||
rawBytesWritten++;
|
||||
writeIntAny(m.size());
|
||||
for(Entry<?, ?> e : m.entrySet()) {
|
||||
writeObject(e.getKey());
|
||||
@@ -152,13 +171,16 @@ class WriterImpl implements Writer {
|
||||
|
||||
public void writeMapStart() throws IOException {
|
||||
out.write(Tag.MAP_INDEF);
|
||||
rawBytesWritten++;
|
||||
}
|
||||
|
||||
public void writeMapEnd() throws IOException {
|
||||
out.write(Tag.END);
|
||||
rawBytesWritten++;
|
||||
}
|
||||
|
||||
public void writeNull() throws IOException {
|
||||
out.write(Tag.NULL);
|
||||
rawBytesWritten++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import java.security.MessageDigest;
|
||||
import java.security.PublicKey;
|
||||
import java.security.Signature;
|
||||
import java.security.spec.EncodedKeySpec;
|
||||
import java.security.spec.InvalidKeySpecException;
|
||||
import java.security.spec.X509EncodedKeySpec;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
@@ -82,10 +83,12 @@ public class BundleReadWriteTest extends TestCase {
|
||||
keyPair = KeyPairGenerator.getInstance(KEY_PAIR_ALGO).generateKeyPair();
|
||||
sig = Signature.getInstance(SIGNATURE_ALGO);
|
||||
digest = MessageDigest.getInstance(DIGEST_ALGO);
|
||||
final KeyFactory keyFactory = KeyFactory.getInstance(KEY_PAIR_ALGO);
|
||||
keyParser = new KeyParser() {
|
||||
public PublicKey parsePublicKey(byte[] encodedKey) throws GeneralSecurityException {
|
||||
public PublicKey parsePublicKey(byte[] encodedKey)
|
||||
throws InvalidKeySpecException {
|
||||
EncodedKeySpec e = new X509EncodedKeySpec(encodedKey);
|
||||
return KeyFactory.getInstance(KEY_PAIR_ALGO).generatePublic(e);
|
||||
return keyFactory.generatePublic(e);
|
||||
}
|
||||
};
|
||||
assertEquals(digest.getDigestLength(), UniqueId.LENGTH);
|
||||
|
||||
@@ -3,6 +3,7 @@ package net.sf.briar.serial;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
@@ -343,6 +344,27 @@ public class ReaderImplTest extends TestCase {
|
||||
assertTrue(r.eof());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetRawBytesRead() throws IOException {
|
||||
setContents("F4" + "00" + "F4" + "00");
|
||||
assertEquals(0L, r.getRawBytesRead());
|
||||
Map<Object, Object> m = r.readMap(Object.class, Object.class);
|
||||
assertEquals(2L, r.getRawBytesRead());
|
||||
assertEquals(Collections.emptyMap(), m);
|
||||
m = r.readMap(Object.class, Object.class);
|
||||
assertEquals(4L, r.getRawBytesRead());
|
||||
assertEquals(Collections.emptyMap(), m);
|
||||
assertTrue(r.eof());
|
||||
assertEquals(4L, r.getRawBytesRead());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadEmptyInput() throws IOException {
|
||||
setContents("");
|
||||
assertTrue(r.eof());
|
||||
assertEquals(0L, r.getRawBytesRead());
|
||||
}
|
||||
|
||||
private void setContents(String hex) {
|
||||
in = new ByteArrayInputStream(StringUtils.fromHexString(hex));
|
||||
r = new ReaderImpl(in);
|
||||
|
||||
@@ -211,5 +211,6 @@ public class WriterImplTest extends TestCase {
|
||||
byte[] expected = StringUtils.fromHexString(hex);
|
||||
assertTrue(StringUtils.toHexString(out.toByteArray()),
|
||||
Arrays.equals(expected, out.toByteArray()));
|
||||
assertEquals(expected.length, w.getRawBytesWritten());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user