SuperAPI AI Directory

zig-crypto

Data & analytics

View repository

Updated 10-15 21:48

About this skill

Zig Encryption and Security

Cryptographic primitives based on std.crypto (Zig 0.16.0).

Capability Boundaries

✅ Strengths

  1. Hash computation (SHA-2, SHA-3, Blake3, BLAKE2)
  2. AEAD encryption/decryption (AES-GCM, ChaCha20-Poly1305)
  3. Digital signatures (Ed25519, ECDSA)
  4. Key exchange (X25519, ML-KEM post-quantum)
  5. Password hashing (Argon2, scrypt, bcrypt, PBKDF2)
  6. Message authentication codes (HMAC, SipHash)
  7. KDF(HKDF)
  8. Secure random number generation

⚠️ Prerequisites

  1. Confirm the Zig version (zig version)
  2. Understand basic cryptography concepts (keys, IV, nonce)

❌ Out of Scope

  1. Random numbers for non-security scenarios → use zig-0.16 's std.Random
  2. HTTP encrypted transport → use the zig-http skill (std.http has built-in TLS)

When to Use

  • "Help me encrypt this data"
  • "How do I compute a SHA256 hash?"
  • "Generate an Ed25519 key pair and sign"
  • "Securely store user passwords"

Data Privacy

This skill does not collect, store, or transmit any user data. All cryptographic operations are performed locally.

Workflow

Step 1. Clarify the requirement — hash/encryption/signature/password? Step 2. Choose the algorithm — refer to the algorithm selection guide below Step 3. Implement — use the std.crypto.* module Step 4. Security verification — confirm key management and nonce uniqueness

Algorithm Selection Guide

需要加密?
├── 带认证 → AEAD(Aes256Gcm, ChaCha20Poly1305)
└── 流加密 → stream.chacha.*(通常应使用 AEAD)

需要哈希?
├── 通用 → Sha256, Sha512, Blake3
├── 密码存储 → argon2, scrypt, bcrypt
└── 遗留兼容 → Md5, Sha1(不推荐新设计)

需要签名?
├── 标准 → Ed25519
└── ECDSA 兼容 → ecdsa.EcdsaP256Sha256

需要密钥交换?
├── 标准 → X25519
└── 后量子 → ml_kem.*(Kyber)

需要 MAC?
├── 带密钥 → HmacSha256
└── 哈希表键控 → siphash

Hashing

SHA-256 (one-shot)

var digest: [std.crypto.hash.sha2.Sha256.digest_length]u8 = undefined;
std.crypto.hash.sha2.Sha256.hash("hello world", &digest, .{});

SHA-256 (streaming)

var hasher = std.crypto.hash.sha2.Sha256.init(.{});
hasher.update("hello ");
hasher.update("world");
var digest: [32]u8 = undefined;
hasher.final(&digest);

Blake3

var out: [32]u8 = undefined;
std.crypto.hash.Blake3.hash("hello world", &out, .{});

AEAD encryption/decryption

ChaCha20-Poly1305

const key: [32]u8 = .{ ... };  // 32 字节密钥
const nonce: [12]u8 = .{ ... }; // 12 字节 nonce(每次加密必须唯一)
var plaintext = "hello";
var ciphertext: [64]u8 = undefined;
var tag: [16]u8 = undefined;

// 加密
try std.crypto.aead.chacha_poly.ChaCha20Poly1305.encrypt(
    ciphertext[0..plaintext.len], &tag, plaintext, nonce, key, "", .{},
);

// 解密
try std.crypto.aead.chacha_poly.ChaCha20Poly1305.decrypt(
    plaintext, ciphertext[0..plaintext.len], tag, nonce, key, "", .{},
);

AES-256-GCM

const key: [32]u8 = .{ ... };
const nonce: [12]u8 = .{ ... };
var pt = "secret data";
var ct: [64]u8 = undefined;
var tag: [16]u8 = undefined;

try std.crypto.aead.aes_gcm.Aes256Gcm.encrypt(ct[0..pt.len], &tag, pt, nonce, key, "", .{});
try std.crypto.aead.aes_gcm.Aes256Gcm.decrypt(pt, ct[0..pt.len], tag, nonce, key, "", .{});

Digital signatures

Ed25519 key generation + signing + verification

// 密钥生成
var keypair = try std.crypto.sign.Ed25519.KeyPair.generate(null);

// 签名
const msg = "hello";
var sig: [std.crypto.sign.Ed25519.Signature.encoded_length]u8 = undefined;
try keypair.sign(&sig, msg, .{});

// 验证
try keypair.public_key.verify(&sig, msg, .{});

Key exchange

X25519

// Alice 生成密钥对
const alice_kp = try std.crypto.dh.X25519.KeyPair.generate(null);
// Bob 生成密钥对
const bob_kp = try std.crypto.dh.X25519.KeyPair.generate(null);

// 共享密钥
var alice_shared: [32]u8 = undefined;
try alice_kp.sharedSecret(&alice_shared, bob_kp.public_key, .{});

var bob_shared: [32]u8 = undefined;
try bob_kp.sharedSecret(&bob_shared, alice_kp.public_key, .{});
// alice_shared == bob_shared

Password hashing

Argon2 (recommended)

const password = "user_password";
var hash: [64]u8 = undefined;
try std.crypto.pwhash.argon2.strHash(password, &hash, .{});

// 验证
try std.crypto.pwhash.argon2.strVerify(&hash, password, .{});

scrypt

var dk: [32]u8 = undefined;
try std.crypto.pwhash.scrypt.kdf(&dk, password, salt, .{});

KDF

HKDF

var dk: [32]u8 = undefined;
try std.crypto.kdf.hkdf.HkdfSha256.derive(&dk, ikm, salt, info, .{});

Secure random numbers

// 生成随机字节
var buf: [32]u8 = undefined;
std.crypto.random.bytes(&buf);

// 生成随机整数
const val = std.crypto.random.int(u64);

// 生成随机浮点数
const f = std.crypto.random.float(f64);

Utility functions

// 安全清零(防止编译器优化)
std.crypto.utils.secureZero(&secret_buffer);

// 常量时间比较(防止时序攻击)
const eq = std.crypto.utils.timingSafeEql([8]u8, a, b);

Gotchas

  1. Nonce must be unique — AEAD encryption usesa different nonce each time, and a repeated nonce will cause the encryption to be broken
  2. Key management is the biggest risk — std.crypto does not handle key storage; keys must be securely kept by yourself
  3. Md5 and Sha1 are insecure — for legacy compatibility only; new designs should use Sha256/Blake3
  4. secureZero prevents optimization — ordinary zeroing may be optimized away by the compiler, so you must use secureZero
  5. timingSafeEql prevents timing attacks — when comparing keys/MACs you must use constant-time comparison

FAQ

Q: Should I choose ChaCha20-Poly1305 or AES-GCM? A: AES-GCM is faster when the hardware supports AES-NI; without hardware acceleration, ChaCha20-Poly1305 performs better and is simpler.

Q: Why not use SHA256 for password hashing? A: SHA256 is too fast and is easily brute-forced with a GPU. Argon2/scrypt/bcrypt are designed to be computationally intensive and are naturally resistant to brute force.

Q: How do I generate a secure random key? A: Use std.crypto.random.bytes(&key). Do not use std.Random.DefaultPrng, that is pseudorandom and not suitable for encryption.