Difference between revisions of "Protocol Encryption"

From wiki.vg
Jump to navigation Jump to search
(→‎Key Exchange: added ASN.1 structure)
(Cleaned up authentication)
Line 7: Line 7:
 
#'''S->C''' 0xFD encryption request - server sends its public key
 
#'''S->C''' 0xFD encryption request - server sends its public key
 
#Client generates symmetric key (shared secret)
 
#Client generates symmetric key (shared secret)
#Client pings minecraft.net
+
#Client authenticates via session.minecraft.net
 
#'''C->S''' 0xFC encryption response - client encrypts shared secret with server's public key and sends
 
#'''C->S''' 0xFC encryption response - client encrypts shared secret with server's public key and sends
 
#Server decrypts shared secret with its private key
 
#Server decrypts shared secret with its private key
#Server pings minecraft.net
+
#Server checks player authenticity via session.minecraft.net
 
#'''S->C''' 0xFC encryption response - empty payload
 
#'''S->C''' 0xFC encryption response - empty payload
 
#Server enables RC4 stream encryption
 
#Server enables RC4 stream encryption
Line 44: Line 44:
 
The server decrypts the shared secret using its private key. It then sends a 0xFC to the client with an empty payload, and enables RC4 encryption. Similarly, the client will also enable encryption upon receipt of the empty 0xFC. From this point forward, everything is encrypted.
 
The server decrypts the shared secret using its private key. It then sends a 0xFC to the client with an empty payload, and enables RC4 encryption. Similarly, the client will also enable encryption upon receipt of the empty 0xFC. From this point forward, everything is encrypted.
  
== minecraft.net ==
+
== Authentication ==
  
Both server and client need to make a request to minecraft.net if the server is in online-mode.
+
Both server and client need to make a request to session.minecraft.net if the server is in online-mode.
  
 
=== Client ===
 
=== Client ===
Line 60: Line 60:
  
 
And sends an HTTP request to
 
And sends an HTTP request to
 
+
<nowiki>http://session.minecraft.net/game/joinserver.jsp?user=</nowiki>''username''&sessionId=''[[Session#Login|user_session]]''&serverId=''hash''
<code>
 
    <nowiki>http://session.minecraft.net/game/joinserver.jsp?user=</nowiki>''username''&sessionId=''[[Session#Login|user_session]]''&serverId=''hash''
 
</code>
 
 
 
 
If it returns '''OK''' then continue, otherwise stop
 
If it returns '''OK''' then continue, otherwise stop
  
 
=== Server ===
 
=== Server ===
  
As above, after decrypting the shared secret in 0xFD.
+
After decrypting the shared secret in 0xFD, the sever generates the login hash as above and sens it to
 +
<nowiki>http://session.minecraft.net/game/checkserver?user=</nowiki>''username''&serverId=''hash''
  
 
If the response is '''YES''' then the client is authenticated and allowed to join. Otherwise the client will/should be [[Protocol#Disconnect.2FKick_.280xFF.29|kicked]] (unencrypted) with "Failed to verify username!"
 
If the response is '''YES''' then the client is authenticated and allowed to join. Otherwise the client will/should be [[Protocol#Disconnect.2FKick_.280xFF.29|kicked]] (unencrypted) with "Failed to verify username!"

Revision as of 05:54, 4 May 2012

As of 12w17a, minecraft implements SSL-like encryption.

Overview

  1. Client connects to server
  2. C->S 0x02 handshake
  3. S->C 0xFD encryption request - server sends its public key
  4. Client generates symmetric key (shared secret)
  5. Client authenticates via session.minecraft.net
  6. C->S 0xFC encryption response - client encrypts shared secret with server's public key and sends
  7. Server decrypts shared secret with its private key
  8. Server checks player authenticity via session.minecraft.net
  9. S->C 0xFC encryption response - empty payload
  10. Server enables RC4 stream encryption
  11. Client enables RC4 stream encryption
  12. C->S 0x01 login
  13. S->C 0x01 login
  14. see Protocol FAQ to get information about what happens next.

Key Exchange

The server generates a 1024-bit RSA keypair on startup. The key, when packed into a 0xFD packet, is in ASN.1 format as defined by x.509. The ASN.1 structure looks as follows

SubjectPublicKeyInfo ::= SEQUENCE {
  algorithm SEQUENCE {
    algorithm         OBJECT IDENTIFIER
    parameters        ANY OPTIONAL
  }
  subjectPublicKey  BITSTRING
}

SubjectPublicKey ::= SEQUENCE {
  modulus           INTEGER
  publicExponent    INTEGER
}

If you're struggling to import this using a crypto library, you can convert it to common PEM by base64-encoding and wrapping in '-----BEGIN PUBLIC KEY-----' and '-----END PUBLIC KEY-----'.

Symmetric Encryption

On receipt of a 0xFD from the server, the client will generate a 16-byte shared secret, to be used with the RC4 stream cipher. It then encrypts it with the server's public key (PKCS#1 padded), and sends it to the server with a 0xFC.

The server decrypts the shared secret using its private key. It then sends a 0xFC to the client with an empty payload, and enables RC4 encryption. Similarly, the client will also enable encryption upon receipt of the empty 0xFC. From this point forward, everything is encrypted.

Authentication

Both server and client need to make a request to session.minecraft.net if the server is in online-mode.

Client

After generating the shared secret, the client generates the following hash:

   hash := sha1(concat(a, b, c))
   where:
     a = serverId from 0xFC
     b = server's public key
     c = shared secret

And sends an HTTP request to

http://session.minecraft.net/game/joinserver.jsp?user=username&sessionId=user_session&serverId=hash

If it returns OK then continue, otherwise stop

Server

After decrypting the shared secret in 0xFD, the sever generates the login hash as above and sens it to

http://session.minecraft.net/game/checkserver?user=username&serverId=hash

If the response is YES then the client is authenticated and allowed to join. Otherwise the client will/should be kicked (unencrypted) with "Failed to verify username!"