首页 > 解决方案 > PS256 签到 Flutter/Dart

问题描述

我需要在 Flutter 应用程序中使用 PS256 算法对 JWT 进行编码,但在搜索了一段时间后,我找不到任何支持 PS256 算法或至少支持 RSASSA-PSS(PS256 中使用的签名算法)的库。我想过从头开始编码,但我的密码学知识太少,我找不到任何关于算法如何工作的全面信息。谁能帮我解决这个问题?也许有一个算法示例或在 dart 中使用其他语言的库的方法?

标签: flutterdartencryptioncryptographysigning

解决方案


PS256 在RFC7518, Sec. 中描述。3.1使用 SHA-256 的 RSASSA-PSS 和使用 SHA-256 的 MGF1。如果您找不到支持 PS256 的 Dart JWT 库,您可以毫不费力地显式使用 RSASSA-PSS 进行签名。

对于以下实现,我选择了库fast_rsa 1.3.5,它支持 RSASSA-PSS。作为测试,在选择 PS256 作为算法后,我使用了网站https://jwt.io/的密钥和 JWT。

下面的 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/上。


推荐阅读