PeculiarVentures / webcrypto-liner

webcrypto-liner is a polyfill that let's down-level User Agents (like IE/Edge) use libraries that depend on WebCrypto. (Keywords: Javascript, WebCrypto, Shim, Polyfill)
MIT License
149 stars 26 forks source link

Work with AES-GCM keys generated with webcrypto-liner #18

Closed rmhrisk closed 7 years ago

rmhrisk commented 7 years ago

In another project I was discussing the need to support AES-GCM and RSA wrapping with pure JS vs our current use of browser native support with @rapropos:

Thanks @rmhrisk, it might be a helpful starting point. A brief glance at the RSA keywrap function suggests that it won't work with AES-GCM keys also generated by webcrypto-liner, as it is expecting the key to be wrapped to be processable by the browser's crypto. Perhaps I don't know enough about JavaScript to know whether one could actually fake out the browser's implementation with a key implemented outside.

My application needs to be able to download an RSA public key in JWK format (had too much trouble with dueling PEM implementations), generate a AES-GCM key in as safe fashion as possible, encode an arbitrary payload as a JWE with it, wrap that key with RSA-OAEP, and have the result be downloadable and decryptable by a different application running potentially on a different platform that possesses the corresponding RSA private key.

This is generally working great with a combination of Square's JS and Golang JOSE libraries, with the glaring exception of WebKit, which is blocking iOS support.

@rapropos yes, our goal was to minimize use of the JS implementations and use the native implementations when present. Since Safari supports RSA-OAEP 'RSA-OAEP mod:2048 pubExp:3 format:jwk' you should be able to get AES-GCM working in Safari with the library as is.

Can you explain what your target scenario is that is not covered by the library?

rmhrisk commented 7 years ago

Just to add, my understanding is you need to import a RSA public key, generate a AES-GCM key, encrypt data with that AES key, and wrap that key to the RSA public key. I am pretty sure this will work on Safari with liner.

rapropos commented 7 years ago

Safari cannot generate AES-GCM keys, only AES-CBC. So if I use liner to generate the AES key, I don't think liner would be able to wrap it. I'm not completely beholden to GCM, but I can't unwrap Safari-wrapped CBC keys in Chromium - I get a mysterious messageless OperationError. I have verified that this is exactly what happens when the wrapped key is corrupt by manually corrupting a byte in the key when it is wrapped by Chromium. Ordinarily Chromium-wrapped CBC keys can be properly unwrapped in Chromium, so I know it's not a general problem in my code and it's not a general problem in js-jose. Something is broken either in Safari's OAEP implementation, the particular way that js-jose exercises it, or the particular way I'm using js-jose.

rmhrisk commented 7 years ago

Even though Safari doesnt support AES-GCM we add support for it via asmcryptojs; we can wrap those keys with the native RSA implementation, or at least should be able to.

rapropos commented 7 years ago

Will the native implementation be willing to wrap liner keys? That would seem surprising to me, and sort of against the spirit of WebCrypto in general.

rmhrisk commented 7 years ago

Should work just fine.

Import an AES-GCM key, which is supported with liner:

image

Then you should be able to wrap that key with the Safari implementation.

Check out https://peculiarventures.github.io/pv-webcrypto-tests/ to see what will be supported in each browser. image

rapropos commented 7 years ago

My understanding is that the actual "key" inside a WebCrypto key is not allowed to be accessed by scripts. As a consequence, I would not think one could pass a liner-derived key directly to WebCrypto functions (such as wrapKey). The only way (as I understand it, please correct if wrong) to get key information in and out of WebCrypto-land is via importKey and exportKey. If Safari won't generate AES-GCM keys for me, I would be surprised if it will import them either.

So, in order to do anything with a key used for an algorithm unsupported by the native WebCrypto, including wrapping it with a supported algorithm, I would think the wrapping operation would have to also be done by liner (as would the actual AES encrypting itself).

rmhrisk commented 7 years ago

I believe, possibly incorrectly that once imported the AES-GCM key is just a blob, and as a result it will be possible to import the key and wrap it. If that is not the case we would consider changing the behavior of liner to accommodate wrapping the AES-GCM key in js based RSA, but we would want to verify first that the hybrid does not work.

rmhrisk commented 7 years ago

Closing as @rapropos's seems to not need this thread any longer.

rapropos commented 7 years ago

Sorry for inactivity. I ended up going with forge to do the keywrapping and GCM to get the app working on Safari.