Osy#the first language built for agents
Agents firstAgentic appsWorkflowsDurable Execution — built inSecurityTestingThe editorThe UI modelOne program

Reference / Function

Crypto.Md5Hex

Crypto.Md5Hex(s) → string (32-char lowercase hex MD5 of s's UTF-8 bytes)

MD5 of a string's UTF-8 bytes rendered as 32-character lowercase hex — the canonical C# fingerprint form. Deterministic, so it pushes down into SQL as Postgres md5(). For NON-adversarial content fingerprints and change detection only — MD5 is collision-broken and must never be used for security. Use Crypto.Sha256Hex instead.

stable1 example compiled by CIfunctioncryptostdlib

Summary#

Crypto.Md5Hex(s) returns the MD5 digest of s's UTF-8 bytes as a 32-character lowercase hex string — the canonical C# BitConverter.ToString(md5).Replace("-", "").ToLowerInvariant() form. It is deterministic: the same input always yields the same digest.

Signature#

Crypto.Md5Hex(<string> s) -> string

Description#

Not a security primitive#

MD5 is collision-broken. An attacker can construct two different inputs that produce the same digest — cheaply, on a laptop. So Crypto.Md5Hex must never be used to sign, authenticate, verify, or fingerprint anything an attacker could influence, and never for passwords. If a check answers the question "did this come from someone I trust?" or "has anyone tampered with this?", MD5 is the wrong tool and using it there is a real vulnerability, not a style issue.

Reach for these instead:

If you need to…Use
Hash a value that could be attacker-influencedCrypto.Sha256Hex
Prove a message came from a key holder, unalteredCrypto.HmacSha256Hex and Crypto.FixedTimeEquals
Store a passwordSecurity.HashPassword (BCrypt — salted and deliberately slow)

What it IS for — a non-adversarial content fingerprint#

Crypto.Md5Hex is kept because it is genuinely the right tool for a non-adversarial content fingerprint: hash a synthesized string and compare it to a stored hash to decide whether downstream work needs to re-run. Nobody is attacking your cache-invalidation key, and MD5 is cheap and stable.

Because it is deterministic, it pushes down into SQL: inside a query it renders as Postgres's md5(), which produces byte-identical lowercase hex, so in-memory and in-database results agree. (Crypto.Sha256Hex pushes down too, so you can use the secure hash in a query without giving that up.)

Examples#

// Safe use: deciding whether OUR OWN content changed, so we can skip redundant work.
// Nobody gains anything by forcing a cache miss here.
bool Changed(string content, string storedHash) {
  return Crypto.Md5Hex(content) != storedHash;
}
// Crypto.Md5Hex("hello")  ->  "5d41402abc4b2a76b9719d911017c592"

See also#

Related

Crypto.Sha256Hex

SHA-256 of a string's UTF-8 bytes as 64-character lowercase hex — the secure default hash. Deterministic, so it pushes…

Crypto.HmacSha256Hex and Crypto.FixedTimeEquals

HMAC-SHA-256 authenticates a message under a shared key — proving it came from a key holder and was not altered, which…

Text.Split

The C# string.Split: breaks a string on a separator and returns the substrings as a List<string> — iterable with…