Rust 加密写入 与 解密读

use cipher::{
    block_padding::{Padding, Pkcs7},
    generic_array::GenericArray,
    BlockDecryptMut, BlockEncryptMut, Unsigned,
};

use std::io::{ErrorKind, Read, Write};
pub struct EncryptWriter<C: BlockEncryptMut, W: Write> {
    inner: W,
    cipher: C,
    last_block: GenericArray<u8, C::BlockSize>,
    pos: usize,
}
impl<C: BlockEncryptMut, W: Write> EncryptWriter<C, W> {
    pub fn new(inner: W, cipher: C) -> Self {
        Self {
            inner,
            cipher,
            last_block: GenericArray::default(),
            pos: 0,
        }
    }
}
impl<C: BlockEncryptMut, W: Write> Write for EncryptWriter<C, W> {
    fn write(&mut self, mut buf: &[u8]) -> std::io::Result<usize> {
        let block_size = C::block_size();
        let mut written = 0;
        if self.pos > 0 {
            let len = self.last_block.len() - self.pos;
            if len > buf.len() {
                self.last_block[self.pos..self.pos + buf.len()].copy_from_slice(buf);
                self.pos += buf.len();
                return Ok(buf.len());
            } else {
                self.last_block[self.pos..].copy_from_slice(&buf[..len]);
                let mut block = self.last_block.clone();
                self.cipher.encrypt_block_mut(&mut block);
                self.inner.write_all(&block)?;
                written += len;
                self.pos = 0;
                buf = &buf[len..];
            }
        }
        let full_blocks = buf.len() / block_size;
        let (buf, last) = buf.split_at(full_blocks * block_size);
        for chunk in buf.chunks(block_size) {
            let mut block = GenericArray::clone_from_slice(chunk);
            self.cipher.encrypt_block_mut(&mut block);
            self.inner.write_all(&block)?;
            written += block_size;
        }
        self.last_block[..last.len()].copy_from_slice(last);
        self.pos = last.len();
        written += last.len();
        Ok(written)
    }
    fn flush(&mut self) -> std::io::Result<()> {
        self.inner.flush()
    }
}

impl<C: BlockEncryptMut, W: Write> Drop for EncryptWriter<C, W> {
    fn drop(&mut self) {
        Pkcs7::pad(&mut self.last_block, self.pos);
        self.cipher.encrypt_block_mut(&mut self.last_block);
        self.inner.write_all(&self.last_block).unwrap();
        self.inner.flush().unwrap();
    }
}

pub struct DecryptoReader<C: BlockDecryptMut, R: Read> {
    inner: R,
    cipher: C,
    last_block: Option<GenericArray<u8, C::BlockSize>>,
    eof: bool,
}

impl<C: BlockDecryptMut, R: Read> DecryptoReader<C, R> {
    pub fn new(inner: R, cipher: C) -> Self {
        Self {
            inner,
            cipher,
            last_block: None,
            eof: false,
        }
    }
}

impl<C: BlockDecryptMut, R: Read> Read for DecryptoReader<C, R> {
    fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
        if self.eof {
            return Ok(0);
        }
        if buf.len() < C::BlockSize::USIZE {
            return Err(ErrorKind::InvalidInput.into());
        }
        let mut read_blocks = 0;
        if let Some(block) = self.last_block.take() {
            buf[..block.len()].copy_from_slice(&block);
            read_blocks += 1;
        }
        let block_size = C::BlockSize::USIZE;

        for i in buf.chunks_mut(block_size).skip(read_blocks) {
            let block = GenericArray::from_mut_slice(i);
            if let Err(e) = self.inner.read_exact(block) {
                if ErrorKind::UnexpectedEof == e.kind() {
                    self.eof = true;
                    break;
                }
                return Err(e);
            };
            self.cipher.decrypt_block_mut(block);
            read_blocks += 1;
        }

        if !self.eof {
            let mut block = GenericArray::default();
            if let Err(e) = self.inner.read_exact(&mut block) {
                if ErrorKind::UnexpectedEof == e.kind() {
                    self.eof = true;
                }
            } else {
                self.cipher.decrypt_block_mut(&mut block);
                self.last_block = Some(block);
            };
        }

        let mut read = read_blocks * block_size;
        if self.eof && read_blocks > 0 {
            let tmp = &mut buf[(read_blocks - 1) * block_size..];
            let block = GenericArray::<u8, C::BlockSize>::from_slice(&tmp[..block_size]);
            let result =
                Pkcs7::unpad(block).map_err(|e| std::io::Error::new(ErrorKind::InvalidData, e))?;
            read = (read_blocks - 1) * block_size + result.len();
        }

        Ok(read)
    }
}
謎麟
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!