Esempio n. 1
0
  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;
    }
  }