PS256 вход в Flutter / Dart

#flutter #dart #encryption #cryptography #signing

#флаттер #dart #шифрование #криптография #подписание

Вопрос:

Мне нужно закодировать JWT с помощью алгоритма PS256 в приложении Flutter, но после некоторого поиска я не смог найти никаких библиотек, поддерживающих алгоритм PS256 или, по крайней мере, RSASSA-PSS (алгоритм подписи, используемый в PS256). Я думал о кодировании его с нуля, но мои знания в криптографии слишком малы, и я не смог найти никакой исчерпывающей информации о том, как работает алгоритм. Может ли кто-нибудь помочь мне с этой проблемой? Может быть, есть пример алгоритма или способ использования библиотек с других языков в dart?

Ответ №1:

PS256 описан в RFC7518, раздел 3.1: RSASSA-PSS с использованием SHA-256 и MGF1 с SHA-256. Если вы не можете найти библиотеку JWT Dart, поддерживающую PS256, вы можете выполнить подписание с помощью RSASSA-PSS явно без особых усилий.

Для следующей реализации я выбрал библиотеку fast_rsa 1.3.5, которая поддерживает RSASSA-PSS. В качестве теста я использовал ключи и JWT сайта https://jwt.io / после выбора PS256 в качестве алгоритма.

Приведенный ниже код Dart генерирует подпись и подписанный JWT:

 Future<void> test() async {

  var privateKey = """-----BEGIN RSA PRIVATE KEY-----
MIIEogIBAAKCAQEAnzyis1ZjfNB0bBgKFMSvvkTtwlvBsaJq7S5wA kzeVOVpVWw
kWdVha4s38XM/pa/yr47av7 z3VTmvDRyAHcaT92whREFpLv9cj5lTeJSibyr/Mr
m/YtjCZVWgaOYIhwrXwKLqPr/11inWsAkfIytvHWTxZYEcXLgAXFuUuaS3uF9gEi
NQwzGTU1v0FqkqTBr4B8nW3HCN47XUu0t8Y0e lf4s4OxQawWD79J9/5d3Ry0vbV
3Am1FtGJiJvOwRsIfVChDpYStTcHTCMqtvWbV6L11BWkpzGXSW4Hv43qa GSYOD2
QU68Mb59oSk2OB BtOLpJofmbGEGgvmwyCI9MwIDAQABAoIBACiARq2wkltjtcjs
kFvZ7w1JAORHbEufEO1Eu27zOIlqbgyAcAl7q /1bip4Z/x1IVES84/yTaM8p0go
amMhvgry/mS8vNi1BN2SAZEnb/7xSxbflb70bX9RHLJqKnp5GZe2jexw wyXlwaM
 bclUCrh9e1ltH7IvUrRrQnFJfh is1fRon9Co9Li0GwoN0x0byrrngU8Ak3Y6D9
D8GjQA4Elm94ST3izJv8iCOLSDBmzsPsXfcCUZfmTfZ5DbUDMbMxRnSo3nQeoKGC
0Lj9FkWcfmLcpGlSXTO Ww1L7EGq PT3NtRae1FZPwjddQ1/4V905kyQFLamAA5Y
lSpE2wkCgYEAy1OPLQcZt4NQnQzPz2SBJqQN2P5u3vXl zNVKP8w4eBv0vWuJJF 
hkGNnSxXQrTkvDOIUddSKOzHHgSg4nY6K02ecyT0PPm/UZvtRpWrnBjcEVtHEJNp
bU9pLD5iZ0J9sbzPU/LxPmuAP2Bs8JmTn6aFRspFrP7W0s1Nmk2jsm0CgYEAyH0X
 jpoqxj4efZfkUrg5GbSEhf dZglf0tTOA5bVg8IYwtmNk/pniLG/zI7c GlTc9B
BwfMr59EzBq/eFMI7 LgXaVUsM/sS4Ry yeK6SJx/otIMWtDfqxsLD8CPMCRvecC
2Pip4uSgrl0MOebl9XKp57GoaUWRWRHqwV4Y6h8CgYAZhI4mh4qZtnhKjY4TKDjx
QYufXSdLAi9v3FxmvchDwOgn4L PRVdMwDNms2bsL0m5uPn104EzM6w1vzz1zwKz
5pTpPI0OjgWN13Tq8 PKvm/4Ga2MjgOgPWQkslulO/oMcXbPwWC3hcRdr9tcQtn9
Imf9n2spL/6EDFId Hp/7QKBgAqlWdiXsWckdE1Fn91/NGHsc8syKvjjk1onDcw0
NvVi5vcba9oGdElJX3e9mxqUKMrw7msJJv1MX8LWyMQC5L6YNYHDfbPF1q5L4i8j
8mRex97UVokJQRRA452V2vCO6S5ETgpnad36de3MUxHgCOX3qL382Qx9/THVmbma
3YfRAoGAUxL/Eu5yvMK8SAt/dJK6FedngcM3JEFNplmtLYVLWhkIlNRGDwkg3I5K
y18Ae9n7dHVueyslrb6weq7dTkYDi3iOYRW8HRkIQh06wEdbxt0shTzAJvvCQfrB
jg/3747WSsf/zBTcHihTRBdAv6OmdhV4/dD5YBfLAkLrd mX7iE=
-----END RSA PRIVATE KEY-----""";

  var unsignedJWT = "eyJhbGciOiJQUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWUsImlhdCI6MTUxNjIzOTAyMn0";
  var signature = await RSA.signPSS(unsignedJWT, Hash.HASH_SHA256, SaltLength.SALTLENGTH_EQUALS_HASH, privateKey);
  var signatureB64url = signature.replaceAll (" ", "-").replaceAll ("/", "_").replaceAll ("=", "");
  var signedJWT = unsignedJWT   "."   signatureB64url;

  print(signedJWT);
}
 

Если код выполняется, например, следующие подписанные результаты JWT:

 eyJhbGciOiJQUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWUsImlhdCI6MTUxNjIzOTAyMn0.Yn5adhSVLL1PZShH16gFYAv1LxmShAro0-2lv9wPea8Vc-6LbvT91xhvLzRve6f5ShKCVQRAIWP3Iqip6cF8q4M25ro7_g5FnWPXK5NoMQnf_08gCizsIrZXmpyLLpCYKds38UYcpni5IgcaFgoqjJlbtPGVf5utdIB1CaZHP_OkwpL0hHTCv4n9qlwLqmiTMV0XCN6OIBq4XIzh4MGJa9xCzNgHnRXBQbygxB5yaoK__f6DUKKJNa9mcII5cQOWNHrI7PGClRr4QYxv0pRjCvaRkjpCSJxJQSw1MapV5JDxanE3XORnOZXbh_BHgNlQX9S6NxjnRlxYiV04VV0Nhw
 

Пожалуйста, обратите внимание, что PSS является вероятностным, поэтому идентичные входные данные каждый раз будут выдавать разные подписи.

Подписанный JWT может быть успешно проверен с помощью открытого ключа:

 -----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnzyis1ZjfNB0bBgKFMSv
vkTtwlvBsaJq7S5wA kzeVOVpVWwkWdVha4s38XM/pa/yr47av7 z3VTmvDRyAHc
aT92whREFpLv9cj5lTeJSibyr/Mrm/YtjCZVWgaOYIhwrXwKLqPr/11inWsAkfIy
tvHWTxZYEcXLgAXFuUuaS3uF9gEiNQwzGTU1v0FqkqTBr4B8nW3HCN47XUu0t8Y0
e lf4s4OxQawWD79J9/5d3Ry0vbV3Am1FtGJiJvOwRsIfVChDpYStTcHTCMqtvWb
V6L11BWkpzGXSW4Hv43qa GSYOD2QU68Mb59oSk2OB BtOLpJofmbGEGgvmwyCI9
MwIDAQAB
-----END PUBLIC KEY-----
 

например, на https://jwt.io /.