Google Cloud Endpoints:verifyToken:签名长度不正确
Posted
技术标签:
【中文标题】Google Cloud Endpoints:verifyToken:签名长度不正确【英文标题】:Google Cloud Endpoints: verifyToken: Signature length not correct 【发布时间】:2015-08-27 04:59:43 【问题描述】:今天早上,从我的 android 应用向我的 Google Cloud Endpoint 发出的每个 API 请求都开始出现以下异常:
com.google.api.server.spi.auth.GoogleIdTokenUtils verifyToken: verifyToken:签名长度不正确:得到 256 但期待 128
在我的 javascript 网络客户端上调用仍然可以正常工作。我没有更改服务器端代码或客户端代码。
最近该服务是否发生了任何可能导致这种情况发生的变化?
更新:第一次出现这种情况似乎是在 11:17:07 UTC
更新:不起作用的事情包括为 android 生成新的客户端 ID 并更新到 App Engine SDK 1.9.22
【问题讨论】:
这只是发生在我身上...... 3 小时前工作正常。 我们联系了 Google Enterprise 支持团队。他们告诉他们已经在努力解决这个问题。 他们告诉他们将在美国/太平洋时间 10:00 提供进一步的更新。一旦我收到他们的任何回复,我就会在此处发布。 这个问题应该只影响混合键长的组合键。当前提供的密钥集仅包括 2048 长度的密钥。由于缓存的密钥集,您可能仍会遇到中断,但如果您重新启动应用程序,问题可能会得到解决。 感谢现在似乎很好!这是一个很好的 7 小时恐慌 :) 感谢大家的更新 【参考方案1】:原因
RSA 具有可变长度的签名,具体取决于密钥大小。 Google 更新了用于签名的密钥对,现在其中一个密钥对生成的签名长度与另一个不同java.security.Signature.verify(byte[] signature)
如果传递了错误长度的签名,则抛出异常(而不是返回 false,这通常在签名与密钥不匹配时完成)
对我来说,解决方案是包装验证调用 (try...catch
),然后返回 false。
您也可以自己对公钥进行早期检查,检查签名的长度是否与公钥模数的长度匹配。
如果您使用库来检查签名,请确保使用最新版本。
查看http://android-developers.blogspot.nl/2013/01/verifying-back-end-calls-from-android.html 上的示例代码,您将不得不更改:
GoogleIdToken token = GoogleIdToken.parse(mJFactory, tokenString);
到
JsonWebSignature jws = JsonWebSignature.parser(mJFactory).setPayloadClass(Payload.class).parse(tokenString);
GoogleIdToken token = new GoogleIdToken(jws.getHeader(), (Payload) jws.getPayload(), jws.getSignatureBytes(), jws.getSignedContentBytes())
public boolean verify(GoogleIdTokenVerifier verifier)
throws GeneralSecurityException, IOException
try
return verifier.verify(this);
catch (java.security.SignatureException e)
return false;
;
很遗憾,我没有确切的设置来测试这个。
对于那些使用 Google Cloud Endpoint 的人,就像问题所述,我认为除了等到 Google 修复它之外,您几乎无能为力。幸运的是它现在已修复。 (从技术上讲,您可能会争辩说像现在所做的那样更改密钥是一种解决方法,并且 Google 提供的库需要修复。但它有效,所以这是一个好的开始)
【讨论】:
感谢您的信息。知道从哪里开始尝试修复它吗? @SanketBerde Google 生成密钥,然后他们只是在消息上签名...如果 Google 生成新密钥,也许会有所帮助,但对我们来说这不是解决方案 这绝对不是我们的问题吧?我们的配置有问题吗? @beetstra 你是指服务器端还是安卓端?这是一个 Play 商店部署的应用程序,因此我无法在客户端快速更改任何内容,因为它需要数小时才能推送给用户。 我尝试生成新的 Android 客户端 ID 和受众。没用,同样的错误。我注意到的是,从 Google Endpoints explorer 发出的 Endpoints 调用是有效的。所以这只是客户端 ID 的问题。【参考方案2】:同样的问题,据我所知,公共证书 URL(现在?我猜以前不是这种情况,或者顺序改变了)返回两个键:
https://www.googleapis.com/oauth2/v1/certs
检查这些,第一个具有 1024 位密钥,第二个具有 2048 位密钥。我相信我从 android 客户端传入的令牌是由第二个证书使用 2048 位密钥签名的,因此“签名长度不正确:得到 256 但期待 128”。
查看 Google 验证程序源 (GoogleTokenVerifier.java),它似乎确实迭代了多个键:
// verify signature
for (PublicKey publicKey : publicKeys.getPublicKeys())
if (googleIdToken.verifySignature(publicKey))
return true;
假设键被正确解析(该代码看起来很合理,但实际上并未检查结果)。
正如 beestra 所指出的,此代码期望在无法验证的情况下返回 false,而是抛出异常。理想情况下,它应该在失败后继续迭代并使用第二个公钥进行验证,这应该可以工作。
要解决这个问题,似乎有两种选择:
-
fork google api 客户端库并修复
在(您的)调用代码中复制验证 (GoogleIdTokenVerifier.verify(GoogleIdToken))
我不知道 2. 有多现实,使用了一些超级功能并且很多内部状态是私有的,必须复制所有这些。忙着调查……
更新:好的,看起来在我使用生产数据的测试中已修复,但尚未将其部署到生产中。这是斯卡拉
val jsonFactory = new JacksonFactory()
val transport = new NetHttpTransport()
val googleIdTokenVerifier = new GoogleIdTokenVerifier(transport, jsonFactory)
class DuplicateVerifier(builder: GoogleIdTokenVerifier.Builder) extends IdTokenVerifier(builder)
val topIdTokenVerifier = new DuplicateVerifier(new GoogleIdTokenVerifier.Builder(transport, jsonFactory))
val publicKeysManager = new GooglePublicKeysManager(transport, jsonFactory)
def duplicateGoogleVerify(token: GoogleIdToken): Boolean =
// check the payload
if (!topIdTokenVerifier.verify(token))
false
else
// verify signature
import scala.collection.JavaConverters._
publicKeysManager.getPublicKeys.asScala.map k =>
Try(token.verifySignature(k))
.foldLeft(false)((c, x) => c || x.getOrElse(false))
如果不明显,请使用此方法而不是 Google 的方法:
// if (googleIdTokenVerifier.verify(token))
if (duplicateGoogleVerify(token))
如果有人需要,我稍后会尝试编写 Java 等价物。
【讨论】:
我认为您对公共证书 URL 的看法是正确的 - 截至 2015 年 3 月 15 日,它有 2 个相同大小的证书web.archive.org/web/20150315022911/https://www.googleapis.com/… 如果成功请提供JAVA等价物..我需要!!以上是关于Google Cloud Endpoints:verifyToken:签名长度不正确的主要内容,如果未能解决你的问题,请参考以下文章
使用 Google Cloud Endpoints 时如何重启 Flask 服务器?
Google Cloud Endpoints 相当于 API 网关,还是 Endpoints 相当于微服务?
Google Cloud Endpoints:身份验证问题(错误 403)