package network.thunder.core.communication.processor.implementations; import network.thunder.core.communication.Message; import network.thunder.core.communication.objects.messages.MessageExecutor; import network.thunder.core.communication.objects.messages.impl.message.encryption.EncryptedMessage; import network.thunder.core.communication.objects.messages.impl.message.encryption.EncryptionInitialMessage; import network.thunder.core.communication.objects.messages.interfaces.factories.ContextFactory; import network.thunder.core.communication.objects.messages.interfaces.factories.EncryptionMessageFactory; import network.thunder.core.communication.objects.messages.interfaces.helper.MessageEncrypter; import network.thunder.core.communication.processor.interfaces.EncryptionProcessor; import network.thunder.core.etc.crypto.ECDH; import network.thunder.core.mesh.NodeClient; import org.bitcoinj.core.ECKey; /** * Created by matsjerratsch on 29/11/2015. */ public class EncryptionProcessorImpl extends EncryptionProcessor { public static final boolean OUTPUT_MESSAGE = false; EncryptionMessageFactory messageFactory; MessageEncrypter messageEncrypter; NodeClient node; MessageExecutor executor; boolean encSent; boolean encFinished; public EncryptionProcessorImpl (ContextFactory contextFactory, NodeClient node) { this.messageFactory = contextFactory.getEncryptionMessageFactory(); this.messageEncrypter = contextFactory.getMessageEncrypter(); this.node = node; } @Override public void onLayerActive (MessageExecutor messageExecutor) { this.executor = messageExecutor; if (shouldSendEncryptionKeyFirst()) { sendInitialMessageIfNotSent(); } } @Override public void onInboundMessage (Message message) { if (encryptionKeyExchangeFinished()) { processEncryptedMessage(message); } else { processEncryptionInitialMessage(message); } } @Override public void onOutboundMessage (Message message) { if (encryptionKeyExchangeFinished()) { processMessageToBeEncrypted(message); } else { throw new RuntimeException("Outbound Message even though Key Exchanged not finished yet.. " + message); } } private boolean shouldSendEncryptionKeyFirst () { return !node.isServer; } private void sendInitialMessageIfNotSent () { if (!encSent) { executor.sendMessageUpwards(messageFactory.getEncryptionInitialMessage(node.ephemeralKeyServer.getPubKey())); encSent = true; } } private boolean encryptionKeyExchangeFinished () { return encFinished; } private void processEncryptedMessage (Message message) { if (!(message instanceof EncryptedMessage)) { throw new RuntimeException("Non-encrypted message after key exchange..? " + message); } EncryptedMessage encryptedMessage = (EncryptedMessage) message; processMessageToBeDecrypted(encryptedMessage); } private void processMessageToBeDecrypted (EncryptedMessage message) { Message decryptedMessage = messageEncrypter.decrypt(message, node.ecdhKeySet); if (OUTPUT_MESSAGE) { System.out.println("I: " + node.host + " " + decryptedMessage); } executor.sendMessageDownwards(decryptedMessage); } private void processEncryptionInitialMessage (Message message) { if (!(message instanceof EncryptionInitialMessage)) { executor.sendMessageUpwards(messageFactory.getFailureMessage("Expecting EncryptionInitial Message.. " + message)); } else { EncryptionInitialMessage encryptionInitial = (EncryptionInitialMessage) message; node.ephemeralKeyClient = ECKey.fromPublicOnly(encryptionInitial.key); node.ecdhKeySet = ECDH.getSharedSecret(node.ephemeralKeyServer, node.ephemeralKeyClient); sendInitialMessageIfNotSent(); onKeyExchangeFinished(); } } private void onKeyExchangeFinished () { encFinished = true; executor.sendNextLayerActive(); } private void processMessageToBeEncrypted (Message message) { if (OUTPUT_MESSAGE) { System.out.println("O: " + node.host + " " + message); } Message encryptedMessage = messageEncrypter.encrypt(message, node.ecdhKeySet); executor.sendMessageUpwards(encryptedMessage); } }