From c3643a037b2abd3d9905809ed0dcf988d4e61bdf Mon Sep 17 00:00:00 2001 From: akwizgran <akwizgran@users.sourceforge.net> Date: Tue, 12 Jul 2011 20:27:37 +0100 Subject: [PATCH] Added accessors for the amount of raw data read and written by readers and writers - this fixes a fixme in MessageParserImpl. --- api/net/sf/briar/api/crypto/KeyParser.java | 4 ++-- api/net/sf/briar/api/serial/Reader.java | 1 + api/net/sf/briar/api/serial/Writer.java | 1 + .../sf/briar/protocol/MessageParserImpl.java | 23 ++++++++----------- .../net/sf/briar/serial/ReaderImpl.java | 20 +++++++++++----- .../net/sf/briar/serial/WriterImpl.java | 22 ++++++++++++++++++ .../briar/protocol/BundleReadWriteTest.java | 7 ++++-- test/net/sf/briar/serial/ReaderImplTest.java | 22 ++++++++++++++++++ test/net/sf/briar/serial/WriterImplTest.java | 1 + 9 files changed, 78 insertions(+), 23 deletions(-) diff --git a/api/net/sf/briar/api/crypto/KeyParser.java b/api/net/sf/briar/api/crypto/KeyParser.java index 2363dee5d8..599c900828 100644 --- a/api/net/sf/briar/api/crypto/KeyParser.java +++ b/api/net/sf/briar/api/crypto/KeyParser.java @@ -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; } diff --git a/api/net/sf/briar/api/serial/Reader.java b/api/net/sf/briar/api/serial/Reader.java index 47bc385919..06fe30b8f3 100644 --- a/api/net/sf/briar/api/serial/Reader.java +++ b/api/net/sf/briar/api/serial/Reader.java @@ -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; diff --git a/api/net/sf/briar/api/serial/Writer.java b/api/net/sf/briar/api/serial/Writer.java index 41f273333b..2efe55e306 100644 --- a/api/net/sf/briar/api/serial/Writer.java +++ b/api/net/sf/briar/api/serial/Writer.java @@ -6,6 +6,7 @@ import java.util.Map; public interface Writer { + long getRawBytesWritten(); void close() throws IOException; void writeBoolean(boolean b) throws IOException; diff --git a/components/net/sf/briar/protocol/MessageParserImpl.java b/components/net/sf/briar/protocol/MessageParserImpl.java index f9b138a621..b2d01c36ef 100644 --- a/components/net/sf/briar/protocol/MessageParserImpl.java +++ b/components/net/sf/briar/protocol/MessageParserImpl.java @@ -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; - } } diff --git a/components/net/sf/briar/serial/ReaderImpl.java b/components/net/sf/briar/serial/ReaderImpl.java index b98383e0e6..dd9e4acf94 100644 --- a/components/net/sf/briar/serial/ReaderImpl.java +++ b/components/net/sf/briar/serial/ReaderImpl.java @@ -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") diff --git a/components/net/sf/briar/serial/WriterImpl.java b/components/net/sf/briar/serial/WriterImpl.java index 18f1760780..a8cddfa1b3 100644 --- a/components/net/sf/briar/serial/WriterImpl.java +++ b/components/net/sf/briar/serial/WriterImpl.java @@ -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++; } } diff --git a/test/net/sf/briar/protocol/BundleReadWriteTest.java b/test/net/sf/briar/protocol/BundleReadWriteTest.java index fcb26721e2..8a8851f925 100644 --- a/test/net/sf/briar/protocol/BundleReadWriteTest.java +++ b/test/net/sf/briar/protocol/BundleReadWriteTest.java @@ -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); diff --git a/test/net/sf/briar/serial/ReaderImplTest.java b/test/net/sf/briar/serial/ReaderImplTest.java index a9e7bf5aa8..c87c00e401 100644 --- a/test/net/sf/briar/serial/ReaderImplTest.java +++ b/test/net/sf/briar/serial/ReaderImplTest.java @@ -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); diff --git a/test/net/sf/briar/serial/WriterImplTest.java b/test/net/sf/briar/serial/WriterImplTest.java index f4afce160e..5d7eeec468 100644 --- a/test/net/sf/briar/serial/WriterImplTest.java +++ b/test/net/sf/briar/serial/WriterImplTest.java @@ -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()); } } -- GitLab