use nettle_sys::{
    nettle_hash, nettle_sha1, nettle_sha1_digest, nettle_sha1_init,
    nettle_sha1_update, sha1_ctx, SHA1_DIGEST_SIZE,
};
use std::default::Default;
use std::mem::zeroed;

use crate::hash::NettleHash;
use crate::hash::Hash;

/// Secure Hash Algorithm 1 (SHA-1) defined in FIPS 180-4
///
/// # Note
/// SHA-1 is no longer considered a secure cryptographic hash function. Only use it for legacy
/// applications.
pub struct Sha1 {
    context: sha1_ctx,
}

impl_write_for_hash!(Sha1);

impl Clone for Sha1 {
    fn clone(&self) -> Self {
        use std::intrinsics::copy_nonoverlapping;

        unsafe {
            let mut ctx: sha1_ctx = zeroed();
            copy_nonoverlapping(&self.context, &mut ctx, 1);

            Sha1 { context: ctx }
        }
    }
}

impl Default for Sha1 {
    fn default() -> Self {
        let mut ctx = unsafe { zeroed() };

        unsafe {
            nettle_sha1_init(&mut ctx as *mut _);
        }

        Sha1 { context: ctx }
    }
}

impl Hash for Sha1 {
    fn digest_size(&self) -> usize {
        SHA1_DIGEST_SIZE as usize
    }

    fn update(&mut self, data: &[u8]) {
        unsafe {
            nettle_sha1_update(
                &mut self.context as *mut _,
                data.len(),
                data.as_ptr(),
            );
        }
    }

    fn digest(&mut self, digest: &mut [u8]) {
        unsafe {
            nettle_sha1_digest(
                &mut self.context as *mut _,
                digest.len(),
                digest.as_mut_ptr(),
            );
        }
    }

    fn box_clone(&self) -> Box<dyn Hash> {
        Box::new(self.clone())
    }
}

impl NettleHash for Sha1 {
    type Context = sha1_ctx;

    unsafe fn nettle_hash() -> &'static nettle_hash {
        &nettle_sha1
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn do_nothing() {
        let _ = Sha1::default();
    }

    //  CAVS 11.0
    //  "SHA-1 ShortMsg" information
    //  SHA-1 tests are configured for BYTE oriented implementations
    //  Generated on Tue Mar 15 08:23:35 2011
    #[test]
    fn nist_cavs_short_msg() {
        let mut ctx = Sha1::default();
        let mut digest = vec![0u8; ctx.digest_size()];

        ctx.digest(&mut digest);
        assert_eq!(digest, b"\xda\x39\xa3\xee\x5e\x6b\x4b\x0d\x32\x55\xbf\xef\x95\x60\x18\x90\xaf\xd8\x07\x09");

        ctx.update(b"\x36");
        ctx.digest(&mut digest);
        assert_eq!(digest, b"\xc1\xdf\xd9\x6e\xea\x8c\xc2\xb6\x27\x85\x27\x5b\xca\x38\xac\x26\x12\x56\xe2\x78");

        ctx.update(b"\x19\x5a");
        ctx.digest(&mut digest);
        assert_eq!(digest, b"\x0a\x1c\x2d\x55\x5b\xbe\x43\x1a\xd6\x28\x8a\xf5\xa5\x4f\x93\xe0\x44\x9c\x92\x32");

        ctx.update(b"\xdf\x4b\xd2");
        ctx.digest(&mut digest);
        assert_eq!(digest, b"\xbf\x36\xed\x5d\x74\x72\x7d\xfd\x5d\x78\x54\xec\x6b\x1d\x49\x46\x8d\x8e\xe8\xaa");

        ctx.update(b"\x54\x9e\x95\x9e");
        ctx.digest(&mut digest);
        assert_eq!(digest, b"\xb7\x8b\xae\x6d\x14\x33\x8f\xfc\xcf\xd5\xd5\xb5\x67\x4a\x27\x5f\x6e\xf9\xc7\x17");

        ctx.update(b"\xf7\xfb\x1b\xe2\x05");
        ctx.digest(&mut digest);
        assert_eq!(digest, b"\x60\xb7\xd5\xbb\x56\x0a\x1a\xcf\x6f\xa4\x57\x21\xbd\x0a\xbb\x41\x9a\x84\x1a\x89");

        ctx.update(b"\xc0\xe5\xab\xea\xea\x63");
        ctx.digest(&mut digest);
        assert_eq!(digest, b"\xa6\xd3\x38\x45\x97\x80\xc0\x83\x63\x09\x0f\xd8\xfc\x7d\x28\xdc\x80\xe8\xe0\x1f");

        ctx.update(b"\x63\xbf\xc1\xed\x7f\x78\xab");
        ctx.digest(&mut digest);
        assert_eq!(digest, b"\x86\x03\x28\xd8\x05\x09\x50\x0c\x17\x83\x16\x9e\xbf\x0b\xa0\xc4\xb9\x4d\xa5\xe5");

        ctx.update(b"\x7e\x3d\x7b\x3e\xad\xa9\x88\x66");
        ctx.digest(&mut digest);
        assert_eq!(digest, b"\x24\xa2\xc3\x4b\x97\x63\x05\x27\x7c\xe5\x8c\x2f\x42\xd5\x09\x20\x31\x57\x25\x20");

        ctx.update(b"\x9e\x61\xe5\x5d\x9e\xd3\x7b\x1c\x20");
        ctx.digest(&mut digest);
        assert_eq!(digest, b"\x41\x1c\xce\xe1\xf6\xe3\x67\x7d\xf1\x26\x98\x41\x1e\xb0\x9d\x3f\xf5\x80\xaf\x97");

        ctx.update(b"\x97\x77\xcf\x90\xdd\x7c\x7e\x86\x35\x06");
        ctx.digest(&mut digest);
        assert_eq!(digest, b"\x05\xc9\x15\xb5\xed\x4e\x4c\x4a\xff\xfc\x20\x29\x61\xf3\x17\x43\x71\xe9\x0b\x5c");

        ctx.update(b"\x4e\xb0\x8c\x9e\x68\x3c\x94\xbe\xa0\x0d\xfa");
        ctx.digest(&mut digest);
        assert_eq!(digest, b"\xaf\x32\x0b\x42\xd7\x78\x5c\xa6\xc8\xdd\x22\x04\x63\xbe\x23\xa2\xd2\xcb\x5a\xfc");

        ctx.update(b"\x09\x38\xf2\xe2\xeb\xb6\x4f\x8a\xf8\xbb\xfc\x91");
        ctx.digest(&mut digest);
        assert_eq!(digest, b"\x9f\x4e\x66\xb6\xce\xea\x40\xdc\xf4\xb9\x16\x6c\x28\xf1\xc8\x84\x74\x14\x1d\xa9");

        ctx.update(b"\x74\xc9\x99\x6d\x14\xe8\x7d\x3e\x6c\xbe\xa7\x02\x9d");
        ctx.digest(&mut digest);
        assert_eq!(digest, b"\xe6\xc4\x36\x3c\x08\x52\x95\x19\x91\x05\x7f\x40\xde\x27\xec\x08\x90\x46\x6f\x01");

        ctx.update(b"\x51\xdc\xa5\xc0\xf8\xe5\xd4\x95\x96\xf3\x2d\x3e\xb8\x74");
        ctx.digest(&mut digest);
        assert_eq!(digest, b"\x04\x6a\x7b\x39\x6c\x01\x37\x9a\x68\x4a\x89\x45\x58\x77\x9b\x07\xd8\xc7\xda\x20");

        ctx.update(
            b"\x3a\x36\xea\x49\x68\x48\x20\xa2\xad\xc7\xfc\x41\x75\xba\x78",
        );
        ctx.digest(&mut digest);
        assert_eq!(digest, b"\xd5\x8a\x26\x2e\xe7\xb6\x57\x7c\x07\x22\x8e\x71\xae\x9b\x3e\x04\xc8\xab\xcd\xa9");

        ctx.update(
            b"\x35\x52\x69\x4c\xdf\x66\x3f\xd9\x4b\x22\x47\x47\xac\x40\x6a\xaf",
        );
        ctx.digest(&mut digest);
        assert_eq!(digest, b"\xa1\x50\xde\x92\x74\x54\x20\x2d\x94\xe6\x56\xde\x4c\x7c\x0c\xa6\x91\xde\x95\x5d");

        ctx.update(b"\xf2\x16\xa1\xcb\xde\x24\x46\xb1\xed\xf4\x1e\x93\x48\x1d\x33\xe2\xed");
        ctx.digest(&mut digest);
        assert_eq!(digest, b"\x35\xa4\xb3\x9f\xef\x56\x0e\x7e\xa6\x12\x46\x67\x6e\x1b\x7e\x13\xd5\x87\xbe\x30");

        ctx.update(b"\xa3\xcf\x71\x4b\xf1\x12\x64\x7e\x72\x7e\x8c\xfd\x46\x49\x9a\xcd\x35\xa6");
        ctx.digest(&mut digest);
        assert_eq!(digest, b"\x7c\xe6\x9b\x1a\xcd\xce\x52\xea\x7d\xbd\x38\x25\x31\xfa\x1a\x83\xdf\x13\xca\xe7");

        ctx.update(b"\x14\x8d\xe6\x40\xf3\xc1\x15\x91\xa6\xf8\xc5\xc4\x86\x32\xc5\xfb\x79\xd3\xb7");
        ctx.digest(&mut digest);
        assert_eq!(digest, b"\xb4\x7b\xe2\xc6\x41\x24\xfa\x9a\x12\x4a\x88\x7a\xf9\x55\x1a\x74\x35\x4c\xa4\x11");

        ctx.update(b"\x63\xa3\xcc\x83\xfd\x1e\xc1\xb6\x68\x0e\x99\x74\xa0\x51\x4e\x1a\x9e\xce\xbb\x6a");
        ctx.digest(&mut digest);
        assert_eq!(digest, b"\x8b\xb8\xc0\xd8\x15\xa9\xc6\x8a\x1d\x29\x10\xf3\x9d\x94\x26\x03\xd8\x07\xfb\xcc");

        ctx.update(b"\x87\x5a\x90\x90\x9a\x8a\xfc\x92\xfb\x70\x70\x04\x7e\x9d\x08\x1e\xc9\x2f\x3d\x08\xb8");
        ctx.digest(&mut digest);
        assert_eq!(digest, b"\xb4\x86\xf8\x7f\xb8\x33\xeb\xf0\x32\x83\x93\x12\x86\x46\xa6\xf6\xe6\x60\xfc\xb1");

        ctx.update(b"\x44\x4b\x25\xf9\xc9\x25\x9d\xc2\x17\x77\x2c\xc4\x47\x8c\x44\xb6\xfe\xff\x62\x35\x36\x73");
        ctx.digest(&mut digest);
        assert_eq!(digest, b"\x76\x15\x93\x68\xf9\x9d\xec\xe3\x0a\xad\xcf\xb9\xb7\xb4\x1d\xab\x33\x68\x88\x58");

        ctx.update(b"\x48\x73\x51\xc8\xa5\xf4\x40\xe4\xd0\x33\x86\x48\x3d\x5f\xe7\xbb\x66\x9d\x41\xad\xcb\xfd\xb7");
        ctx.digest(&mut digest);
        assert_eq!(digest, b"\xdb\xc1\xcb\x57\x5c\xe6\xae\xb9\xdc\x4e\xbf\x0f\x84\x3b\xa8\xae\xb1\x45\x1e\x89");

        ctx.update(b"\x46\xb0\x61\xef\x13\x2b\x87\xf6\xd3\xb0\xee\x24\x62\xf6\x7d\x91\x09\x77\xda\x20\xae\xd1\x37\x05");
        ctx.digest(&mut digest);
        assert_eq!(digest, b"\xd7\xa9\x82\x89\x67\x90\x05\xeb\x93\x0a\xb7\x5e\xfd\x8f\x65\x0f\x99\x1e\xe9\x52");

        ctx.update(b"\x38\x42\xb6\x13\x7b\xb9\xd2\x7f\x3c\xa5\xba\xfe\x5b\xbb\x62\x85\x83\x44\xfe\x4b\xa5\xc4\x15\x89\xa5");
        ctx.digest(&mut digest);
        assert_eq!(digest, b"\xfd\xa2\x6f\xa9\xb4\x87\x4a\xb7\x01\xed\x0b\xb6\x4d\x13\x4f\x89\xb9\xc4\xcc\x50");

        ctx.update(b"\x44\xd9\x1d\x3d\x46\x5a\x41\x11\x46\x2b\xa0\xc7\xec\x22\x3d\xa6\x73\x5f\x4f\x52\x00\x45\x3c\xf1\x32\xc3");
        ctx.digest(&mut digest);
        assert_eq!(digest, b"\xc2\xff\x7c\xcd\xe1\x43\xc8\xf0\x60\x1f\x69\x74\xb1\x90\x3e\xb8\xd5\x74\x1b\x6e");

        ctx.update(b"\xcc\xe7\x3f\x2e\xab\xcb\x52\xf7\x85\xd5\xa6\xdf\x63\xc0\xa1\x05\xf3\x4a\x91\xca\x23\x7f\xe5\x34\xee\x39\x9d");
        ctx.digest(&mut digest);
        assert_eq!(digest, b"\x64\x3c\x9d\xc2\x0a\x92\x96\x08\xf6\xca\xa9\x70\x9d\x84\x3c\xa6\xfa\x7a\x76\xf4");

        ctx.update(b"\x66\x4e\x6e\x79\x46\x83\x92\x03\x03\x7a\x65\xa1\x21\x74\xb2\x44\xde\x8c\xbc\x6e\xc3\xf5\x78\x96\x7a\x84\xf9\xce");
        ctx.digest(&mut digest);
        assert_eq!(digest, b"\x50\x9e\xf7\x87\x34\x3d\x5b\x5a\x26\x92\x29\xb9\x61\xb9\x62\x41\x86\x4a\x3d\x74");

        ctx.update(b"\x95\x97\xf7\x14\xb2\xe4\x5e\x33\x99\xa7\xf0\x2a\xec\x44\x92\x1b\xd7\x8b\xe0\xfe\xfe\xe0\xc5\xe9\xb4\x99\x48\x8f\x6e");
        ctx.digest(&mut digest);
        assert_eq!(digest, b"\xb6\x1c\xe5\x38\xf1\xa1\xe6\xc9\x04\x32\xb2\x33\xd7\xaf\x5b\x65\x24\xeb\xfb\xe3");

        ctx.update(b"\x75\xc5\xad\x1f\x3c\xbd\x22\xe8\xa9\x5f\xc3\xb0\x89\x52\x67\x88\xfb\x4e\xbc\xee\xd3\xe7\xd4\x44\x3d\xa6\xe0\x81\xa3\x5e");
        ctx.digest(&mut digest);
        assert_eq!(digest, b"\x5b\x7b\x94\x07\x6b\x2f\xc2\x0d\x6a\xdb\x82\x47\x9e\x6b\x28\xd0\x7c\x90\x2b\x75");

        ctx.update(b"\xdd\x24\x5b\xff\xe6\xa6\x38\x80\x66\x67\x76\x83\x60\xa9\x5d\x05\x74\xe1\xa0\xbd\x0d\x18\x32\x9f\xdb\x91\x5c\xa4\x84\xac\x0d");
        ctx.digest(&mut digest);
        assert_eq!(digest, b"\x60\x66\xdb\x99\xfc\x35\x89\x52\xcf\x7f\xb0\xec\x4d\x89\xcb\x01\x58\xed\x91\xd7");

        ctx.update(b"\x03\x21\x79\x4b\x73\x94\x18\xc2\x4e\x7c\x2e\x56\x52\x74\x79\x1c\x4b\xe7\x49\x75\x2a\xd2\x34\xed\x56\xcb\x0a\x63\x47\x43\x0c\x6b");
        ctx.digest(&mut digest);
        assert_eq!(digest, b"\xb8\x99\x62\xc9\x4d\x60\xf6\xa3\x32\xfd\x60\xf6\xf0\x7d\x4f\x03\x2a\x58\x6b\x76");

        ctx.update(b"\x4c\x3d\xcf\x95\xc2\xf0\xb5\x25\x8c\x65\x1f\xcd\x1d\x51\xbd\x10\x42\x5d\x62\x03\x06\x7d\x07\x48\xd3\x7d\x13\x40\xd9\xdd\xda\x7d\xb3");
        ctx.digest(&mut digest);
        assert_eq!(digest, b"\x17\xbd\xa8\x99\xc1\x3d\x35\x41\x3d\x25\x46\x21\x2b\xcd\x8a\x93\xce\xb0\x65\x7b");

        ctx.update(b"\xb8\xd1\x25\x82\xd2\x5b\x45\x29\x0a\x6e\x1b\xb9\x5d\xa4\x29\xbe\xfc\xfd\xbf\x5b\x4d\xd4\x1c\xdf\x33\x11\xd6\x98\x8f\xa1\x7c\xec\x07\x23");
        ctx.digest(&mut digest);
        assert_eq!(digest, b"\xba\xdc\xdd\x53\xfd\xc1\x44\xb8\xbf\x2c\xc1\xe6\x4d\x10\xf6\x76\xee\xbe\x66\xed");

        ctx.update(b"\x6f\xda\x97\x52\x7a\x66\x25\x52\xbe\x15\xef\xae\xba\x32\xa3\xae\xa4\xed\x44\x9a\xbb\x5c\x1e\xd8\xd9\xbf\xff\x54\x47\x08\xa4\x25\xd6\x9b\x72");
        ctx.digest(&mut digest);
        assert_eq!(digest, b"\x01\xb4\x64\x61\x80\xf1\xf6\xd2\xe0\x6b\xbe\x22\xc2\x0e\x50\x03\x03\x22\x67\x3a");

        ctx.update(b"\x09\xfa\x27\x92\xac\xbb\x24\x17\xe8\xed\x26\x90\x41\xcc\x03\xc7\x70\x06\x46\x6e\x6e\x7a\xe0\x02\xcf\x3f\x1a\xf5\x51\xe8\xce\x0b\xb5\x06\xd7\x05");
        ctx.digest(&mut digest);
        assert_eq!(digest, b"\x10\x01\x6d\xc3\xa2\x71\x9f\x90\x34\xff\xcc\x68\x94\x26\xd2\x82\x92\xc4\x2f\xc9");

        ctx.update(b"\x5e\xfa\x29\x87\xda\x0b\xaf\x0a\x54\xd8\xd7\x28\x79\x2b\xcf\xa7\x07\xa1\x57\x98\xdc\x66\x74\x37\x54\x40\x69\x14\xd1\xcf\xe3\x70\x9b\x13\x74\xea\xeb");
        ctx.digest(&mut digest);
        assert_eq!(digest, b"\x9f\x42\xfa\x2b\xce\x6e\xf0\x21\xd9\x3c\x6b\x2d\x90\x22\x73\x79\x7e\x42\x65\x35");

        ctx.update(b"\x28\x36\xde\x99\xc0\xf6\x41\xcd\x55\xe8\x9f\x5a\xf7\x66\x38\x94\x7b\x82\x27\x37\x7e\xf8\x8b\xfb\xa6\x62\xe5\x68\x2b\xab\xc1\xec\x96\xc6\x99\x2b\xc9\xa0");
        ctx.digest(&mut digest);
        assert_eq!(digest, b"\xcd\xf4\x8b\xac\xbf\xf6\xf6\x15\x25\x15\x32\x3f\x9b\x43\xa2\x86\xe0\xcb\x81\x13");

        ctx.update(b"\x42\x14\x3a\x2b\x9e\x1d\x0b\x35\x4d\xf3\x26\x4d\x08\xf7\xb6\x02\xf5\x4a\xad\x92\x2a\x3d\x63\x00\x6d\x09\x7f\x68\x3d\xc1\x1b\x90\x17\x84\x23\xbf\xf2\xf7\xfe");
        ctx.digest(&mut digest);
        assert_eq!(digest, b"\xb8\x8f\xb7\x52\x74\xb9\xb0\xfd\x57\xc0\x04\x59\x88\xcf\xce\xf6\xc3\xce\x65\x54");

        ctx.update(b"\xeb\x60\xc2\x8a\xd8\xae\xda\x80\x7d\x69\xeb\xc8\x75\x52\x02\x4a\xd8\xac\xa6\x82\x04\xf1\xbc\xd2\x9d\xc5\xa8\x1d\xd2\x28\xb5\x91\xe2\xef\xb7\xc4\xdf\x75\xef\x03");
        ctx.digest(&mut digest);
        assert_eq!(digest, b"\xc0\x6d\x3a\x6a\x12\xd9\xe8\xdb\x62\xe8\xcf\xf4\x0c\xa2\x38\x20\xd6\x1d\x8a\xa7");

        ctx.update(b"\x7d\xe4\xba\x85\xec\x54\x74\x7c\xdc\x42\xb1\xf2\x35\x46\xb7\xe4\x90\xe3\x12\x80\xf0\x66\xe5\x2f\xac\x11\x7f\xd3\xb0\x79\x2e\x4d\xe6\x2d\x58\x43\xee\x98\xc7\x20\x15");
        ctx.digest(&mut digest);
        assert_eq!(digest, b"\x6e\x40\xf9\xe8\x3a\x4b\xe9\x38\x74\xbc\x97\xcd\xeb\xb8\xda\x68\x89\xae\x2c\x7a");

        ctx.update(b"\xe7\x06\x53\x63\x7b\xc5\xe3\x88\xcc\xd8\xdc\x44\xe5\xea\xce\x36\xf7\x39\x8f\x2b\xac\x99\x30\x42\xb9\xbc\x2f\x4f\xb3\xb0\xee\x7e\x23\xa9\x64\x39\xdc\x01\x13\x4b\x8c\x7d");
        ctx.digest(&mut digest);
        assert_eq!(digest, b"\x3e\xfc\x94\x0c\x31\x2e\xf0\xdf\xd4\xe1\x14\x38\x12\x24\x8d\xb8\x95\x42\xf6\xa5");

        ctx.update(b"\xdd\x37\xbc\x9f\x0b\x3a\x47\x88\xf9\xb5\x49\x66\xf2\x52\x17\x4c\x8c\xe4\x87\xcb\xe5\x9c\x53\xc2\x2b\x81\xbf\x77\x62\x1a\x7c\xe7\x61\x6d\xcb\x5b\x1e\x2e\xe6\x3c\x2c\x30\x9b");
        ctx.digest(&mut digest);
        assert_eq!(digest, b"\xa0\xcf\x03\xf7\xba\xdd\x0c\x3c\x3c\x4e\xa3\x71\x7f\x5a\x4f\xb7\xe6\x7b\x2e\x56");

        ctx.update(b"\x5f\x48\x5c\x63\x7a\xe3\x0b\x1e\x30\x49\x7f\x0f\xb7\xec\x36\x4e\x13\xc9\x06\xe2\x81\x3d\xaa\x34\x16\x1b\x7a\xc4\xa4\xfd\x7a\x1b\xdd\xd7\x96\x01\xbb\xd2\x2c\xef\x1f\x57\xcb\xc7");
        ctx.digest(&mut digest);
        assert_eq!(digest, b"\xa5\x44\xe0\x6f\x1a\x07\xce\xb1\x75\xa5\x1d\x6d\x9c\x01\x11\xb3\xe1\x5e\x98\x59");

        ctx.update(b"\xf6\xc2\x37\xfb\x3c\xfe\x95\xec\x84\x14\xcc\x16\xd2\x03\xb4\x87\x4e\x64\x4c\xc9\xa5\x43\x46\x5c\xad\x2d\xc5\x63\x48\x8a\x65\x9e\x8a\x2e\x7c\x98\x1e\x2a\x9f\x22\xe5\xe8\x68\xff\xe1");
        ctx.digest(&mut digest);
        assert_eq!(digest, b"\x19\x9d\x98\x6e\xd9\x91\xb9\x9a\x07\x1f\x45\x0c\x6b\x11\x21\xa7\x27\xe8\xc7\x35");

        ctx.update(b"\xda\x7a\xb3\x29\x15\x53\xc6\x59\x87\x3c\x95\x91\x37\x68\x95\x3c\x6e\x52\x6d\x3a\x26\x59\x08\x98\xc0\xad\xe8\x9f\xf5\x6f\xbd\x11\x0f\x14\x36\xaf\x59\x0b\x17\xfe\xd4\x9f\x8c\x4b\x2b\x1e");
        ctx.digest(&mut digest);
        assert_eq!(digest, b"\x33\xba\xc6\x10\x4b\x0a\xd6\x12\x8d\x09\x1b\x5d\x5e\x29\x99\x09\x9c\x9f\x05\xde");

        ctx.update(b"\x8c\xfa\x5f\xd5\x6e\xe2\x39\xca\x47\x73\x75\x91\xcb\xa1\x03\xe4\x1a\x18\xac\xf8\xe8\xd2\x57\xb0\xdb\xe8\x85\x11\x34\xa8\x1f\xf6\xb2\xe9\x71\x04\xb3\x9b\x76\xe1\x9d\xa2\x56\xa1\x7c\xe5\x2d");
        ctx.digest(&mut digest);
        assert_eq!(digest, b"\x76\xd7\xdb\x6e\x18\xc1\xf4\xae\x22\x5c\xe8\xcc\xc9\x3c\x8f\x9a\x0d\xfe\xb9\x69");

        ctx.update(b"\x57\xe8\x96\x59\xd8\x78\xf3\x60\xaf\x6d\xe4\x5a\x9a\x5e\x37\x2e\xf4\x0c\x38\x49\x88\xe8\x26\x40\xa3\xd5\xe4\xb7\x6d\x2e\xf1\x81\x78\x0b\x9a\x09\x9a\xc0\x6e\xf0\xf8\xa7\xf3\xf7\x64\x20\x97\x20");
        ctx.digest(&mut digest);
        assert_eq!(digest, b"\xf6\x52\xf3\xb1\x54\x9f\x16\x71\x0c\x74\x02\x89\x59\x11\xe2\xb8\x6a\x9b\x2a\xee");

        ctx.update(b"\xb9\x1e\x64\x23\x5d\xbd\x23\x4e\xea\x2a\xe1\x4a\x92\xa1\x73\xeb\xe8\x35\x34\x72\x39\xcf\xf8\xb0\x20\x74\x41\x6f\x55\xc6\xb6\x0d\xc6\xce\xd0\x6a\xe9\xf8\xd7\x05\x50\x5f\x0d\x61\x7e\x4b\x29\xae\xf9");
        ctx.digest(&mut digest);
        assert_eq!(digest, b"\x63\xfa\xeb\xb8\x07\xf3\x2b\xe7\x08\xcf\x00\xfc\x35\x51\x99\x91\xdc\x4e\x7f\x68");

        ctx.update(b"\xe4\x2a\x67\x36\x2a\x58\x1e\x8c\xf3\xd8\x47\x50\x22\x15\x75\x5d\x7a\xd4\x25\xca\x03\x0c\x43\x60\xb0\xf7\xef\x51\x3e\x69\x80\x26\x5f\x61\xc9\xfa\x18\xdd\x9c\xe6\x68\xf3\x8d\xbc\x2a\x1e\xf8\xf8\x3c\xd6");
        ctx.digest(&mut digest);
        assert_eq!(digest, b"\x0e\x67\x30\xbc\x4a\x0e\x93\x22\xea\x20\x5f\x4e\xdf\xff\x1f\xff\xda\x26\xaf\x0a");

        ctx.update(b"\x63\x4d\xb9\x2c\x22\x01\x0e\x1c\xbf\x1e\x16\x23\x92\x31\x80\x40\x6c\x51\x52\x72\x20\x9a\x8a\xcc\x42\xde\x05\xcc\x2e\x96\xa1\xe9\x4c\x1f\x9f\x6b\x93\x23\x4b\x7f\x4c\x55\xde\x8b\x19\x61\xa3\xbf\x35\x22\x59");
        ctx.digest(&mut digest);
        assert_eq!(digest, b"\xb6\x1a\x3a\x6f\x42\xe8\xe6\x60\x4b\x93\x19\x6c\x43\xc9\xe8\x4d\x53\x59\xe6\xfe");

        ctx.update(b"\xcc\x6c\xa3\xa8\xcb\x39\x1c\xd8\xa5\xaf\xf1\xfa\xa7\xb3\xff\xbd\xd2\x1a\x5a\x3c\xe6\x6c\xfa\xdd\xbf\xe8\xb1\x79\xe4\xc8\x60\xbe\x5e\xc6\x6b\xd2\xc6\xde\x6a\x39\xa2\x56\x22\xf9\xf2\xfc\xb3\xfc\x05\xaf\x12\xb5");
        ctx.digest(&mut digest);
        assert_eq!(digest, b"\x32\xd9\x79\xca\x1b\x3e\xd0\xed\x8c\x89\x0d\x99\xec\x6d\xd8\x5e\x6c\x16\xab\xf4");

        ctx.update(b"\x7c\x0e\x6a\x0d\x35\xf8\xac\x85\x4c\x72\x45\xeb\xc7\x36\x93\x73\x1b\xbb\xc3\xe6\xfa\xb6\x44\x46\x6d\xe2\x7b\xb5\x22\xfc\xb9\x93\x07\x12\x6a\xe7\x18\xfe\x8f\x00\x74\x2e\x6e\x5c\xb7\xa6\x87\xc8\x84\x47\xcb\xc9\x61");
        ctx.digest(&mut digest);
        assert_eq!(digest, b"\x6f\x18\x19\x0b\xd2\xd0\x2f\xc9\x3b\xce\x64\x75\x65\x75\xce\xa3\x6d\x08\xb1\xc3");

        ctx.update(b"\xc5\x58\x1d\x40\xb3\x31\xe2\x40\x03\x90\x1b\xd6\xbf\x24\x4a\xca\x9e\x96\x01\xb9\xd8\x12\x52\xbb\x38\x04\x86\x42\x73\x1f\x11\x46\xb8\xa4\xc6\x9f\x88\xe1\x48\xb2\xc8\xf8\xc1\x4f\x15\xe1\xd6\xda\x57\xb2\xda\xa9\x99\x1e");
        ctx.digest(&mut digest);
        assert_eq!(digest, b"\x68\xf5\x25\xfe\xea\x1d\x8d\xbe\x01\x17\xe4\x17\xca\x46\x70\x8d\x18\xd7\x62\x9a");

        ctx.update(b"\xec\x6b\x4a\x88\x71\x3d\xf2\x7c\x0f\x2d\x02\xe7\x38\xb6\x9d\xb4\x3a\xbd\xa3\x92\x13\x17\x25\x9c\x86\x4c\x1c\x38\x6e\x9a\x5a\x3f\x53\x3d\xc0\x5f\x3b\xee\xb2\xbe\xc2\xaa\xc8\xe0\x6d\xb4\xc6\xcb\x3c\xdd\xcf\x69\x7e\x03\xd5");
        ctx.digest(&mut digest);
        assert_eq!(digest, b"\xa7\x27\x2e\x23\x08\x62\x2f\xf7\xa3\x39\x46\x0a\xdc\x61\xef\xd0\xea\x8d\xab\xdc");

        ctx.update(b"\x03\x21\x73\x6b\xeb\xa5\x78\xe9\x0a\xbc\x1a\x90\xaa\x56\x15\x7d\x87\x16\x18\xf6\xde\x0d\x76\x4c\xc8\xc9\x1e\x06\xc6\x8e\xcd\x3b\x9d\xe3\x82\x40\x64\x50\x33\x84\xdb\x67\xbe\xb7\xfe\x01\x22\x32\xda\xca\xef\x93\xa0\x00\xfb\xa7");
        ctx.digest(&mut digest);
        assert_eq!(digest, b"\xae\xf8\x43\xb8\x69\x16\xc1\x6f\x66\xc8\x4d\x83\xa6\x00\x5d\x23\xfd\x00\x5c\x9e");

        ctx.update(b"\xd0\xa2\x49\xa9\x7b\x5f\x14\x86\x72\x1a\x50\xd4\xc4\xab\x3f\x5d\x67\x4a\x0e\x29\x92\x5d\x5b\xf2\x67\x8e\xf6\xd8\xd5\x21\xe4\x56\xbd\x84\xaa\x75\x53\x28\xc8\x3f\xc8\x90\x83\x77\x26\xa8\xe7\x87\x7b\x57\x0d\xba\x39\x57\x9a\xab\xdd");
        ctx.digest(&mut digest);
        assert_eq!(digest, b"\xbe\x2c\xd6\xf3\x80\x96\x9b\xe5\x9c\xde\x2d\xff\x5e\x84\x8a\x44\xe7\x88\x0b\xd6");

        ctx.update(b"\xc3\x21\x38\x53\x11\x18\xf0\x8c\x7d\xcc\x29\x24\x28\xad\x20\xb4\x5a\xb2\x7d\x95\x17\xa1\x84\x45\xf3\x8b\x8f\x0c\x27\x95\xbc\xdf\xe3\xff\xe3\x84\xe6\x5e\xcb\xf7\x4d\x2c\x9d\x0d\xa8\x83\x98\x57\x53\x26\x07\x49\x04\xc1\x70\x9b\xa0\x72");
        ctx.digest(&mut digest);
        assert_eq!(digest, b"\xe5\xeb\x45\x43\xde\xee\x8f\x6a\x52\x87\x84\x5a\xf8\xb5\x93\xa9\x5a\x97\x49\xa1");

        ctx.update(b"\xb0\xf4\xcf\xb9\x39\xea\x78\x5e\xab\xb7\xe7\xca\x7c\x47\x6c\xdd\x9b\x22\x7f\x01\x5d\x90\x53\x68\xba\x00\xae\x96\xb9\xaa\xf7\x20\x29\x74\x91\xb3\x92\x12\x67\x57\x6b\x72\xc8\xf5\x8d\x57\x76\x17\xe8\x44\xf9\xf0\x75\x9b\x39\x9c\x6b\x06\x4c");
        ctx.digest(&mut digest);
        assert_eq!(digest, b"\x53\x4c\x85\x04\x48\xdd\x48\x67\x87\xb6\x2b\xde\xc2\xd4\xa0\xb1\x40\xa1\xb1\x70");

        ctx.update(b"\xbd\x02\xe5\x1b\x0c\xf2\xc2\xb8\xd2\x04\xa0\x26\xb4\x1a\x66\xfb\xfc\x2a\xc3\x7e\xe9\x41\x1f\xc4\x49\xc8\xd1\x19\x4a\x07\x92\xa2\x8e\xe7\x31\x40\x7d\xfc\x89\xb6\xdf\xc2\xb1\x0f\xaa\x27\x72\x3a\x18\x4a\xfe\xf8\xfd\x83\xde\xf8\x58\xa3\x2d\x3f");
        ctx.digest(&mut digest);
        assert_eq!(digest, b"\x6f\xbf\xa6\xe4\xed\xce\x4c\xc8\x5a\x84\x5b\xf0\xd2\x28\xdc\x39\xac\xef\xc2\xfa");

        ctx.update(b"\xe3\x31\x46\xb8\x3e\x4b\xb6\x71\x39\x22\x18\xda\x9a\x77\xf8\xd9\xf5\x97\x41\x47\x18\x2f\xb9\x5b\xa6\x62\xcb\x66\x01\x19\x89\xc1\x6d\x9a\xf1\x04\x73\x5d\x6f\x79\x84\x1a\xa4\xd1\xdf\x27\x66\x15\xb5\x01\x08\xdf\x8a\x29\xdb\xc9\xde\x31\xf4\x26\x0d");
        ctx.digest(&mut digest);
        assert_eq!(digest, b"\x01\x88\x72\x69\x1d\x9b\x04\xe8\x22\x0e\x09\x18\x7d\xf5\xbc\x5f\xa6\x25\x7c\xd9");

        ctx.update(b"\x41\x1c\x13\xc7\x50\x73\xc1\xe2\xd4\xb1\xec\xf1\x31\x39\xba\x96\x56\xcd\x35\xc1\x42\x01\xf1\xc7\xc6\xf0\xee\xb5\x8d\x2d\xbf\xe3\x5b\xfd\xec\xcc\x92\xc3\x96\x1c\xfa\xbb\x59\x0b\xc1\xeb\x77\xea\xc1\x57\x32\xfb\x02\x75\x79\x86\x80\xe0\xc7\x29\x2e\x50");
        ctx.digest(&mut digest);
        assert_eq!(digest, b"\xd9\x8d\x51\x2a\x35\x57\x2f\x8b\xd2\x0d\xe6\x2e\x95\x10\xcc\x21\x14\x5c\x5b\xf4");

        ctx.update(b"\xf2\xc7\x6e\xf6\x17\xfa\x2b\xfc\x8a\x4d\x6b\xcb\xb1\x5f\xe8\x84\x36\xfd\xc2\x16\x5d\x30\x74\x62\x95\x79\x07\x9d\x4d\x5b\x86\xf5\x08\x1a\xb1\x77\xb4\xc3\xf5\x30\x37\x6c\x9c\x92\x4c\xbd\x42\x1a\x8d\xaf\x88\x30\xd0\x94\x0c\x4f\xb7\x58\x98\x65\x83\x06\x99");
        ctx.digest(&mut digest);
        assert_eq!(digest, b"\x9f\x3e\xa2\x55\xf6\xaf\x95\xc5\x45\x4e\x55\xd7\x35\x4c\xab\xb4\x53\x52\xea\x0b");

        ctx.update(b"\x45\x92\x7e\x32\xdd\xf8\x01\xca\xf3\x5e\x18\xe7\xb5\x07\x8b\x7f\x54\x35\x27\x82\x12\xec\x6b\xb9\x9d\xf8\x84\xf4\x9b\x32\x7c\x64\x86\xfe\xae\x46\xba\x18\x7d\xc1\xcc\x91\x45\x12\x1e\x14\x92\xe6\xb0\x6e\x90\x07\x39\x4d\xc3\x3b\x77\x48\xf8\x6a\xc3\x20\x7c\xfe");
        ctx.digest(&mut digest);
        assert_eq!(digest, b"\xa7\x0c\xfb\xfe\x75\x63\xdd\x0e\x66\x5c\x7c\x67\x15\xa9\x6a\x8d\x75\x69\x50\xc0");
    }
}
