如何从 JWK 重建 RSA 公钥

问题描述 投票:0回答:1

我在受限环境中工作,无法利用任何第三方系统来简化此操作,例如 Firebase/php-jwt

我已收到我想要验证的 JWT。我有一个 JWK,我需要从中重建公钥,以完成验证。

JWK如下

{
"kty": "RSA",
"use": "enc",
"n": "ozmvkuGzWNHs9cEcC5PWwbG-dmSjPcoQFxEbqH_fBjkj_nfTTKshdiSq5ciulWEa_rrqQ2qwcSADNxtTzRR1qfud-NvsM8VltT7xDuVVqPTZoWLKa0BWXgQQ-1mCm1KdGltYWccB0R1LoF-rb3DEEZySsHvqErYzYt4M_rqjEiK5Y9y1h3k1h5Yk4zGLWchko3jiDS-pVevvWsQsN-Y3KuB19485G9P_MXLtfJWQ4wC4jlo9etdD_hgDfxX-hQy3wuwHfHifLdxvxiB8X5Is4m6DuY4_7hS5RwXAjO1QSd-zUYZNT_2yWVR56_jyiZEiOdgIm9QtLPZCTKzqsXoqZQ",
"e": "AQAB"
}

我用来生成公钥的代码如下

$jwk = json_decode($jwk);

$rsaPublicKey = "-----BEGIN PUBLIC KEY-----\n";
$rsaPublicKey .= "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA{$jwk->modulus}";
$rsaPublicKey .= "{$jwk->exponent}\n-----END PUBLIC KEY-----";

$isSignatureValid = openssl_verify($dataToVerify, $signature, $rsaPublicKey, OPENSSL_ALGO_SHA256);

这会导致错误

openssl_verify(): supplied key param cannot be coerced into a public key

我觉得我错过了一些明显的东西,并且我以某种方式错误地生成了密钥。我尝试向 ChatGPT 寻求帮助,但它给了我许多不同的解决方案,所有这些都导致了相同的错误。进一步的阅读让我想到了一些类似于人工智能建议的想法,但又都导致了同样的错误

其中包括:

  • 尝试各种不同的空白,从根本没有空白到按 64 个字符分块
  • 以不同的方式编码模数和指数(我根本不理解这些建议)
  • 在模数前面加上固定字符串
    MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA
    ,这似乎与RSA密钥有关,但我不太明白这是什么

我真的不知道我还能在这里做什么,这感觉应该是一件很简单的事情,但我只是不明白,而且我已经没有办法接近

php jwt public-key jwk
1个回答
0
投票

我认为这可能只是一个简单的格式问题,一些简单的代码可以修复,所以我编写了以下内容来尝试生成有效的 pem。但使用您提供的 JWK 时,它不起作用。该代码使用显示的示例 pem 运行,不会发出“...无法强制转换为公钥”错误。您可能会注意到它生成的文本长度与示例不同。你确定JWK是正确的吗?无论如何,你可以玩这个。可能有用,也可能没用。

<?php
  
  $json = array();  
  $json['kty'] = 'RSA';
  $json['use'] = 'enc';
  $json['n'] = 'ozmvkuGzWNHs9cEcC5PWwbG-dmSjPcoQFxEbqH_fBjkj_nfTTKshdiSq5ciulWEa_rrqQ2qwcSADNxtTzRR1qfud-NvsM8VltT7xDuVVqPTZoWLKa0BWXgQQ-1mCm1KdGltYWccB0R1LoF-rb3DEEZySsHvqErYzYt4M_rqjEiK5Y9y1h3k1h5Yk4zGLWchko3jiDS-pVevvWsQsN-Y3KuB19485G9P_MXLtfJWQ4wC4jlo9etdD_hgDfxX-hQy3wuwHfHifLdxvxiB8X5Is4m6DuY4_7hS5RwXAjO1QSd-zUYZNT_2yWVR56_jyiZEiOdgIm9QtLPZCTKzqsXoqZQ';
  $json['e'] = 'AQAB';
  $rsaPublicHeader = "-----BEGIN PUBLIC KEY-----\n";
  $rsaPublicBody = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA".strtr($json['n'].$json['e'], '-_', '+/');
  $rsaPublicFooter = "-----END PUBLIC KEY-----";
  $pem = $rsaPublicHeader;
  $k = 0;
  $rsaPublicBodyLen = strlen($rsaPublicBody);
  for ($i = 0; $i<$rsaPublicBodyLen; $i+=64) {
    $pem .= substr($rsaPublicBody, $i, 64)."\n";
  }
  $pem .= $rsaPublicFooter;
  $dataToVerify = "";
  $signature = "";
  /*
  // Example pem taken from https://github.com/Strobotti/php-jwk
  $pem = "-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4dGQ7bQK8LgILOdLsYzf
ZjkEAoQeVC/aqyc8GC6RX7dq/KvRAQAWPvkam8VQv4GK5T4ogklEKEvj5ISBamdD
Nq1n52TpxQwI2EqxSk7I9fKPKhRt4F8+2yETlYvye+2s6NeWJim0KBtOVrk0gWvE
Dgd6WOqJl/yt5WBISvILNyVg1qAAM8JeX6dRPosahRVDjA52G2X+Tip84wqwyRpU
lq2ybzcLh3zyhCitBOebiRWDQfG26EH9lTlJhll+p/Dg8vAXxJLIJ4SNLcqgFeZe
4OfHLgdzMvxXZJnPp/VgmkcpUdRotazKZumj6dBPcXI/XID4Z4Z3OM1KrZPJNdUh
xwIDAQAB
-----END PUBLIC KEY-----";
*/
  echo $pem."\n";
  $isSignatureValid = openssl_verify($dataToVerify, $signature, $pem, OPENSSL_ALGO_SHA256);
  if ($isSignatureValid) {
    echo ("Valid\n");
  } else {
    echo ("Invalid\n");
  }
?>
© www.soinside.com 2019 - 2024. All rights reserved.