diff -r 5315a5713dd5 -r b2e1b45382a4 src/net/java/otr4j/io/OtrInputStream.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/net/java/otr4j/io/OtrInputStream.java Fri Apr 15 03:01:09 2011 +0200 @@ -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); + } +}