use of net.java.otr4j.crypto.OtrCryptoEngineImpl in project Conversations by siacs.
the class Account method getOtrFingerprint.
public String getOtrFingerprint() {
if (this.otrFingerprint == null) {
try {
if (this.mOtrService == null) {
return null;
}
final PublicKey publicKey = this.mOtrService.getPublicKey();
if (publicKey == null || !(publicKey instanceof DSAPublicKey)) {
return null;
}
this.otrFingerprint = new OtrCryptoEngineImpl().getFingerprint(publicKey).toLowerCase(Locale.US);
return this.otrFingerprint;
} catch (final OtrCryptoException ignored) {
return null;
}
} else {
return this.otrFingerprint;
}
}
use of net.java.otr4j.crypto.OtrCryptoEngineImpl 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;
}
}
use of net.java.otr4j.crypto.OtrCryptoEngineImpl in project Zom-Android by zom.
the class SessionImpl method handleDataMessage.
private synchronized String handleDataMessage(DataMessage data, List<TLV> tlvs) throws OtrException {
if (DEBUG_ENABLED)
Log.d(LOG_TAG, getSessionID().getLocalUserId() + " received a data message from " + getSessionID().getRemoteUserId() + ".");
switch(this.getSessionStatus()) {
case ENCRYPTED:
if (DEBUG_ENABLED)
Log.d(LOG_TAG, "Message state is ENCRYPTED. Trying to decrypt message.");
// Find matching session keys.
int senderKeyID = data.senderKeyID;
int receipientKeyID = data.recipientKeyID;
SessionKeys matchingKeys = this.getSessionKeysByID(receipientKeyID, senderKeyID);
if (matchingKeys == null) {
throw new OtrException("no matching keys found");
}
// Verify received MAC with a locally calculated MAC.
if (DEBUG_ENABLED)
Log.d(LOG_TAG, "Transforming T to byte[] to calculate it's HmacSHA1.");
byte[] serializedT;
try {
serializedT = SerializationUtils.toByteArray(data.getT());
} catch (IOException e) {
throw new OtrException(e);
}
OtrCryptoEngine otrCryptoEngine = new OtrCryptoEngineImpl();
byte[] computedMAC = otrCryptoEngine.sha1Hmac(serializedT, matchingKeys.getReceivingMACKey(), SerializationConstants.TYPE_LEN_MAC);
String decryptedMsgContent = null;
if (!Arrays.equals(computedMAC, data.mac)) {
// throw new OtrException("MAC verification failed, ignoring message");
if (DEBUG_ENABLED)
Log.d(LOG_TAG, "MAC verification failed, ignoring message");
} else {
if (DEBUG_ENABLED)
Log.d(LOG_TAG, "Computed HmacSHA1 value matches sent one.");
// Mark this MAC key as old to be revealed.
matchingKeys.setIsUsedReceivingMACKey(true);
matchingKeys.setReceivingCtr(data.ctr);
byte[] dmc = otrCryptoEngine.aesDecrypt(matchingKeys.getReceivingAESKey(), matchingKeys.getReceivingCtr(), data.encryptedMessage);
try {
// Expect bytes to be text encoded in UTF-8.
decryptedMsgContent = new String(dmc, "UTF-8");
if (DEBUG_ENABLED)
Log.d(LOG_TAG, "Decrypted message: \"" + decryptedMsgContent + "\"");
// Handle TLVs
if (tlvs == null) {
tlvs = new ArrayList<TLV>();
}
int tlvIndex = decryptedMsgContent.indexOf((char) 0x0);
if (tlvIndex > -1) {
decryptedMsgContent = decryptedMsgContent.substring(0, tlvIndex);
tlvIndex++;
byte[] tlvsb = new byte[dmc.length - tlvIndex];
System.arraycopy(dmc, tlvIndex, tlvsb, 0, tlvsb.length);
ByteArrayInputStream tin = new ByteArrayInputStream(tlvsb);
while (tin.available() > 0) {
int type;
byte[] tdata;
OtrInputStream eois = new OtrInputStream(tin);
try {
type = eois.readShort();
tdata = eois.readTlvData();
eois.close();
} catch (IOException e) {
throw new OtrException(e);
}
tlvs.add(new TLV(type, tdata));
}
}
if (tlvs.size() > 0) {
for (TLV tlv : tlvs) {
switch(tlv.getType()) {
case TLV.DISCONNECTED:
this.setSessionStatus(SessionStatus.FINISHED);
return null;
default:
for (OtrTlvHandler handler : tlvHandlers) {
handler.processTlv(tlv);
}
}
}
}
} catch (UnsupportedEncodingException e) {
// throw new OtrException(e);
if (DEBUG_ENABLED)
Log.e(LOG_TAG, "unsupported encoding exception", e);
}
}
// Rotate keys if necessary.
SessionKeys mostRecent = this.getMostRecentSessionKeys();
if (mostRecent.getLocalKeyID() == receipientKeyID)
this.rotateLocalSessionKeys();
if (mostRecent.getRemoteKeyID() == senderKeyID)
this.rotateRemoteSessionKeys(data.nextDH);
return decryptedMsgContent;
case FINISHED:
case PLAINTEXT:
showError("Unreadable encrypted message was received.");
refreshSession();
// "You sent me an unreadable encrypted message"));
throw new OtrException("Unreadable encrypted message received");
}
return null;
}
use of net.java.otr4j.crypto.OtrCryptoEngineImpl in project Zom-Android by zom.
the class SessionImpl method rotateLocalSessionKeys.
private void rotateLocalSessionKeys() throws OtrException {
if (DEBUG_ENABLED)
Log.d(LOG_TAG, "Rotating local keys.");
SessionKeys sess1 = getSessionKeysByIndex(SessionKeys.Previous, SessionKeys.Current);
if (sess1.getIsUsedReceivingMACKey()) {
if (DEBUG_ENABLED)
Log.d(LOG_TAG, "Detected used Receiving MAC key. Adding to old MAC keys to reveal it.");
getOldMacKeys().add(sess1.getReceivingMACKey());
}
SessionKeys sess2 = getSessionKeysByIndex(SessionKeys.Previous, SessionKeys.Previous);
if (sess2.getIsUsedReceivingMACKey()) {
if (DEBUG_ENABLED)
Log.d(LOG_TAG, "Detected used Receiving MAC key. Adding to old MAC keys to reveal it.");
getOldMacKeys().add(sess2.getReceivingMACKey());
}
SessionKeys sess3 = getSessionKeysByIndex(SessionKeys.Current, SessionKeys.Current);
sess1.setLocalPair(sess3.getLocalPair(), sess3.getLocalKeyID());
SessionKeys sess4 = getSessionKeysByIndex(SessionKeys.Current, SessionKeys.Previous);
sess2.setLocalPair(sess4.getLocalPair(), sess4.getLocalKeyID());
KeyPair newPair = new OtrCryptoEngineImpl().generateDHKeyPair();
sess3.setLocalPair(newPair, sess3.getLocalKeyID() + 1);
sess4.setLocalPair(newPair, sess4.getLocalKeyID() + 1);
}
use of net.java.otr4j.crypto.OtrCryptoEngineImpl in project Zom-Android by zom.
the class SessionImpl method setSessionStatus.
private void setSessionStatus(SessionStatus sessionStatusNew) throws OtrException {
boolean sessionStatusChanged = (sessionStatus != sessionStatusNew);
sessionStatus = sessionStatusNew;
switch(sessionStatus) {
case ENCRYPTED:
AuthContext auth = this.getAuthContext(false);
ess = auth.getS();
if (DEBUG_ENABLED)
Log.d(LOG_TAG, "Setting most recent session keys from auth.");
for (int i = 0; i < this.getSessionKeys()[0].length; i++) {
SessionKeys current = getSessionKeysByIndex(0, i);
current.setLocalPair(auth.getLocalDHKeyPair(), 1);
current.setRemoteDHPublicKey(auth.getRemoteDHPublicKey(), 1);
current.setS(auth.getS());
}
KeyPair nextDH = new OtrCryptoEngineImpl().generateDHKeyPair();
for (int i = 0; i < this.getSessionKeys()[1].length; i++) {
SessionKeys current = getSessionKeysByIndex(1, i);
current.setRemoteDHPublicKey(auth.getRemoteDHPublicKey(), 1);
current.setLocalPair(nextDH, 2);
}
this.setRemotePublicKey(auth.getRemoteLongTermPublicKey());
auth.reset();
break;
case PLAINTEXT:
// nothing here
break;
default:
}
if (sessionStatus == SessionStatus.ENCRYPTED && doTransmitLastMessage && lastSentMessage != null) {
// String retransmit = (isLastMessageRetransmit ? "[resent] " : "");
String msg = transformSending(lastSentMessage, null);
getHost().injectMessage(getSessionID(), msg);
sessionStatusChanged = true;
}
doTransmitLastMessage = false;
isLastMessageRetransmit = false;
lastSentMessage = null;
if (sessionStatusChanged) {
for (OtrEngineListener l : this.listeners) l.sessionStatusChanged(getSessionID());
}
}
Aggregations