use of net.java.otr4j.io.messages.DataMessage in project Zom-Android by zom.
the class SerializationUtils method toString.
// 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);
}
writer.write(OtrConstants.CommonRequest);
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(Base64.encodeToString(o.toByteArray(), Base64.NO_WRAP));
writer.write(".");
break;
default:
throw new IOException("Illegal message type.");
}
return writer.toString();
}
use of net.java.otr4j.io.messages.DataMessage in project Zom-Android by zom.
the class SerializationUtils method toMessage.
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<Integer> versions;
if (v1 && v2) {
versions = new Vector<Integer>(2);
versions.add(0, 1);
versions.add(0, 2);
} else if (v1) {
versions = new Vector<Integer>(1);
versions.add(0, 1);
} else if (v2) {
versions = new Vector<Integer>(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, Base64.NO_WRAP));
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_MESSAGE:
return new ErrorMessage(AbstractMessage.MESSAGE_ERROR, content);
case SerializationConstants.HEAD_QUERY_V:
case SerializationConstants.HEAD_QUERY_Q:
List<Integer> versions = new Vector<Integer>();
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("Unknown message type.");
}
}
}
use of net.java.otr4j.io.messages.DataMessage in project Zom-Android by zom.
the class SessionImpl method transformSending.
// Retransmit last sent message. Spec document does not mention where or
// when that should happen, must check libotr code.
public String transformSending(String msgText, List<TLV> tlvs) throws OtrException {
switch(this.getSessionStatus()) {
case PLAINTEXT:
if (getSessionPolicy().getRequireEncryption()) {
lastSentMessage = msgText;
doTransmitLastMessage = true;
this.startSession();
return null;
} else
// specification.
return msgText;
case ENCRYPTED:
this.lastSentMessage = msgText;
if (DEBUG_ENABLED)
Log.d(LOG_TAG, getSessionID().getLocalUserId() + " sends an encrypted message to " + getSessionID().getRemoteUserId() + " through " + getSessionID().getProtocolName() + ".");
// Get encryption keys.
SessionKeys encryptionKeys = this.getEncryptionSessionKeys();
int senderKeyID = encryptionKeys.getLocalKeyID();
int receipientKeyID = encryptionKeys.getRemoteKeyID();
// Increment CTR.
encryptionKeys.incrementSendingCtr();
byte[] ctr = encryptionKeys.getSendingCtr();
ByteArrayOutputStream out = new ByteArrayOutputStream();
if (msgText != null && msgText.length() > 0)
try {
out.write(msgText.getBytes("UTF8"));
} catch (IOException e) {
throw new OtrException(e);
}
// Append tlvs
if (tlvs != null && tlvs.size() > 0) {
out.write((byte) 0x00);
OtrOutputStream eoos = new OtrOutputStream(out);
for (TLV tlv : tlvs) {
try {
eoos.writeShort(tlv.type);
eoos.writeTlvData(tlv.value);
eoos.close();
} catch (IOException e) {
throw new OtrException(e);
}
}
}
OtrCryptoEngine otrCryptoEngine = new OtrCryptoEngineImpl();
byte[] data = out.toByteArray();
// Encrypt message.
if (DEBUG_ENABLED)
Log.d(LOG_TAG, "Encrypting message with keyids (localKeyID, remoteKeyID) = (" + senderKeyID + ", " + receipientKeyID + ")");
byte[] encryptedMsg = otrCryptoEngine.aesEncrypt(encryptionKeys.getSendingAESKey(), ctr, data);
// Get most recent keys to get the next D-H public key.
SessionKeys mostRecentKeys = this.getMostRecentSessionKeys();
DHPublicKey nextDH = (DHPublicKey) mostRecentKeys.getLocalPair().getPublic();
// Calculate T.
MysteriousT t = new MysteriousT(2, 0, senderKeyID, receipientKeyID, nextDH, ctr, encryptedMsg);
// Calculate T hash.
byte[] sendingMACKey = encryptionKeys.getSendingMACKey();
if (DEBUG_ENABLED)
Log.d(LOG_TAG, "Transforming T to byte[] to calculate it's HmacSHA1.");
byte[] serializedT;
try {
serializedT = SerializationUtils.toByteArray(t);
} catch (IOException e) {
throw new OtrException(e);
}
byte[] mac = otrCryptoEngine.sha1Hmac(serializedT, sendingMACKey, SerializationConstants.TYPE_LEN_MAC);
// Get old MAC keys to be revealed.
byte[] oldKeys = this.collectOldMacKeys();
DataMessage m = new DataMessage(t, mac, oldKeys);
try {
return SerializationUtils.toString(m);
} catch (IOException e) {
throw new OtrException(e);
}
case FINISHED:
this.lastSentMessage = msgText;
showError("Your message to " + sessionID.getRemoteUserId() + " was not sent. Either end your private conversation, or restart it.");
return null;
default:
if (DEBUG_ENABLED)
Log.d(LOG_TAG, "Unknown message state, not processing.");
return msgText;
}
}
Aggregations