微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

关于使用 Cloud KMS 进行签名验证的问题

如何解决关于使用 Cloud KMS 进行签名验证的问题

我正在尝试验证由 Google 的云 KMS 生成的签名,但我不断收到无效响应。

这是我测试它的方式:

const versionName = client.cryptokeyversionPath(
      projectId,locationId,keyRingId,keyId,versionId
    )

    const [publicKey] = await client.getPublicKey({
      name: versionName,})

    const valuetoSign = 'hola,que tal'

    const digest = crypto.createHash('sha256').update(valuetoSign).digest()

    const [signResponse] = await client.asymmetricSign({
      name: versionName,digest: {
        sha256: digest,},})

    const valid = crypto.createVerify('sha256').update(digest).verify(publicKey.pem,signResponse.signature)

    if (!valid) return console.log('INVALID SIGNATURE')

    console.log('SIGNATURE IS VALID!')

// output: INVALID SIGNATURE

代码将始终记录“无效签名”除非我使用原始消息而不是其哈希值:

const valid = crypto.createVerify('sha256').update(valuetoSign).verify(publicKey.pem,signResponse.signature) // true

但是使用本地私钥,我可以对消息进行签名并使用其哈希值进行验证:

const valuetoSign = 'hola,the tal'
const msgHash = crypto.createHash("sha256").update(valuetoSign).digest('base64');

const signer = crypto.createSign('sha256');
signer.update(msgHash);
const signature = signer.sign(pk,'base64');

const verifier = crypto.createVerify('sha256');
verifier.update(msgHash);
const valid = verifier.verify(pubKey,signature,'base64');
console.log(valid) // true

这是为什么? kms 签名有什么不同吗?

解决方法

根据加密模块文档中的 this example 和您的观察,我想说您可能误解了 client.asymmetricSign 的工作原理。让我们分析一下发生了什么:

您的本地私钥代码:

const valueToSign = 'hola,the tal'

// Create sha256 hash
const msgHash = crypto.createHash("sha256").update(valueToSign).digest('base64');

// Let signer sign sha256(hash)
const signer = crypto.createSign('sha256');
signer.update(msgHash);
const signature = signer.sign(pk,'base64');
// We now got sign(sha256(hash))

// Let verifier verify sha256(hash)
const verifier = crypto.createVerify('sha256');
verifier.update(msgHash);

const valid = verifier.verify(pubKey,signature,'base64');
console.log(valid) // true

我们正在使用 sign(sha256(hash)) 验证 verify(sha256(hash))


您的 KMS 代码:

const valueToSign = 'hola,que tal'

// Create sha256 hash
const digest = crypto.createHash('sha256').update(valueToSign).digest()

// Let KMS sign the hash
const [signResponse] = await client.asymmetricSign({
    name: versionName,digest: {
        sha256: digest,// we already say "we hashed our data using sha256"
    },});
// We now got `sign(hash)`,NOT `sign(sha256(hash))` (where hash == digest)

// Let verifier verify sha256(hash)
const valid = crypto.createVerify('sha256').update(digest).verify(publicKey.pem,signResponse.signature)

我们正在使用 sign(hash) 验证 verify(sha256(hash))


基本上,您在本地签署您的哈希并验证签名的哈希。使用 KMS,您正在对您的数据进行签名并验证签名哈希,这实际上是您签名的数据,因此您对 .update(valueToSign) 的第二次尝试有效。

解决方案?在让 KMS 签名之前再次散列您的 sha256 哈希值,因为 KMS 需要待签名数据的 sha256 哈希值,而 crypto 需要待签名数据(根据您传递给 createSign 的算法,它会自行散列)

,

换句话说,答案与凯文的答案非常相似,但观点不同。

当您使用 crypto.createSign(<algorithm>)crypto.createVerify(<algorithm>) 时,您表示将分别用于签名创建和验证的摘要 algorithm

当您对返回的 SignVerify 对象调用 update 时,您需要按原样提供数据crypto 会处理在您稍后signverify时适当地消化该信息。

相比之下,GCP KMS asymmetricSign operation 需要一条消息 digest 使用指定的 algorithm 生成在您的原始数据上 作为参数。这就是为什么您需要先用 crypto.createHash 计算消息摘要。

但请注意,正如所指出的,这一事实不会改变 crypto 验证过程的行为,它始终需要原始数据作为输入,这就是为什么当您通过原始数据时您的代码有效未经哈希处理的数据。

尽管您在问题中提供了一个工作示例以供参考,但 GCP documentation 提供了其他示例。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。