mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-04-22 08:44:01 +00:00
Change encryption to use CTR instead of GCM
despite MCPE claiming to use GCM, it omits the auth tag, which defeats the whole point of using GCM. CTR can be used instead, with the final 4 bytes of the IV being 0002.
This commit is contained in:
parent
0df2677464
commit
04a6e89d6f
@ -670,7 +670,7 @@ class NetworkSession{
|
||||
}
|
||||
$this->sendDataPacket(ServerToClientHandshakePacket::create($handshakeJwt), true); //make sure this gets sent before encryption is enabled
|
||||
|
||||
$this->cipher = new EncryptionContext($encryptionKey, EncryptionContext::ENCRYPTION_SCHEME);
|
||||
$this->cipher = EncryptionContext::fakeGCM($encryptionKey);
|
||||
|
||||
$this->setHandler(new HandshakePacketHandler(function() : void{
|
||||
$this->onServerLoginSuccess();
|
||||
|
@ -32,7 +32,6 @@ use function strlen;
|
||||
use function substr;
|
||||
|
||||
class EncryptionContext{
|
||||
public const ENCRYPTION_SCHEME = "AES-256-GCM";
|
||||
private const CHECKSUM_ALGO = "sha256";
|
||||
|
||||
/** @var bool */
|
||||
@ -51,16 +50,40 @@ class EncryptionContext{
|
||||
/** @var int */
|
||||
private $encryptCounter = 0;
|
||||
|
||||
public function __construct(string $encryptionKey, string $algorithm){
|
||||
public function __construct(string $encryptionKey, string $algorithm, string $iv){
|
||||
$this->key = $encryptionKey;
|
||||
|
||||
$this->decryptCipher = new Cipher($algorithm);
|
||||
$ivLength = $this->decryptCipher->getIVLength();
|
||||
$this->decryptCipher->decryptInit($this->key, substr($this->key, 0, $ivLength));
|
||||
$this->decryptCipher->decryptInit($this->key, $iv);
|
||||
|
||||
$this->encryptCipher = new Cipher($algorithm);
|
||||
$ivLength = $this->encryptCipher->getIVLength();
|
||||
$this->encryptCipher->encryptInit($this->key, substr($this->key, 0, $ivLength));
|
||||
$this->encryptCipher->encryptInit($this->key, $iv);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an EncryptionContext suitable for decrypting Minecraft packets from 1.16.200 and up.
|
||||
*
|
||||
* MCPE uses GCM, but without the auth tag, which defeats the whole purpose of using GCM.
|
||||
* GCM is just a wrapper around CTR which adds the auth tag, so CTR can replace GCM for this case.
|
||||
* However, since GCM passes only the first 12 bytes of the IV followed by 0002, we must do the same for
|
||||
* compatibility with MCPE.
|
||||
* In PM, we could skip this and just use GCM directly (since we use OpenSSL), but this way is more portable, and
|
||||
* better for developers who come digging in the PM code looking for answers.
|
||||
*/
|
||||
public static function fakeGCM(string $encryptionKey) : self{
|
||||
return new EncryptionContext(
|
||||
$encryptionKey,
|
||||
"AES-256-CTR",
|
||||
substr($encryptionKey, 0, 12) . "\x00\x00\x00\x02"
|
||||
);
|
||||
}
|
||||
|
||||
public static function cfb8(string $encryptionKey) : self{
|
||||
return new EncryptionContext(
|
||||
$encryptionKey,
|
||||
"AES-256-CFB8",
|
||||
substr($encryptionKey, 0, 16)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
x
Reference in New Issue
Block a user