Add the dependency

In your project’s ziran.toml; pin ref to a commit for reproducible builds.

[dependencies.crypto]
git = "https://github.com/ziranlang/crypto.git"
ref = "master"

crypto/src/crypto.zi

crypto

Import with #import "crypto/crypto".

Equal :: (a: []u8, b: []u8) -> bool
Wipe :: (bytes: []u8)
Pbkdf2 :: (password: []u8, salt: []u8, iterations: s32, output: []u8) -> bool

Arbitrary salt length and output length; no silent truncation.

Source ↗

crypto/src/sha256.zi

sha256

Ordinary library procedures retain package-qualified native symbols. A consuming executable owns any explicit C ABI it chooses to export. SHA-256 and HMAC-SHA-256, extracted from Waozi’s Daochi implementation. Portable Ziran; no foreign cryptographic implementation.

Import with #import "crypto/sha256".

Sha256Context :: struct { state: [8]u32; bit_length: u64; block: [64]u8; block_length: s32; words: [64]u32; }
Sha256RoundConstants: [64]u32
Sha256RotateRight :: (value: u32, bits: u32) -> u32
Sha256Transform :: (context: *Sha256Context)

The buffered block. Each loader reads the block's 16 big-endian words where it lies; Sha256Rounds hashes them.

Sha256TransformBlock :: (context: *Sha256Context, block: []u8)

One 64-byte block from a slice, so portable bundles can hash too.

Sha256TransformAt :: (context: *Sha256Context, block: *u8)

One 64-byte block read in place at BLOCK, for the pointer forms. Without a bounds check per byte, a package hashes as fast on phones, which build at -Oz, as it did with Daochi Client's own SHA-256.

Sha256Rounds :: (context: *Sha256Context)

The message schedule from the block's first 16 words, then the 64 rounds.

Sha256Initialize :: (context: *Sha256Context)
Sha256Update :: (context: *Sha256Context, data: *u8, length: s64)
Sha256UpdateBytes :: (context: *Sha256Context, data: []u8)

Bytes from a slice, for portable bundles; Sha256Update takes a pointer.

Sha256Finish :: (context: *Sha256Context, output: *u8)
Sha256FinishBytes :: (context: *Sha256Context, output: []u8)

The digest into a slice of 32 bytes, for portable bundles.

Sha256 :: (data: *u8, length: s64, output: *u8)
HexCharacter :: (value: u8) -> u8
HexNibble :: (value: u8) -> s32
BytesToHex :: (bytes: *u8, length: s64, output: *u8, output_size: s64) -> s32
HexToBytes :: (hex: string, output: *u8, output_size: s64) -> s32
Sha256Hex :: (data: *u8, length: s64, output: *u8)
HmacBlockBytes :: 64

HMAC-SHA-256 and PBKDF2 keep the account key-file derivation format. Historical PBKDF2 exports included at most 32 salt bytes.

Sha256DigestBytes :: 32
Sha256UpdateText :: (context: *Sha256Context, value: string)
HmacSha256Input :: (key: *u8, key_length: s64, key_text: string, use_key_text: bool, data: *u8, data_length: s64, text: string, use_text: bool, output: *u8) -> s32
HmacSha256 :: (key: *u8, key_length: s64, data: *u8, data_length: s64, output: *u8) -> s32
HmacSha256Text :: (key: *u8, key_length: s64, data: string, output: *u8) -> s32
Sha256Of :: (data: string) -> [32]u8

String forms, by value, for callers that hash text: a string's digest, HMAC-SHA-256 under a string key, and PBKDF2-HMAC-SHA-256's first block, such as a vault key. Each matches the byte forms above.

HmacSha256Of :: (key: string, message: string) -> [32]u8
Pbkdf2Sha256 :: (password: string, salt: string, iterations: s32) -> [32]u8
HmacSha256TextKey :: (key: string, data: *u8, data_length: s64, output: *u8) -> s32

Source ↗

crypto/src/sha1.zi

sha1

SHA-1 is used only where Telegram's legacy key-exchange format requires it.

Import with #import "crypto/sha1".

Context :: struct { state: [5]u32; block: [64]u8; used: s32; length: u64; }
Rotate :: (x: u32, n: u32) -> u32
Transform :: (c: *Context)
Start :: (c: *Context)
Update :: (c: *Context, bytes: []u8)
Finish :: (c: *Context, output: []u8) -> bool
Sha1 :: (bytes: []u8, output: []u8) -> bool

Source ↗

crypto/src/aes.zi

aes

FIPS 197 AES-256. The S-box uses fixed field arithmetic, avoiding secret-indexed lookup tables. The IGE mode is Telegram's specified mode.

Import with #import "crypto/aes".

Key :: struct { bytes: [240]u8; valid: bool; }
Multiply :: (left: u8, right: u8) -> u8
Inverse :: (x: u8) -> u8
Rotate :: (x: u8, n: u32) -> u8
Sub :: (x: u8) -> u8
Unsub :: (x: u8) -> u8
Expand :: (bytes: []u8) -> Key
Add :: (state: []u8, key: *Key, round: s32)
Shift :: (state: []u8, decrypt: bool)
Mix :: (state: []u8, decrypt: bool)
Block :: (key: *Key, input: []u8, output: []u8, decrypt: bool) -> bool
Ige :: (key_bytes: []u8, iv: []u8, input: []u8, output: []u8, decrypt: bool) -> bool

Source ↗

crypto/src/bigint.zi

bigint

Fixed-width unsigned 2048-bit Montgomery arithmetic. Sixteen-bit limbs keep every product within u64 on all native targets. Exponent bits select results with masks; both multiplications execute for every bit.

Import with #import "crypto/bigint".

Integer :: struct { limbs: [128]u32; }
Modulus :: struct { value: Integer; squared: Integer; inverse: u32; valid: bool; }
FromBytes :: (bytes: []u8) -> Integer
ToBytes :: (value: *Integer, bytes: []u8) -> bool
Compare :: (a: *Integer, b: *Integer) -> s32
Subtract :: (a: *Integer, b: *Integer) -> Integer
Reduce :: (value: *Integer, modulus: *Integer, high: u32) -> Integer
Double :: (value: *Integer, modulus: *Integer) -> Integer
Prepare :: (bytes: []u8) -> Modulus
Multiply :: (a: *Integer, b: *Integer, modulus: *Modulus) -> Integer
Power :: (base_bytes: []u8, exponent: []u8, modulus: *Modulus, output: []u8) -> bool
Product :: (left: []u8, right: []u8, modulus: *Modulus, output: []u8) -> bool
Difference :: (left: []u8, right: []u8, modulus: *Modulus, output: []u8) -> bool

Source ↗

crypto/src/sha512.zi

sha512

FIPS 180-4 SHA-512 and HMAC-SHA-512 in portable Ziran.

Import with #import "crypto/sha512".

Context :: struct { state: [8]u64; block: [128]u8; used: s32; length: u64; }

The 80 round constants as high and low 32-bit halves, as portable

ConstantHalves: [160]u32
Constant :: (index: s32) -> u64
Rotate :: (x: u64, n: u64) -> u64
Transform :: (context: *Context)
Start :: (context: *Context)
Update :: (context: *Context, bytes: []u8)
Finish :: (context: *Context, output: []u8) -> bool
Sha512 :: (input: []u8, output: []u8) -> bool
Hmac :: (key: []u8, input: []u8, output: []u8) -> bool
Pbkdf2 :: (password: []u8, salt: []u8, iterations: s32, output: []u8) -> bool

Source ↗