SubtleCrypto.sign()

安全上下文: 此项功能仅在一些支持的浏览器安全上下文(HTTPS)中可用。

SubtleCrypto 接口的 sign() 方法用于生成数字签名

它以签名密钥、一些特定于算法的参数和待签名的数据作为参数,返回一个 Promise,会兑现数据的签名。

你可以使用对应的 SubtleCrypto.verify() 方法来验证签名。

语法

js
sign(algorithm, key, data)

参数

algorithm

一个字符串或指定了算法和要使用的参数的对象:

key

一个包含了用于签名的密钥的 CryptoKey 对象。 如果 algorithm 标识了公开密钥加密算法,则它是一个私钥。

data

一个包含待签名数据的 ArrayBufferTypedArrayDataView 对象。

返回值

一个 Promise,会兑现包含数据签名的 ArrayBuffer 对象。

异常

当遇到以下异常时,promise 将会被拒绝:

InvalidAccessError DOMException

当签名密钥不是要求的签名算法的密钥,或尝试使用未知或不适用于签名的算法时触发。

支持的算法

Web Crypto API 提供了 4 种可用于签名和签名验证的算法。

其中的三种算法(RSASSA-PKCS1-v1_5、RSA-PSS 和 ECDSA)是公开密钥加密算法 (en-US),它们使用私钥进行签名,使用公钥验证签名。所有的算法均使用摘要算法在签名前将消息计算为短的、固定大小的散列值。除了 ECDSA(是将摘要算法传递给 algorithm 对象),其他算法均是通过将参数传递给 generateKey()importKey() 函数来选择摘要算法的。

第四种算法(HMAC)使用相同的算法、密钥来签名和验证签名:这意味着签名验证的密钥必须保密,换句话说,该算法不适用与很多签名的场景。但是,当签名者和验证签名者是同一个实体时,这也是一个不错的选择。

RSASSA-PKCS1-v1_5

RSASSA-PKCS1-v1_5 算法在 RFC 3447 中定义。

RSA-PSS

RSA-PSS 算法在 RFC 3447 中定义。

它与 RSASSA-PKCS1-v1_5 算法的不同之处在于:它在签名运算中使用了加盐操作,因此使用相同密钥对相同的消息进行签名会产生不同的结果。其使用一个额外的属性来定义盐的长度,需要在调用时传递给 sign()verify() 函数。

ECDSA

ECDSA(椭圆曲线数字签名算法)是 FIPS-186 中定义的数字签名算法的一种变体,它使用了椭圆曲线密码学(Elliptic Curve Cryptography,RFC 6090)。

签名被编码为 RFC 6090 中指定的 s1s2 值(在 RFC 4754 中分别被称为 rs)。两个值都是大端字节数组,长度为曲线的位数,向上取整为整数个字节。这些值按顺序连接在一起。

这种编码也被 IEEE 1363-2000 标准所提出,因此有时也被称为 IEEE P1363 格式。它不同于 X.509 签名结构,后者是一些工具和库(例如 OpenSSL)默认生成的格式。

HMAC

HMAC 算法根据 FIPS 198-1 标准 计算和验证基于散列的消息认证码。

需要在传入 generateKey()HmacKeyGenParams (en-US) 对象或传入 importKey()HmacImportParams (en-US) 对象中指定要使用的散列算法。

示例

备注: 你可以在 Github 上尝试可用的示例

RSASSA-PKCS1-v1_5

以下代码从文本框获取内容,将其编码,并使用私钥对其进行签名。在 GitHub 上查看完整代码。

js
/*
从“message”文本框获取内容,并将其编码为
我们可用于签名运算的形式。
*/
function getMessageEncoding() {
  const messageBox = document.querySelector(".rsassa-pkcs1 #message");
  let message = messageBox.value;
  let enc = new TextEncoder();
  return enc.encode(message);
}

let encoded = getMessageEncoding();
let signature = await window.crypto.subtle.sign(
  "RSASSA-PKCS1-v1_5",
  privateKey,
  encoded,
);

RSA-PSS

以下代码获取文本框的内容,将其编码,并使用私钥对其进行签名。在 GitHub 上查看完整代码。

js
/*
从“message”文本框获取内容,并将其编码为
我们可用于签名运算的形式。
*/
function getMessageEncoding() {
  const messageBox = document.querySelector(".rsa-pss #message");
  let message = messageBox.value;
  let enc = new TextEncoder();
  return enc.encode(message);
}

let encoded = getMessageEncoding();
let signature = await window.crypto.subtle.sign(
  {
    name: "RSA-PSS",
    saltLength: 32,
  },
  privateKey,
  encoded,
);

ECDSA

以下代码获取文本框的内容,将其编码,并使用私钥对其进行签名。在 GitHub 上查看完整代码。

js
/*
从“message”文本框获取内容,并将其编码为
我们可用于签名运算的形式。
*/
function getMessageEncoding() {
  const messageBox = document.querySelector(".ecdsa #message");
  let message = messageBox.value;
  let enc = new TextEncoder();
  return enc.encode(message);
}

let encoded = getMessageEncoding();
let signature = await window.crypto.subtle.sign(
  {
    name: "ECDSA",
    hash: { name: "SHA-384" },
  },
  privateKey,
  encoded,
);

HMAC

以下代码获取文本框的内容,将其编码,并使用密钥对其进行签名。在 GitHub 上查看完整代码。

js
/*
从“message”文本框获取内容,并将其编码为
我们可用于签名运算的形式。
*/
function getMessageEncoding() {
  const messageBox = document.querySelector(".hmac #message");
  let message = messageBox.value;
  let enc = new TextEncoder();
  return enc.encode(message);
}

let encoded = getMessageEncoding();
let signature = await window.crypto.subtle.sign("HMAC", key, encoded);

规范

Specification
Web Cryptography API
# SubtleCrypto-method-sign

浏览器兼容性

BCD tables only load in the browser

参见