Как я могу подписать 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 ...?