Mihail Malostanidis
Mihail Malostanidis

Reputation: 3024

How to ES6 Proxy an ArrayBuffer or Uint8Array?

These work:

crypto.subtle.digest('SHA-512', new Uint8Array([0]))
crypto.subtle.digest('SHA-512', new Uint8Array([0]).buffer)

These don't:

crypto.subtle.digest('SHA-512', new Proxy(new Uint8Array([0]),{}))
crypto.subtle.digest('SHA-512', new Proxy(new Uint8Array([0]).buffer,{})

Error:

Failed to execute 'digest' on 'SubtleCrypto': The provided value is not of type '(ArrayBuffer or ArrayBufferView)'

instanceof Uint8Array and instanceof ArrayBuffer return true in both cases.

Upvotes: 4

Views: 3121

Answers (1)

apsillers
apsillers

Reputation: 115980

digest is specified by its IDL interface to only accept a BufferSource, which is either an ArrayBufferView or an ArrayBuffer. This IDL-level typing indicates that a correct implementation will categorically reject any inputs that doesn't have the correct internal type.

Any tricks you might want to use a Proxy for simply aren't going to work on digest. Instead, you could do proxy tricks to get the exact ArrayBuffer you want immediately before you pass in your data to digest.

For example, here's a proxy that fakes a buffer that differs from the buffer on its internal object. The buffer is genuine, so it can be passed into digest, but it was created by Proxy magic:

var proxy = new Proxy(new Uint8Array([0]), {
                          get:function(obj, prop) {
                              if(prop=="buffer"){ return new Uint8Array([42]).buffer }
                              else { return obj[prop]; }
                          }
            });
crypto.subtle.digest('SHA-512', proxy.buffer)

If it is impossible to produce the buffer (for example if it is too big to fit in RAM) you would currently have to rely on something other than SubtleCrypto.

This seems like a great point to raise with the W3C, e.g., to support an update mechanism to iteratively collect input.

Upvotes: 2

Related Questions