Home > Net >  Java IllegalStateException: Protocol error from sending a Encryption Response packet to server
Java IllegalStateException: Protocol error from sending a Encryption Response packet to server

Time:09-11

I am trying to make a java program to be able to login to a minecraft server. From this and help of some other related posts like this I have been able to deal with the Handshake, Login Start and Encryption Request packets. The problem is in the Encryption Response packet, I managed to generate and encrypt the shared secret and VerifyToken with the server's public key which have to be sent in this packet and send it; but instead of the server responding with Login Success, it gives a Disconnect packet with the error:

{"translate":"disconnect.genericReason","with":["Internal Exception: java.lang.IllegalStateException: Protocol error"]}

here is my code related to Encryption Response:

System.out.println("Proceeding with Encryption Response...");
        byte[] encryptionResponse = encryptionResponse(encryptedSecret.length, encryptedSecret,
                encryptedVerifyToken.length, encryptedVerifyToken);
        // C->S Encryption Response
        writeVarInt(output, encryptionResponse.length);
        output.write(encryptionResponse);


        System.out.println("Response length: "   encryptionResponse.length   " Response: "   Arrays.toString(encryptionResponse));
        System.out.println("Done!");
public static byte [] encryptionResponse(int secretLen, byte[] secret, int tokenLen, byte[] token) throws IOException {
        ByteArrayOutputStream buffers = new ByteArrayOutputStream();

        DataOutputStream response = new DataOutputStream(buffers);

        System.out.println(secretLen   " "   tokenLen);
        System.out.println("Secret: "   Arrays.toString(secret));
        System.out.println("Token: "   Arrays.toString(token));


        response.writeByte(0x01); //packet id for Encryption Response

        writeVarInt(response, secretLen); //secret length
        for (byte b : secret){ // send secret
            response.writeByte(b);
        }

        response.writeBoolean(true); // we have the verifyToken
        writeVarInt(response, tokenLen); // send the length of token
        for (byte b : token){ // send the token
            response.writeByte(b);
        }

        return buffers.toByteArray();
    }

This is the things that get printed to the console(or log or whatever):

Proceeding with Encryption Response...

128 128

Secret: [2, 105, 39, 117, -19, 27, -103, -102, -126, 58, 31, -75, 48, 26, -4, 116, 60, 52, 119, -37, -102, 127, 120, -21, 66, 72, 12, 127, -122, -27, -67, 53, -98, -23, -79, 28, 41, 10, 105, 45, 80, 14, -117, -4, 121, -82, 79, -57, 109, 31, 55, -36, -122, -78, -17, 33, -101, 67, -103, -103, -7, -99, -113, -86, -90, -1, 11, -75, -57, -90, -17, 97, 56, 39, 49, -107, -40, 119, 28, 52, -23, 75, -115, -9, 45, -117, -24, -49, -33, 19, -91, -45, 62, 119, 32, 52, -117, -121, -82, -44, -74, -17, -58, 54, 123, -114, 65, -75, 114, 62, -8, -6, 11, -35, -113, 64, 18, 33, -108, -62, -72, -119, -55, 96, 110, -75, 81, -84]

Token: [47, 114, -1, 115, -95, -35, 90, -27, -117, 92, 13, -78, -43, -96, 71, 112, 56, 34, 27, 127, 1, -22, -32, 123, 32, 88, -38, 28, -92, 24, -106, 57, 97, -25, -2, 87, 39, -57, -67, 48, -126, 113, -44, -31, 79, -72, 17, -97, 62, 90, -123, -117, 119, 37, 88, -116, 63, 84, -100, -92, 71, -88, 102, 55, 24, 100, -69, -115, 30, 27, -41, 123, -115, 67, 18, -110, -23, -71, 84, 38, -114, -32, 72, 10, -110, 22, -89, 24, -82, 110, 51, 46, 38, -112, 29, -65, -49, 83, 115, -70, 110, 32, -96, 35, -31, 7, -59, -71, -98, 22, 28, -108, -126, -83, 0, -18, 107, 125, -120, -50, -79, -44, -94, 111, -117, -53, 32, 51]

Response length: 262. Response: [1, -128, 1, 2, 105, 39, 117, -19, 27, -103, -102, -126, 58, 31, -75, 48, 26, -4, 116, 60, 52, 119, -37, -102, 127, 120, -21, 66, 72, 12, 127, -122, -27, -67, 53, -98, -23, -79, 28, 41, 10, 105, 45, 80, 14, -117, -4, 121, -82, 79, -57, 109, 31, 55, -36, -122, -78, -17, 33, -101, 67, -103, -103, -7, -99, -113, -86, -90, -1, 11, -75, -57, -90, -17, 97, 56, 39, 49, -107, -40, 119, 28, 52, -23, 75, -115, -9, 45, -117, -24, -49, -33, 19, -91, -45, 62, 119, 32, 52, -117, -121, -82, -44, -74, -17, -58, 54, 123, -114, 65, -75, 114, 62, -8, -6, 11, -35, -113, 64, 18, 33, -108, -62, -72, -119, -55, 96, 110, -75, 81, -84, 1, -128, 1, 47, 114, -1, 115, -95, -35, 90, -27, -117, 92, 13, -78, -43, -96, 71, 112, 56, 34, 27, 127, 1, -22, -32, 123, 32, 88, -38, 28, -92, 24, -106, 57, 97, -25, -2, 87, 39, -57, -67, 48, -126, 113, -44, -31, 79, -72, 17, -97, 62, 90, -123, -117, 119, 37, 88, -116, 63, 84, -100, -92, 71, -88, 102, 55, 24, 100, -69, -115, 30, 27, -41, 123, -115, 67, 18, -110, -23, -71, 84, 38, -114, -32, 72, 10, -110, 22, -89, 24, -82, 110, 51, 46, 38, -112, 29, -65, -49, 83, 115, -70, 110, 32, -96, 35, -31, 7, -59, -71, -98, 22, 28, -108, -126, -83, 0, -18, 107, 125, -120, -50, -79, -44, -94, 111, -117, -53, 32, 51]

Done!

more information on this can be found here

here is all of the code of my program

CodePudding user response:

The problem is the lines where you encrypt the shared secret and the verify token:

byte[] encryptedSecret = encrypt(publicKeyBytes, Arrays.toString(secret.getEncoded()).getBytes(StandardCharsets.UTF_8), ALGORITHM);
...
byte[] encryptedVerifyToken = encrypt(publicKeyBytes, Arrays.toString(verifyTokenBytes).getBytes(StandardCharsets.UTF_8), ALGORITHM);

These should be:

byte[] encryptedSecret = encrypt(publicKeyBytes, secret.getEncoded(), ALGORITHM);
...
byte[] encryptedVerifyToken = encrypt(publicKeyBytes, verifyTokenBytes, ALGORITHM);

You want to encrypt the actual bytes of the shared secret / verify token, not the bytes of the string representation of the byte array.

  • Related