42    private function __construct(){
 
   46    private static function validateKey(\OpenSSLAsymmetricKey $key) : 
void{
 
   47        $keyDetails = Utils::assumeNotFalse(openssl_pkey_get_details($key));
 
   48        if(!isset($keyDetails[
"ec"][
"curve_name"])){
 
   49            throw new \InvalidArgumentException(
"Key must be an EC key");
 
   51        $curveName = $keyDetails[
"ec"][
"curve_name"];
 
   52        if($curveName !== JwtUtils::BEDROCK_SIGNING_KEY_CURVE_NAME){
 
   53            throw new \InvalidArgumentException(
"Key must belong to the " . JwtUtils::BEDROCK_SIGNING_KEY_CURVE_NAME . 
" elliptic curve, got $curveName");
 
   57    public static function generateSharedSecret(\OpenSSLAsymmetricKey $localPriv, \OpenSSLAsymmetricKey $remotePub) : \GMP{
 
   58        self::validateKey($localPriv);
 
   59        self::validateKey($remotePub);
 
   60        $hexSecret = openssl_pkey_derive($remotePub, $localPriv, 48);
 
   61        if($hexSecret === 
false){
 
   62            throw new \InvalidArgumentException(
"Failed to derive shared secret: " . openssl_error_string());
 
   64        return gmp_init(bin2hex($hexSecret), 16);
 
   67    public static function generateKey(\GMP $secret, 
string $salt) : 
string{
 
   68        return Utils::assumeNotFalse(openssl_digest($salt . hex2bin(str_pad(gmp_strval($secret, 16), 96, 
"0", STR_PAD_LEFT)), 
'sha256', 
true));
 
   71    public static function generateServerHandshakeJwt(\OpenSSLAsymmetricKey $serverPriv, 
string $salt) : 
string{
 
   72        $derPublicKey = JwtUtils::emitDerPublicKey($serverPriv);
 
   75                "x5u" => base64_encode($derPublicKey),
 
   79                "salt" => base64_encode($salt)