--- /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);
+ }
+}