private RevealSignatureMessage getRevealSignatureMessage() throws OtrException { try { SignatureM m = new SignatureM( (DHPublicKey) getLocalDHKeyPair().getPublic(), getRemoteDHPublicKey(), getLocalLongTermKeyPair().getPublic(), getLocalDHKeyPairID()); OtrCryptoEngine otrCryptoEngine = new OtrCryptoEngineImpl(); byte[] mhash = otrCryptoEngine.sha256Hmac(SerializationUtils.toByteArray(m), getM1()); byte[] signature = otrCryptoEngine.sign(mhash, getLocalLongTermKeyPair().getPrivate()); SignatureX mysteriousX = new SignatureX(getLocalLongTermKeyPair().getPublic(), getLocalDHKeyPairID(), signature); byte[] xEncrypted = otrCryptoEngine.aesEncrypt(getC(), null, SerializationUtils.toByteArray(mysteriousX)); byte[] tmp = SerializationUtils.writeData(xEncrypted); byte[] xEncryptedHash = otrCryptoEngine.sha256Hmac160(tmp, getM2()); return new RevealSignatureMessage(getProtocolVersion(), xEncrypted, xEncryptedHash, getR()); } catch (IOException e) { throw new OtrException(e); } }
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 // TODO this does not precisly behave according to // specification. return msgText; case ENCRYPTED: this.lastSentMessage = msgText; logger.finest( getSessionID().getAccountID() + " sends an encrypted message to " + getSessionID().getUserID() + " 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); } catch (IOException e) { throw new OtrException(e); } } } OtrCryptoEngine otrCryptoEngine = new OtrCryptoEngineImpl(); byte[] data = out.toByteArray(); // Encrypt message. logger.finest( "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(); logger.finest("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.getUserID() + " was not sent. Either end your private conversation, or restart it."); return null; default: logger.finest("Uknown message state, not processing."); return msgText; } }