Standard library · Cryptography
crypto/passwd
Imported as import "crypto/passwd" as passwd, its names are then passwd.…. Every signature below is the one the checker infers.
Functions
fn hmac_sha1(key: Str, msg: Str) -> Str
HMAC-SHA-1. A key longer than the block is hashed down to fit; a shorter one is padded with zeros, which is why a key of nulls and an empty key are the same key — a property of the construction, not of this writing of it.
passwd.to_hex(passwd.hmac_sha1("key", "The quick brown fox jumps over the lazy dog")) # => de7c9b85b8b78aa6bc8a7a36f70a90701c9db4d9
fn xor_byte(s: Str, b: Int) -> Str
Every byte of a string against one constant. The pads of HMAC are nothing more than this.
passwd.xor_byte("AB", 32) # => ab
fn xor_str(a: Str, b: Str) -> Str
Two strings of the same length, byte against byte. PBKDF2 folds its rounds together this way.
passwd.to_hex(passwd.xor_str("AB", " ")) # => 6162
fn pbkdf2_sha1(key: Str, salt: Str, rounds: Int) -> Str
PBKDF2-HMAC-SHA-1, one block of it: twenty bytes, which is all this asks for and all a SHA-1 has to give. The block index the specification appends is therefore always one.
rounds is a count, not a duration. It is written down where the accounts are made rather than here, so that raising it later is one number in one place — and so that a stored password can say which count made it.
passwd.to_hex(passwd.pbkdf2_sha1("password", "salt", 2)) # => ea6c014dc72d6f8ccd1ed92ace1d41f0d8de8957
fn to_hex(s: Str) -> Str
passwd.to_hex("AZ") # => 415a
fn from_hex(s: Str) -> Str
passwd.from_hex("415a") # => AZ
fn same_secret(a: Str, b: Str) -> Int
Whether two secrets are the same, in a time that does not depend on how far along they first differ.
The obvious a == b returns the moment it finds a mismatched byte, and how long it took is a measurement of how much of the answer was right — over enough tries, that is the answer. This walks both in full and folds the differences together. Unequal lengths are refused up front: that much is public, since the length of a hash is a constant of the scheme.
passwd.same_secret("abc", "abc") # => 1 passwd.same_secret("abc", "abd") # => 0 passwd.same_secret("abc", "abcd") # => 0