src/net/java/otr4j/io/OtrInputStream.java
changeset 810 0ff0059f2ec3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/net/java/otr4j/io/OtrInputStream.java	Sun Dec 05 18:43:51 2010 +0100
@@ -0,0 +1,135 @@
+package net.java.otr4j.io;
+
+import java.io.FilterInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.math.BigInteger;
+import java.security.KeyFactory;
+import java.security.NoSuchAlgorithmException;
+import java.security.PublicKey;
+import java.security.interfaces.DSAParams;
+import java.security.interfaces.DSAPublicKey;
+import java.security.spec.DSAPublicKeySpec;
+import java.security.spec.InvalidKeySpecException;
+
+import javax.crypto.interfaces.DHPublicKey;
+
+import net.java.otr4j.crypto.OtrCryptoEngineImpl;
+import net.java.otr4j.io.messages.SignatureX;
+
+public class OtrInputStream extends FilterInputStream implements
+		SerializationConstants {
+
+	public OtrInputStream(InputStream in) {
+		super(in);
+	}
+
+	private int readNumber(int length) throws IOException {
+		byte[] b = new byte[length];
+		read(b);
+
+		int value = 0;
+		for (int i = 0; i < b.length; i++) {
+			int shift = (b.length - 1 - i) * 8;
+			value += (b[i] & 0x000000FF) << shift;
+		}
+
+		return value;
+	}
+
+	public int readByte() throws IOException {
+		return readNumber(TYPE_LEN_BYTE);
+	}
+
+	public int readInt() throws IOException {
+		return readNumber(TYPE_LEN_INT);
+	}
+
+	public int readShort() throws IOException {
+		return readNumber(TYPE_LEN_SHORT);
+	}
+
+	public byte[] readCtr() throws IOException {
+		byte[] b = new byte[TYPE_LEN_CTR];
+		read(b);
+		return b;
+	}
+
+	public byte[] readMac() throws IOException {
+		byte[] b = new byte[TYPE_LEN_MAC];
+		read(b);
+		return b;
+	}
+
+	public BigInteger readBigInt() throws IOException {
+		byte[] b = readData();
+		return new BigInteger(1, b);
+	}
+
+	public byte[] readData() throws IOException {
+		int dataLen = readNumber(DATA_LEN);
+		byte[] b = new byte[dataLen];
+		read(b);
+		return b;
+	}
+
+	public PublicKey readPublicKey() throws IOException {
+		int type = readShort();
+		switch (type) {
+		case 0:
+			BigInteger p = readBigInt();
+			BigInteger q = readBigInt();
+			BigInteger g = readBigInt();
+			BigInteger y = readBigInt();
+			DSAPublicKeySpec keySpec = new DSAPublicKeySpec(y, p, q, g);
+			KeyFactory keyFactory;
+			try {
+				keyFactory = KeyFactory.getInstance("DSA");
+			} catch (NoSuchAlgorithmException e) {
+				throw new IOException();
+			}
+			try {
+				return keyFactory.generatePublic(keySpec);
+			} catch (InvalidKeySpecException e) {
+				throw new IOException();
+			}
+		default:
+			throw new UnsupportedOperationException();
+		}
+	}
+
+	public DHPublicKey readDHPublicKey() throws IOException {
+		BigInteger gyMpi = readBigInt();
+		try {
+			return new OtrCryptoEngineImpl().getDHPublicKey(gyMpi);
+		} catch (Exception ex) {
+			throw new IOException();
+		}
+	}
+
+	public byte[] readTlvData() throws IOException {
+		int len = readNumber(TYPE_LEN_BYTE);
+
+		byte[] b = new byte[len];
+		in.read(b);
+		return b;
+	}
+
+	public byte[] readSignature(PublicKey pubKey) throws IOException {
+		if (!pubKey.getAlgorithm().equals("DSA"))
+			throw new UnsupportedOperationException();
+
+		DSAPublicKey dsaPubKey = (DSAPublicKey) pubKey;
+		DSAParams dsaParams = dsaPubKey.getParams();
+		byte[] sig = new byte[dsaParams.getQ().bitLength() / 4];
+		read(sig);
+		return sig;
+	}
+
+	public SignatureX readMysteriousX() throws IOException {
+		PublicKey pubKey = readPublicKey();
+		int dhKeyID = readInt();
+		byte[] sig = readSignature(pubKey);
+		return new SignatureX(pubKey, dhKeyID, sig);
+	}
+}