Проблема кода PKCE - это кодированный Base64-URL SHA256 га sh верификатора. Это означает, что вам нужно взять исходную строку, вычислить SHA256 га sh, а затем Base64-URL-кодировать га sh. Это много слов, так что давайте пройдемся по нему.
Есть две проблемы с тем, что вы пытались сделать выше:
Онлайн-калькулятор SHA256 га sh, который вы нашли, выводит ха sh в виде шестнадцатеричной строки, а не необработанных байтов. Это обычно полезно, но в этом случае нет. Итак, следующая вещь, которую вы делаете с помощью base64-кодирования, это то, что вы base64-кодируете шестнадцатеричное представление ha sh, а не необработанные байты. Вам необходимо использовать функцию ha sh, которая выводит необработанные байты и передает необработанные байты в base64-url-encoder.
Следующая проблема заключается в том, что вам нужно кодировать base64-url, а не base64 закодировать. Base64-URL-кодировка является незначительным вариантом кодировки Base64, где единственное отличие состоит в использовании символа -
вместо +
и _
вместо /
и обрезке символов заполнения =
с конца , Это делает его безопасным для URL-адреса, поскольку в противном случае символы +/=
должны быть экранированы в URL-адресе.
Таким образом, для вычисления проблемы кода PKCE необходимо использовать функцию SHA256, которая может дать вам необработанные байты, а затем используйте модифицированную функцию кодирования Base64 для кодирования этих байтов.
Вот код в PHP, который сделает это:
function pkce_code_challenge($verifier) {
$hash = hash('sha256', $verifier, true);
return rtrim(strtr(base64_encode($hash), '+/', '-_'), '=');
}
Это также возможно в простом JavaScript в браузере, но код немного длиннее из-за сложности API WebCrypto:
function sha256(plain) {
// returns promise ArrayBuffer
const encoder = new TextEncoder();
const data = encoder.encode(plain);
return window.crypto.subtle.digest('SHA-256', data);
}
function base64urlencode(a) {
// Convert the ArrayBuffer to string using Uint8 array.
// btoa takes chars from 0-255 and base64 encodes.
// Then convert the base64 encoded to base64url encoded.
// (replace + with -, replace / with _, trim trailing =)
return btoa(String.fromCharCode.apply(null, new Uint8Array(a)))
.replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
}
async function pkce_challenge_from_verifier(v) {
hashed = await sha256(v);
base64encoded = base64urlencode(hashed);
return base64encoded;
}