--- title: SubtleCrypto slug: Web/API/SubtleCrypto tags: - 加密 translation_of: Web/API/SubtleCrypto --- <p>{{APIRef("Web Crypto API")}}</p> <p>基于<a href="https://developer.mozilla.org/en-US/docs/Web/API/Web_Crypto_API">Web Crypto API</a>的<strong>SubtleCrypto</strong> 接口提供了许多底层加密功能。它通过窗口上下文提供可用的{{domxref("Crypto.subtle")}} 属性来访问(通过{{domxref("Window.crypto")}})。</p> <div class="warning"> <p>注意: 此API提供了许多底层加密源语。滥用他们很容易陷入微妙的陷阱中。</p> <p>即使你正确的使用基础加密方法,也很难设计一套正确的安全密钥管理及整体安全设计方案,这些往往是安全专家的领域。</p> <p>错误的安全系统设计和实现会使系统的安全性完全失效</p> <p><strong>如果你不知道此API能为你提供什么,则不应该使用该API</strong></p> </div> <h2 id="概览">概览</h2> <p>我们可以将此API的功能分为两类:加密功能和密钥管理功能。</p> <h3 id="加密功能">加密功能</h3> <p>这些函数你可以用来实现系统中的隐私和身份验证等安全功能。<strong>SubtleCrypto </strong>API提供了如下加密函数:</p> <p>* <code><a href="https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/sign">sign()</a></code> 、 <code><a href="https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/verify">verify()</a></code>: 创建和验证数字签名。<br> * <code><a href="https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/encrypt">encrypt()</a></code> 和 <code><a href="https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/decrypt">decrypt()</a></code>: 加密和解密数据。<br> * <code><a href="https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/digest">digest()</a></code>:为数据生成一个定长的,防碰撞的消息摘要。</p> <h3 id="密钥管理功能">密钥管理功能</h3> <p>除了 <code>digest()</code>,在<strong>SubtleCrypto </strong>API中所有加密功能都会使用密钥,并使用CryptoKey对象表示加密密钥。要执行签名和加密操作, 请将 <code>CryptoKey</code> 对象传参给 <code>sign()</code> 或 <code>encrypt()</code> 函数.</p> <h4 id="生成和派生密钥"><strong>生成和派生密钥</strong></h4> <p><code><a href="https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/generateKey">generateKey()</a></code> 和 <code><a href="https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/deriveKey">deriveKey()</a></code> 函数都可以创建一个新的 <code><a href="https://developer.mozilla.org/en-US/docs/Web/API/CryptoKey">CryptoKey</a></code> 对象。</p> <p>不同之处在于 <code>generateKey()</code> 每次都会生成一个新的键值对, 而 <code>deriveKey()</code> 通过从基础密钥资源中生成一个新的密钥。如果为两个独立的<code>deriveKey()</code>提供相同的基础密钥资源,那么你会获得两个具有相同基础值的 <code>CryptoKey</code> 对象。如果你想通过密码派生加密密钥,然后从相同的密码派生相同的密钥以解密数据,那么这将会非常有用。</p> <h4 id="导入和导出密钥">导入和导出密钥</h4> <p>要在应用程序外部使密钥可用,您需要导出密钥,<code><a href="https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/exportKey">exportKey()</a> </code>可以为你提供该功能。你可以选择多种导出格式。</p> <p><code><a href="https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/importKey">importKey()</a></code>与 <code>exportKey()</code> 刚好相反。你可以从其他系统导入密钥,并且支持像 <a href="https://tools.ietf.org/html/rfc5208">PKCS #8</a> 和 <a href="https://tools.ietf.org/html/rfc7517">JSON Web Key</a> 这样可以帮助你执行此操作的标准格式。<code>exportKey()</code> 函数以非标准格式导出密钥。</p> <p>如果密钥是敏感的,你需要使用 <code><a href="https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/wrapKey">wrapKey()</a></code>, 该函数导出密钥并且使用另外一个密钥加密它。</p> <p><code><a href="https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/unwrapKey">unwrapKey()</a><font face="Arial, x-locale-body, sans-serif"><span style="background-color: #ffffff;">与</span></font></code><code>wrapKey()</code>相反,该函数解密密钥后导入解密的密钥</p> <h4 id="存储密钥">存储密钥</h4> <p><code>CryptoKey</code>对象可以通过 <code><a href="https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm">structured clone algorithm</a></code>来存储,这意味着你可以通过web storage APIs来存储和获取他们。更为规范的方式是通过使用<code><a href="https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API">IndexedDB API</a></code> 来存储<code>CryptoKey</code>对象。</p> <h3 id="支持的算法">支持的算法</h3> <p><code>Web Crypto API</code>提供的加密函数可以由一个或多个不同的加密算法执行:</p> <p>函数可以通过参数来指定使用的算法。一些算法需要额外的参数,在这些情况下通过将算法参数作为对象字典传入额外的参数中实现。</p> <p>下表总结了哪些算法适用于哪些加密操作:</p> <table> <thead> <tr> <th scope="row"> </th> <th scope="col"> <p><a href="https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/sign">sign()</a></p> <p><a href="https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/verify">verify()</a></p> </th> <th scope="col"> <p><a href="https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/encrypt">encrypt()</a></p> <p><a href="https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/decrypt">decrypt()</a></p> </th> <th scope="col"><a href="https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/digest">digest()</a></th> <th scope="col"> <p><a href="https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/deriveBits">deriveBits()</a></p> <p><a href="https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/deriveKey">deriveKey()</a></p> </th> <th scope="col"> <p><a href="https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/wrapKey">wrapKey()</a></p> <p><a href="https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/unwrapKey">unwrapKey()</a></p> </th> </tr> </thead> <tbody> <tr> <th scope="row">RSASSA-PKCS1-v1_5</th> <td>✓</td> <td> </td> <td> </td> <td> </td> <td> </td> </tr> <tr> <th scope="row">RSA-PSS</th> <td>✓</td> <td> </td> <td> </td> <td> </td> <td> </td> </tr> <tr> <th scope="row">ECDSA</th> <td>✓</td> <td> </td> <td> </td> <td> </td> <td> </td> </tr> <tr> <th scope="row">HMAC</th> <td>✓</td> <td> </td> <td> </td> <td> </td> <td> </td> </tr> <tr> <th scope="row">RSA-OAEP</th> <td> </td> <td>✓</td> <td> </td> <td> </td> <td>✓</td> </tr> <tr> <th scope="row">AES-CTR</th> <td> </td> <td>✓</td> <td> </td> <td> </td> <td>✓</td> </tr> <tr> <th scope="row">AES-CBC</th> <td> </td> <td>✓</td> <td> </td> <td> </td> <td>✓</td> </tr> <tr> <th scope="row">AES-GCM</th> <td> </td> <td>✓</td> <td> </td> <td> </td> <td>✓</td> </tr> <tr> <th scope="row">SHA-1</th> <td> </td> <td> </td> <td>✓</td> <td> </td> <td> </td> </tr> <tr> <th scope="row">SHA-256</th> <td> </td> <td> </td> <td>✓</td> <td> </td> <td> </td> </tr> <tr> <th scope="row">SHA-384</th> <td> </td> <td> </td> <td>✓</td> <td> </td> <td> </td> </tr> <tr> <th scope="row">SHA-512</th> <td> </td> <td> </td> <td>✓</td> <td> </td> <td> </td> </tr> <tr> <th scope="row">ECDH</th> <td> </td> <td> </td> <td> </td> <td>✓</td> <td> </td> </tr> <tr> <th scope="row">HKDF</th> <td> </td> <td> </td> <td> </td> <td>✓</td> <td> </td> </tr> <tr> <th scope="row">PBKDF2</th> <td> </td> <td> </td> <td> </td> <td>✓</td> <td> </td> </tr> <tr> <th scope="row">AES-KW</th> <td> </td> <td> </td> <td> </td> <td> </td> <td>✓</td> </tr> </tbody> </table> <h2 id="属性">属性</h2> <p><em>此接口既不继承也不实现任何属性。</em></p> <h2 id="方法">方法</h2> <p><em>此接口不继承任何方法。</em></p> <dl> <dt>{{domxref("SubtleCrypto.encrypt()")}}</dt> <dd>以算法、密钥、明文为参数,返回一个包含加密数据的 {{jsxref("Promise")}} 对象。</dd> <dt>{{domxref("SubtleCrypto.decrypt()")}}</dt> <dd>以算法、密钥、密文为参数,返回一个包含解密数据的 {{jsxref("Promise")}} 对象。</dd> <dt>{{domxref("SubtleCrypto.sign()")}}</dt> <dd>以文本、算法和密码为参数,返回一个包含签名的 {{jsxref("Promise")}}。</dd> <dt>{{domxref("SubtleCrypto.verify()")}}</dt> <dd>以签名、与之匹配的文本、算法、密码为参数,验证签名的真实性,返回一个包含布尔型的 {jsxref("Promise")}} 对象。</dd> <dt>{{domxref("SubtleCrypto.digest()")}}</dt> <dd>以生成摘要的算法和文本作为参数,返回一个包含数据摘要的 {{jsxref("Promise")}} 对象。</dd> <dt>{{domxref("SubtleCrypto.generateKey()")}}</dt> <dd>以给出的用法和返可提取性作为参数,返回一个包含用于对称算法的新生成的 {{domxref("CryptoKey")}} 或者包含两个新的生成的密钥用于非对称加密的 {{domxref("CryptoKeyPair")}} 的 {{jsxref("Promise")}} 对象。</dd> <dt>{{domxref("SubtleCrypto.deriveKey()")}}</dt> <dd>以从 master key 派生出来的密钥和特定的算法作为参数,返回一个包含新生成的 {{domxref("CryptoKey")}} 的 {{jsxref("Promise")}}对象。</dd> <dt>{{domxref("SubtleCrypto.deriveBits()")}}</dt> <dd>以从 master key 派生出来的密钥和特定的算法作为参数,返回一个包含新生成的伪随机字节的 Buffer的 {{jsxref("Promise")}} 对象。</dd> <dt>{{domxref("SubtleCrypto.importKey()")}}</dt> <dd>以格式、算法、原始密钥数据、用途和可提取性作为参数,返回一个包含 {{domxref("CryptoKey")}} 的 {{jsxref("Promise")}} 对象。</dd> <dt>{{domxref("SubtleCrypto.exportKey()")}}</dt> <dd>返回一个包含所请求格式的密钥的 Buffer 的 {{jsxref("Promise")}} 对象。</dd> <dt>{{domxref("SubtleCrypto.wrapKey()")}}</dt> <dd>返回一个包含在不安全环境中使用(传输,存储)的包裹对称密钥的 {{jsxref("Promise")}} 对象。返回的被包裹的缓冲数据是按照参数中给出的格式的,包含使用给定算法的给予包装密钥包裹的密钥。</dd> <dt>{{domxref("SubtleCrypto.unwrapKey()")}}</dt> <dd>返回一个包含对应于参数中给出的包裹密钥的 {{domxref("CryptoKey")}} 的 {{jsxref("Promise")}} 对象。</dd> </dl> <h2 id="规范">规范</h2> <table class="standard-table"> <tbody> <tr> <th scope="col">Specification</th> <th scope="col">Status</th> <th scope="col">Comment</th> </tr> <tr> <td>{{ SpecName('Web Crypto API', '#subtlecrypto-interface', 'SubtleCrypto') }}</td> <td>{{ Spec2('Web Crypto API') }}</td> <td>Initial definition.</td> </tr> </tbody> </table> <h2 id="浏览器支持">浏览器支持</h2> {{Compat("api.SubtleCrypto")}} <h2 id="另见">另见</h2> <ul> <li>{{domxref("Crypto")}} 和 {{domxref("Crypto.subtle")}}.</li> <li><a href="https://www.crypto101.io/">Crypto 101</a>: an introductory course on cryptography.</li> </ul>