dart-lang / sdk

The Dart SDK, including the VM, JS and Wasm compilers, analysis, core libraries, and more.
https://dart.dev
BSD 3-Clause "New" or "Revised" License
10.09k stars 1.56k forks source link

Expose dart:html Crypto.subtle with an actual class with actual methods #42144

Open edyu opened 4 years ago

edyu commented 4 years ago

Currently, Crypto.subtle is a variable that's completely useless. It doesn't expose a usable interface to be able to call any methods that the web cryptography api exposes. There is simply no methods to be usable at all. In fact, I don't even know why is Crypto.subtle (the exposed class is _SubtleCrypto with no methods) exposed at all.

sigmundch commented 4 years ago

Thanks for your request. While we figure out the right thing to do here, you can workaround this limitation by using JS-interop in a special way. You can't use js-interop declaring types for Crypto and SubtleCrypto because they will collide with what dart:html definitions, but you can access them using js_util methods. For instance:

import 'dart:js_util' as js_util;

...

// Yes, here subtle has the _StubleCrypto class with no methods
dynamic subtle = window.crypto.subtle; 

// But you can invoke methods that you know are supported in JavaScript via js_util:
js_util.callMethod(subtle, "encrypt", []);

Let us know if this unblocks you.

edyu commented 4 years ago

@sigmundch I assume I can still declare other types such as the types needed in order to make these calls? For example, HmacKeyGenParams class is needed in order to call subtle.generateKey.

edyu commented 4 years ago

Let me give an example rationale. I currently need to do 2 cryptographic functions on my front-end (angulardart): 1. generate a symmetric key for keyed hashing and rsa asymmetric keys. 2. calculate keyed hashes using the symmetric key generated earlier. I originally used the library pointycastle which would take about 3 minutes to generate the rsa keypair. I then came upon the cryptography library which reduced that to seconds by using web crypto api (I had to patch a couple of things but that's minor). However, I then encountered #42194 .

@sigmundch I believe ideally I would like 'dart:crypto' to be fully implemented and automatically use web crypto under the hood in a browser setting. That would be the best user experience (developer experience). Thank you and I actually don't even mind helping as I'm enjoying dart experience so far (and I'm surprised I actually enjoy angulardart as well except it desperately need another new release)

edyu commented 4 years ago

@sigmundch how do I cast the return type of callMethod to what I need? for example,

jsCryptoKey = await js_util.promiseToFuture<CryptoKey>(js.callMethod(subtle, 'importKey', [...]));

doesn't work as I get the following error:

Uncaught (in promise) TypeError: Instance of 'CryptoKey': type 'Interceptor' is not a subtype of type 'FutureOr'
    at Object.wrapException (js_helper.dart:1343)
    at Rti._generalAsCheckImplementation [as _as] (rti.dart:915)
    at promiseToFuture_closure.call$1 (js_util.dart:157)
    at invokeClosure (js_helper.dart:2018)
    at js_helper.dart:2050