Сделать знак JWT через PHP без использования openssl - PullRequest
0 голосов
/ 29 марта 2020

Как я могу подписать JWT без openssl в PHP. В моем случае мне нужно подписать строку заголовка 64 в кодировке и строку полезной нагрузки в кодировке 64 с ключом publi c и получить определенную подпись, которая проверяется приложением PHP следующим образом:

    $plainSignature = base64_decode(strtr($sigB64, '-_', '+/'), true);

    //OpenSSL wants a DER-encoded signature, so we extract R and S from the plain signature and crudely serialize it.

    assert(strlen($plainSignature) === 96);

    [$rString,$sString] = str_split($plainSignature, 48);

    $rString = ltrim($rString, "\x00");
    if(ord($rString[0]) >= 128){ //Would be considered signed, pad it with an extra zero
        $rString = "\x00" . $rString;
    }

    $sString = ltrim($sString, "\x00");
    if(ord($sString[0]) >= 128){ //Would be considered signed, pad it with an extra zero
        $sString = "\x00" . $sString;
    }

    //0x02 = Integer ASN.1 tag
    $sequence = "\x02" . chr(strlen($rString)) . $rString . "\x02" . chr(strlen($sString)) . $sString;
    //0x30 = Sequence ASN.1 tag
    $derSignature = "\x30" . chr(strlen($sequence)) . $sequence;

    $v = openssl_verify("$headB64.$payloadB64", $derSignature, "-----BEGIN PUBLIC KEY-----\n" . wordwrap($currentPublicKey, 64, "\n", true) . "\n-----END PUBLIC KEY-----\n", OPENSSL_ALGO_SHA384);

Я знаю, что я могу использовать openssl_sign, но это не дает мне необходимого результата (в приложении, которое обрабатывает этот JWT openssl_verify возвращает 0).

Теперь я использую openssl и мой код:

public static function encodeJWT(array $payload){
    putenv("OPENSSL_CONF=C:\Work\path\to\bin\php\openssl.cnf");

    $config = array(
        'config' => getenv('OPENSSL_CONF'),
        "digest_alg" => 'sha384',
        //"private_key_bits" => 768,
        "private_key_bits" => 768,
        "private_key_type" => OPENSSL_KEYTYPE_RSA
    );

    // Create the private and public key
    $res = openssl_pkey_new($config);

    openssl_pkey_export($res, $privKey, null, $config);

    // Extract the public key from $res to $pubKey
    $pubKey = openssl_pkey_get_details($res);

    $pubKey = $pubKey["key"];

    $pubKey = str_replace([
        '-----BEGIN PUBLIC KEY-----',
        '-----END PUBLIC KEY-----',
        "\n"
    ], '', $pubKey);

    $header = [];
    $header['x5u'] = $pubKey;

    $payload['identityPublicKey'] = $pubKey;

    $headB64 = self::encodeUrl(json_encode($header));
    $payloadB64 = self::encodeUrl(json_encode($payload));

    openssl_sign("$headB64.$payloadB64", $signature, $privKey, 'SHA384');


    //$pub_verify = "-----BEGIN PUBLIC KEY-----\n" . wordwrap($pubKey, 64, "\n", true) . "\n-----END PUBLIC KEY-----\n";

   //$verify = openssl_verify("$headB64.$payloadB64", $signature, $pub_verify, OPENSSL_ALGO_SHA384);
   //var_dump($verify); //returns 1
  //it works, but in application that handle it doesn’t work and openssl_verify return 0.

$signature = self::encodeUrl($signature);

 return $headB64 . "." . $payloadB64 . "." . $signature;
}

Есть ли альтернатива openssl для этого? Или, может быть, я неправильно использую расширение OpenSSl ...?

...