- From: <bugzilla@jessica.w3.org>
- Date: Wed, 18 Jun 2014 19:14:43 +0000
- To: public-script-coord@w3.org
https://www.w3.org/Bugs/Public/show_bug.cgi?id=23369 --- Comment #37 from Ryan Sleevi <sleevi@google.com> --- (In reply to Domenic Denicola from comment #34) > I think you guys are talking past each other a bit. Allen is envisioning an > API that allows you to "mark as immutable" array buffers, and suggesting > that these methods should throw whenever given array buffers that aren't > marked as such. No, I understood this. This has two surprising consequences: 1) It prevents the use of ArrayBufferViews from working on slices of data with such APIs - that is, you have to mark the underlying buffer as immutable, which means if you want your use of ABV to have no non-local state, you're forcing the application developer to copy. This can be seen in the neutering behaviour discussions, which is essentially the same thing. 2) It essentially forces copying into the application's responsibility, rather than having it be part of the API. This doesn't seem to do anyone any favours. Almost certainly, the logical consequence of such an API is you'd want to 'unmark' something as immutable. This approach (mutable then unmutable) is what Web Audio tried to do with "temporarily neuter". If you do introduce a markMutable, when what you've really done is introduce a reader/writer lock on ArrayBuffers. Is that really a good API choice? I honestly don't know, but I feel like probably not. I'm probably biased, because I'm approaching this from the cryptographic operations. Consider something like PBKDF2 or HKDF, which are algorithms that compose on existing algorithms (eg: HMAC) in a somewhat iterative way to 'expand' key material into a suitable derived key. HKDF is defined somewhat recursively T(0) = empty string (zero length) T(1) = HMAC-Hash(PRK, T(0) | info | 0x01) T(2) = HMAC-Hash(PRK, T(1) | info | 0x02) T(3) = HMAC-Hash(PRK, T(2) | info | 0x03) The resulting key is concatenating T(1), T(2), ... T(N) until you have enough data to fit the desired length. If I were writing this in C/C++, I'd typically start by allocating T (aligned to HMAC-Hash length), and an "intermediate" buffer. Then I'd write a loop for (i = 1; i < N; ++i) { if (i == 1) { // set up intermediate HMAC(PRK, intermediate, intermediateLength, &T[0]); } else { memcpy(&intermediate[0], &T[(i - 1) * hashLength], hashLength); intermediate[intermediate.length - 1] = i; HMAC(PRK, intermediate, intermediateLength, &T[i * hashLength]); } } While likely bugged in many ways, the net effect is that my code has performed two allocations - one for the resulting buffer, and one for the intermediate result. If I were to implement this in ES, with WebCrypto, I'd likely do something similar. I'd have a Uint8Array called T, which had my targetted results. I'd have a Uint8Array, intermediate, that contains my intermediate data. Now, WebCrypto doesn't do emplacement-writes, it always returns a fresh ArrayBuffer, so I'd do a Promise to get T(1), then copy that into T[0...hashLength]. Then I'd do a Promise to get T(2), and copy that into [hashLength...hashLength*2], then a Promise for T(3), copy that into [hashLength*2...hashLength*3] As Web Crypto is currently specified, I can use "intermediate" as my scratch, and keep mutating it (updating the count and copying the result from T(i-1) in). Web Crypto will take responsibility for 'snapshotting' intermediate for each state. If we required .markImmutable(), then I, as the application author, would be forced to create a new copy of the data each time, as part of my algorithm. That 'smells' to me for two reasons: 1) I assume (perhaps incorrectly) that by keeping the copying on the UA side of things, I'm allowing greater flexibility for memory management strategies 2) As an author, that's more boilerplate for me to write in order for things to "Just Work" -- You are receiving this mail because: You are on the CC list for the bug.
Received on Wednesday, 18 June 2014 19:14:45 UTC