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.