Cryptopasta: The Copy-Paste Crypto Library That Refuses to Let You Fail
Hook
Most crypto libraries give you enough rope to hang yourself. Cryptopasta takes away the rope entirely—and that's exactly the point.
Context
Go's standard library crypto package is powerful but dangerous. It gives you primitives—AES, HMAC, ECDSA—but leaves implementation details to you. Should you use GCM or CTR mode? What nonce size? Which hash function? Make the wrong choice and you've created a security vulnerability that won't surface until an attacker exploits it.
This decision paralysis leads developers down two paths: either they spend days researching cryptographic best practices (time most projects don't have), or they copy code from Stack Overflow that looks reasonable but might be subtly broken. George Tankersley created cryptopasta in 2016 to address this reality. Rather than building another comprehensive crypto framework, he created a recipe book of safe patterns with CC0 licensing—explicitly designed to be copied into your codebase. It's crypto for pragmatists who acknowledge that most developers shouldn't be making cryptographic decisions at all.
Technical Insight
The genius of cryptopasta lies in how it weaponizes Go's type system to prevent misuse. Take encryption: most libraries accept []byte for keys, allowing any slice of any length. Cryptopasta uses fixed-size arrays instead:
type [32]byte // Encryption key
type [24]byte // Nonce for NaCl compatibility
func Encrypt(plaintext []byte, key *[32]byte) ([]byte, error) {
block, err := aes.NewCipher(key[:])
if err != nil {
return nil, err
}
gcm, err := cipher.NewGCM(block)
if err != nil {
return nil, err
}
nonce := make([]byte, gcm.NonceSize())
if _, err := io.ReadFull(rand.Reader, nonce); err != nil {
return nil, err
}
return gcm.Seal(nonce, nonce, plaintext, nil), nil
}
This type signature makes it impossible to pass a 16-byte key when 32 bytes are required—the compiler rejects it. You can't accidentally confuse encryption keys with signing keys because they're different types. This compile-time safety is rare in cryptography, where most mistakes only manifest as runtime vulnerabilities.
The opinionated defaults eliminate another attack vector: developer indecision. Cryptopasta chooses AES-256-GCM for encryption, not because it's the fastest, but because it provides authenticated encryption by default. Many developers encrypt with AES-CBC and forget authentication, leaving data vulnerable to padding oracle attacks. By making authenticated encryption the only option, cryptopasta removes this entire class of vulnerabilities.
For hashing, cryptopasta uses HMAC-SHA512/256—SHA-512 truncated to 256 bits. This seems odd until you understand the reasoning: on 64-bit systems, SHA-512 is often faster than SHA-256 due to native 64-bit operations, while truncation provides the same security properties as SHA-256. It's a subtle performance optimization that most developers would never discover:
func NewHMACKey() *[32]byte {
key := &[32]byte{}
_, err := io.ReadFull(rand.Reader, key[:])
if err != nil {
panic(err)
}
return key
}
func Hash(message []byte, key *[32]byte) []byte {
mac := hmac.New(sha512.New512_256, key[:])
mac.Write(message)
return mac.Sum(nil)
}
Notice the panic in NewHMACKey(). This is deliberate. If your system can't generate random bytes, it's fundamentally broken—you shouldn't continue execution. Most libraries return errors here, which developers might ignore or mishandle. Cryptopasta's fail-fast philosophy ensures catastrophic failures are impossible to miss.
Password hashing demonstrates another principle: choosing boring, proven technology. Instead of exotic algorithms, cryptopasta uses bcrypt with a work factor of 14:
func HashPassword(password string) ([]byte, error) {
return bcrypt.GenerateFromPassword([]byte(password), 14)
}
func CheckPasswordHash(password string, hash []byte) error {
return bcrypt.CompareHashAndPassword(hash, []byte(password))
}
Bcrypt isn't the newest algorithm—Argon2 won the Password Hashing Competition in 2015—but it's battle-tested and sufficient for most applications. Cryptopasta prioritizes proven safety over cutting-edge features, a philosophy that aged surprisingly well despite the library's 2017 abandonment.
The signing implementation reveals a final insight: constant-time operations trump performance. Cryptopasta uses ECDSA with P-256 and constant-time implementations to prevent timing attacks. Faster curves exist, but they might leak information through execution time variations. For a library designed to prevent mistakes, this tradeoff is obvious—but it's one many developers wouldn't consider without guidance.
Gotcha
Cryptopasta's inflexibility is both its strength and weakness. You can't configure key sizes, switch algorithms, or adjust parameters. Need AES-128 for compliance? Want ChaCha20-Poly1305 for better mobile performance? You're out of luck. The library assumes AES-256-GCM is always right, which isn't true for edge cases like embedded systems with hardware AES-128 support or environments where AES-NI isn't available.
The 2017 abandonment matters more than it might seem. Go's crypto ecosystem has evolved: x/crypto added ChaCha20-Poly1305, bcrypt's work factor of 14 is now considered low for high-security applications, and modern APIs use context.Context for cancellation. More critically, cryptopasta predates Go modules, making dependency management awkward. You could fork it (the CC0 license encourages this), but then you're maintaining crypto code yourself—exactly what you wanted to avoid. The library also lacks features that real applications need: key rotation, streaming encryption for large files, or key derivation functions for deriving multiple keys from a master secret. It's educational scaffolding, not production infrastructure.
Verdict
Use if: You're building a standard web application that needs basic cryptography (encrypting database fields, signing JWTs, hashing passwords) and you'd rather spend time on business logic than researching AEAD modes. Copy the relevant functions into your codebase—that's what the CC0 license encourages—and treat them as well-documented starting points. It's perfect for learning cryptographic patterns or prototyping where security matters but you need to move fast. Skip if: You need algorithm flexibility, require actively maintained dependencies for production systems, have compliance requirements that mandate specific cryptographic standards, or need modern features like streaming encryption or post-quantum algorithms. For production systems in 2024, consider golang.org/x/crypto for maintained primitives or Tink for a misuse-resistant API with Google's backing. Cryptopasta's real value isn't as a dependency—it's as a教科书 of safe patterns that shows what opinionated crypto design looks like.