你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn

适用于 JavaScript 的 Azure 密钥保管库 密钥客户端库 - 版本 4.8.0

Azure 密钥保管库 是一项服务,可用于使用安全密钥加密身份验证密钥、存储帐户密钥、数据加密密钥、.pfx 文件和密码。 若要详细了解 Azure 密钥保管库,可能需要查看:什么是 Azure 密钥保管库?

Azure 密钥保管库托管 HSM 是一种完全托管、高度可用、单租户且符合标准的云服务,可用于使用 FIPS 140-2 级别 3 验证的 HSM 保护云应用程序的加密密钥。 若要详细了解 Azure 密钥保管库 托管 HSM,可能需要查看:什么是 Azure 密钥保管库托管 HSM?

Azure 密钥保管库密钥库客户端支持 RSA 密钥、椭圆曲线 (EC) 密钥,以及针对托管 HSM 运行时的对称 (oct) 密钥,每个密钥在硬件安全模块 (HSM) 中都有相应的支持。 它提供创建、检索、更新、删除、清除、备份、还原以及列出密钥及其版本的操作。

在 Node.js 应用程序中使用 Azure 密钥保管库密钥的客户端库可以:

  • 使用椭圆曲线或 RSA 加密创建密钥,可以选择由硬件安全模块 (HSM) 提供支持。
  • 导入、删除和更新密钥。
  • 获取一个或多个密钥和已删除的密钥及其属性。
  • 恢复已删除的密钥并还原备份的密钥。
  • 获取密钥的版本。

使用此库中提供的加密客户端,还可以访问:

  • Encrypting
  • 解密
  • 签名
  • 验证
  • 包装密钥
  • 解包密钥

注意:由于 Azure 密钥保管库服务限制,无法在浏览器中使用此包,请参阅此文档以获取指导。

关键链接:

入门

目前支持的环境

先决条件

安装包

使用 npm 安装 Azure 密钥保管库密钥客户端库

npm install @azure/keyvault-keys

安装标识库

Azure 密钥保管库客户端使用 Azure 标识库进行身份验证。 也使用 npm 安装它

npm install @azure/identity

配置 TypeScript

TypeScript 用户需要安装 Node 类型定义:

npm install @types/node

还需要在tsconfig.json中启用 compilerOptions.allowSyntheticDefaultImports 。 请注意,如果已启用 compilerOptions.esModuleInteropallowSyntheticDefaultImports 则默认启用 。 有关详细信息 ,请参阅 TypeScript 的编译器选项手册

关键概念

  • 密钥客户端是与 JavaScript 应用程序中的 Azure 密钥保管库 API 中的密钥相关的 API 方法进行交互的主要接口。 初始化后,它提供一组可用于创建、读取、更新和删除密钥的基本方法。
  • 密钥版本是密钥保管库中密钥的版本。 每次用户向唯一键名称分配值时,都会创建该密钥的 新版本 。 除非向查询提供特定版本,否则按名称检索密钥将始终返回分配的最新值。
  • 软删除 允许 Key Vault 支持将删除和清除作为两个单独的步骤,因此删除的密钥不会立即丢失。 仅当密钥保管库启用了软删除时,才会发生这种情况。
  • 可以从任何创建的 密钥生成密钥备份 。 这些备份以二进制数据的形式提供,只能用于重新生成以前删除的密钥。
  • 加密客户端是一个单独的接口,与 密钥保管库 API 中的密钥 API 方法交互。 此客户端仅侧重于可以使用已在密钥保管库中创建的密钥执行的加密操作。 有关此客户端的详细信息,请参阅 加密 部分。

使用 Azure Active Directory 进行身份验证

密钥保管库服务依赖于 Azure Active Directory 对其 API 的请求进行身份验证。 @azure/identity 包提供应用程序可用于执行此操作的各种凭据类型。 的 自述文件 @azure/identity 提供了更多详细信息和示例来帮助你入门。

若要与 Azure 密钥保管库 服务交互,需要创建 类的KeyClient实例、保管库 URL 和凭据对象。 本文档中显示的示例使用名为 的 DefaultAzureCredential凭据对象,该对象适用于大多数方案,包括本地开发和生产环境。 此外,我们建议使用 托管标识 在生产环境中进行身份验证。

可以在 Azure 标识文档中找到有关不同身份验证方式及其相应凭据类型的详细信息。

下面是一个快速示例。 首先,导入 DefaultAzureCredentialKeyClient

const { DefaultAzureCredential } = require("@azure/identity");
const { KeyClient } = require("@azure/keyvault-keys");

导入这些服务后,接下来可以连接到 密钥保管库 服务:

const { DefaultAzureCredential } = require("@azure/identity");
const { KeyClient } = require("@azure/keyvault-keys");

const credential = new DefaultAzureCredential();

// Build the URL to reach your key vault
const vaultName = "<YOUR KEYVAULT NAME>";
const url = `https://${vaultName}.vault.azure.net`; // or `https://${vaultName}.managedhsm.azure.net` for managed HSM.

// Lastly, create our keys client and connect to the service
const client = new KeyClient(url, credential);

指定 Azure 密钥保管库 服务 API 版本

默认情况下,此包使用最新的 Azure 密钥保管库 服务版本,即 7.2。 可以通过在客户端构造函数中设置 选项 serviceVersion 来更改正在使用的服务版本,如下所示:

const { DefaultAzureCredential } = require("@azure/identity");
const { KeyClient } = require("@azure/keyvault-keys");

const credential = new DefaultAzureCredential();

const vaultName = "<YOUR KEYVAULT NAME>";
const url = `https://${vaultName}.vault.azure.net`;

// Change the Azure Key Vault service API version being used via the `serviceVersion` option
const client = new KeyClient(url, credential, {
  serviceVersion: "7.0", // Or 7.1
});

示例

以下部分提供代码片段,这些代码片段涵盖了使用 Azure 密钥保管库 密钥的一些常见任务。 此处介绍的方案包括:

创建密钥

createKey创建要存储在 Azure 密钥保管库中的密钥。 如果已存在同名的密钥,则会创建该密钥的新版本。

const { DefaultAzureCredential } = require("@azure/identity");
const { KeyClient } = require("@azure/keyvault-keys");

const credential = new DefaultAzureCredential();

const vaultName = "<YOUR KEYVAULT NAME>";
const url = `https://${vaultName}.vault.azure.net`;

const client = new KeyClient(url, credential);

const keyName = "MyKeyName";

async function main() {
  const result = await client.createKey(keyName, "RSA");
  console.log("result: ", result);
}

main();

发送到 createKey 的第二个参数是密钥的类型。 支持的密钥类型取决于 SKU 以及使用的是 Azure 密钥保管库还是 Azure 托管 HSM。 有关受支持的密钥类型的最新列表,请参阅 关于密钥

获取密钥

从保管库中读取密钥的最简单方法是按名称获取密钥。 这将检索密钥的最新版本。 如果将密钥指定为可选参数的一部分,可以选择获取不同版本的密钥。

getKey检索密钥保管库中上一个存储的密钥。

const { DefaultAzureCredential } = require("@azure/identity");
const { KeyClient } = require("@azure/keyvault-keys");

const credential = new DefaultAzureCredential();

const vaultName = "<YOUR KEYVAULT NAME>";
const url = `https://${vaultName}.vault.azure.net`;

const client = new KeyClient(url, credential);

const keyName = "MyKeyName";

async function main() {
  const latestKey = await client.getKey(keyName);
  console.log(`Latest version of the key ${keyName}: `, latestKey);
  const specificKey = await client.getKey(keyName, { version: latestKey.properties.version! });
  console.log(`The key ${keyName} at the version ${latestKey.properties.version!}: `, specificKey);
}

main();

使用属性创建和更新密钥

还可以将以下属性分配给密钥保管库中的任何键:

  • tags:可用于搜索和筛选键的任意键值集。
  • keyOps:此键能够执行 (encrypt、、decryptwrapKeysignverifyunwrapKey) 的操作数组。
  • enabled:一个布尔值,确定是否可以读取键值。
  • notBefore:一个给定的日期,在此日期之后可以检索键值。
  • expires:一个给定日期,在此日期之后无法检索键值。

具有这些属性的对象可以作为 的第三个 createKey参数发送,紧跟在键的名称和值之后,如下所示:

const { DefaultAzureCredential } = require("@azure/identity");
const { KeyClient } = require("@azure/keyvault-keys");

const credential = new DefaultAzureCredential();

const vaultName = "<YOUR KEYVAULT NAME>";
const url = `https://${vaultName}.vault.azure.net`;

const client = new KeyClient(url, credential);

const keyName = "MyKeyName";

async function main() {
  const result = await client.createKey(keyName, "RSA", {
    enabled: false,
  });
  console.log("result: ", result);
}

main();

这将创建同一密钥的新版本,该密钥将具有最新提供的属性。

还可以使用 updateKeyProperties将属性更新为现有密钥版本,如下所示:

const { DefaultAzureCredential } = require("@azure/identity");
const { KeyClient } = require("@azure/keyvault-keys");

const credential = new DefaultAzureCredential();

const vaultName = "<YOUR KEYVAULT NAME>";
const url = `https://${vaultName}.vault.azure.net`;

const client = new KeyClient(url, credential);

const keyName = "MyKeyName";

async function main() {
  const result = await client.createKey(keyName, "RSA");
  await client.updateKeyProperties(keyName, result.properties.version, {
    enabled: false,
  });
}

main();

删除密钥

方法 beginDeleteKey 开始删除密钥。 一旦必要资源可用,此过程就会在后台发生。

const { DefaultAzureCredential } = require("@azure/identity");
const { KeyClient } = require("@azure/keyvault-keys");

const credential = new DefaultAzureCredential();

const vaultName = "<YOUR KEYVAULT NAME>";
const url = `https://${vaultName}.vault.azure.net`;

const client = new KeyClient(url, credential);

const keyName = "MyKeyName";

async function main() {
  const poller = await client.beginDeleteKey(keyName);
  await poller.pollUntilDone();
}

main();

如果为密钥保管库启用了软删除,此操作将仅将密钥标记为已删除的密钥。 无法更新已删除的密钥。 只能读取、恢复或清除它们。

const { DefaultAzureCredential } = require("@azure/identity");
const { KeyClient } = require("@azure/keyvault-keys");

const credential = new DefaultAzureCredential();

const vaultName = "<YOUR KEYVAULT NAME>";
const url = `https://${vaultName}.vault.azure.net`;

const client = new KeyClient(url, credential);

const keyName = "MyKeyName";

async function main() {
  const poller = await client.beginDeleteKey(keyName);

  // You can use the deleted key immediately:
  const deletedKey = poller.getResult();

  // The key is being deleted. Only wait for it if you want to restore it or purge it.
  await poller.pollUntilDone();

  // You can also get the deleted key this way:
  await client.getDeletedKey(keyName);

  // Deleted keys can also be recovered or purged:

  // recoverDeletedKey also returns a poller, just like beginDeleteKey.
  const recoverPoller = await client.beginRecoverDeletedKey(keyName);
  await recoverPoller.pollUntilDone();

  // And here is how to purge a deleted key
  await client.purgeDeletedKey(keyName);
}

main();

由于密钥需要一些时间才能完全删除,因此返回一个 Poller 对象, beginDeleteKey 该对象根据我们的准则跟踪基础长时间运行操作: https://azure.github.io/azure-sdk/typescript_design.html#ts-lro

接收的轮询器将允许你通过调用 poller.getResult()来获取已删除的密钥。 还可以通过运行单个服务调用,直到密钥被删除,或等到该过程完成,等待删除完成:

const { DefaultAzureCredential } = require("@azure/identity");
const { KeyClient } = require("@azure/keyvault-keys");

const credential = new DefaultAzureCredential();

const vaultName = "<YOUR KEYVAULT NAME>";
const url = `https://${vaultName}.vault.azure.net`;

const client = new KeyClient(url, credential);

const keyName = "MyKeyName";

async function main() {
  const poller = await client.beginDeleteKey(keyName);

  // You can use the deleted key immediately:
  let deletedKey = poller.getResult();

  // Or you can wait until the key finishes being deleted:
  deletedKey = await poller.pollUntilDone();
  console.log(deletedKey);
}

main();

等待密钥完全删除的另一种方法是执行单个调用,如下所示:

const { DefaultAzureCredential } = require("@azure/identity");
const { KeyClient } = require("@azure/keyvault-keys");
const { delay } = require("@azure/core-util");

const credential = new DefaultAzureCredential();

const vaultName = "<YOUR KEYVAULT NAME>";
const url = `https://${vaultName}.vault.azure.net`;

const client = new KeyClient(url, credential);

const keyName = "MyKeyName";

async function main() {
  const poller = await client.beginDeleteKey(keyName);

  while (!poller.isDone()) {
    await poller.poll();
    await delay(5000);
  }

  console.log(`The key ${keyName} is fully deleted`);
}

main();

配置自动密钥轮换

使用 KeyClient,可以通过指定轮换策略为密钥配置自动密钥轮换。 此外,KeyClient 提供了一种通过创建给定密钥的新版本按需轮换密钥的方法。

const { DefaultAzureCredential } = require("@azure/identity");
const { KeyClient } = require("@azure/keyvault-keys");

const url = `https://<YOUR KEYVAULT NAME>.vault.azure.net`;
const client = new KeyClient(url, new DefaultAzureCredential());

async function main() {
  const keyName = "MyKeyName";

  // Set the key's automated rotation policy to rotate the key 30 days before expiry.
  const policy = await client.updateKeyRotationPolicy(keyName, {
    lifetimeActions: [
      {
        action: "Rotate",
        timeBeforeExpiry: "P30D",
      },
    ],
    // You may also specify the duration after which any newly rotated key will expire.
    // In this case, any new key versions will expire after 90 days.
    expiresIn: "P90D",
  });

  // You can get the current key rotation policy of a given key by calling the getKeyRotationPolicy method.
  const currentPolicy = await client.getKeyRotationPolicy(keyName);

  // Finally, you can rotate a key on-demand by creating a new version of the given key.
  const rotatedKey = await client.rotateKey(keyName);
}

main();

迭代键列表

使用 KeyClient,可以检索和循环访问 Azure 密钥保管库中的所有密钥,以及所有已删除的密钥和特定密钥的版本。 以下 API 方法可用:

  • listPropertiesOfKeys 将按名称列出所有未删除的密钥,仅在最新版本中列出。
  • listDeletedKeys 将按名称列出所有已删除密钥,仅在最新版本中列出。
  • listPropertiesOfKeyVersions 将基于密钥名称列出密钥的所有版本。

可按如下方式使用:

const { DefaultAzureCredential } = require("@azure/identity");
const { KeyClient } = require("@azure/keyvault-keys");

const credential = new DefaultAzureCredential();

const vaultName = "<YOUR KEYVAULT NAME>";
const url = `https://${vaultName}.vault.azure.net`;

const client = new KeyClient(url, credential);

const keyName = "MyKeyName";

async function main() {
  for await (let keyProperties of client.listPropertiesOfKeys()) {
    console.log("Key properties: ", keyProperties);
  }
  for await (let deletedKey of client.listDeletedKeys()) {
    console.log("Deleted: ", deletedKey);
  }
  for await (let versionProperties of client.listPropertiesOfKeyVersions(keyName)) {
    console.log("Version properties: ", versionProperties);
  }
}

main();

所有这些方法都将一次性返回 所有可用结果 。 若要按页面检索它们,请在调用要使用的 API 方法后立即添加 .byPage() ,如下所示:

const { DefaultAzureCredential } = require("@azure/identity");
const { KeyClient } = require("@azure/keyvault-keys");

const credential = new DefaultAzureCredential();

const vaultName = "<YOUR KEYVAULT NAME>";
const url = `https://${vaultName}.vault.azure.net`;

const client = new KeyClient(url, credential);

const keyName = "MyKeyName";

async function main() {
  for await (let page of client.listPropertiesOfKeys().byPage()) {
    for (let keyProperties of page) {
      console.log("Key properties: ", keyProperties);
    }
  }
  for await (let page of client.listDeletedKeys().byPage()) {
    for (let deletedKey of page) {
      console.log("Deleted key: ", deletedKey);
    }
  }
  for await (let page of client.listPropertiesOfKeyVersions(keyName).byPage()) {
    for (let versionProperties of page) {
      console.log("Version: ", versionProperties);
    }
  }
}

main();

密码

此库还提供一组通过 CryptographyClient提供的加密实用工具。 与 类似,KeyClientCryptographyClient将使用提供的一组凭据连接到 Azure 密钥保管库。 连接后, CryptographyClient 可以加密、解密、签名、验证、包装密钥和解包密钥。

接下来,我们可以连接到密钥保管库服务, KeyClient就像使用 一样。 我们需要将要连接到的密钥保管库中的一些设置复制到环境变量中。 一旦它们进入我们的环境,我们就可以使用以下代码访问它们:

import { DefaultAzureCredential } from "@azure/identity";
import { KeyClient, CryptographyClient } from "@azure/keyvault-keys";

const credential = new DefaultAzureCredential();

const vaultName = "<YOUR KEYVAULT NAME>";
const url = `https://${vaultName}.vault.azure.net`;

const keysClient = new KeyClient(url, credential);

async function main() {
  // Create or retrieve a key from the keyvault
  let myKey = await keysClient.createKey("MyKey", "RSA");

  // Lastly, create our cryptography client and connect to the service
  const cryptographyClient = new CryptographyClient(myKey, credential);
}

main();

加密

encrypt 将加密消息。

import { DefaultAzureCredential } from "@azure/identity";
import { KeyClient, CryptographyClient } from "@azure/keyvault-keys";

const credential = new DefaultAzureCredential();

const vaultName = "<YOUR KEYVAULT NAME>";
const url = `https://${vaultName}.vault.azure.net`;

const keysClient = new KeyClient(url, credential);

async function main() {
  let myKey = await keysClient.createKey("MyKey", "RSA");
  const cryptographyClient = new CryptographyClient(myKey.id, credential);

  const encryptResult = await cryptographyClient.encrypt({
    algorithm: "RSA1_5",
    plaintext: Buffer.from("My Message"),
  });
  console.log("encrypt result: ", encryptResult.result);
}

main();

解密

decrypt 将解密加密的消息。

import { DefaultAzureCredential } from "@azure/identity";
import { KeyClient, CryptographyClient } from "@azure/keyvault-keys";

const credential = new DefaultAzureCredential();

const vaultName = "<YOUR KEYVAULT NAME>";
const url = `https://${vaultName}.vault.azure.net`;

const keysClient = new KeyClient(url, credential);

async function main() {
  let myKey = await keysClient.createKey("MyKey", "RSA");
  const cryptographyClient = new CryptographyClient(myKey.id, credential);

  const encryptResult = await cryptographyClient.encrypt({
    algorithm: "RSA1_5",
    plaintext: Buffer.from("My Message"),
  });
  console.log("encrypt result: ", encryptResult.result);

  const decryptResult = await cryptographyClient.decrypt({
    algorithm: "RSA1_5",
    ciphertext: encryptResult.result,
  });
  console.log("decrypt result: ", decryptResult.result.toString());
}

main();

签名

sign 将使用签名对消息的摘要 (哈希) 进行加密签名。

import { DefaultAzureCredential } from "@azure/identity";
import { KeyClient, CryptographyClient } from "@azure/keyvault-keys";
import { createHash } from "crypto";

const credential = new DefaultAzureCredential();

const vaultName = "<YOUR KEYVAULT NAME>";
const url = `https://${vaultName}.vault.azure.net`;

const keysClient = new KeyClient(url, credential);

async function main() {
  let myKey = await keysClient.createKey("MyKey", "RSA");
  const cryptographyClient = new CryptographyClient(myKey, credential);

  const signatureValue = "MySignature";
  let hash = createHash("sha256");

  let digest = hash.update(signatureValue).digest();
  console.log("digest: ", digest);

  const signResult = await cryptographyClient.sign("RS256", digest);
  console.log("sign result: ", signResult.result);
}

main();

对数据进行签名

signData 将使用签名对消息进行加密签名。

import { DefaultAzureCredential } from "@azure/identity";
import { KeyClient, CryptographyClient } from "@azure/keyvault-keys";

const credential = new DefaultAzureCredential();

const vaultName = "<YOUR KEYVAULT NAME>";
const url = `https://${vaultName}.vault.azure.net`;

const keysClient = new KeyClient(url, credential);

async function main() {
  let myKey = await keysClient.createKey("MyKey", "RSA");
  const cryptographyClient = new CryptographyClient(myKey, credential);

  const signResult = await cryptographyClient.signData("RS256", Buffer.from("My Message"));
  console.log("sign result: ", signResult.result);
}

main();

验证

verify 将加密验证已签名的摘要是否使用给定的签名进行签名。

import { DefaultAzureCredential } from "@azure/identity";
import { KeyClient, CryptographyClient } from "@azure/keyvault-keys";
import { createHash } from "crypto";

const credential = new DefaultAzureCredential();

const vaultName = "<YOUR KEYVAULT NAME>";
const url = `https://${vaultName}.vault.azure.net`;

const keysClient = new KeyClient(url, credential);

async function main() {
  let myKey = await keysClient.createKey("MyKey", "RSA");
  const cryptographyClient = new CryptographyClient(myKey, credential);

  const hash = createHash("sha256");
  hash.update("My Message");
  const digest = hash.digest();

  const signResult = await cryptographyClient.sign("RS256", digest);
  console.log("sign result: ", signResult.result);

  const verifyResult = await cryptographyClient.verify("RS256", digest, signResult.result);
  console.log("verify result: ", verifyResult.result);
}

main();

验证数据

verifyData 将加密验证已签名消息是否已使用给定签名进行签名。

import { DefaultAzureCredential } from "@azure/identity";
import { KeyClient, CryptographyClient } from "@azure/keyvault-keys";

const credential = new DefaultAzureCredential();

const vaultName = "<YOUR KEYVAULT NAME>";
const url = `https://${vaultName}.vault.azure.net`;

const keysClient = new KeyClient(url, credential);

async function main() {
  let myKey = await keysClient.createKey("MyKey", "RSA");
  const cryptographyClient = new CryptographyClient(myKey, credential);

  const buffer = Buffer.from("My Message");

  const signResult = await cryptographyClient.signData("RS256", buffer);
  console.log("sign result: ", signResult.result);

  const verifyResult = await cryptographyClient.verifyData("RS256", buffer, signResult.result);
  console.log("verify result: ", verifyResult.result);
}

main();

包装键

wrapKey 将使用加密层包装密钥。

import { DefaultAzureCredential } from "@azure/identity";
import { KeyClient, CryptographyClient } from "@azure/keyvault-keys";

const credential = new DefaultAzureCredential();

const vaultName = "<YOUR KEYVAULT NAME>";
const url = `https://${vaultName}.vault.azure.net`;

const keysClient = new KeyClient(url, credential);

async function main() {
  let myKey = await keysClient.createKey("MyKey", "RSA");
  const cryptographyClient = new CryptographyClient(myKey, credential);

  const wrapResult = await cryptographyClient.wrapKey("RSA-OAEP", Buffer.from("My Key"));
  console.log("wrap result:", wrapResult.result);
}

main();

解包密钥

unwrapKey 将解包已包装的密钥。

import { DefaultAzureCredential } from "@azure/identity";
import { KeyClient, CryptographyClient } from "@azure/keyvault-keys";

const credential = new DefaultAzureCredential();

const vaultName = "<YOUR KEYVAULT NAME>";
const url = `https://${vaultName}.vault.azure.net`;

const keysClient = new KeyClient(url, credential);

async function main() {
  let myKey = await keysClient.createKey("MyKey", "RSA");
  const cryptographyClient = new CryptographyClient(myKey, credential);

  const wrapResult = await cryptographyClient.wrapKey("RSA-OAEP", Buffer.from("My Key"));
  console.log("wrap result:", wrapResult.result);

  const unwrapResult = await cryptographyClient.unwrapKey("RSA-OAEP", wrapResult.result);
  console.log("unwrap result: ", unwrapResult.result);
}

main();

故障排除

有关如何诊断各种故障方案的详细信息,请参阅 故障排除指南

启用日志记录可能有助于发现有关故障的有用信息。 若要查看 HTTP 请求和响应的日志,请将 AZURE_LOG_LEVEL 环境变量设置为 info。 或者,可以在运行时通过调用 @azure/logger 中的 setLogLevel 来启用日志记录:

const { setLogLevel } = require("@azure/logger");

setLogLevel("info");

后续步骤

可以通过以下链接找到更多代码示例:

贡献

若要为此库做出贡献,请阅读贡献指南,详细了解如何生成和测试代码。

曝光数