Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/dotnet/runtime.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Erhardt <eric.erhardt@microsoft.com>2022-07-09 05:51:14 +0300
committerGitHub <noreply@github.com>2022-07-09 05:51:14 +0300
commit8f75cc9306b0508506f60a94f94d2227ee020798 (patch)
tree484732c7536978082c09b2a2d8e04acf1d850b30 /src/mono/wasm/runtime
parent4a38ac3c3f2155218e01336f0fdeefffdece65ef (diff)
Enable Rfc2898DeriveBytes on Browser WASM (#71768)
* Enable Rfc2898DeriveBytes on Browser WASM Marks the APIs as supported on Browser, and enables Rfc2898 tests on Browser WASM. Use SubtleCrypto deriveBits API to implement one shot Pbkdf2. * Mark HKDF as supported on Browser and enable tests Contributes to #40074
Diffstat (limited to 'src/mono/wasm/runtime')
-rw-r--r--src/mono/wasm/runtime/cjs/dotnet.cjs.lib.js1
-rw-r--r--src/mono/wasm/runtime/crypto-worker.ts59
-rw-r--r--src/mono/wasm/runtime/es6/dotnet.es6.lib.js1
-rw-r--r--src/mono/wasm/runtime/exports.ts4
-rw-r--r--src/mono/wasm/runtime/workers/dotnet-crypto-worker.js25
5 files changed, 61 insertions, 29 deletions
diff --git a/src/mono/wasm/runtime/cjs/dotnet.cjs.lib.js b/src/mono/wasm/runtime/cjs/dotnet.cjs.lib.js
index cd78c6a2240..ce03a29be03 100644
--- a/src/mono/wasm/runtime/cjs/dotnet.cjs.lib.js
+++ b/src/mono/wasm/runtime/cjs/dotnet.cjs.lib.js
@@ -91,6 +91,7 @@ const linked_functions = [
"dotnet_browser_simple_digest_hash",
"dotnet_browser_sign",
"dotnet_browser_encrypt_decrypt",
+ "dotnet_browser_derive_bits",
/// mono-threads-wasm.c
#if USE_PTHREADS
diff --git a/src/mono/wasm/runtime/crypto-worker.ts b/src/mono/wasm/runtime/crypto-worker.ts
index d27e185ac63..c270bc924b1 100644
--- a/src/mono/wasm/runtime/crypto-worker.ts
+++ b/src/mono/wasm/runtime/crypto-worker.ts
@@ -27,18 +27,7 @@ export function dotnet_browser_simple_digest_hash(ver: number, input_buffer: num
data: Array.from(Module.HEAPU8.subarray(input_buffer, input_buffer + input_len))
};
- const result = _send_msg_worker(msg);
- if (typeof result === "number") {
- return result;
- }
-
- if (result.length > output_len) {
- console.error("DIGEST HASH: Digest length exceeds output length: " + result.length + " > " + output_len);
- return ERR_ARGS;
- }
-
- Module.HEAPU8.set(result, output_buffer);
- return 0;
+ return _send_simple_msg(msg, "DIGEST HASH", output_buffer, output_len);
}
export function dotnet_browser_sign(hashAlgorithm: number, key_buffer: number, key_len: number, input_buffer: number, input_len: number, output_buffer: number, output_len: number): number {
@@ -49,18 +38,7 @@ export function dotnet_browser_sign(hashAlgorithm: number, key_buffer: number, k
data: Array.from(Module.HEAPU8.subarray(input_buffer, input_buffer + input_len))
};
- const result = _send_msg_worker(msg);
- if (typeof result === "number") {
- return result;
- }
-
- if (result.length > output_len) {
- console.error("SIGN HASH: Sign length exceeds output length: " + result.length + " > " + output_len);
- return ERR_ARGS;
- }
-
- Module.HEAPU8.set(result, output_buffer);
- return 0;
+ return _send_simple_msg(msg, "SIGN HASH", output_buffer, output_len);
}
const AesBlockSizeBytes = 16; // 128 bits
@@ -84,7 +62,7 @@ export function dotnet_browser_encrypt_decrypt(isEncrypting: boolean, key_buffer
}
if (result.length > output_len) {
- console.error("ENCRYPT DECRYPT: Encrypt/Decrypt length exceeds output length: " + result.length + " > " + output_len);
+ console.error(`ENCRYPT DECRYPT: Encrypt/Decrypt length exceeds output length: ${result.length} > ${output_len}`);
return ERR_ARGS;
}
@@ -92,6 +70,35 @@ export function dotnet_browser_encrypt_decrypt(isEncrypting: boolean, key_buffer
return result.length;
}
+export function dotnet_browser_derive_bits(password_buffer: number, password_len: number, salt_buffer: number, salt_len: number, iterations: number, hashAlgorithm: number, output_buffer: number, output_len: number): number {
+ const msg = {
+ func: "derive_bits",
+ password: Array.from(Module.HEAPU8.subarray(password_buffer, password_buffer + password_len)),
+ salt: Array.from(Module.HEAPU8.subarray(salt_buffer, salt_buffer + salt_len)),
+ iterations: iterations,
+ hashAlgorithm: hashAlgorithm,
+ lengthInBytes: output_len
+ };
+
+ return _send_simple_msg(msg, "DERIVE BITS", output_buffer, output_len);
+}
+
+function _send_simple_msg(msg: any, prefix: string, output_buffer: number, output_len: number): number {
+ const result = _send_msg_worker(msg);
+
+ if (typeof result === "number") {
+ return result;
+ }
+
+ if (result.length > output_len) {
+ console.error(`${prefix}: Result length exceeds output length: ${result.length} > ${output_len}`);
+ return ERR_ARGS;
+ }
+
+ Module.HEAPU8.set(result, output_buffer);
+ return 0;
+}
+
export function init_crypto(): void {
if (typeof globalThis.crypto !== "undefined" && typeof globalThis.crypto.subtle !== "undefined"
&& typeof SharedArrayBuffer !== "undefined"
@@ -117,7 +124,7 @@ export function init_crypto(): void {
}
}
-function _send_msg_worker(msg: any): any {
+function _send_msg_worker(msg: any): number | any {
mono_assert(!!mono_wasm_crypto, "subtle crypto not initialized");
try {
diff --git a/src/mono/wasm/runtime/es6/dotnet.es6.lib.js b/src/mono/wasm/runtime/es6/dotnet.es6.lib.js
index a559c8f42de..5d3d5d3ecb3 100644
--- a/src/mono/wasm/runtime/es6/dotnet.es6.lib.js
+++ b/src/mono/wasm/runtime/es6/dotnet.es6.lib.js
@@ -128,6 +128,7 @@ const linked_functions = [
"dotnet_browser_simple_digest_hash",
"dotnet_browser_sign",
"dotnet_browser_encrypt_decrypt",
+ "dotnet_browser_derive_bits",
/// mono-threads-wasm.c
#if USE_PTHREADS
diff --git a/src/mono/wasm/runtime/exports.ts b/src/mono/wasm/runtime/exports.ts
index 436e0ba347a..22e1fdf340e 100644
--- a/src/mono/wasm/runtime/exports.ts
+++ b/src/mono/wasm/runtime/exports.ts
@@ -72,7 +72,8 @@ import {
dotnet_browser_can_use_subtle_crypto_impl,
dotnet_browser_simple_digest_hash,
dotnet_browser_sign,
- dotnet_browser_encrypt_decrypt
+ dotnet_browser_encrypt_decrypt,
+ dotnet_browser_derive_bits,
} from "./crypto-worker";
import { mono_wasm_cancel_promise_ref } from "./cancelable-promise";
import { mono_wasm_web_socket_open_ref, mono_wasm_web_socket_send, mono_wasm_web_socket_receive, mono_wasm_web_socket_close_ref, mono_wasm_web_socket_abort } from "./web-socket";
@@ -408,6 +409,7 @@ export const __linker_exports: any = {
dotnet_browser_simple_digest_hash,
dotnet_browser_sign,
dotnet_browser_encrypt_decrypt,
+ dotnet_browser_derive_bits,
// threading exports, if threading is enabled
...mono_wasm_threads_exports,
diff --git a/src/mono/wasm/runtime/workers/dotnet-crypto-worker.js b/src/mono/wasm/runtime/workers/dotnet-crypto-worker.js
index 5fa89790c22..f93256c169a 100644
--- a/src/mono/wasm/runtime/workers/dotnet-crypto-worker.js
+++ b/src/mono/wasm/runtime/workers/dotnet-crypto-worker.js
@@ -256,6 +256,24 @@ async function sign(type, key, data) {
return Array.from(new Uint8Array(signResult));
}
+async function derive_bits(password, salt, iterations, hashAlgorithm, lengthInBytes) {
+ const hash_name = get_hash_name(hashAlgorithm);
+
+ const passwordKey = await importKey(password, "PBKDF2", ["deriveBits"]);
+ const result = await crypto.subtle.deriveBits(
+ {
+ name: "PBKDF2",
+ salt: salt,
+ iterations: iterations,
+ hash: hash_name
+ },
+ passwordKey,
+ lengthInBytes * 8 // deriveBits takes number of bits
+ );
+
+ return Array.from(new Uint8Array(result));
+}
+
function get_hash_name(type) {
switch (type) {
case 0: return "SHA-1";
@@ -272,7 +290,7 @@ const AesBlockSizeBytes = 16; // 128 bits
async function encrypt_decrypt(isEncrypting, key, iv, data) {
const algorithmName = "AES-CBC";
const keyUsage = isEncrypting ? ["encrypt"] : ["encrypt", "decrypt"];
- const cryptoKey = await importKey(key, algorithmName, keyUsage);
+ const cryptoKey = await importKey(new Uint8Array(key), algorithmName, keyUsage);
const algorithm = {
name: algorithmName,
iv: new Uint8Array(iv)
@@ -328,7 +346,7 @@ async function decrypt(algorithm, cryptoKey, data) {
function importKey(key, algorithmName, keyUsage) {
return crypto.subtle.importKey(
"raw",
- new Uint8Array(key),
+ key,
{
name: algorithmName
},
@@ -349,6 +367,9 @@ async function handle_req_async(msg) {
else if (req.func === "encrypt_decrypt") {
return await encrypt_decrypt(req.isEncrypting, req.key, req.iv, req.data);
}
+ else if (req.func === "derive_bits") {
+ return await derive_bits(new Uint8Array(req.password), new Uint8Array(req.salt), req.iterations, req.hashAlgorithm, req.lengthInBytes);
+ }
else {
throw new ArgumentsError("CRYPTO: Unknown request: " + req.func);
}