* Polyfills stream support until the Web Crypto API does so: * @see https://github.com/wintercg/proposal-webcrypto-streams
(
algorithm: DigestAlgorithm,
data: BufferSource | AsyncIterable<BufferSource> | Iterable<BufferSource>,
)
| 203 | * @see {@link https://github.com/wintercg/proposal-webcrypto-streams} |
| 204 | */ |
| 205 | async digest( |
| 206 | algorithm: DigestAlgorithm, |
| 207 | data: BufferSource | AsyncIterable<BufferSource> | Iterable<BufferSource>, |
| 208 | ): Promise<ArrayBuffer> { |
| 209 | const { name, length } = normalizeAlgorithm(algorithm); |
| 210 | |
| 211 | assertValidDigestLength(length); |
| 212 | |
| 213 | // We delegate to WebCrypto whenever possible, |
| 214 | if ( |
| 215 | // if the algorithm is supported by the WebCrypto standard, |
| 216 | (WEB_CRYPTO_DIGEST_ALGORITHM_NAMES as readonly string[]).includes( |
| 217 | name, |
| 218 | ) && |
| 219 | // and the data is a single buffer, |
| 220 | isBufferSource(data) |
| 221 | ) { |
| 222 | return await webCrypto.subtle.digest(algorithm, data); |
| 223 | } else if (DIGEST_ALGORITHM_NAMES.includes(name as DigestAlgorithmName)) { |
| 224 | if (isBufferSource(data)) { |
| 225 | // Otherwise, we use our bundled Wasm implementation via digestSync |
| 226 | // if it supports the algorithm. |
| 227 | return stdCrypto.subtle.digestSync(algorithm, data); |
| 228 | } else if (isIterable(data)) { |
| 229 | return stdCrypto.subtle.digestSync( |
| 230 | algorithm, |
| 231 | data as Iterable<BufferSource>, |
| 232 | ); |
| 233 | } else if (isAsyncIterable(data)) { |
| 234 | const context = new DigestContext(name); |
| 235 | for await (const chunk of data as AsyncIterable<BufferSource>) { |
| 236 | const chunkBytes = toUint8Array(chunk); |
| 237 | if (!chunkBytes) { |
| 238 | throw new TypeError( |
| 239 | "Cannot digest the data: A chunk is not ArrayBuffer nor ArrayBufferView", |
| 240 | ); |
| 241 | } |
| 242 | context.update(chunkBytes); |
| 243 | } |
| 244 | return context.digestAndDrop(length).buffer as ArrayBuffer; |
| 245 | } else { |
| 246 | throw new TypeError( |
| 247 | // deno-lint-ignore deno-style-guide/error-message |
| 248 | "data must be a BufferSource or [Async]Iterable<BufferSource>", |
| 249 | ); |
| 250 | } |
| 251 | } |
| 252 | // (TypeScript type definitions prohibit this case.) If they're trying |
| 253 | // to call an algorithm we don't recognize, pass it along to WebCrypto |
| 254 | // in case it's a non-standard algorithm supported by the the runtime |
| 255 | // they're using. |
| 256 | return await webCrypto.subtle.digest(algorithm, data as BufferSource); |
| 257 | }, |
| 258 | |
| 259 | digestSync( |
| 260 | algorithm: DigestAlgorithm, |
no test coverage detected