[О блоге] [наверх] [пред] [2025-09-02 10:48:27+03:00] [5c5e4b887dec0891f90bbb85955a3112e819b5ff]
Темы: [c][rust]

Керниган про Rust

https://thenewstack.io/unix-co-creator-brian-kernighan-on-rust-distros-and-nixos/
Говорит, что его попытка использовать Rust была болью.
Он не считает что он может заменить Си.

Я за неделю, имея под рукой всю его документацию, не смог написать
программу которая бы просто зашифровала AES-ом (самое банальное и под
рукой) файлик через stdin/stdout с указанным из аргументов ключом.

    [оставить комментарий]
    комментарий 0:
    From: kmeaw
    Date: 2025-09-02 19:36:55Z
    
    А что именно заняло больше всего времени и вызвало больше всего трудностей?
    
    Я сделал cargo search aes, взял первый попавшийся crate, скопировал пример и
    чуть подправил его. Затем попытался скормить результат в openssl enc -d
    -aes128, и только тогда понял, что забыл про cipher modes и IV.
    
    После этого сделал cargo search cbc и почитал другой пример, а потом исправлял
    ошибки компиляции, подгоняя типы.
    
    Получилось вот так:
    
    [nix-shell:/tmp/sgaes]$ ( cat src/main.rs ; head -c 16 /dev/zero ) |
    > cargo run 11223344556677881122334455667788 00000000000000000000000000000000 |
    > openssl enc -d -aes128 -nosalt -K 11223344556677881122334455667788 -iv 00000000000000000000000000000000 -nopad
        Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.02s
         Running `target/debug/sgaes 11223344556677881122334455667788 00000000000000000000000000000000`
    use aes::Aes128;
    use aes::cipher::{BlockEncryptMut, KeyIvInit, generic_array::GenericArray};
    use cbc;
    use hex;
    use std::env;
    use std::io;
    use std::io::{Read, Write};
    
    type Aes128CbcEnc = cbc::Encryptor<Aes128>;
    
    fn main() {
        let args: Vec<String> = env::args().collect();
        let hexkey = args
            .get(1)
            .unwrap_or_else(|| panic!("pass 128 bit hex key and iv in args"));
        let hexiv = args
            .get(2)
            .unwrap_or_else(|| panic!("pass 128 bit hex key and iv in args"));
        let key = hex::decode(hexkey).unwrap_or_else(|_| panic!("bad key hex"));
        let key: [u8; 16] = key.try_into().unwrap_or_else(|_| panic!("bad key len"));
        let iv = hex::decode(hexiv).unwrap_or_else(|_| panic!("bad iv hex"));
        let iv: [u8; 16] = iv.try_into().unwrap_or_else(|_| panic!("bad iv len"));
    
        let mut input = io::stdin().lock();
        let mut output = io::stdout().lock();
    
        let key = GenericArray::from(key);
        let mut block = GenericArray::from([42u8; 16]);
        let mut cipher = Aes128CbcEnc::new(&key.into(), &iv.into());
        while let Ok(_) = input.read_exact(&mut block) {
            cipher.encrypt_block_mut(&mut block);
            output.write_all(&block).expect("cannot write");
        }
    }
    
    комментарий 1:
    From: Sergey Matveev
    Date: 2025-09-02 19:56:32Z
    
    *** kmeaw@kmeaw.com [2025-09-02 19:37]:
    >А что именно заняло больше всего времени и вызвало больше всего трудностей?
    
    Было давно, уже не вспомню, совсем. Кода не осталось.
    Никаких "cbc" я внешних точно не собирался использовать, а делать это
    руками. Помню, что при каждом действии он ругался что "не могу
    скомпилировать", говно я какое-то написал. Читаешь про типы, синтаксис,
    все эти ownership (у меня не только main функа была). Видимо я
    принципиально не понимал многого. В итоге я так и не смог написать
    работающее приложение.
    
    Может быть мне не хватило ещё одного дня повозиться? Может быть, не
    знаю. Я точно не знаю, но когда-то немного трогав Erlang, я за неделю уж
    точно бы смог написать такую программу на нём. Это просто пример
    ЯП/инструмента, довольно сильно отличающегося от "штатного" моего стэка.
    Но когда я за неделю не смог осилить инструмент, чтобы написать
    простейшую программу -- для меня это перебор. Может нужно бы было
    какую-то особую книжку почитать по Rust? Но почему для многих других
    языков достаточно только их документации (к ней и tutorial на офсайтах
    тоже могу отнести)?
    
    Я помню что принципиально себе тогда поставил условие: под рукой только
    иметь документацию и не смотреть ни в чужой код, ни в код библиотек.
    Само собой за пять минут я бы быстро мог найти пример кода выполняющего
    работу с AES, с CBC, сделал бы copy-paste, нашёл код для работы с hex и
    argv, и через полчаса бы у меня была работающая программа. И когда я
    сдался, то я всё же пошёл смотреть как работают с AES/whatever в других
    местах и оно всё выглядело понятно как и в этом комментарии вы написали.
    Но я не смог допереть всего этого самостоятельно. Там было много (взял
    из 34c103d1b115de3e2f05b5eb4b31dbe2b34bb78a) такого (это полушутка):
    
            impl I<Don't> {
                fn know<'a, How::Someone>(could: &'a Say) -> This<'a>
                    with A: Straight<Face> + Send + Sync + 'a
    
    где я не понимал бы что значит та или иная кавычка, скобочки всякие и
    прочее. Я видел бы, что они (вроде) делают что мне надо, но без
    понимания почему именно так, а не иначе написано.