webcrypto.dart icon indicating copy to clipboard operation
webcrypto.dart copied to clipboard

Null check error in web worker when using `RsaOaepPrivateKey.importPkcs8Key` for RSA decryption

Open chaudharydeepanshu opened this issue 1 year ago • 2 comments

Description

I'm using this package for RSA decryption in both isolates and web workers. While it works fine in isolates, I encounter a null check error when running in a web worker.

Code

This is the function that runs for decryption:

import 'dart:convert';
import 'package:encrypt/encrypt.dart';
import 'package:webcrypto/webcrypto.dart';
import 'package:pem/pem.dart';
import 'package:basic_utils/basic_utils.dart';

Future<String> decryptDEKWeb({
  required String encryptedDek,
  required String rsaPrivateKeyPKCS1,
}) async {
  // Get RSAPrivateKey from the rsaPrivateKeyPKCS1
  final rSAPrivateKey =
  RSAKeyParser().parse(rsaPrivateKeyPKCS1) as RSAPrivateKey;

  // Get PKCS#8 from RSAPrivateKey
  String pkcs8 = CryptoUtils.encodeRSAPrivateKeyToPem(rSAPrivateKey);

  // Decode PKCS#8 key to get key data
  List<int> keyData = PemCodec(PemLabel.privateKey).decode(pkcs8);

  // Import key data as a private key
  final privateKey = await RsaOaepPrivateKey.importPkcs8Key(keyData, Hash.sha1);

  if (encryptedDek.startsWith('encRsa_')) {
    final encryptedData = base64.decode(encryptedDek.substring(7));

    // Decrypt the encrypted data
    final decryptedBytes = await privateKey.decryptBytes(encryptedData);

    return base64.encode(decryptedBytes);
  } else {
    throw ('Invalid encrypted dek');
  }
}

Error

This is the error I get in the web worker:

[   +1 ms] RethrownDartError: Null check operator used on a null value

           dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/errors.dart 329:10  createErrorWithStack
           dart-sdk/lib/_internal/js_dev_runtime/patch/core_patch.dart 265:28            _throw
           dart-sdk/lib/core/errors.dart 120:5                                           throwWithStackTrace
           dart-sdk/lib/async/zone.dart 1386:11                                          callback
           dart-sdk/lib/async/schedule_microtask.dart 40:11                              _microtaskLoop
           dart-sdk/lib/async/schedule_microtask.dart 49:5                               _startMicrotaskLoop
           dart-sdk/lib/_internal/js_dev_runtime/patch/async_patch.dart 181:7            <fn>

From what I can tell, the error is being thrown on this line:

final privateKey = await RsaOaepPrivateKey.importPkcs8Key(keyData, Hash.sha1);

Environment

  • The code runs fine in isolates, but throws this error when used in a web worker.
  • The web worker code is generated using isolate_manager with the following command:
    dart run isolate_manager:generate
    

Steps to Reproduce

  1. Run the provided decryptDEKWeb function inside a web worker environment.
  2. Observe the null check error when calling RsaOaepPrivateKey.importPkcs8Key.

Expected Behavior

The function should successfully import the private key and decrypt the data, as it does in an isolate.

Additional Information

  • The keyData passed to importPkcs8Key is valid, as confirmed by logging it before the function call.
  • This issue seems specific to web workers, as the same code works without issues outside of web worker.

Let me know if any further details are required for debugging.

chaudharydeepanshu avatar Sep 06 '24 07:09 chaudharydeepanshu

Please provide a gist with all the code your running.

A script that shows how to compile it.

And how to open it in a browser AND what browser!


Do not that WebCrypto only works in https://, so if you're opening it as a file or opening it on localhost it shouldn't work.

image

image

I've occasionally done such setups locally with ngrok, come to think of it I'm actually surprised our integration tests work in all browsers -- I think those just load from localhost, but maybe package:test does some magic :rofl:

jonasfj avatar Sep 06 '24 08:09 jonasfj

Please provide a gist with all the code your running.

A script that shows how to compile it.

And how to open it in a browser AND what browser!

I'll soon add a small example app to recreate the issue.

Do not that WebCrypto only works in https://

Btw, this secure content requirement is weird because I was running the app on localhost without using a web worker and it worked fine. Does the secure content requirement only apply when I run it inside web workers?

Thanks for the response!

chaudharydeepanshu avatar Sep 06 '24 09:09 chaudharydeepanshu

Does the secure content requirement only apply when I run it inside web workers?

Don't know this might differ from browser to browser, and can probably be disabled when starting the browser.

If you're interested in documenting when this works, we're happy to take a PR another bullet point to the compatibility notes in the README.

Otherwise, I think we consider this outside the scope of this package. We offer what the browser offers.

Filed https://github.com/google/webcrypto.dart/issues/159

jonasfj avatar Oct 11 '24 11:10 jonasfj