[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

где я не понимал бы что значит та или иная кавычка, скобочки всякие и
прочее. Я видел бы, что они (вроде) делают что мне надо, но без
понимания почему именно так, а не иначе написано.