diff -r 7d6f2526244a -r 197a85a35cba src/net/java/otr4j/io/SerializationUtils.java --- a/src/net/java/otr4j/io/SerializationUtils.java Sun Mar 15 17:28:04 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,341 +0,0 @@ -/* - * otr4j, the open source java otr library. - * - * Distributable under LGPL license. - * See terms of license at gnu.org. - */ -package net.java.otr4j.io; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.StringReader; -import java.io.StringWriter; -import java.math.BigInteger; -import java.security.PublicKey; -import java.util.List; -import java.util.Vector; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import javax.crypto.interfaces.DHPublicKey; - -import org.bouncycastle2.util.encoders.Base64; - -import net.java.otr4j.io.messages.AbstractEncodedMessage; -import net.java.otr4j.io.messages.AbstractMessage; -import net.java.otr4j.io.messages.DHCommitMessage; -import net.java.otr4j.io.messages.DHKeyMessage; -import net.java.otr4j.io.messages.DataMessage; -import net.java.otr4j.io.messages.ErrorMessage; -import net.java.otr4j.io.messages.MysteriousT; -import net.java.otr4j.io.messages.PlainTextMessage; -import net.java.otr4j.io.messages.QueryMessage; -import net.java.otr4j.io.messages.RevealSignatureMessage; -import net.java.otr4j.io.messages.SignatureM; -import net.java.otr4j.io.messages.SignatureMessage; -import net.java.otr4j.io.messages.SignatureX; - -/** - * - * @author George Politis - */ -public class SerializationUtils { - // Mysterious X IO. - public static SignatureX toMysteriousX(byte[] b) throws IOException { - ByteArrayInputStream in = new ByteArrayInputStream(b); - OtrInputStream ois = new OtrInputStream(in); - SignatureX x = ois.readMysteriousX(); - ois.close(); - return x; - } - - public static byte[] toByteArray(SignatureX x) throws IOException { - ByteArrayOutputStream out = new ByteArrayOutputStream(); - OtrOutputStream oos = new OtrOutputStream(out); - oos.writeMysteriousX(x); - byte[] b = out.toByteArray(); - oos.close(); - return b; - } - - // Mysterious M IO. - public static byte[] toByteArray(SignatureM m) throws IOException { - ByteArrayOutputStream out = new ByteArrayOutputStream(); - OtrOutputStream oos = new OtrOutputStream(out); - oos.writeMysteriousX(m); - byte[] b = out.toByteArray(); - oos.close(); - return b; - } - - // Mysterious T IO. - public static byte[] toByteArray(MysteriousT t) throws IOException { - ByteArrayOutputStream out = new ByteArrayOutputStream(); - OtrOutputStream oos = new OtrOutputStream(out); - oos.writeMysteriousT(t); - byte[] b = out.toByteArray(); - oos.close(); - return b; - } - - // Basic IO. - public static byte[] writeData(byte[] b) throws IOException { - ByteArrayOutputStream out = new ByteArrayOutputStream(); - OtrOutputStream oos = new OtrOutputStream(out); - oos.writeData(b); - byte[] otrb = out.toByteArray(); - oos.close(); - return otrb; - } - - // BigInteger IO. - public static byte[] writeMpi(BigInteger bigInt) throws IOException { - ByteArrayOutputStream out = new ByteArrayOutputStream(); - OtrOutputStream oos = new OtrOutputStream(out); - oos.writeBigInt(bigInt); - byte[] b = out.toByteArray(); - oos.close(); - return b; - } - - public static BigInteger readMpi(byte[] b) throws IOException { - ByteArrayInputStream in = new ByteArrayInputStream(b); - OtrInputStream ois = new OtrInputStream(in); - BigInteger bigint = ois.readBigInt(); - ois.close(); - return bigint; - } - - // Public Key IO. - public static byte[] writePublicKey(PublicKey pubKey) throws IOException { - ByteArrayOutputStream out = new ByteArrayOutputStream(); - OtrOutputStream oos = new OtrOutputStream(out); - oos.writePublicKey(pubKey); - byte[] b = out.toByteArray(); - oos.close(); - return b; - } - - // Message IO. - public static String toString(AbstractMessage m) throws IOException { - StringWriter writer = new StringWriter(); - writer.write(SerializationConstants.HEAD); - - switch (m.messageType) { - case AbstractMessage.MESSAGE_ERROR: - ErrorMessage error = (ErrorMessage) m; - writer.write(SerializationConstants.HEAD_ERROR); - writer.write(error.error); - break; - case AbstractMessage.MESSAGE_PLAINTEXT: - PlainTextMessage plaintxt = (PlainTextMessage) m; - writer.write(plaintxt.cleanText); - if (plaintxt.versions != null && plaintxt.versions.size() > 0) { - writer.write(" \\t \\t\\t\\t\\t \\t \\t \\t "); - for (int version : plaintxt.versions) { - if (version == 1) - writer.write(" \\t\\t \\t "); - - if (version == 2) - writer.write(" \\t \\t \\t "); - } - } - break; - case AbstractMessage.MESSAGE_QUERY: - QueryMessage query = (QueryMessage) m; - if (query.versions.size() == 1 && query.versions.get(0) == 1) { - writer.write(SerializationConstants.HEAD_QUERY_Q); - } else { - writer.write(SerializationConstants.HEAD_QUERY_V); - for (int version : query.versions) - writer.write(String.valueOf(version)); - - writer.write(SerializationConstants.HEAD_QUERY_Q); - } - break; - case AbstractEncodedMessage.MESSAGE_DHKEY: - case AbstractEncodedMessage.MESSAGE_REVEALSIG: - case AbstractEncodedMessage.MESSAGE_SIGNATURE: - case AbstractEncodedMessage.MESSAGE_DH_COMMIT: - case AbstractEncodedMessage.MESSAGE_DATA: - ByteArrayOutputStream o = new ByteArrayOutputStream(); - OtrOutputStream s = new OtrOutputStream(o); - - switch (m.messageType) { - case AbstractEncodedMessage.MESSAGE_DHKEY: - DHKeyMessage dhkey = (DHKeyMessage) m; - s.writeShort(dhkey.protocolVersion); - s.writeByte(dhkey.messageType); - s.writeDHPublicKey(dhkey.dhPublicKey); - break; - case AbstractEncodedMessage.MESSAGE_REVEALSIG: - RevealSignatureMessage revealsig = (RevealSignatureMessage) m; - s.writeShort(revealsig.protocolVersion); - s.writeByte(revealsig.messageType); - s.writeData(revealsig.revealedKey); - s.writeData(revealsig.xEncrypted); - s.writeMac(revealsig.xEncryptedMAC); - break; - case AbstractEncodedMessage.MESSAGE_SIGNATURE: - SignatureMessage sig = (SignatureMessage) m; - s.writeShort(sig.protocolVersion); - s.writeByte(sig.messageType); - s.writeData(sig.xEncrypted); - s.writeMac(sig.xEncryptedMAC); - break; - case AbstractEncodedMessage.MESSAGE_DH_COMMIT: - DHCommitMessage dhcommit = (DHCommitMessage) m; - s.writeShort(dhcommit.protocolVersion); - s.writeByte(dhcommit.messageType); - s.writeData(dhcommit.dhPublicKeyEncrypted); - s.writeData(dhcommit.dhPublicKeyHash); - break; - case AbstractEncodedMessage.MESSAGE_DATA: - DataMessage data = (DataMessage) m; - s.writeShort(data.protocolVersion); - s.writeByte(data.messageType); - s.writeByte(data.flags); - s.writeInt(data.senderKeyID); - s.writeInt(data.recipientKeyID); - s.writeDHPublicKey(data.nextDH); - s.writeCtr(data.ctr); - s.writeData(data.encryptedMessage); - s.writeMac(data.mac); - s.writeData(data.oldMACKeys); - break; - } - - writer.write(SerializationConstants.HEAD_ENCODED); - writer.write(new String(Base64.encode(o.toByteArray()))); - writer.write("."); - break; - default: - throw new IOException("Illegal message type."); - } - - return writer.toString(); - } - - static final Pattern patternWhitespace = Pattern - .compile("( \\t \\t\\t\\t\\t \\t \\t \\t )( \\t\\t \\t )?( \\t \\t \\t )?"); - - public static AbstractMessage toMessage(String s) throws IOException { - if (s == null || s.length() <= 1) - return null; - - if (s.indexOf(SerializationConstants.HEAD) != 0 - || s.length() <= SerializationConstants.HEAD.length()) { - // Try to detect whitespace tag. - final Matcher matcher = patternWhitespace.matcher(s); - - boolean v1 = false; - boolean v2 = false; - while (matcher.find()) { - if (!v1 && matcher.start(2) > -1) - v1 = true; - - if (!v2 && matcher.start(3) > -1) - v2 = true; - - if (v1 && v2) - break; - } - - String cleanText = matcher.replaceAll(""); - List versions; - if (v1 && v2) { - versions = new Vector(2); - versions.add(0, 1); - versions.add(0, 2); - } else if (v1) { - versions = new Vector(1); - versions.add(0, 1); - } else if (v2) { - versions = new Vector(1); - versions.add(2); - } else - versions = null; - - return new PlainTextMessage(versions, cleanText); - } else { - char contentType = s.charAt(SerializationConstants.HEAD.length()); - String content = s - .substring(SerializationConstants.HEAD.length() + 1); - switch (contentType) { - case SerializationConstants.HEAD_ENCODED: - ByteArrayInputStream bin = new ByteArrayInputStream(Base64 - .decode(content.getBytes())); - OtrInputStream otr = new OtrInputStream(bin); - // We have an encoded message. - int protocolVersion = otr.readShort(); - int messageType = otr.readByte(); - switch (messageType) { - case AbstractEncodedMessage.MESSAGE_DATA: - int flags = otr.readByte(); - int senderKeyID = otr.readInt(); - int recipientKeyID = otr.readInt(); - DHPublicKey nextDH = otr.readDHPublicKey(); - byte[] ctr = otr.readCtr(); - byte[] encryptedMessage = otr.readData(); - byte[] mac = otr.readMac(); - byte[] oldMacKeys = otr.readMac(); - return new DataMessage(protocolVersion, flags, senderKeyID, - recipientKeyID, nextDH, ctr, encryptedMessage, mac, - oldMacKeys); - case AbstractEncodedMessage.MESSAGE_DH_COMMIT: - byte[] dhPublicKeyEncrypted = otr.readData(); - byte[] dhPublicKeyHash = otr.readData(); - return new DHCommitMessage(protocolVersion, - dhPublicKeyHash, dhPublicKeyEncrypted); - case AbstractEncodedMessage.MESSAGE_DHKEY: - DHPublicKey dhPublicKey = otr.readDHPublicKey(); - return new DHKeyMessage(protocolVersion, dhPublicKey); - case AbstractEncodedMessage.MESSAGE_REVEALSIG: { - byte[] revealedKey = otr.readData(); - byte[] xEncrypted = otr.readData(); - byte[] xEncryptedMac = otr.readMac(); - return new RevealSignatureMessage(protocolVersion, - xEncrypted, xEncryptedMac, revealedKey); - } - case AbstractEncodedMessage.MESSAGE_SIGNATURE: { - byte[] xEncryted = otr.readData(); - byte[] xEncryptedMac = otr.readMac(); - return new SignatureMessage(protocolVersion, xEncryted, - xEncryptedMac); - } - default: - throw new IOException("Illegal message type."); - } - case SerializationConstants.HEAD_ERROR: - return new ErrorMessage(AbstractMessage.MESSAGE_ERROR, content); - case SerializationConstants.HEAD_QUERY_V: - case SerializationConstants.HEAD_QUERY_Q: - List versions = new Vector(); - String versionString = null; - if (SerializationConstants.HEAD_QUERY_Q == contentType) { - versions.add(1); - if (content.charAt(0) == 'v') { - versionString = content.substring(1, content - .indexOf('?')); - } - } else if (SerializationConstants.HEAD_QUERY_V == contentType) { - versionString = content.substring(0, content.indexOf('?')); - } - - if (versionString != null) { - StringReader sr = new StringReader(versionString); - int c; - while ((c = sr.read()) != -1) - if (!versions.contains(c)) - versions.add(Integer.parseInt(String - .valueOf((char) c))); - } - QueryMessage query = new QueryMessage(versions); - return query; - default: - throw new IOException("Uknown message type."); - } - } - } -}