Standard library · Security and cryptography

crypto

SHA and MD5 digests, HMAC signatures, secure random numbers and password hashing.

import crypto
On this page
  1. Types
  2. Functions

This package gives the basic cryptography tools, all of them written in Salam. For the digest of a piece of text the ...Hex functions are the simplest way; the ...Bytes functions write the digest into memory you pass in yourself.

Never store a user password raw or under a plain digest; use HashPassword and VerifyPassword. To compare tokens, use SecretEquals rather than ==. To encrypt data, see the tls package.

Types

Sha256

struct Sha256
The SHA-256 state for data that arrives in pieces, such as a large file.
NameTypeDescription
hu32[]The internal state.
blku8[]The partial block.
blenint = 0The length of the partial block.
totalu64 = 0The total number of bytes.
crypto-Hash.salam
import crypto
import encoding
import mem

func main:
    println crypto.Sha256Hex("abc")
    println crypto.Sha512Hex("abc").len()
    println crypto.Sha1Hex("abc")
    println crypto.Sha1Base64("abc")
    println crypto.Md5Hex("abc")

    text := "abc"
    out := mem.Allocate(64 as u64)
    crypto.Sha256Bytes(text as void*, 3, out)
    println encoding.Base64EncodeBytes(out, 32)
    crypto.Sha384Bytes(text as void*, 3, out)
    println encoding.Base64EncodeBytes(out, 48)
    crypto.Sha512Bytes(text as void*, 3, out)
    println encoding.Base64EncodeBytes(out, 16).len()
    crypto.Sha1Bytes(text as void*, 3, out)
    println encoding.Base64EncodeBytes(out, 20)
    crypto.Md5Bytes(text as void*, 3, out)
    println encoding.Base64EncodeBytes(out, 16)

    mut h := crypto.Sha256New()
    crypto.Sha256Update(h, "a" as void*, 1)
    crypto.Sha256Update(h, "bc" as void*, 2)
    crypto.Sha256Final(h, out)
    println encoding.Base64EncodeBytes(out, 32)
    mut b := crypto.Sha512New()
    crypto.Sha512Update(b, text as void*, 3)
    crypto.Sha512Final(b, out)
    println b.outlen
    mut s := crypto.Sha384New()
    crypto.Sha512Update(s, text as void*, 3)
    crypto.Sha512Final(s, out)
    println s.outlen, encoding.Base64EncodeBytes(out, 48)
    mem.Free(out)

    println crypto.HashStr("hello") == crypto.HashStr("hello"), crypto.HashStr("a") != crypto.HashStr("b")
    println crypto.HashBytes(text as void*, 3 as u64) == crypto.HashStr("abc")
    println crypto.HashInt(42 as u64) != crypto.HashInt(43 as u64)
end
Outputba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad 128 a9993e364706816aba3e25717850c26c9cd0d89d qZk+NkcGgWq6PiVxeFDCbJzQ2J0= 900150983cd24fb0d6963f7d28e17f72 ungWv48Bz+pBQUDeXa4iI7ADYaOWF3qctBD/YfIAFa0= ywB1P0WjXou1oD1pmsZQBycsMqsO3tFjGotgWkP/W+2AhgcroefMI1i67KE0yCWn 24 qZk+NkcGgWq6PiVxeFDCbJzQ2J0= kAFQmDzST7DWlj99KOF/cg== ungWv48Bz+pBQUDeXa4iI7ADYaOWF3qctBD/YfIAFa0= 64 48 ywB1P0WjXou1oD1pmsZQBycsMqsO3tFjGotgWkP/W+2AhgcroefMI1i67KE0yCWn true true true true

Sha512

struct Sha512
The SHA-512 or SHA-384 state for data in pieces.
NameTypeDescription
hu64[]The internal state.
blku8[]The partial block.
blenint = 0The length of the partial block.
totalu64 = 0The total number of bytes.
outlenint = 64The digest length: 64 for SHA-512 and 48 for SHA-384.

The example for this item is shown with the ones above: crypto-Hash.salam

Functions

Sha256Hex

func Sha256Hex(data: str): str
The SHA-256 digest as hex, 64 characters.

The example for this item is shown with the ones above: crypto-Hash.salam

Pbkdf2HmacSha256Hex

func Pbkdf2HmacSha256Hex(password: str, salt: str, iterations: int, keylen: int): str
Derives a key with PBKDF2-HMAC-SHA256 from a password and a salt, at the given iteration count.
crypto-Password.salam
import crypto
import str
import mem

func main:
    stored := crypto.HashPassword("s3cret-password")
    println str.StartsWith(stored, "pbkdf2-sha256$")
    println crypto.VerifyPassword("s3cret-password", stored), crypto.VerifyPassword("wrong", stored)
    println stored != crypto.HashPassword("s3cret-password")

    println crypto.Pbkdf2HmacSha256Hex("password", "salt", 1, 32)
    println crypto.SecretEquals("abc", "abc"), crypto.SecretEquals("abc", "xyz")

    println crypto.RandomHex(16).len(), crypto.RandomToken(32).len() > 0
    b := mem.Allocate(8 as u64)
    crypto.RandomBytes(b, 8)
    mem.Free(b)
end
Outputtrue true false true 120fb6cffcf8b32c43e7225256c4f837a86548c92ccc35480805987cb70be17b true false 32 true

HashPassword

func HashPassword(password: str): str
Hashes the password with a random salt and returns a string of the form pbkdf2-sha256$iterations$salt$hash to keep in your database. The output is different every time.

The example for this item is shown with the ones above: crypto-Password.salam

VerifyPassword

func VerifyPassword(password: str, encoded: str): bool
Checks a password against a string that HashPassword made.

The example for this item is shown with the ones above: crypto-Password.salam

SecretEquals

func SecretEquals(a: str, b: str): bool
Compares two secrets in constant time, so the answer time gives nothing away about them; for tokens and signatures.

The example for this item is shown with the ones above: crypto-Password.salam

HmacSha256Hex

func HmacSha256Hex(key: str, msg: str): str
The HMAC-SHA256 signature of a message under a key, as hex; for checking that the message is untouched and comes from whoever holds the key.
crypto-Hmac.salam
import crypto
import encoding
import mem

func main:
    key := "key"
    message := "The quick brown fox jumps over the lazy dog"
    println crypto.HmacSha256Hex(key, message)
    println crypto.HmacSha1Hex(key, message)
    println crypto.HmacSha1Base64(key, message)
    println crypto.HmacSha384Hex(key, message).len(), crypto.HmacSha512Hex(key, message).len()

    out := mem.Allocate(64 as u64)
    crypto.HmacSha256Bytes(key, message, out)
    a := encoding.Base64EncodeBytes(out, 32)
    crypto.HmacSha256Raw(key as void*, 3, message as void*, message.len(), out)
    println a == encoding.Base64EncodeBytes(out, 32)
    crypto.HmacSha1Bytes(key, message, out)
    b := encoding.Base64EncodeBytes(out, 20)
    crypto.HmacSha1Raw(key as void*, 3, message as void*, message.len(), out)
    println b == encoding.Base64EncodeBytes(out, 20), b == crypto.HmacSha1Base64(key, message)
    crypto.HmacSha384Bytes(key, message, out)
    c := encoding.Base64EncodeBytes(out, 48)
    crypto.HmacSha384Raw(key as void*, 3, message as void*, message.len(), out)
    println c == encoding.Base64EncodeBytes(out, 48)
    crypto.HmacSha512Bytes(key, message, out)
    d := encoding.Base64EncodeBytes(out, 64)
    crypto.HmacSha512Raw(key as void*, 3, message as void*, message.len(), out)
    println d == encoding.Base64EncodeBytes(out, 64)
    mem.Free(out)
end
Outputf7bc83f430538424b13298e6aa6fb143ef4d59a14946175997479dbc2d1a3cd8 de7c9b85b8b78aa6bc8a7a36f70a90701c9db4d9 3nybhbi3iqa8ino29wqQcBydtNk= 96 128 true true true true true

Sha1Hex

func Sha1Hex(data: str): str
The SHA-1 digest as hex. SHA-1 is no longer strong enough for security either; use SHA-256 for signatures.

The example for this item is shown with the ones above: crypto-Hash.salam

Sha1Base64

func Sha1Base64(data: str): str
The SHA-1 digest as base64; for the WebSocket handshake, for instance.

The example for this item is shown with the ones above: crypto-Hash.salam

Sha1Bytes

func Sha1Bytes(p: void*, n: int, out: void*)
Writes the SHA-1 digest, 20 bytes, into the output.

The example for this item is shown with the ones above: crypto-Hash.salam

Sha256Bytes

func Sha256Bytes(p: void*, n: int, out: void*)
Writes the SHA-256 digest, 32 bytes, into the output.

The example for this item is shown with the ones above: crypto-Hash.salam

Sha384Bytes

func Sha384Bytes(p: void*, n: int, out: void*)
The SHA-384 digest, 48 bytes.

The example for this item is shown with the ones above: crypto-Hash.salam

Sha512Bytes

func Sha512Bytes(p: void*, n: int, out: void*)
The SHA-512 digest, 64 bytes.

The example for this item is shown with the ones above: crypto-Hash.salam

Sha256New

func Sha256New(): Sha256
A fresh SHA-256 state.

The example for this item is shown with the ones above: crypto-Hash.salam

Sha256Update

func Sha256Update(s &: Sha256, p: void*, n: int)
Adds the next piece of data.

The example for this item is shown with the ones above: crypto-Hash.salam

Sha256Final

func Sha256Final(s: Sha256, out: void*)
Writes the final digest into the output.

The example for this item is shown with the ones above: crypto-Hash.salam

Sha384New

func Sha384New(): Sha512
A fresh SHA-384 state; carry on with the Sha512 functions.

The example for this item is shown with the ones above: crypto-Hash.salam

Sha512New

func Sha512New(): Sha512
A fresh SHA-512 state.

The example for this item is shown with the ones above: crypto-Hash.salam

Sha512Update

func Sha512Update(s &: Sha512, p: void*, n: int)
Adds the next piece of data.

The example for this item is shown with the ones above: crypto-Hash.salam

Sha512Final

func Sha512Final(s: Sha512, out: void*)
Writes the final digest at the length in outlen.

The example for this item is shown with the ones above: crypto-Hash.salam

HashBytes

func HashBytes(p: void*, n: u64): u64
A fast, non cryptographic hash of some bytes; for hash tables and the like, not for security.

The example for this item is shown with the ones above: crypto-Hash.salam

HashStr

func HashStr(s: str): u64
A fast hash of a string.

The example for this item is shown with the ones above: crypto-Hash.salam

HashInt

func HashInt(x: u64): u64
A fast hash of a number.

The example for this item is shown with the ones above: crypto-Hash.salam

RandomHex

func RandomHex(n: int): str
n secure random bytes from the operating system, as hex with 2n characters; for ids and salts.

The example for this item is shown with the ones above: crypto-Password.salam

RandomToken

func RandomToken(n: int): str
A secure random token of n bytes, as url safe base64; for session and password reset tokens.

The example for this item is shown with the ones above: crypto-Password.salam

RandomBytes

func RandomBytes(p: void*, n: int)
Writes n secure random bytes into the given memory. When the operating system cannot, the program stops.

The example for this item is shown with the ones above: crypto-Password.salam

Md5Bytes

func Md5Bytes(p: void*, n: int, out: void*)
Writes the MD5 digest, 16 bytes, into the output. MD5 is broken; only for compatibility with old systems.

The example for this item is shown with the ones above: crypto-Hash.salam

Md5Hex

func Md5Hex(data: str): str
The MD5 digest as hex.

The example for this item is shown with the ones above: crypto-Hash.salam

HmacSha256Raw

func HmacSha256Raw(key: void*, klen: int, msg: void*, mlen: int, out: void*)
HMAC-SHA256 with the key and message given as a pointer and a length; for binary data.

The example for this item is shown with the ones above: crypto-Hmac.salam

HmacSha384Raw

func HmacSha384Raw(key: void*, klen: int, msg: void*, mlen: int, out: void*)
Raw HMAC-SHA384.

The example for this item is shown with the ones above: crypto-Hmac.salam

HmacSha512Raw

func HmacSha512Raw(key: void*, klen: int, msg: void*, mlen: int, out: void*)
Raw HMAC-SHA512.

The example for this item is shown with the ones above: crypto-Hmac.salam

HmacSha256Bytes

func HmacSha256Bytes(key: str, msg: str, out: void*)
Writes HMAC-SHA256, 32 bytes, into the output.

The example for this item is shown with the ones above: crypto-Hmac.salam

HmacSha384Bytes

func HmacSha384Bytes(key: str, msg: str, out: void*)
HMAC-SHA384, 48 bytes.

The example for this item is shown with the ones above: crypto-Hmac.salam

HmacSha512Bytes

func HmacSha512Bytes(key: str, msg: str, out: void*)
HMAC-SHA512, 64 bytes.

The example for this item is shown with the ones above: crypto-Hmac.salam

HmacSha384Hex

func HmacSha384Hex(key: str, msg: str): str
HMAC-SHA384 as hex.

The example for this item is shown with the ones above: crypto-Hmac.salam

HmacSha512Hex

func HmacSha512Hex(key: str, msg: str): str
HMAC-SHA512 as hex.

The example for this item is shown with the ones above: crypto-Hmac.salam

Sha512Hex

func Sha512Hex(data: str): str
The SHA-512 digest as hex, 128 characters.

The example for this item is shown with the ones above: crypto-Hash.salam

HmacSha1Raw

func HmacSha1Raw(key: void*, klen: int, msg: void*, mlen: int, out: void*)
Raw HMAC-SHA1.

The example for this item is shown with the ones above: crypto-Hmac.salam

HmacSha1Bytes

func HmacSha1Bytes(key: str, msg: str, out: void*)
HMAC-SHA1, 20 bytes.

The example for this item is shown with the ones above: crypto-Hmac.salam

HmacSha1Hex

func HmacSha1Hex(key: str, msg: str): str
HMAC-SHA1 as hex; for old services.

The example for this item is shown with the ones above: crypto-Hmac.salam

HmacSha1Base64

func HmacSha1Base64(key: str, msg: str): str
HMAC-SHA1 as base64; an OAuth 1 signature, for instance.

The example for this item is shown with the ones above: crypto-Hmac.salam