splitting this off from #ideas > Cryptography in Roc?:
Oskar Hahn said:
Would it be possible to add a crypto module to the builtins? That could be implemented in zig or something, zig can import.
I'm leaning towards this being a good idea. Concretely, add a builtin module called Crypt and include, as a baseline, some subset (or possibly all) of the ones Go has as builtins
all of these would of course need to be pure functions, and getting a secure random seed would necessarily (forever) need to be done as an effect in the host, so secure pseudorandom number generation would be out of scope for this module
the main motivation would be:
Richard Feldman said:
here's an article written by the author of one of the most widely used Rust cryptography packages calling for Rust to introduce primitives like that; currently Rust is in the same category of languages that Roc is (that is, you can't implement cryptography routines that are safe from timing attacks in pure Rust either)
https://briansmith.org/rust-cryptography-should-be-written-in-rust-01
other motivations would be speed (you can't implement cryptography primitives as fast as builtins could be in pure Roc, since builtins can use target-specific assembly etc.)
and also having a trustworthy default (so you don't have to worry about a third-party package having a backdoor or something)
I'm curious what others think of this idea!
The main downside you mentioned is that this module would grow over time as more crypto algorithms are required. Would there ever be a need to deprecate or remove an implementation?
Do we need to ensure the implementation is secure? Is this as simple as deferring to a zig somehow? Do we need to provide any assurance at this time, or can we just put a big ALPHA status on it?
Luke Boswell said:
The main downside you mentioned is that this module would grow over time as more crypto algorithms are required. Would there ever be a need to deprecate or remove an implementation?
well certainly algorithms can be cracked, at which point they should become deprecated...but the module would still be just as big if they're still present, but now deprecated
if we end up doing something like Rust Editions, we could remove things from builtins when changing editions
Luke Boswell said:
Do we need to ensure the implementation is secure? Is this as simple as deferring to a zig somehow? Do we need to provide any assurance at this time, or can we just put a big ALPHA status on it?
we certainly would need to do our best, which likely means picking an off-the-shelf low-level implementation that's been thoroughly vetted (e.g. vendoring some highly reputable C library and letting Zig include it in the build)
I don't think an "alpha" warning would be necessary honestly...either we find a sufficiently reputable implementation, in which case that's what we use, or else we can't find one and probably don't support that algorithm :big_smile:
Does anyone have an immediate use case in mind? It might be worthwhile implementing just one and testing the idea for a builtin Crypto module out. We could maybe add a compiler flag --experimental-crypto-builtins until we are satisfied it's a good idea.
I started working on writing what could be the beginnings of the roc forum; the next thing I need to be able to do is password hashing which is I why I started implementing bcrypt. So I would be interested in having that or another password hashing algorithm like scrypt or Argon2
yeah that's the classic use case
or one of them haha
It's in the zig std lib https://ziglang.org/documentation/master/std/#std.crypto.bcrypt
I guess a potential solution to the "huge module" problem is to have 1 module per algorithm (or family of them) but that would dramatically increase the number of builtin modules over time
not sure which would have better ergonomics
maybe we could have something like Crypt.hmac and then it takes a config which gets bigger and bigger with the more algorithms we support
actually nm that doesn't help
Richard Feldman said:
splitting this off from #ideas > Cryptography in Roc?:
Oskar Hahn said:
Would it be possible to add a crypto module to the builtins? That could be implemented in zig or something, zig can import.
I'm leaning towards this being a good idea. Concretely, add a builtin module called
Cryptand include, as a baseline, some subset (or possibly all) of the ones Go has as builtins
I like where this is heading. Just a small note, Golang's stdlib crypto is actually split between two packages: https://pkg.go.dev/crypto and https://pkg.go.dev/golang.org/x/crypto. They are on the process of being merged though https://github.com/golang/go/issues/65269
@Richard Feldman is there a reason for going with Crypt rather than Crypto? Is that to avoid accidental associate with cryptocurrency? :sweat_smile:
literally yes
Haha nice
otherwise I can imagine a ton of double-takes reading through the builtins list, like "wait is there etherium in this language's stdlib?!"
Crypt sounds a bit ominous to me (being a tomb) but I can’t think of anything better
Cry certainly isn’t desirable :joy:
Isaac Van Doren said:
Crypt sounds a bit ominous to me (being a tomb) but I can’t think of anything better
it seems to be ok for bcrypt, scrypt, etc :big_smile:
Richard Feldman said:
all of these would of course need to be pure functions, and getting a secure random seed would necessarily (forever) need to be done as an effect in the host, so secure pseudorandom number generation would be out of scope for this module
Couldn’t this be done when Task is a builtin? The benefit would be that we could make an opaque type for this, preventing the user from passing an non-secure number
hm, potentially!
Having an opaque type for it sounds great!
The main downside you mentioned is that this module would grow over time as more crypto algorithms are required.
This wouldn't just mean a big module, it could also mean that the language can never become stable, similar to concerns about a builtin Unicode library. You'd have to release a new compiler version to update any cryptography primitives.
This is a long-term concern, cuz in the short+medium term there would be plenty of new language versions anyway. So it's probably good for now, but I can see trying to take it back out of the builtins in 10 years.
Is there some in-between, where you could have an official trusted library that can include hand-written assembly, but it has its own package versioning separate from builtins? Elm sort of has this, where elm-explorations is blessed by the compiler to circumvent purity guarantees, which works, but has led to some frustration and compiler forks.
Sky Rose said:
This wouldn't just mean a big module, it could also mean that the language can never become stable, similar to concerns about a builtin Unicode library. You'd have to release a new compiler version to update any cryptography primitives.
this is importantly different from Unicode; the Unicode standard can have breaking changes, whereas cryptographic algorithms can either have new releases or become deprecated (because they have been cracked) and that's it. Breaking changes aren't really a thing in cryptography as far as I'm aware. :big_smile:
so it wouldn't affect language stability
Ah good point. It'd cause language patch/minor versions instead of language major versions, which aren't as bad.
yeah I don't consider them negative at all haha
Just seconding the notion that fast crypto often requires using very specific parts of the CPU. Some crypto is literally baked into the silicon on various chips. We need to make sure to compile roc/the builtins in a way to take advantage of this.
Also implementing crypto can be a big security issue, so delegating to experts in zig/c sound alike a win
One big concern is if we need to ingest any c as opposed to zig crypto libraries.
Oh also, totally possible that the crypto libraries break the surgical linker.
yeah I think compiling to llvm ir will be the way to go
also if it breaks surgical linking, I guess that’s something we’ll need to fix anyway right? (Because any host could do the same thing)
if things get too big, we can potentially do some segmenting - like only bring things in when they’re actually used
but obviously it would be better if that didn’t turn out to be necessary :big_smile:
Surgical linker changes should be fixable. Just potentially extra complexity. I think crypto is just more likely to do complex things not seem elsewhere in builtins
Came across this language. Relevant to the discussion
https://github.com/PLSysSec/FaCT
Last updated: Jun 16 2026 at 16:19 UTC