Supporting the WebCrypto API

One of the barriers for me to use Elm at work is the lack of the WebCrypto API. I see some projects on GitHub that are basically bindings, and I assume they don’t work with 0.19. At my job use of WebCrypto makes up probably 30% or more of our front-end code. I’d be interested in helping get this API supported natively in Elm. I know these kinds of things take a long time and plenty of discussion, and I just want to get the ball rolling. A search for WebCrypto here returned no results, and that surprised me. What can I do to help?


My gut feeling tells me, since it is an experimental api, and the progress in the past, there won’t be a native implementation soon.

Looking at this example the interface is straightforward and could work well with ports. The JS API has async calls and so a potential native elm API would have Cmds. There shouldn’t be a big difference to implementing it as of today with ports. The implementation needs to match responses and requests. But other than that it should work well.

Have you tried implementing a POC?


If you need it right away, it could be done through ports. But if you want to get more robust, native support, you’d need to get it into Elm-Explorations.

The best way to go about that is to write about it a little bit, probably here on discourse: Write a little about the API, for those who don’t know about it, why it would be useful, and a discussion of what an API might look like in Elm, taking particular care to make sure the API feels Elm-like.

But yes, this is likely a slow process.


It’s interesting they call it experimental. I’ve been using it in production for three years (, the API hasn’t changed, and all major browsers support it, except it took a little bit for Safari to catch up to the spec. I’ll have to look into that a bit further.

The implementation needs to match responses and requests.

Right. Everything I’ve seen seems to indicate that that is an antipattern and that ports aren’t meant to be used that way. It would feel quite hacky to wrap ports that way. Ports are a natural fit, on the other hand, for things like saving to local storage or using a web worker.

I’ve not tried a POC yet. Do you mean with ports or an Elm API or both? I wanted to start with getting a little feedback on the general idea. (Thanks!) I saw in another thread here that help covering the web API is appreciated, so I thought I’d give it a go since WebCrypto is definitely something I’m interested in seeing.

1 Like

Thanks, Dan! That’s exactly the kind of guidance I was looking for. Would you suggest a new topic here in the Request Feedback category?

Honestly, it’s a new process (even calling a process at this point might be a bit much), but generally Request Feedback is probably the way to go.

This is all very ad-hoc, but basically the decision is that talking thoroughly with other smart people about an API design, and doing this until you get it right, is better than just doing it.

One thing I’d suggest: well-named functions with explanatory type signatures convey a lot of information in Elm.


Makes sense to me! Thanks.

If you need to couple ports calls to/from the crypto web api, you could try something like this:

The example shows how much flexibility I could get out of this approach. The module is working, but incomplete, and abuses the Task terminology in a way I didn’t understand at the time.


Yeah. I figured I’d need to do something like that to give each request an id. Thanks for the link!

1 Like

For anyone else landing here and interested in API design, I wanted to share some more helpful resources courtesy of @zinggi:

This post lays out guidance for contribution the most clearly of anything I’ve seen: Building Trust: What Has Worked

This talk from Evan is helpful too:

Here’s a podcast interviewing Robin, someone not on the core team who contributed to core:

And finally, if you’re still up for designing an API, there’s a Slack channel for that: #api-design

1 Like

We’ve looked into the WebCrypto API a bunch already. The barriers to progress have been

  • Trying to decide if it’s best to expose low-level primitives with tons of options, or to provide a high-level encryption package, or both as with
  • The WebCrypto API is mostly async, which would mean that pretty much everything would have to be done with Tasks or Cmds. This might be weird when Elm exists on other platforms that support synchronous crypto calls. To me, this also undermines the case that an official package would be nicer than ports.
  • The WebCrypto API’s design is fairly orthogonal to the design philosophy that makes for good web platform Elm packages. Tons of overloading and string identifiers and stuff. It makes it difficult to figure out where to even begin.

A good writeup should at least indirectly address these issues.

And, a less important note: I personally think an official package could be a good thing to prioritize at some point for the minimum reason that it discourages people from writing their own implementations of crypto algorithms and publishing them as packages, which no one should ever do. But I think the async thing undermines this case as well.

tl;dr: we’ve looked into it, there are some big design challenges to address. in the mean time, use interop and don’t install anyone’s hand-rolled crypto packages


Thanks, @luke!

This will help guide my writeup for sure. I’d love to give thoughts and ask questions about those specific points now though:

  • I think eventually having both low-level primitives and high-level APIs would be nice, although I would probably advocate for high-level first. Is that a pattern that makes sense to the Elm team – start with functionality that works for most people and prevents shooting oneself in the foot, and then in a later version expose lower level APIs for advanced use cases?

  • It’s hard to say YAGNI when designing a language for the future, I suppose. :smile: That said, if Elm compiles to another platform with synchronous crypto calls, an async Elm API will still be compatible with it. The opposite isn’t true, but async provides the most flexibility. I’m not sure why it would be weird. We’d still be writing the same Elm code, rather than writing code for the platform to which Elm is compiling. Could you expand on why that makes you uncomfortable?

  • The idea of abstracting WebCrypto’s quirks into an Elmish API makes this project even more exciting to me. I’m probably still in the overly optimistic phase, so maybe I’ll understand this point more when my feet are back on the ground. :slight_smile:

  • I think preventing hand-rolled crypto packages is super important. I didn’t quite follow your comment about async at the end of that, unless you were just restating point 2?

1 Like

I wasn’t clear about this. My intuition is that some small number of folks will be frustrated by a Task- or Cmd-based API and want to roll their own sync version just to have it. I think it’s a reasonable guess based on being in and observing the community for a while but I’m really just speculating, which is why I wrote it separately from the main list.

Let me know if you need anything at all while you’re doing your research!


That makes sense. What did you think about my first question? Is it reasonable to start with a high level API and add lower level primitives later (if/as necessary)?

I’m not sure. It’s a question that should be answered but we didn’t come to any useful conclusions in past research. I think at this point a good writeup would first posit what values we’re trying to promote and what questions a hypothetical package would answer, and then use that framework to synthesize pros and cons of each approach and make a recommendation.

For example, if in your research you gather use cases and discover that they are fairly diverse then the low-level option seems more attractive, but if everyone is doing symmetric encryption and no one cares about the implementation details then a high level package that does fernet encryption would probably be better.


Actually, I can add a data point to the list:

I’m working on a project where I want to encrypt user data end-to-end and let the user keep the key, a la 1password or day one. I’d just want to use 128 bit AES, I’m not particularly interested in lots of options or fancy details.

1 Like

Ok. I guess my thought is that we would definitely want a high level API to make secure behavior as easy and obvious as possible (like libsodium), but there will inevitably be advanced use cases that will require lower level APIs.

So my question is more generally speaking I suppose. We could expose only part of a web API in a very high level way and require ports to use the rest of the API. Then potentially add more native support for the rest in a later version of the language. Being new around these parts, though, I’m just not sure if there is a precedent in Elm for that, or if not, if it’s a precedent that a sensible recommendation could effect.

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.