src/net/java/otr4j/io/OtrInputStream.java
changeset 810 0ff0059f2ec3
equal deleted inserted replaced
797:fbd3585af53e 810:0ff0059f2ec3
       
     1 package net.java.otr4j.io;
       
     2 
       
     3 import java.io.FilterInputStream;
       
     4 import java.io.IOException;
       
     5 import java.io.InputStream;
       
     6 import java.math.BigInteger;
       
     7 import java.security.KeyFactory;
       
     8 import java.security.NoSuchAlgorithmException;
       
     9 import java.security.PublicKey;
       
    10 import java.security.interfaces.DSAParams;
       
    11 import java.security.interfaces.DSAPublicKey;
       
    12 import java.security.spec.DSAPublicKeySpec;
       
    13 import java.security.spec.InvalidKeySpecException;
       
    14 
       
    15 import javax.crypto.interfaces.DHPublicKey;
       
    16 
       
    17 import net.java.otr4j.crypto.OtrCryptoEngineImpl;
       
    18 import net.java.otr4j.io.messages.SignatureX;
       
    19 
       
    20 public class OtrInputStream extends FilterInputStream implements
       
    21 		SerializationConstants {
       
    22 
       
    23 	public OtrInputStream(InputStream in) {
       
    24 		super(in);
       
    25 	}
       
    26 
       
    27 	private int readNumber(int length) throws IOException {
       
    28 		byte[] b = new byte[length];
       
    29 		read(b);
       
    30 
       
    31 		int value = 0;
       
    32 		for (int i = 0; i < b.length; i++) {
       
    33 			int shift = (b.length - 1 - i) * 8;
       
    34 			value += (b[i] & 0x000000FF) << shift;
       
    35 		}
       
    36 
       
    37 		return value;
       
    38 	}
       
    39 
       
    40 	public int readByte() throws IOException {
       
    41 		return readNumber(TYPE_LEN_BYTE);
       
    42 	}
       
    43 
       
    44 	public int readInt() throws IOException {
       
    45 		return readNumber(TYPE_LEN_INT);
       
    46 	}
       
    47 
       
    48 	public int readShort() throws IOException {
       
    49 		return readNumber(TYPE_LEN_SHORT);
       
    50 	}
       
    51 
       
    52 	public byte[] readCtr() throws IOException {
       
    53 		byte[] b = new byte[TYPE_LEN_CTR];
       
    54 		read(b);
       
    55 		return b;
       
    56 	}
       
    57 
       
    58 	public byte[] readMac() throws IOException {
       
    59 		byte[] b = new byte[TYPE_LEN_MAC];
       
    60 		read(b);
       
    61 		return b;
       
    62 	}
       
    63 
       
    64 	public BigInteger readBigInt() throws IOException {
       
    65 		byte[] b = readData();
       
    66 		return new BigInteger(1, b);
       
    67 	}
       
    68 
       
    69 	public byte[] readData() throws IOException {
       
    70 		int dataLen = readNumber(DATA_LEN);
       
    71 		byte[] b = new byte[dataLen];
       
    72 		read(b);
       
    73 		return b;
       
    74 	}
       
    75 
       
    76 	public PublicKey readPublicKey() throws IOException {
       
    77 		int type = readShort();
       
    78 		switch (type) {
       
    79 		case 0:
       
    80 			BigInteger p = readBigInt();
       
    81 			BigInteger q = readBigInt();
       
    82 			BigInteger g = readBigInt();
       
    83 			BigInteger y = readBigInt();
       
    84 			DSAPublicKeySpec keySpec = new DSAPublicKeySpec(y, p, q, g);
       
    85 			KeyFactory keyFactory;
       
    86 			try {
       
    87 				keyFactory = KeyFactory.getInstance("DSA");
       
    88 			} catch (NoSuchAlgorithmException e) {
       
    89 				throw new IOException();
       
    90 			}
       
    91 			try {
       
    92 				return keyFactory.generatePublic(keySpec);
       
    93 			} catch (InvalidKeySpecException e) {
       
    94 				throw new IOException();
       
    95 			}
       
    96 		default:
       
    97 			throw new UnsupportedOperationException();
       
    98 		}
       
    99 	}
       
   100 
       
   101 	public DHPublicKey readDHPublicKey() throws IOException {
       
   102 		BigInteger gyMpi = readBigInt();
       
   103 		try {
       
   104 			return new OtrCryptoEngineImpl().getDHPublicKey(gyMpi);
       
   105 		} catch (Exception ex) {
       
   106 			throw new IOException();
       
   107 		}
       
   108 	}
       
   109 
       
   110 	public byte[] readTlvData() throws IOException {
       
   111 		int len = readNumber(TYPE_LEN_BYTE);
       
   112 
       
   113 		byte[] b = new byte[len];
       
   114 		in.read(b);
       
   115 		return b;
       
   116 	}
       
   117 
       
   118 	public byte[] readSignature(PublicKey pubKey) throws IOException {
       
   119 		if (!pubKey.getAlgorithm().equals("DSA"))
       
   120 			throw new UnsupportedOperationException();
       
   121 
       
   122 		DSAPublicKey dsaPubKey = (DSAPublicKey) pubKey;
       
   123 		DSAParams dsaParams = dsaPubKey.getParams();
       
   124 		byte[] sig = new byte[dsaParams.getQ().bitLength() / 4];
       
   125 		read(sig);
       
   126 		return sig;
       
   127 	}
       
   128 
       
   129 	public SignatureX readMysteriousX() throws IOException {
       
   130 		PublicKey pubKey = readPublicKey();
       
   131 		int dhKeyID = readInt();
       
   132 		byte[] sig = readSignature(pubKey);
       
   133 		return new SignatureX(pubKey, dhKeyID, sig);
       
   134 	}
       
   135 }