2

In a browser I want to use SublteCrypto (https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto) to create a key pair and store it locally in the IndexedDB (https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API).

Storing the key pair in the IndexedDB has some security advantages as the private key never needs to be exposed to JavaScript. The key pair can be generated non-extractable, and storing the key and loading it works fine.

Example: https://gist.github.com/saulshanabrook/b74984677bccd08b028b30d9968623f5

I need to share the key pair among a restricted list of different domains. However, browsers restrict IndexedDB to first party origin, so it cannot be accessed within an IFrame.

The only solutions I found so far is not to use IndexedDB at all but store the key pair in LocalStorage (https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage) as this allows me to access the keys through an IFrame (from the origin where the keys are stored, with some window messaging), but it has the disadvantage that the private key needs to be extractable and is accessible to the JavaScript, as LocalStorage only allows to store plain text.

Another solution that seems to work only in Google Chrome but not Firefox is to do the cross-domain access of the keys via a new (temporary) browser window opened by window.open. This has the disadvantage that I always need to open a distracting window when accessing the keys. Of course this works only with user interaction as window.open is only allowed when triggered directly by the user, which should not be a problem in my case. Surprisingly that works pretty well in Google Chrome and I can use the key pair from the IndexedDB cross-origin with some window messaging. Maybe a security bug?

Firefox however seems to block access to the IndexedDB in that case. Access is only given when manually opening the window to the origin where the keys are stored.

Any ideas how to use SubtleCrypto with non-extractable keys stored in IndexedDB cross origin in a clean way that works with all browsers supporting that features?

schroeder
  • 123,438
  • 55
  • 284
  • 319
dominik
  • 21
  • 2
  • What makes you believe that indexddb isn't available to javascript? –  Dec 20 '21 at 20:28

1 Answers1

0

I sure hope it is not possible to do what you are trying to do.

Imagine a web-based crypto currency wallet (let's call it cryptowallet.com) that uses the Web Crypto API to create and sign transactions client-side, in-browser. The wallet's private key is stored in IndexedDB as a CryptoKey object, with the .extractable() property set to false, as you describe in your question.

Now, the user is lured to evil.com, by a phishing email. If what you are describing is possible, scripting in the page at evil.com could access the CryptoKey object and use the private key to sign a transaction that sends all of the user's coins to evil.com.

The fact that a Cryptokey object stored in IndexedDB storage by scripting originating from cryptowallet.com cannot be accessed by scripting originating from evil.com is a good thing.

mti2935
  • 19,868
  • 2
  • 45
  • 64
  • 1
    The OP mentions using it mediated by some window messaging with their own code, so there would be no such vulnerability (well, the validation code needs to be right e.g. cryptowallet.com/messaging allowing key operations if the caller is cryptowallet.eu, but not evilwallet.com). I think the question boils down to why can't the OP communicate cross-origin with a document which is able to use the IndexedDB of its own origin. Apparently it _should_ be possible. – Ángel Jul 25 '21 at 00:18
  • That's exactly what I mean. The domain owning the keys would operate on the keys only when the origin of the window message querying the key operation is in a strict list of well known domains, directly generated into that script code from the server of that domain, so it cannot be overruled by any other origin. Furthermore the IFrame can be protected by CSP mechanisms to only be loaded from the browser by specified frame anchestors, so other domains would not even be able to load the IFrame. – dominik Jul 26 '21 at 07:49
  • As far as I know most IFrame authentication mechanisms use OAuth and store the client's access token into LocalStorage, which would basically lead to the same situation. Data from the LocalStorage can easily be shared among cross origin with window messaging, which of course needs to be implemented correctly and needs a strict origin validation in the JavaScript code. So why is LocalStorage allowed in IFrames, but IndexedDB not? Am I missing something here? – dominik Jul 26 '21 at 07:50
  • OP, Thanks for clarifying the bit about `a strict list of well known domains, directly generated into that script code from the server of that domain, so it cannot be overruled by any other origin`. After re-reading your question, I see that you alluded to this in your question, but I didn't pick up on it at the time. This mitigates the problem that I described in my answer. But I have no idea why it's possible to do this in with LocalStorage, but not with IndexedDB. – mti2935 Jul 26 '21 at 12:09