@Override public void handle(NetworkContext context, MessageLoginInEncryptionResponse message) { Session session = context.getSession(); PrivateKey privateKey = session.getServer().getKeyPair().getPrivate(); // Create rsaCipher Cipher rsaCipher; try { rsaCipher = Cipher.getInstance("RSA"); } catch (GeneralSecurityException e) { LanternGame.log().error("Could not initialize RSA cipher", e); session.disconnect("Unable to initialize RSA cipher."); return; } // Decrypt shared secret SecretKey sharedSecret; try { rsaCipher.init(Cipher.DECRYPT_MODE, privateKey); sharedSecret = new SecretKeySpec(rsaCipher.doFinal(message.getSharedSecret()), "AES"); } catch (Exception e) { LanternGame.log().warn("Could not decrypt shared secret", e); session.disconnect("Unable to decrypt shared secret."); return; } // Decrypt verify token byte[] verifyToken; try { rsaCipher.init(Cipher.DECRYPT_MODE, privateKey); verifyToken = rsaCipher.doFinal(message.getVerifyToken()); } catch (Exception e) { LanternGame.log().warn("Could not decrypt verify token", e); session.disconnect("Unable to decrypt verify token."); return; } // Check verify token if (!Arrays.equals(verifyToken, session.getVerifyToken())) { session.disconnect("Invalid verify token."); return; } // Initialize stream encryption session.setEncryption(sharedSecret); // Create hash for auth String hash; try { MessageDigest digest = MessageDigest.getInstance("SHA-1"); String sessionId = context.getChannel().attr(HandlerLoginStart.SESSION_ID).getAndRemove(); digest.update(sessionId.getBytes()); digest.update(sharedSecret.getEncoded()); digest.update(session.getServer().getKeyPair().getPublic().getEncoded()); // BigInteger takes care of sign and leading zeroes hash = new BigInteger(digest.digest()).toString(16); } catch (NoSuchAlgorithmException e) { LanternGame.log().error("Unable to generate SHA-1 digest", e); session.disconnect("Failed to hash login data."); return; } // Start auth thread Thread clientAuthThread = new Thread(new ClientAuthRunnable(session, session.getVerifyUsername(), hash)); clientAuthThread.setName("ClientAuth{" + session.getVerifyUsername() + "}"); clientAuthThread.start(); }