mirror of
https://github.com/ziglang/zig.git
synced 2024-11-15 08:33:06 +00:00
391 lines
13 KiB
Zig
391 lines
13 KiB
Zig
//! Cryptography.
|
|
|
|
const root = @import("root");
|
|
|
|
pub const timing_safe = @import("crypto/timing_safe.zig");
|
|
|
|
/// Authenticated Encryption with Associated Data
|
|
pub const aead = struct {
|
|
pub const aegis = struct {
|
|
pub const Aegis128L = @import("crypto/aegis.zig").Aegis128L;
|
|
pub const Aegis128L_256 = @import("crypto/aegis.zig").Aegis128L_256;
|
|
pub const Aegis256 = @import("crypto/aegis.zig").Aegis256;
|
|
pub const Aegis256_256 = @import("crypto/aegis.zig").Aegis256_256;
|
|
};
|
|
|
|
pub const aes_gcm = struct {
|
|
pub const Aes128Gcm = @import("crypto/aes_gcm.zig").Aes128Gcm;
|
|
pub const Aes256Gcm = @import("crypto/aes_gcm.zig").Aes256Gcm;
|
|
};
|
|
|
|
pub const aes_ocb = struct {
|
|
pub const Aes128Ocb = @import("crypto/aes_ocb.zig").Aes128Ocb;
|
|
pub const Aes256Ocb = @import("crypto/aes_ocb.zig").Aes256Ocb;
|
|
};
|
|
|
|
pub const chacha_poly = struct {
|
|
pub const ChaCha20Poly1305 = @import("crypto/chacha20.zig").ChaCha20Poly1305;
|
|
pub const ChaCha12Poly1305 = @import("crypto/chacha20.zig").ChaCha12Poly1305;
|
|
pub const ChaCha8Poly1305 = @import("crypto/chacha20.zig").ChaCha8Poly1305;
|
|
pub const XChaCha20Poly1305 = @import("crypto/chacha20.zig").XChaCha20Poly1305;
|
|
pub const XChaCha12Poly1305 = @import("crypto/chacha20.zig").XChaCha12Poly1305;
|
|
pub const XChaCha8Poly1305 = @import("crypto/chacha20.zig").XChaCha8Poly1305;
|
|
};
|
|
|
|
pub const isap = @import("crypto/isap.zig");
|
|
|
|
pub const salsa_poly = struct {
|
|
pub const XSalsa20Poly1305 = @import("crypto/salsa20.zig").XSalsa20Poly1305;
|
|
};
|
|
};
|
|
|
|
/// Authentication (MAC) functions.
|
|
pub const auth = struct {
|
|
pub const hmac = @import("crypto/hmac.zig");
|
|
pub const siphash = @import("crypto/siphash.zig");
|
|
pub const aegis = struct {
|
|
pub const Aegis128LMac = @import("crypto/aegis.zig").Aegis128LMac;
|
|
pub const Aegis128LMac_128 = @import("crypto/aegis.zig").Aegis128LMac_128;
|
|
pub const Aegis256Mac = @import("crypto/aegis.zig").Aegis256Mac;
|
|
pub const Aegis256Mac_128 = @import("crypto/aegis.zig").Aegis256Mac_128;
|
|
};
|
|
pub const cmac = @import("crypto/cmac.zig");
|
|
};
|
|
|
|
/// Core functions, that should rarely be used directly by applications.
|
|
pub const core = struct {
|
|
pub const aes = @import("crypto/aes.zig");
|
|
pub const keccak = @import("crypto/keccak_p.zig");
|
|
|
|
pub const Ascon = @import("crypto/ascon.zig").State;
|
|
|
|
/// Modes are generic compositions to construct encryption/decryption functions from block ciphers and permutations.
|
|
///
|
|
/// These modes are designed to be building blocks for higher-level constructions, and should generally not be used directly by applications, as they may not provide the expected properties and security guarantees.
|
|
///
|
|
/// Most applications may want to use AEADs instead.
|
|
pub const modes = @import("crypto/modes.zig");
|
|
};
|
|
|
|
/// Diffie-Hellman key exchange functions.
|
|
pub const dh = struct {
|
|
pub const X25519 = @import("crypto/25519/x25519.zig").X25519;
|
|
};
|
|
|
|
/// Key Encapsulation Mechanisms.
|
|
pub const kem = struct {
|
|
pub const kyber_d00 = @import("crypto/ml_kem.zig").d00;
|
|
pub const ml_kem = @import("crypto/ml_kem.zig").nist;
|
|
pub const ml_kem_01 = @compileError("deprecated: final version of the specification has been published, use ml_kem instead");
|
|
};
|
|
|
|
/// Elliptic-curve arithmetic.
|
|
pub const ecc = struct {
|
|
pub const Curve25519 = @import("crypto/25519/curve25519.zig").Curve25519;
|
|
pub const Edwards25519 = @import("crypto/25519/edwards25519.zig").Edwards25519;
|
|
pub const P256 = @import("crypto/pcurves/p256.zig").P256;
|
|
pub const P384 = @import("crypto/pcurves/p384.zig").P384;
|
|
pub const Ristretto255 = @import("crypto/25519/ristretto255.zig").Ristretto255;
|
|
pub const Secp256k1 = @import("crypto/pcurves/secp256k1.zig").Secp256k1;
|
|
};
|
|
|
|
/// Hash functions.
|
|
pub const hash = struct {
|
|
pub const blake2 = @import("crypto/blake2.zig");
|
|
pub const Blake3 = @import("crypto/blake3.zig").Blake3;
|
|
pub const Md5 = @import("crypto/md5.zig").Md5;
|
|
pub const Sha1 = @import("crypto/sha1.zig").Sha1;
|
|
pub const sha2 = @import("crypto/sha2.zig");
|
|
pub const sha3 = @import("crypto/sha3.zig");
|
|
pub const composition = @import("crypto/hash_composition.zig");
|
|
};
|
|
|
|
/// Key derivation functions.
|
|
pub const kdf = struct {
|
|
pub const hkdf = @import("crypto/hkdf.zig");
|
|
};
|
|
|
|
/// MAC functions requiring single-use secret keys.
|
|
pub const onetimeauth = struct {
|
|
pub const Ghash = @import("crypto/ghash_polyval.zig").Ghash;
|
|
pub const Polyval = @import("crypto/ghash_polyval.zig").Polyval;
|
|
pub const Poly1305 = @import("crypto/poly1305.zig").Poly1305;
|
|
};
|
|
|
|
/// A password hashing function derives a uniform key from low-entropy input material such as passwords.
|
|
/// It is intentionally slow or expensive.
|
|
///
|
|
/// With the standard definition of a key derivation function, if a key space is small, an exhaustive search may be practical.
|
|
/// Password hashing functions make exhaustive searches way slower or way more expensive, even when implemented on GPUs and ASICs, by using different, optionally combined strategies:
|
|
///
|
|
/// - Requiring a lot of computation cycles to complete
|
|
/// - Requiring a lot of memory to complete
|
|
/// - Requiring multiple CPU cores to complete
|
|
/// - Requiring cache-local data to complete in reasonable time
|
|
/// - Requiring large static tables
|
|
/// - Avoiding precomputations and time/memory tradeoffs
|
|
/// - Requiring multi-party computations
|
|
/// - Combining the input material with random per-entry data (salts), application-specific contexts and keys
|
|
///
|
|
/// Password hashing functions must be used whenever sensitive data has to be directly derived from a password.
|
|
pub const pwhash = struct {
|
|
pub const Encoding = enum {
|
|
phc,
|
|
crypt,
|
|
};
|
|
|
|
pub const Error = HasherError || error{AllocatorRequired};
|
|
pub const HasherError = KdfError || phc_format.Error;
|
|
pub const KdfError = errors.Error || std.mem.Allocator.Error || std.Thread.SpawnError;
|
|
|
|
pub const argon2 = @import("crypto/argon2.zig");
|
|
pub const bcrypt = @import("crypto/bcrypt.zig");
|
|
pub const scrypt = @import("crypto/scrypt.zig");
|
|
pub const pbkdf2 = @import("crypto/pbkdf2.zig").pbkdf2;
|
|
|
|
pub const phc_format = @import("crypto/phc_encoding.zig");
|
|
};
|
|
|
|
/// Digital signature functions.
|
|
pub const sign = struct {
|
|
pub const Ed25519 = @import("crypto/25519/ed25519.zig").Ed25519;
|
|
pub const ecdsa = @import("crypto/ecdsa.zig");
|
|
};
|
|
|
|
/// Stream ciphers. These do not provide any kind of authentication.
|
|
/// Most applications should be using AEAD constructions instead of stream ciphers directly.
|
|
pub const stream = struct {
|
|
pub const chacha = struct {
|
|
pub const ChaCha20IETF = @import("crypto/chacha20.zig").ChaCha20IETF;
|
|
pub const ChaCha12IETF = @import("crypto/chacha20.zig").ChaCha12IETF;
|
|
pub const ChaCha8IETF = @import("crypto/chacha20.zig").ChaCha8IETF;
|
|
pub const ChaCha20With64BitNonce = @import("crypto/chacha20.zig").ChaCha20With64BitNonce;
|
|
pub const ChaCha12With64BitNonce = @import("crypto/chacha20.zig").ChaCha12With64BitNonce;
|
|
pub const ChaCha8With64BitNonce = @import("crypto/chacha20.zig").ChaCha8With64BitNonce;
|
|
pub const XChaCha20IETF = @import("crypto/chacha20.zig").XChaCha20IETF;
|
|
pub const XChaCha12IETF = @import("crypto/chacha20.zig").XChaCha12IETF;
|
|
pub const XChaCha8IETF = @import("crypto/chacha20.zig").XChaCha8IETF;
|
|
};
|
|
|
|
pub const salsa = struct {
|
|
pub const Salsa = @import("crypto/salsa20.zig").Salsa;
|
|
pub const XSalsa = @import("crypto/salsa20.zig").XSalsa;
|
|
pub const Salsa20 = @import("crypto/salsa20.zig").Salsa20;
|
|
pub const XSalsa20 = @import("crypto/salsa20.zig").XSalsa20;
|
|
};
|
|
};
|
|
|
|
pub const nacl = struct {
|
|
const salsa20 = @import("crypto/salsa20.zig");
|
|
|
|
pub const Box = salsa20.Box;
|
|
pub const SecretBox = salsa20.SecretBox;
|
|
pub const SealedBox = salsa20.SealedBox;
|
|
};
|
|
|
|
/// Finite-field arithmetic.
|
|
pub const ff = @import("crypto/ff.zig");
|
|
|
|
/// This is a thread-local, cryptographically secure pseudo random number generator.
|
|
pub const random = @import("crypto/tlcsprng.zig").interface;
|
|
|
|
const std = @import("std.zig");
|
|
|
|
pub const errors = @import("crypto/errors.zig");
|
|
|
|
pub const tls = @import("crypto/tls.zig");
|
|
pub const Certificate = @import("crypto/Certificate.zig");
|
|
|
|
/// Side-channels mitigations.
|
|
pub const SideChannelsMitigations = enum {
|
|
/// No additional side-channel mitigations are applied.
|
|
/// This is the fastest mode.
|
|
none,
|
|
/// The `basic` mode protects against most practical attacks, provided that the
|
|
/// application or implements proper defenses against brute-force attacks.
|
|
/// It offers a good balance between performance and security.
|
|
basic,
|
|
/// The `medium` mode offers increased resilience against side-channel attacks,
|
|
/// making most attacks unpractical even on shared/low latency environements.
|
|
/// This is the default mode.
|
|
medium,
|
|
/// The `full` mode offers the highest level of protection against side-channel attacks.
|
|
/// Note that this doesn't cover all possible attacks (especially power analysis or
|
|
/// thread-local attacks such as cachebleed), and that the performance impact is significant.
|
|
full,
|
|
};
|
|
|
|
pub const default_side_channels_mitigations = .medium;
|
|
|
|
test {
|
|
_ = aead.aegis.Aegis128L;
|
|
_ = aead.aegis.Aegis256;
|
|
|
|
_ = aead.aes_gcm.Aes128Gcm;
|
|
_ = aead.aes_gcm.Aes256Gcm;
|
|
|
|
_ = aead.aes_ocb.Aes128Ocb;
|
|
_ = aead.aes_ocb.Aes256Ocb;
|
|
|
|
_ = aead.chacha_poly.ChaCha20Poly1305;
|
|
_ = aead.chacha_poly.ChaCha12Poly1305;
|
|
_ = aead.chacha_poly.ChaCha8Poly1305;
|
|
_ = aead.chacha_poly.XChaCha20Poly1305;
|
|
_ = aead.chacha_poly.XChaCha12Poly1305;
|
|
_ = aead.chacha_poly.XChaCha8Poly1305;
|
|
|
|
_ = aead.isap;
|
|
_ = aead.salsa_poly.XSalsa20Poly1305;
|
|
|
|
_ = auth.hmac;
|
|
_ = auth.cmac;
|
|
_ = auth.siphash;
|
|
|
|
_ = core.aes;
|
|
_ = core.Ascon;
|
|
_ = core.modes;
|
|
|
|
_ = dh.X25519;
|
|
|
|
_ = kem.kyber_d00;
|
|
|
|
_ = ecc.Curve25519;
|
|
_ = ecc.Edwards25519;
|
|
_ = ecc.P256;
|
|
_ = ecc.P384;
|
|
_ = ecc.Ristretto255;
|
|
_ = ecc.Secp256k1;
|
|
|
|
_ = hash.blake2;
|
|
_ = hash.Blake3;
|
|
_ = hash.Md5;
|
|
_ = hash.Sha1;
|
|
_ = hash.sha2;
|
|
_ = hash.sha3;
|
|
_ = hash.composition;
|
|
|
|
_ = kdf.hkdf;
|
|
|
|
_ = onetimeauth.Ghash;
|
|
_ = onetimeauth.Poly1305;
|
|
|
|
_ = pwhash.Encoding;
|
|
|
|
_ = pwhash.Error;
|
|
_ = pwhash.HasherError;
|
|
_ = pwhash.KdfError;
|
|
|
|
_ = pwhash.argon2;
|
|
_ = pwhash.bcrypt;
|
|
_ = pwhash.scrypt;
|
|
_ = pwhash.pbkdf2;
|
|
|
|
_ = pwhash.phc_format;
|
|
|
|
_ = sign.Ed25519;
|
|
_ = sign.ecdsa;
|
|
|
|
_ = stream.chacha.ChaCha20IETF;
|
|
_ = stream.chacha.ChaCha12IETF;
|
|
_ = stream.chacha.ChaCha8IETF;
|
|
_ = stream.chacha.ChaCha20With64BitNonce;
|
|
_ = stream.chacha.ChaCha12With64BitNonce;
|
|
_ = stream.chacha.ChaCha8With64BitNonce;
|
|
_ = stream.chacha.XChaCha20IETF;
|
|
_ = stream.chacha.XChaCha12IETF;
|
|
_ = stream.chacha.XChaCha8IETF;
|
|
|
|
_ = stream.salsa.Salsa20;
|
|
_ = stream.salsa.XSalsa20;
|
|
|
|
_ = nacl.Box;
|
|
_ = nacl.SecretBox;
|
|
_ = nacl.SealedBox;
|
|
|
|
_ = secureZero;
|
|
_ = timing_safe;
|
|
_ = ff;
|
|
_ = random;
|
|
_ = errors;
|
|
_ = tls;
|
|
_ = Certificate;
|
|
}
|
|
|
|
test "CSPRNG" {
|
|
const a = random.int(u64);
|
|
const b = random.int(u64);
|
|
const c = random.int(u64);
|
|
try std.testing.expect(a ^ b ^ c != 0);
|
|
}
|
|
|
|
test "issue #4532: no index out of bounds" {
|
|
const types = [_]type{
|
|
hash.Md5,
|
|
hash.Sha1,
|
|
hash.sha2.Sha224,
|
|
hash.sha2.Sha256,
|
|
hash.sha2.Sha384,
|
|
hash.sha2.Sha512,
|
|
hash.sha3.Sha3_224,
|
|
hash.sha3.Sha3_256,
|
|
hash.sha3.Sha3_384,
|
|
hash.sha3.Sha3_512,
|
|
hash.blake2.Blake2s128,
|
|
hash.blake2.Blake2s224,
|
|
hash.blake2.Blake2s256,
|
|
hash.blake2.Blake2b128,
|
|
hash.blake2.Blake2b256,
|
|
hash.blake2.Blake2b384,
|
|
hash.blake2.Blake2b512,
|
|
};
|
|
|
|
inline for (types) |Hasher| {
|
|
var block = [_]u8{'#'} ** Hasher.block_length;
|
|
var out1: [Hasher.digest_length]u8 = undefined;
|
|
var out2: [Hasher.digest_length]u8 = undefined;
|
|
const h0 = Hasher.init(.{});
|
|
var h = h0;
|
|
h.update(block[0..]);
|
|
h.final(&out1);
|
|
h = h0;
|
|
h.update(block[0..1]);
|
|
h.update(block[1..]);
|
|
h.final(&out2);
|
|
|
|
try std.testing.expectEqual(out1, out2);
|
|
}
|
|
}
|
|
|
|
/// Sets a slice to zeroes.
|
|
/// Prevents the store from being optimized out.
|
|
pub inline fn secureZero(comptime T: type, s: []volatile T) void {
|
|
@memset(s, 0);
|
|
}
|
|
|
|
test secureZero {
|
|
var a = [_]u8{0xfe} ** 8;
|
|
var b = [_]u8{0xfe} ** 8;
|
|
|
|
@memset(&a, 0);
|
|
secureZero(u8, &b);
|
|
|
|
try std.testing.expectEqualSlices(u8, &a, &b);
|
|
}
|
|
|
|
/// Deprecated in favor of `std.crypto`. To be removed after Zig 0.14.0 is released.
|
|
///
|
|
/// As a reminder, never use "utils" in a namespace (in any programming language).
|
|
/// https://ziglang.org/documentation/0.13.0/#Avoid-Redundancy-in-Names
|
|
pub const utils = struct {
|
|
/// Deprecated in favor of `std.crypto.secureZero`.
|
|
pub const secureZero = std.crypto.secureZero;
|
|
/// Deprecated in favor of `std.crypto.timing_safe.eql`.
|
|
pub const timingSafeEql = timing_safe.eql;
|
|
/// Deprecated in favor of `std.crypto.timing_safe.compare`.
|
|
pub const timingSafeCompare = timing_safe.compare;
|
|
/// Deprecated in favor of `std.crypto.timing_safe.add`.
|
|
pub const timingSafeAdd = timing_safe.add;
|
|
/// Deprecated in favor of `std.crypto.timing_safe.sub`.
|
|
pub const timingSafeSub = timing_safe.sub;
|
|
};
|