当前位置: 首页 > 知识库问答 >
问题:

azure keyvault:本地验证由EC-HSM签名的数据

吴修洁
2023-03-14

我用Azure JS SDK做了一个测试,通过EC-HSM使用key vault来签名和验证数据

当我使用Azure JS SDK来验证它是否正常工作时,我将输出放在注释中

describe('crypto services', () => {
  it('Azure HSM', async () => {
    const client = new KeyClient(
      'https://xxx.vault.azure.net',
      new EnvironmentCredential(),
    );

    const keys: { [key: string]: KeyVaultKey } = {};
    for await (const key of client.listPropertiesOfKeys()) {
      keys[key.name] = await client.getKey(key.name);
    }
    console.log('available keys', Object.keys(keys)); //logging ['tmp']

    const cryptoClient = new CryptographyClient(
      keys['tmp'],
      new EnvironmentCredential(),
    );
    const content = Buffer.from('Hello world');
    const sig = await cryptoClient.signData('ES256', content);
    console.log('signature', Buffer.from(sig.result).toString('base64')); //logging different output on each call
    console.log('key crv', keys['tmp'].key.crv); //P-256
    console.log('key x', Buffer.from(keys['tmp'].key?.x).toString('base64')); //OC76WxZ/TMzJnRqv/cy9llDqSIMWlplgREY3jMxDCks=
    console.log('key y', Buffer.from(keys['tmp'].key?.y).toString('base64')); //Dxgw8nqXoO3xXQruejfQa/Z+aFpo/4ilC64JUHoRoog=

    const verif = await cryptoClient.verifyData('ES256', content, sig.result);
    expect(verif.result).toBe(true);
  });
})

现在,我想在不调用azure sdk的情况下在本地验证(这正是首先使用非对称加密的原因)

  it.only('local HSM verif', () => {
    const content = Buffer.from('Hello world'); //same content
    const sigs = [ //some values I received
      'bxw1nS8Q39mnQVkAhvJctXuLHz4n0wUjLbE+phj1XlUeWDxl7DCK5bG4d7YrL7zGtAnUq3YT9AdrrAXjpwhCzQ==',
      'hlh1CJSKivFYcdVygI0KJfUCGYor+whUu6NsJZhNTCllHHRmgh9FvcvxBSFVu0am7A9lryG/N5vLAv/B1Niiew==',
    ];
    const base64X = 'OC76WxZ/TMzJnRqv/cy9llDqSIMWlplgREY3jMxDCks='; //same as output of previous test
    const base64Y = 'Dxgw8nqXoO3xXQruejfQa/Z+aFpo/4ilC64JUHoRoog=';//same as output of previous test
    //converting the jwk to PEM thanks to the jwk-to-pem package
    const publicKey = jwkToPem({
      kty: 'EC',
      crv: 'P-256',
      x: base64X,
      y: base64Y,
    });
    for (const sig of sigs) {
      const verifyLocal = crypto.createVerify('sha256');
      verifyLocal.update(content);        
      const verifLocal = verifyLocal.verify(publicKey, sig);
      expect(verifLocal).toBe(true); //it always fails here
    }
  });

有人可以解释发生了什么吗?

我的猜测是公共签名不正确,因此<code>x在base64中不正确

例如,如果我用mkjwk.org生成JWK

{
kty: 'EC',
d: '7LU9Y16XKiFMcPVm39B5fVOtG0s-bnJwaeEtMrk9udE',
crv: 'P-256',
x: 'g-68Nakmi41xMv6zKduBn4dqcqJ0KXDqdS2rFpxUQOA',
y: 'pYRqhl2YDKBwGGkIXdYQQWuNjOtPcCe1bz_VYalXFW0',
}

它们看起来更短,没有“/”或“=”

共有1个答案

党佐
2023-03-14

问题是NodeJS需要ASN.1 DER签名,而Azure Key Vault创建IEEE-P1363签名(又名串联签名)。

使用Node.js/crypto生成ECDSA签名将详细介绍这一点。

以下代码段可用于将级联签名转换为NodeJS期望的格式(借助于jwk到pemasn1.jsbn.js包的帮助):

import { CryptographyClient, KeyClient } from "@azure/keyvault-keys";
import { AzureCliCredential } from "@azure/identity";
import jwkToPem from "jwk-to-pem";
import * as crypto from "crypto";
import asn1 from "asn1.js";
import BN from "bn.js";

const EcdsaDerSig = asn1.define("ECPrivateKey", function (this: any) {
  return this.seq().obj(this.key("r").int(), this.key("s").int());
});

function concatSigToAsn1SigSig(concatSigBuffer: any) {
  const r = new BN(concatSigBuffer.slice(0, 32).toString("hex"), 16, "be");
  const s = new BN(concatSigBuffer.slice(32).toString("hex"), 16, "be");
  return EcdsaDerSig.encode({ r, s }, "der");
}

async function main() {
  const content = Buffer.from("Hello world"); // some content
  const client = new KeyClient(
    "https://<your_vault_name>.vault.azure.net",
    new AzureCliCredential()
  );
  const key = await client.createEcKey("eckeytest");

  const cryptoClient = new CryptographyClient(key, new AzureCliCredential());
  const signature = await cryptoClient.signData("ES256", content); // sign data remotely in Azure Key Vault
  const sig = concatSigToAsn1SigSig(signature.result); // convert sig to the node.js expected format

  const base64X = Buffer.from(key.key!.x!).toString("base64");
  const base64Y = Buffer.from(key.key!.y!).toString("base64");
  // convert JWK to PEM for verification
  const publicKey = jwkToPem({
    kty: "EC",
    crv: "P-256",
    x: base64X,
    y: base64Y,
  });

  // Depending on the version of Node used, you could use `crypto.verify` directly.
  const keyObj = crypto.createPublicKey(publicKey);
  let result = crypto.verify("sha256", content, keyObj, sig);
  console.log("Result using crypto.verify", result);

  // using a verifier which can be used directly with the `publicKey`
  let verify = crypto.createVerify("sha256");
  verify.update(content);
  verify.end();
  result = verify.verify(publicKey, sig);
  console.log("Result using crypto.createVerify", result);
}

main()
  .then(() => console.log("done"))
  .catch((err) => console.log(err));

 类似资料:
  • 我需要用c语言验证由JAVA签名API生成的签名。我有一套相同的公钥和私钥。我还验证了c语言的签名和验证工作。但是我在验证JAVA生成的签名时遇到了问题。我看了所有的文件,尝试了不同的方法,但我似乎还是不明白。我将使用用于验证的原始JAVA代码粘贴等效的c代码。 原始JAVA代码: C代码: 我有3个问题: 这是验证签名的正确方法吗? 我需要在验证数据之前对其进行散列吗?如果是,那么JAVA在签名

  • 我有字节数组格式的公钥。在我的数据库里。像这样 在此处输入图像描述 总是suc=false。我确信bytetoverify的值与方法符号中的输入值相同。 我不知道我用这种方式生成公钥是问题还是符号有问题。在符号方法中,我使用sh1和pkcs1,但在验证中,我只找到sh1。 每个人都能帮我吗?

  • 我的手被https、ssl、PKI之类的东西弄得脏兮兮的。对于自签名证书,有一点我不太理解。假设我想创建一个自签名证书,并在我们想要建立安全连接时将其发送给我的朋友。 所以步骤是: 创建一个私钥。 创建一个公钥。 用我的公钥在证书上签名。 因此,当我的朋友得到我的证书时,他必须验证他得到的证书是我的,他需要解密数字签名。但为了解密和验证他必须拥有我的私钥。所以,我有点困惑。

  • 概览 首先同步下项目概况: 上篇文章分享了,路由中间件 - Jaeger 链路追踪(实战篇),文章反响真是出乎意料, 「Go中国」 公众号也转发了,有很多朋友加我好友交流,直呼我大神,其实我哪是什么大神,只不过在本地实践了而已,对于 Go 语言的使用,我还是个新人,在这里感谢大家的厚爱! 这篇文章咱们分享:路由中间件 - 签名验证。 为什么使用签名验证? 这个就不用多说了吧,主要是为了保证接口安全

  • 在我的应用程序中,我有一个公钥(表示为字符串),普通消息和数字签名,表示为base64编码字符串,用SHA256散列,用RSA加密)。现在,我需要验证数字签名。我试图做如下操作: 从创建(取自此处) 根据原始消息创建SHA256摘要 使用函数验证签名 (我正在努力避免使用OpenSSL函数) 此外,我的数字签名是使用Java的SHA256withRSA方法创建的。我在这里读到SHA256WithR

  • 问题内容: 我正在尝试以编程方式验证jar文件是否未被明显篡改。我有2个要防止的用例。1)修改现有类2)在罐子中添加新类 我使用jarsigner签名了罐子。当我用jarsigner验证以上两种情况之一时,它的工作方式就与我期望的一样。 当我尝试使用如何以编程方式验证用jarsigner签名的jar 或如何通过自签名的jar验证签名中的示例以编程方式进行操作时 ?但是,我没有任何SecurityE