Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

webapp: Encryption fails in Chrome #29

Open
str4d opened this issue Mar 21, 2021 · 5 comments
Open

webapp: Encryption fails in Chrome #29

str4d opened this issue Mar 21, 2021 · 5 comments

Comments

@str4d
Copy link
Owner

str4d commented Mar 21, 2021

Environment

  • OS: Windows 10
  • Browser version: Chrome 89.0.4389.90
  • wage version: fce4b8b

What were you trying to do

I generated a new identity, and then tried to encrypt a file to it.

What happened

App.vue:250 Uncaught (in promise) TypeError: Failed to execute 'pipeTo' on 'ReadableStream': parameter 1 is not of type 'WritableStream'.
    at o.encryptSingleFile (App.vue:250)
    at App.vue:231
  encryptSingleFile @ App.vue:250
  (anonymous) @ App.vue:231
  Promise.then (async)    
  encryptSingleFile @ App.vue:250
  (anonymous) @ App.vue:231
  Promise.then (async)    
  (anonymous) @ App.vue:229
  prepareEncryptStream @ App.vue:221
  encryptToRecipients @ App.vue:225
@fyears
Copy link

fyears commented Nov 11, 2021

Hi. Same issue here in passphrase mode in Chrome. But (strangely) the page works in Firefox...

@str4d
Copy link
Owner Author

str4d commented Nov 21, 2022

I am now seeing the same exception in Firefox 107 on macOS 13.0.1 with 5de7b79:

Uncaught (in promise) TypeError: ReadableStream.pipeTo: Argument 1 does not implement interface WritableStream.
    encryptSingleFile App.vue:250
    encryptWithPassphrase App.vue:241
    promise callback*encryptWithPassphrase/< App.vue:239
    prepareEncryptStream App.vue:221
    encryptWithPassphrase App.vue:236
    VueJS 4
    encryptFile EncryptPane.vue:232
    VueJS 33

@MattiasBuelens
Copy link

MattiasBuelens commented Nov 22, 2022

I think the problem is that you're using native streams and polyfilled streams interchangeably. And unfortunately, web-streams-polyfill doesn't support this... 😞

Consider the following snippet:

wage/www/src/App.vue

Lines 245 to 251 in 1a64717

encryptSingleFile() {
let fileStream = this.dropFiles[0].stream();
// Use the more optimized ReadableStream.pipeTo if available.
if (window.WritableStream && fileStream.pipeTo) {
return fileStream.pipeTo(this.downloadStream).then(this.reset);
}

this.dropFiles[0] is a native File, so this.dropFiles[0].stream() is a native ReadableStream. However, by loading the polyfill, window.WritableStream is replaced by the polyfill's version, so the constructed this.downloadStream is a polyfilled WritableStream. The native ReadableStream.pipeTo() only works with native WritableStream destinations, so that's why that call throws.

One solution would be to manually convert all your native streams to polyfilled ones before usage. I made a small library to help with that. You add a bit of initialization code:

import { createReadableStreamWrapper, createWritableStreamWrapper } from '@mattiasbuelens/web-streams-adapter';
const toPolyfillReadable = createReadableStreamWrapper(window.ReadableStream);
const toPolyfillWritable = createWritableStreamWrapper(window.WritableStream);

and then you convert where necessary:

encryptSingleFile() {
  let fileStream = toPolyfillReadable(this.dropFiles[0].stream());
  let downloadStream = toPolyfillWritable(this.downloadStream);
  return fileStream.pipeTo(downloadStream).then(this.reset);
},

@str4d
Copy link
Owner Author

str4d commented Nov 23, 2022

Aha, that makes a lot of sense in hindsight! I was definitely assuming that the polyfill was handling this for me (or that the interface was being duck-typed). It might be useful to mention the wrapper library in the polyfill library documentation (if it's not already there; I don't recall seeing it when I implemented this). I'll try this and see if it resolves the issue.

@MattiasBuelens
Copy link

MattiasBuelens commented Nov 23, 2022

Aha, that makes a lot of sense in hindsight! I was definitely assuming that the polyfill was handling this for me (or that the interface was being duck-typed).

I was trying to make that work for version 4.0 of the polyfill, but unfortunately I had to throw in the towel (see MattiasBuelens/web-streams-polyfill#122 (comment)). 😞

It might be useful to mention the wrapper library in the polyfill library documentation (if it's not already there; I don't recall seeing it when I implemented this).

Yes, the documentation needs improvement. 😅 I'm also considering adding these conversion methods to web-streams-polyfill itself, because they're so commonly needed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants