【问题标题】:Google Identity Platform: Using OAuth 2.0 in Powershell using Firebase Admin SDK private keyGoogle Identity Platform:使用 Firebase Admin SDK 私钥在 Powershell 中使用 OAuth 2.0
【发布时间】:2018-08-14 01:26:28
【问题描述】:

尝试使用 Powershell HTTP/REST 并按照本教程实现 Firebase Admin SDK 服务帐户访问(Powershell 中没有方便的 API);

Using OAuth 2.0 for Server to Server Applications

形成 JWT 标头和 JWT 声明集非常简单,我可以重现本教程中的示例,但这就是棘手的地方;

使用从 Google API 控制台获得的私钥使用 SHA256withRSA(也称为带有 SHA-256 哈希函数的 RSASSA-PKCS1-V1_5-SIGN)对输入的 UTF-8 表示进行签名。输出将是一个字节数组。然后签名必须是 Base64url 编码的

这是我的相关代码 sn-p(感谢 @Will_Nevis 提供线索)

...
$jws = "$encodedheader.$encodedclaim";
$encodedjws = [System.Text.Encoding]::UTF8.GetBytes($jws);

$rsaobj = New-Object System.Security.Cryptography.RSACryptoServiceProvider;
$rsaobj.FromXmlString($rsaobj.ToXmlString($jsonfile.private_key));
$sha256OID = [System.Security.Cryptography.CryptoConfig]::MapNameToOID("SHA256");
$signature = $rsaobj.SignData($encodedjws, $sha256OID);

$encodedsignature = [System.Convert]::ToBase64String($signature);
$encodedsignature = $encodedsignature.Split('=')[0]
$encodedsignature = $encodedsignature.Replace('+', '-')
$encodedsignature = $encodedsignature.Replace('/', '_')

$jwt = "$encodedheader.$encodedclaim.$encodedsignature"
...

它生成了一个令人印象深刻的签名,比教程示例短,尽管我不知道它是否正确。它实际上不起作用(400)错误请求。

上面的代码是错误的还是在Powershell中有其他方法可以做到这一点..?

我想正确生成签名很重要。

感谢这个问题以前被问过,但似乎没有人“确定”它

以下是为我的 Firebase Admin SDK 服务帐号生成的 Json 私钥文件示例。这就是生成令牌所需的全部内容;

{
"type": "service_account",
"project_id": "abc-xyz",
"private_key_id": "nL9zQkSB1GXwF49MNcaEgCp9i7BmFr9JCBKYwgg",
"private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvADANB_massive_key... 03i8lG\nrlsDWw==\n-----END PRIVATE KEY-----\n",
"client_email": "firebase-adminsdk-fuhti@abc-xyz.iam.gserviceaccount.com",
"client_id": "156461654611800605490",
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://accounts.google.com/o/oauth2/token",
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
"client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/firebase-adminsdk-fuhti%40abc-xyz.iam.gserviceaccount.com"
  }

测试场景

([system.security.cryptography.rsacryptograpgyserviceprovider]::create(2048)).toxmlstring($true)

产生这段 XML(为了可读性而截断的值)“D”显然是 privateExponent(private_key?)

<RSAKeyValue>
    <Modulus>2htVi  ... Fay9qQ==</Modulus>
    <Exponent>AQAB</Exponent>
    <P>4dOudM8 ... t0JM=</P>
    <Q>9z+W6qw ... p+KlM=</Q>
    <DP>lOgN6  ... tbApX0=</DP>
    <DQ>h75s0 ... w93Jys=</DQ>
    <InverseQ>dDFa8H ... BlTuWs=</InverseQ>
    <D>n4EN9rDQm ... Nj7lY7G4Q==</D>
</RSAKeyValue>

这几乎证实了这行代码完全没有任何作用

$rsaobj.FromXmlString($rsaobj.ToXmlString($jsonfile.private_key));

【问题讨论】:

  • 看来 google 为其 API 提供了 .Net 包装器,并且 powershell 应该能够很好地使用任何 .net 代码。您是否已经探索过这条道路?
  • 您的代码中有一件值得注意的事情。它似乎只将私钥传递给 RSACryptoProvider,但documentation 表示它需要公钥或公钥和私钥。
  • 还有更多可疑之处。 RSA.toXMLString 的文档采用布尔值。它似乎正在导出现有的密钥对,布尔值确定是否包含私钥数据。它不需要字符串,尽管 powershell 可能会将字符串重新解释为 $true
  • 不,我认为 RSACryptoServiceProvider 可能是正确的方法,只是从外部源初始化很复杂。我认为你是对的,用私钥签名哈希不应该需要公钥,但是......这就是文档中写的内容。
  • @rangi 你有没有想过这个问题?我遇到了同样的问题,我也在使用 PowerShell。

标签: powershell oauth-2.0 rsa google-play-services


【解决方案1】:

我怀疑问题在于使用正确的公钥和私钥初始化 RSACryptoServiceProvider,您已作为 JSON 对象提供。您调用的 .toXML() 方法可能不起作用。

关于如何在this question 中设置您自己的公钥/私钥的一些讨论可能是一条可行的路径。

您可以尝试生成一个新的密钥对并在结果上生成.toXML($true) 以查看 XML 的格式,然后将基于 JSON 的密钥数据转换为该格式。

编辑

经过研究,您面临的挑战是将 Google 提供的 PKCS#8 编码密钥转换为 RSACryptoServiceProvider 可使用的形式。 .NET 目前没有用于读取此密钥的 API,但有兴趣纠正此缺陷。

似乎可行的一种解决方法是为您的服务帐户生成 P12 密钥。如果无法创建新的服务帐户,则有 ways to convert the private key file in the .json file to P12

我使用 p12 密钥创建了一个新的服务帐户,用于签名的 powershell 代码比以前更简单:

$certificate = [System.Security.Cryptography.X509Certificates.X509Certificate2]::new($p12file,'thepasswordforthekeystore')

$dataToSign = "This is some data"
$certificate.privateKey.SignData(
    [system.text.encoding]::utf8.getbytes($dataToSign), 
    [System.Security.Cryptography.HashAlgorithmName]::SHA256,
    [System.Security.Cryptography.RSASignaturePadding]::Pkcs1)

【讨论】:

  • 编辑了上面的答案,更新了对问题的理解,并提出了使用 powershell 示例代码的解决方法。
  • 哇@veefu 感谢您的所有提示.. 太棒了..!对于我来说,一份相当全面的可能性清单可能需要我一到三天的时间。现在我明白为什么 Google 告诉我们只使用现成的 API,如果您在大约 3 行代码中使用 Java 或 Python,这很好,但使用 REST/HTTP 就不是那么容易
  • 只是暂时没有时间做这方面的工作,所以我会把它放在 Upwork.com 上,看看有没有其他人知道
猜你喜欢
  • 2018-10-22
  • 2021-04-07
  • 2020-09-11
  • 1970-01-01
  • 2018-09-02
  • 1970-01-01
  • 2019-05-23
  • 2015-03-18
  • 1970-01-01
相关资源
最近更新 更多