1

我正在尝试验证由Google Identity Toolkit返回的 JSON Web 令牌“gtoken”的签名。

但是,“签名”似乎是 256 个字节,但在https://www.googleapis.com/oauth2/v1/certs找到的证书中的公钥只有 128 个字节。因此,我收到错误“签名比密钥长”。

我正在使用这个 Perl 代码:

use JSON;
use CGI;
use LWP::Simple;
use Crypt::OpenSSL::X509;
use Crypt::OpenSSL::RSA;
use MIME::Base64;

my $cgi = CGI->new();
my $json = JSON->new();

my $gtoken = $cgi->cookie('gtoken');

my ($header64, $body64, $signature64) = split(/\./, $gtoken, 3);
my $signed64 = "$header64.$body64";

$signature64 =~ s/\-/+/g;
$signature64 =~ s/\_/\//g;
my $m = length($signature64) % 4;
$signature64.="==" if($m == 2);
$signature64.="=" if($m == 3);
my $signature = decode_base64($signature64);
# Note that length($signature) == 256 here.

my $certs = $json->decode(get("https://www.googleapis.com/oauth2/v1/certs"));
foreach my $cert (values %$certs) {
    eval {
        my $x509 = Crypt::OpenSSL::X509->new_from_string( $cert );
        my $rsa_pub = Crypt::OpenSSL::RSA->new_public_key($x509->pubkey());
        # Note that $rsa_pub->size() == 128 here.
        $rsa_pub->use_sha256_hash();
        $rsa_pub->verify($signed64, $signature);
    };
    warn $@ if $@;
}

还有其他地方我应该寻找谷歌用来为谷歌身份工具包签署 JWT 的 2048 位(256 字节)密钥吗?或者有没有办法用 128 字节的公钥验证 256 字节的签名?还是我从证书中错误地提取了公钥?签名是 256 字节的事实意味着,据我所知,我用来验证签名的公钥也应该是 256 字节。

我也尝试使用 JSON::WebToken CPAN 模块,但同样的问题是密钥比签名短。

4

1 回答 1

1

Google 提供了移植到各种语言的 gitkit 库,并且它(至少对于我使用的 node.js 版本)有一种从公共 uri 轻松检索公钥的方法。Perl 似乎不是其中一种语言,因此我建议您获取 Python 版本并尝试以 Perl 方式模仿它。

在此处查看 API 参考和 gitgit 库从中获取公钥的 uri:https ://developers.google.com/identity/toolkit/web/reference/relyingparty/getPublicKeys 。

在此处查看 Python 快速入门应用程序。它有图书馆的链接:https ://developers.google.com/identity/toolkit/web/quickstart/python 。

祝你好运。

于 2015-05-20T05:09:39.810 回答