src/net/java/otr4j/io/OtrOutputStream.java
changeset 810 0ff0059f2ec3
child 895 b2e1b45382a4
equal deleted inserted replaced
797:fbd3585af53e 810:0ff0059f2ec3
       
     1 package net.java.otr4j.io;
       
     2 
       
     3 import java.io.FilterOutputStream;
       
     4 import java.io.IOException;
       
     5 import java.io.OutputStream;
       
     6 import java.math.BigInteger;
       
     7 import java.security.PublicKey;
       
     8 import java.security.interfaces.DSAParams;
       
     9 import java.security.interfaces.DSAPublicKey;
       
    10 
       
    11 import javax.crypto.interfaces.DHPublicKey;
       
    12 
       
    13 import net.java.otr4j.io.messages.SignatureM;
       
    14 import net.java.otr4j.io.messages.MysteriousT;
       
    15 import net.java.otr4j.io.messages.SignatureX;
       
    16 
       
    17 import org.bouncycastle.util.BigIntegers;
       
    18 
       
    19 public class OtrOutputStream extends FilterOutputStream implements
       
    20 		SerializationConstants {
       
    21 
       
    22 	public OtrOutputStream(OutputStream out) {
       
    23 		super(out);
       
    24 	}
       
    25 
       
    26 	private void writeNumber(int value, int length) throws IOException {
       
    27 		byte[] b = new byte[length];
       
    28 		for (int i = 0; i < length; i++) {
       
    29 			int offset = (b.length - 1 - i) * 8;
       
    30 			b[i] = (byte) ((value >>> offset) & 0xFF);
       
    31 		}
       
    32 		write(b);
       
    33 	}
       
    34 
       
    35 	public void writeBigInt(BigInteger bi) throws IOException {
       
    36 		byte[] b = BigIntegers.asUnsignedByteArray(bi);
       
    37 		writeData(b);
       
    38 	}
       
    39 
       
    40 	public void writeByte(int b) throws IOException {
       
    41 		writeNumber(b, TYPE_LEN_BYTE);
       
    42 	}
       
    43 
       
    44 	public void writeData(byte[] b) throws IOException {
       
    45 		int len = (b == null || b.length < 0) ? 0 : b.length;
       
    46 		writeNumber(len, DATA_LEN);
       
    47 		if (len > 0)
       
    48 			write(b);
       
    49 	}
       
    50 
       
    51 	public void writeInt(int i) throws IOException {
       
    52 		writeNumber(i, TYPE_LEN_INT);
       
    53 
       
    54 	}
       
    55 
       
    56 	public void writeShort(int s) throws IOException {
       
    57 		writeNumber(s, TYPE_LEN_SHORT);
       
    58 
       
    59 	}
       
    60 
       
    61 	public void writeMac(byte[] mac) throws IOException {
       
    62 		if (mac == null || mac.length != TYPE_LEN_MAC)
       
    63 			throw new IllegalArgumentException();
       
    64 
       
    65 		write(mac);
       
    66 	}
       
    67 
       
    68 	public void writeCtr(byte[] ctr) throws IOException {
       
    69 		if (ctr == null || ctr.length < 1)
       
    70 			return;
       
    71 
       
    72 		int i = 0;
       
    73 		while (i < TYPE_LEN_CTR && i < ctr.length) {
       
    74 			write(ctr[i]);
       
    75 			i++;
       
    76 		}
       
    77 	}
       
    78 
       
    79 	public void writeDHPublicKey(DHPublicKey dhPublicKey) throws IOException {
       
    80 		byte[] b = BigIntegers.asUnsignedByteArray(dhPublicKey.getY());
       
    81 		writeData(b);
       
    82 	}
       
    83 
       
    84 	public void writePublicKey(PublicKey pubKey) throws IOException {
       
    85 		if (!(pubKey instanceof DSAPublicKey))
       
    86 			throw new UnsupportedOperationException(
       
    87 					"Key types other than DSA are not supported at the moment.");
       
    88 
       
    89 		DSAPublicKey dsaKey = (DSAPublicKey) pubKey;
       
    90 
       
    91 		writeShort(0);
       
    92 
       
    93 		DSAParams dsaParams = dsaKey.getParams();
       
    94 		writeBigInt(dsaParams.getP());
       
    95 		writeBigInt(dsaParams.getQ());
       
    96 		writeBigInt(dsaParams.getG());
       
    97 		writeBigInt(dsaKey.getY());
       
    98 
       
    99 	}
       
   100 
       
   101 	public void writeTlvData(byte[] b) throws IOException {
       
   102 		int len = (b == null || b.length < 0) ? 0 : b.length;
       
   103 		writeNumber(len, TLV_LEN);
       
   104 		if (len > 0)
       
   105 			write(b);
       
   106 	}
       
   107 
       
   108 	public void writeSignature(byte[] signature, PublicKey pubKey)
       
   109 			throws IOException {
       
   110 		if (!pubKey.getAlgorithm().equals("DSA"))
       
   111 			throw new UnsupportedOperationException();
       
   112 		out.write(signature);
       
   113 	}
       
   114 
       
   115 	public void writeMysteriousX(SignatureX x) throws IOException {
       
   116 		writePublicKey(x.longTermPublicKey);
       
   117 		writeInt(x.dhKeyID);
       
   118 		writeSignature(x.signature, x.longTermPublicKey);
       
   119 	}
       
   120 
       
   121 	public void writeMysteriousX(SignatureM m) throws IOException {
       
   122 		writeBigInt(m.localPubKey.getY());
       
   123 		writeBigInt(m.remotePubKey.getY());
       
   124 		writePublicKey(m.localLongTermPubKey);
       
   125 		writeInt(m.keyPairID);
       
   126 	}
       
   127 
       
   128 	public void writeMysteriousT(MysteriousT t) throws IOException {
       
   129 		writeShort(t.protocolVersion);
       
   130 		writeByte(t.messageType);
       
   131 		writeByte(t.flags);
       
   132 
       
   133 		writeInt(t.senderKeyID);
       
   134 		writeInt(t.recipientKeyID);
       
   135 		writeDHPublicKey(t.nextDH);
       
   136 		writeCtr(t.ctr);
       
   137 		writeData(t.encryptedMessage);
       
   138 
       
   139 	}
       
   140 }