// SHA-1 (FIPS 180-4). Included for RFC 4226/6238 compatibility: HOTP and
// TOTP default to SHA-1. SHA-1 is broken for collision resistance but remains
// the mandatory default for one-time passwords.

///|
const SHA1_H0 : UInt = 0x67452301U

///|
const SHA1_H1 : UInt = 0xEFCDAB89U

///|
const SHA1_H2 : UInt = 0x98BADCFEU

///|
const SHA1_H3 : UInt = 0x10325476U

///|
const SHA1_H4 : UInt = 0xC3D2E1F0U

///|
const SHA1_K1 : UInt = 0x5A827999U

///|
const SHA1_K2 : UInt = 0x6ED9EBA1U

///|
const SHA1_K3 : UInt = 0x8F1BBCDCU

///|
const SHA1_K4 : UInt = 0xCA62C1D6U

///|
fn rotl_u32(x : UInt, n : Int) -> UInt {
  (x << n) | (x >> (32 - n))
}

///|
/// Compute the SHA-1 digest of `data`, returning 20 raw bytes.
pub fn sha1(data : BytesView) -> Bytes {
  // Padded message: data || 0x80 || zero bytes || 64-bit big-endian bit length.
  let padded = Buffer()
  padded.write_bytesview(data)
  padded.write_byte(0x80)
  while padded.length() % 64 != 56 {
    padded.write_byte(0)
  }
  let bit_length = data.length() * 8
  padded.write_uint_be(0U) // high 32 bits (messages fit in low 32 bits)
  padded.write_uint_be(bit_length.reinterpret_as_uint()) // low 32 bits
  let msg = padded.to_bytes()

  let mut h0 = SHA1_H0
  let mut h1 = SHA1_H1
  let mut h2 = SHA1_H2
  let mut h3 = SHA1_H3
  let mut h4 = SHA1_H4

  let words = FixedArray::make(80, 0U)
  let block_count = msg.length() / 64
  for block in 0..