【发布时间】:2015-07-30 02:36:19
【问题描述】:
我正在尝试验证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 模块,但遇到了同样的问题,即密钥比签名短。
【问题讨论】:
-
总是
use strict和use warnings,尤其是在寻求代码帮助之前。您私下做什么取决于您,但请至少在此处写问题之前表现出已做出努力。 -
嗯,我从一个较长的脚本中剪切和粘贴。我总是使用严格并使用警告。我已经尝试以十几种不同的方式(包括不同的语言)来实现这个东西十几次。这里的问题不在于语言,而在于 256 字节签名与 128 字节公钥。代码仅供参考。我也没有包括 #!行或内容类型标题输出或任何数量的其他细节,我认为这些细节会分散我的注意力。但我确实测试了发布的脚本。
-
我的意思是,无论如何您都不能轻松运行此脚本。您需要设置 Google Identity Toolkit 并为自己获取一个 gtoken cookie 集。这需要做一些事情,所以我不是在寻找代码审查,而是在寻找已经知道验证 Google 签名的 id 令牌 JWT 上的签名所需的加密步骤的人。我通读了谷歌库上几种不同语言的源代码。一切似乎都表明你应该完全按照我上面所做的那样做。所以我想知道我是否使用了错误的加密算法或获取了错误的密钥。
标签: perl x509 sha256 jwt google-identity-toolkit