public static void remove(File sourceDirectoryRoot) { Session session = sourceDirectoryRootToSessionMap.remove(sourceDirectoryRoot); if (session == null) { throw new RuntimeException("no such session:" + sourceDirectoryRoot.getAbsolutePath()); } Sessions.remove(session.getSessionID()); }
private void handleDHKeyMessage(DHKeyMessage m) throws OtrException { Session session = getSession(); SessionID sessionID = session.getSessionID(); logger.finest( sessionID.getLocalUserId() + " received a D-H key message from " + sessionID.getRemoteUserId() + " throught " + sessionID.getProtocolName() + "."); if (!session.getSessionPolicy().getAllowV2()) { logger.finest("If ALLOW_V2 is not set, ignore this message."); return; } switch (this.getAuthenticationState()) { case AWAITING_DHKEY: // Reply with a Reveal Signature Message and transition // authstate to // AUTHSTATE_AWAITING_SIG this.setRemoteDHPublicKey(m.dhPublicKey); this.setAuthenticationState(AuthContext.AWAITING_SIG); getSession().injectMessage(messageFactory.getRevealSignatureMessage()); logger.finest("Sent Reveal Signature."); break; case AWAITING_SIG: if (m.dhPublicKey.getY().equals(this.getRemoteDHPublicKey().getY())) { // If this D-H Key message is the same the one you received // earlier (when you entered AUTHSTATE_AWAITING_SIG): // Retransmit // your Reveal Signature Message. getSession().injectMessage(messageFactory.getRevealSignatureMessage()); logger.finest("Resent Reveal Signature."); } else { // Otherwise: Ignore the message. logger.finest("Ignoring message."); } break; default: // Ignore the message break; } }
private void handleDHCommitMessage(DHCommitMessage m) throws OtrException { Session session = getSession(); SessionID sessionID = session.getSessionID(); logger.finest( sessionID.getLocalUserId() + " received a D-H commit message from " + sessionID.getRemoteUserId() + " throught " + sessionID.getProtocolName() + "."); if (!session.getSessionPolicy().getAllowV2()) { logger.finest("ALLOW_V2 is not set, ignore this message."); return; } switch (this.getAuthenticationState()) { case NONE: // Reply with a D-H Key Message, and transition authstate to // AUTHSTATE_AWAITING_REVEALSIG. this.reset(); this.setProtocolVersion(2); this.setRemoteDHPublicKeyEncrypted(m.dhPublicKeyEncrypted); this.setRemoteDHPublicKeyHash(m.dhPublicKeyHash); this.setAuthenticationState(AuthContext.AWAITING_REVEALSIG); getSession().injectMessage(messageFactory.getDHKeyMessage()); logger.finest("Sent D-H key."); break; case AWAITING_DHKEY: // This is the trickiest transition in the whole protocol. It // indicates that you have already sent a D-H Commit message to // your // correspondent, but that he either didn't receive it, or just // didn't receive it yet, and has sent you one as well. The // symmetry // will be broken by comparing the hashed gx you sent in your // D-H // Commit Message with the one you received, considered as // 32-byte // unsigned big-endian values. BigInteger ourHash = new BigInteger(1, this.getLocalDHPublicKeyHash()); BigInteger theirHash = new BigInteger(1, m.dhPublicKeyHash); if (theirHash.compareTo(ourHash) == -1) { // Ignore the incoming D-H Commit message, but resend your // D-H // Commit message. getSession().injectMessage(messageFactory.getDHCommitMessage()); logger.finest( "Ignored the incoming D-H Commit message, but resent our D-H Commit message."); } else { // *Forget* your old gx value that you sent (encrypted) // earlier, // and pretend you're in AUTHSTATE_NONE; i.e. reply with a // D-H // Key Message, and transition authstate to // AUTHSTATE_AWAITING_REVEALSIG. this.reset(); this.setProtocolVersion(2); this.setRemoteDHPublicKeyEncrypted(m.dhPublicKeyEncrypted); this.setRemoteDHPublicKeyHash(m.dhPublicKeyHash); this.setAuthenticationState(AuthContext.AWAITING_REVEALSIG); getSession().injectMessage(messageFactory.getDHKeyMessage()); logger.finest( "Forgot our old gx value that we sent (encrypted) earlier, and pretended we're in AUTHSTATE_NONE -> Sent D-H key."); } break; case AWAITING_REVEALSIG: // Retransmit your D-H Key Message (the same one as you sent // when // you entered AUTHSTATE_AWAITING_REVEALSIG). Forget the old D-H // Commit message, and use this new one instead. this.setRemoteDHPublicKeyEncrypted(m.dhPublicKeyEncrypted); this.setRemoteDHPublicKeyHash(m.dhPublicKeyHash); getSession().injectMessage(messageFactory.getDHKeyMessage()); logger.finest("Sent D-H key."); break; case AWAITING_SIG: // Reply with a new D-H Key message, and transition authstate to // AUTHSTATE_AWAITING_REVEALSIG this.reset(); this.setRemoteDHPublicKeyEncrypted(m.dhPublicKeyEncrypted); this.setRemoteDHPublicKeyHash(m.dhPublicKeyHash); this.setAuthenticationState(AuthContext.AWAITING_REVEALSIG); getSession().injectMessage(messageFactory.getDHKeyMessage()); logger.finest("Sent D-H key."); break; case V1_SETUP: throw new UnsupportedOperationException(); } }
private void handleRevealSignatureMessage(RevealSignatureMessage m) throws OtrException { Session session = getSession(); SessionID sessionID = session.getSessionID(); logger.finest( sessionID.getLocalUserId() + " received a reveal signature message from " + sessionID.getRemoteUserId() + " throught " + sessionID.getProtocolName() + "."); if (!session.getSessionPolicy().getAllowV2()) { logger.finest("Policy does not allow OTRv2, ignoring message."); return; } switch (this.getAuthenticationState()) { case AWAITING_REVEALSIG: // Use the received value of r to decrypt the value of gx // received // in the D-H Commit Message, and verify the hash therein. // Decrypt // the encrypted signature, and verify the signature and the // MACs. // If everything checks out: // * Reply with a Signature Message. // * Transition authstate to AUTHSTATE_NONE. // * Transition msgstate to MSGSTATE_ENCRYPTED. // * TODO If there is a recent stored message, encrypt it and // send // it as a Data Message. OtrCryptoEngine otrCryptoEngine = new OtrCryptoEngineImpl(); // Uses r to decrypt the value of gx sent earlier byte[] remoteDHPublicKeyDecrypted = otrCryptoEngine.aesDecrypt(m.revealedKey, null, this.getRemoteDHPublicKeyEncrypted()); // Verifies that HASH(gx) matches the value sent earlier byte[] remoteDHPublicKeyHash = otrCryptoEngine.sha256Hash(remoteDHPublicKeyDecrypted); if (!Arrays.equals(remoteDHPublicKeyHash, this.getRemoteDHPublicKeyHash())) { logger.finest("Hashes don't match, ignoring message."); return; } // Verifies that Bob's gx is a legal value (2 <= gx <= // modulus-2) BigInteger remoteDHPublicKeyMpi; try { remoteDHPublicKeyMpi = SerializationUtils.readMpi(remoteDHPublicKeyDecrypted); } catch (IOException e) { throw new OtrException(e); } this.setRemoteDHPublicKey(otrCryptoEngine.getDHPublicKey(remoteDHPublicKeyMpi)); // Verify received Data. if (!m.verify(this.getM2())) { logger.finest("Signature MACs are not equal, ignoring message."); return; } // Decrypt X. byte[] remoteXDecrypted = m.decrypt(this.getC()); SignatureX remoteX; try { remoteX = SerializationUtils.toMysteriousX(remoteXDecrypted); } catch (IOException e) { throw new OtrException(e); } // Compute signature. PublicKey remoteLongTermPublicKey = remoteX.longTermPublicKey; SignatureM remoteM = new SignatureM( this.getRemoteDHPublicKey(), (DHPublicKey) this.getLocalDHKeyPair().getPublic(), remoteLongTermPublicKey, remoteX.dhKeyID); // Verify signature. byte[] signature; try { signature = otrCryptoEngine.sha256Hmac(SerializationUtils.toByteArray(remoteM), this.getM1()); } catch (IOException e) { throw new OtrException(e); } if (!otrCryptoEngine.verify(signature, remoteLongTermPublicKey, remoteX.signature)) { session.showWarning("Bad revealed signature"); logger.finest("Signature verification failed."); return; } logger.finest("Signature verification succeeded."); this.setAuthenticationState(AuthContext.NONE); this.setIsSecure(true); this.setRemoteLongTermPublicKey(remoteLongTermPublicKey); getSession().injectMessage(messageFactory.getSignatureMessage()); break; default: logger.finest("Ignoring message."); break; } }
private void handleSignatureMessage(SignatureMessage m) throws OtrException { Session session = getSession(); SessionID sessionID = session.getSessionID(); logger.finest( sessionID.getLocalUserId() + " received a signature message from " + sessionID.getRemoteUserId() + " throught " + sessionID.getProtocolName() + "."); if (!session.getSessionPolicy().getAllowV2()) { logger.finest("Policy does not allow OTRv2, ignoring message."); return; } switch (this.getAuthenticationState()) { case AWAITING_SIG: // Verify MAC. if (!m.verify(this.getM2p())) { logger.finest("Signature MACs are not equal, ignoring message."); return; } // Decrypt X. byte[] remoteXDecrypted = m.decrypt(this.getCp()); SignatureX remoteX; try { remoteX = SerializationUtils.toMysteriousX(remoteXDecrypted); } catch (IOException e) { throw new OtrException(e); } // Compute signature. PublicKey remoteLongTermPublicKey = remoteX.longTermPublicKey; SignatureM remoteM = new SignatureM( this.getRemoteDHPublicKey(), (DHPublicKey) this.getLocalDHKeyPair().getPublic(), remoteLongTermPublicKey, remoteX.dhKeyID); OtrCryptoEngine otrCryptoEngine = new OtrCryptoEngineImpl(); // Verify signature. byte[] signature; try { signature = otrCryptoEngine.sha256Hmac(SerializationUtils.toByteArray(remoteM), this.getM1p()); } catch (IOException e) { throw new OtrException(e); } if (!otrCryptoEngine.verify(signature, remoteLongTermPublicKey, remoteX.signature)) { session.showWarning("Bad signature"); logger.finest("Signature verification failed."); return; } this.setIsSecure(true); this.setRemoteLongTermPublicKey(remoteLongTermPublicKey); break; default: logger.finest("We were not expecting a signature, ignoring message."); return; } }