PageRenderTime 237ms CodeModel.GetById 26ms RepoModel.GetById 1ms app.codeStats 0ms

/thunder-core/src/main/java/network/thunder/core/communication/layer/low/authentication/AuthenticationProcessorImpl.java

https://gitlab.com/github-cloud-corporation/thunder
Java | 179 lines | 139 code | 38 blank | 2 comment | 15 complexity | 778426b7bcc304a548cb494372513a07 MD5 | raw file
  1. package network.thunder.core.communication.layer.low.authentication;
  2. import network.thunder.core.communication.ClientObject;
  3. import network.thunder.core.communication.ServerObject;
  4. import network.thunder.core.communication.layer.ContextFactory;
  5. import network.thunder.core.communication.layer.Message;
  6. import network.thunder.core.communication.layer.MessageExecutor;
  7. import network.thunder.core.communication.layer.low.authentication.messages.Authentication;
  8. import network.thunder.core.communication.layer.low.authentication.messages.AuthenticationMessage;
  9. import network.thunder.core.communication.layer.low.authentication.messages.AuthenticationMessageFactory;
  10. import network.thunder.core.helper.callback.Command;
  11. import network.thunder.core.helper.crypto.CryptoTools;
  12. import network.thunder.core.helper.events.LNEventHelper;
  13. import org.bitcoinj.core.ECKey;
  14. import java.security.NoSuchAlgorithmException;
  15. import java.security.NoSuchProviderException;
  16. import java.util.Arrays;
  17. public class AuthenticationProcessorImpl extends AuthenticationProcessor {
  18. AuthenticationMessageFactory messageFactory;
  19. LNEventHelper eventHelper;
  20. ClientObject node;
  21. ServerObject serverObject;
  22. MessageExecutor messageExecutor;
  23. public boolean sentAuth;
  24. public boolean authFinished;
  25. public AuthenticationProcessorImpl (ContextFactory contextFactory, ClientObject node) {
  26. this.messageFactory = contextFactory.getAuthenticationMessageFactory();
  27. this.eventHelper = contextFactory.getEventHelper();
  28. this.node = node;
  29. this.serverObject = contextFactory.getServerSettings();
  30. }
  31. @Override
  32. public void onLayerActive (MessageExecutor messageExecutor) {
  33. this.messageExecutor = messageExecutor;
  34. if (shouldSendAuthenticationFirst()) {
  35. sendAuthentication();
  36. }
  37. }
  38. @Override
  39. public void onInboundMessage (Message message) {
  40. if (message instanceof Authentication) {
  41. processMessage(message);
  42. } else if (!authenticationExchangeFinished()) {
  43. sendAuthenticatedErrorMessage("Not authenticated..");
  44. } else {
  45. passMessageToNextLayer(message);
  46. }
  47. }
  48. @Override
  49. public void onOutboundMessage (Message message) {
  50. if (allowOutboundMessage(message)) {
  51. messageExecutor.sendMessageUpwards(message);
  52. } else {
  53. throw new RuntimeException("Should not happen, which class is this? " + message);
  54. }
  55. }
  56. public boolean shouldSendAuthenticationFirst () {
  57. return !node.isServer;
  58. }
  59. public void sendAuthentication () {
  60. if (!sentAuth) {
  61. messageExecutor.sendMessageUpwards(getAuthenticationMessage());
  62. sentAuth = true;
  63. }
  64. }
  65. public void processMessage (Message message) {
  66. if (authenticationExchangeFinished()) {
  67. messageExecutor.sendMessageUpwards(messageFactory.getFailureMessage("Already authenticated"));
  68. } else {
  69. processAuthenticationMessage(message);
  70. }
  71. }
  72. public boolean allowOutboundMessage (Message message) {
  73. return message instanceof Authentication || authFinished;
  74. }
  75. public void processAuthenticationMessage (Message message) {
  76. AuthenticationMessage authObject = (AuthenticationMessage) message;
  77. try {
  78. checkAuthenticationMessage(authObject, node);
  79. sendAuthentication();
  80. authFinished = true;
  81. eventHelper.onConnectionOpened(node);
  82. messageExecutor.sendNextLayerActive();
  83. } catch (Exception e) {
  84. e.printStackTrace();
  85. messageExecutor.sendMessageUpwards(messageFactory.getFailureMessage(e.getMessage()));
  86. }
  87. }
  88. @Override
  89. public void onLayerClose () {
  90. eventHelper.onConnectionClosed(node);
  91. }
  92. public AuthenticationMessage getAuthenticationMessage () {
  93. try {
  94. ECKey keyServer = serverObject.pubKeyServer;
  95. ECKey keyClient = node.ephemeralKeyClient;
  96. byte[] data = new byte[keyServer.getPubKey().length + keyClient.getPubKey().length];
  97. System.arraycopy(keyServer.getPubKey(), 0, data, 0, keyServer.getPubKey().length);
  98. System.arraycopy(keyClient.getPubKey(), 0, data, keyServer.getPubKey().length, keyClient.getPubKey().length);
  99. byte[] pubkeyServer = keyServer.getPubKey();
  100. byte[] signature = CryptoTools.createSignature(keyServer, data);
  101. return messageFactory.getAuthenticationMessage(pubkeyServer, signature);
  102. } catch (NoSuchProviderException | NoSuchAlgorithmException e) {
  103. throw new RuntimeException(e);
  104. }
  105. }
  106. public void checkAuthenticationMessage (AuthenticationMessage authentication, ClientObject node) throws NoSuchProviderException,
  107. NoSuchAlgorithmException {
  108. ECKey ecKey = ECKey.fromPublicOnly(authentication.pubKeyServer);
  109. if (node.pubKeyClient != null) {
  110. //Must be an outgoing connection, check if the nodeKey is what we expect it to be
  111. if (!Arrays.equals(ecKey.getPubKey(), node.pubKeyClient.getPubKey())) {
  112. //We connected to the wrong node?
  113. System.out.println("Connected to wrong node? Expected: " + node.pubKeyClient.getPublicKeyAsHex() + ". Is: " + ecKey.getPublicKeyAsHex());
  114. authenticationFailed();
  115. }
  116. }
  117. node.pubKeyClient = ecKey;
  118. ECKey pubKeyClient = node.pubKeyClient;
  119. ECKey pubKeyTempServer = node.ephemeralKeyServer;
  120. byte[] data = new byte[pubKeyClient.getPubKey().length + pubKeyTempServer.getPubKey().length];
  121. System.arraycopy(pubKeyClient.getPubKey(), 0, data, 0, pubKeyClient.getPubKey().length);
  122. System.arraycopy(pubKeyTempServer.getPubKey(), 0, data, pubKeyClient.getPubKey().length, pubKeyTempServer.getPubKey().length);
  123. if (!CryptoTools.verifySignature(pubKeyClient, data, authentication.signature)) {
  124. System.out.println("Node was not able to authenticate..");
  125. authenticationFailed();
  126. }
  127. }
  128. private void authenticationFailed () {
  129. node.onAuthenticationFailed.stream().forEach(Command::execute);
  130. this.messageExecutor.closeConnection();
  131. }
  132. private boolean authenticationExchangeFinished () {
  133. return authFinished;
  134. }
  135. private void sendAuthenticatedErrorMessage (String error) {
  136. messageExecutor.sendMessageUpwards(messageFactory.getFailureMessage(error));
  137. }
  138. private void passMessageToNextLayer (Message message) {
  139. messageExecutor.sendMessageDownwards(message);
  140. }
  141. }