Rust · DSTU 7624 / 7564 / 8845 / 4145 / 9041 Rust · ДСТУ 7624 / 7564 / 8845 / 4145 / 9041

Ukrainian cryptography, engineered like libsodium.

uacrypt implements Ukraine's national cryptographic standards — the Kalyna block cipher, the Kupyna hash, the Strumok stream cipher, DSTU 4145 signatures, and DSTU 9041 public-key encryption — as a Rust library with hard, safe-by-default APIs. No mode to misconfigure, no nonce to reuse by accident, no algorithm choice to get wrong.

Українська криптографія, зроблена в дусі libsodium.

uacrypt реалізує національні криптографічні стандарти України — блочний шифр Калина, геш-функцію Купина, потоковий шифр Струмок, підписи ДСТУ 4145 і асиметричне шифрування ДСТУ 9041 — як Rust-бібліотеку з жорсткими, безпечними за замовчуванням API. Немає режиму, який можна неправильно налаштувати, немає nonce, який можна випадково повторно використати, немає вибору алгоритму, який можна переплутати.

v0.3.8. dstu-core is live on PyPI, npm, and RubyGems (Python/Node.js/Ruby bindings, one npm platform package still deferred — see docs/DECISIONS.md D-189). dstu-core/uacrypt stay published to crates.io as of 0.3.0. See docs/CHANGELOG.md for what changed each release. Kalyna and Kupyna are dual-oracle verified: official DSTU test vectors, cross-checked against real Bouncy Castle. Strumok, the Kalyna-CCM/GCM modes, and the CLI's AEAD framing each carry their own, more specific status below — read those before trusting a claim at face value. Not independently audited. Not a claim of resistance to hardware side-channel attacks (SPA/DPA) — that needs a separate, dedicated hardware audit this project hasn't had.

v0.3.8. dstu-core живий на PyPI і npm (Python/Node.js-байндинги, один платформний пакет npm ще відкладено — див. docs/DECISIONS.md RubyGems (Python/Node.js/Ruby-байндинги, один платформний пакет npm ще відкладено — D-189). dstu-core/uacrypt лишаються опублікованими на crates.io з версії 0.3.0. Що змінилось у кожному релізі — див. docs/CHANGELOG.md. Калина і Купина верифіковані за принципом подвійного оракула: офіційні тестові вектори ДСТУ, звірені з реальною Bouncy Castle. Струмок, режими Kalyna-CCM/GCM та AEAD-обгортка CLI мають власні, детальніші статуси нижче — варто прочитати їх, а не довіряти узагальненню на слово. Незалежного аудиту немає. Це не заява про стійкість до апаратних атак побічними каналами (SPA/DPA) — для цього потрібен окремий апаратний аудит, якого в проєкту не було.

Architecture Архітектура

Two layers, one library

DSTU is a Ukrainian national standard (ДСТУ) — think of it as the Ukrainian counterpart to a FIPS or ISO cryptographic standard. uacrypt implements five of them, split across two layers so neither a careful expert nor a casual user is stuck with the wrong API.

Два шари, одна бібліотека

ДСТУ — державний стандарт України, український аналог FIPS чи ISO у криптографії. uacrypt реалізує п'ять таких стандартів, розділених на два шари, щоб ані уважний фахівець, ані звичайний користувач не застрягли з непридатним для них API.

hazmat::*

The raw DSTU primitives — Kalyna, Kupyna, Strumok, DSTU 4145, DSTU 9041 — exposed with full control over mode, key size, and parameters, for people who genuinely need it and know what they're doing. Named after libsodium's own convention for exactly this kind of module.

Сирі примітиви ДСТУ — Калина, Купина, Струмок, ДСТУ 4145, ДСТУ 9041 — з повним контролем над режимом, розміром ключа й параметрами, для тих, кому це справді потрібно і хто розуміє, що робить. Назва — за тією ж конвенцією, що й у libsodium, саме для такого роду модулів.

crypto_*

A libsodium-shaped high-level layer — crypto_secretbox, crypto_secretstream, crypto_box, crypto_sign, crypto_auth, crypto_kdf, crypto_generichash, crypto_stream, crypto_pwhash — that deletes the knobs: one mode, one key size, nonces generated for you. The uacrypt CLI is built entirely on this layer.

Високорівневий шар у стилі libsodium — crypto_secretbox, crypto_secretstream, crypto_box, crypto_sign, crypto_auth, crypto_kdf, crypto_generichash, crypto_stream, crypto_pwhash — який прибирає всі параметри: один режим, один розмір ключа, nonce генерується сам. CLI uacrypt побудований повністю на цьому шарі.

The standards Стандарти

Five algorithms, five honest statuses

Each card states what's actually verified — not what's merely implemented. "Verified" means official test vectors and an independent reference implementation both agree; this project treats anything less as provisional, no matter how many of its own unit tests pass.

П'ять алгоритмів, п'ять чесних статусів

Кожна картка показує, що саме перевірено — а не що просто реалізовано. «Верифіковано» означає, що офіційні тестові вектори і незалежна референсна реалізація узгоджуються між собою; усе слабше за це проєкт вважає попереднім, скільки б власних unit-тестів не проходило.

Kalyna / Калина
DSTU 7624:2014 · block cipherблочний шифр
verified верифіковано

"kalyna" — guelder rose / viburnum, a plant name

«калина» — назва рослини, символічної для української культури

All 5 block/key-size variants; full DSTU 7624 mode coverage (ECB/CBC/CFB/OFB/CTR/CMAC/KW/CCM/GCM/GMAC/XTS).

Усі 5 варіантів блоку/ключа; повне покриття режимів DSTU 7624 (ECB/CBC/CFB/OFB/CTR/CMAC/KW/CCM/GCM/GMAC/XTS).

Official test vectors, cross-checked against real Bouncy Castle (Java & .NET). CCM/GCM modes are dual-oracle but not yet confirmed against the primary DSTU 7624 text itself — see the callout below.

Офіційні тестові вектори, звірені з реальною Bouncy Castle (Java і .NET). Режими CCM/GCM пройшли подвійний оракул, але ще не звірені з самим первинним текстом DSTU 7624 — див. примітку нижче.

Kupyna / Купина
DSTU 7564:2014 · hash functionгеш-функція
verified верифіковано

"kupyna" — literally "bush"

«купина» — буквально «кущ»

256- and 512-bit output, one-shot digest and streaming update/finalize.

Вихід 256 і 512 біт, одноразовий дайджест і потокові update/finalize.

Official test vectors, cross-checked against real Bouncy Castle (Java & .NET).

Офіційні тестові вектори, звірені з реальною Bouncy Castle (Java і .NET).

Strumok / Струмок
DSTU 8845:2019 · stream cipherпотоковий шифр
provisional попередньо

"strumok" — brook, a small stream

«струмок» — невеликий потік води, струмочок

256- and 512-bit keystream generation.

Генерація keystream, 256 і 512 біт.

UAPKI-attributed vectors, plus additional officially-sourced supplementary vectors obtained separately — an upgrade, not a closure: still not confirmed against the primary, paid DSTU 8845 text itself.

Вектори, атрибутовані UAPKI, плюс додаткові офіційні вектори, отримані окремо, — це підвищення довіри, а не закриття питання: досі не звірено з самим первинним, платним текстом DSTU 8845.

DSTU 4145
DSTU 4145-2002 · digital signatureцифровий підпис
verified верифіковано

ECDSA-style signatures on a national elliptic curve

ECDSA-подібний підпис на національній еліптичній кривій

crypto_sign: deterministic, Kupyna-KMAC-derived nonce — no caller-supplied randomness to get wrong.

crypto_sign: детермінований nonce, похідний від Kupyna-KMAC — немає користувацької випадковості, яку можна зіпсувати.

Vector-confirmed against the primary standard text.

Звірено з первинним текстом стандарту за тестовими векторами.

DSTU 9041
DSTU 9041:2020 · asymmetric encryptionасиметричне шифрування
verified верифіковано

Hybrid encryption over twisted Edwards curves

Гібридне шифрування на скручених кривих Едвардса

crypto_box: the libsodium crypto_box_seal equivalent — a KEM wraps a random seed, which derives the key for the actual message via crypto_secretstream.

crypto_box: аналог crypto_box_seal з libsodium — KEM обгортає випадкове зерно, яке породжує ключ для самого повідомлення через crypto_secretstream.

Vector-confirmed against the standard's own worked example (Додаток Г), but only the recommended l(p)=256/E256/1 curve — the standard also defines 384/512/768-bit variants, not yet implemented. The crypto_box composition itself (KEM + KDF + crypto_secretstream) isn't DSTU-specified, so it has no vector oracle of its own — verified by property and tamper testing instead, the same posture as crypto_secretstream.

Звірено з власним прикладом стандарту (Додаток Г), але лише для рекомендованої кривої l(p)=256/E256/1 — стандарт також визначає варіанти на 384/512/768 біт, ще не реалізовані. Сама композиція crypto_box (KEM + KDF + crypto_secretstream) не визначена стандартом, тож не має власного тестового оракула — верифікована властивісними тестами й тестами на підробку, як і crypto_secretstream.

Two constructions worth reading the fine print on

Дві конструкції, варті уваги в деталях

Kalyna-CCM/GCM (used by the mid-level kalyna-ccm CLI command and by crypto_secretbox): dual-oracle verified, but not yet confirmed against the primary DSTU 7624 text for these specific modes. The AEAD framing behind uacrypt encrypt/decrypt (crypto_secretstream) is provisional in a stronger sense still — it's an original, chunked-streaming construction with no DSTU standard defining anything like it, so no official vector can ever exist for it. It's verified instead by property, tamper, and misuse testing, not by a vector match.

Kalyna-CCM/GCM (використовується у CLI-команді kalyna-ccm та в crypto_secretbox): пройшли подвійний оракул, але ще не звірені з первинним текстом DSTU 7624 саме для цих режимів. AEAD-обгортка за uacrypt encrypt/decrypt (crypto_secretstream) — попередня в ще сильнішому сенсі: це власна, чанкована потокова конструкція, для якої в DSTU взагалі немає відповідника, тож офіційний тестовий вектор для неї в принципі не може існувати. Її перевіряють властивісними тестами, тестами на підробку та тестами на хибне використання — а не звірянням із вектором.

Looking for something familiar?

Шукаєш щось знайоме?

Rough orientation for readers who don't know these standards by name — not a claim of cryptographic equivalence. Real differences exist under every row below.

Приблизний орієнтир для тих, хто не знає ці стандарти на пам'ять — не твердження про криптографічну еквівалентність. Під кожним рядком є реальні відмінності.

DSTUДСТУ RoleРоль Closest global analogНайближчий світовий аналог What actually differsЩо насправді відрізняється Speed, this machineШвидкість, ця машина
Kalyna / Калина block cipherблочний шифр AES / Rijndael Same SPN shape (S-box, shift, MDS mix, key add), but its own S-box/MDS tables and five block/key sizes, not AES's fixed 128-bit block. Та сама структура SPN (S-box, зсув, MDS-змішування, додавання ключа), але власні таблиці S-box/MDS і п'ять варіантів блоку/ключа, а не фіксований 128-бітний блок AES. ~1.7x slower than AES in pure software. AES-NI (hardware) is ~5x faster — that gap is CPU instruction support, not this project's code. ~1.7x повільніше за AES у чистому софті. Апаратний AES-NI — приблизно у 5 разів швидший, але це різниця в підтримці процесора, а не в коді проєкту.
Kupyna / Купина hash function — the SHA-2/SHA-3 slotгеш-функція — та сама ніша, що й SHA-2/SHA-3 Whirlpool Same idea — an AES-like permutation inside a Miyaguchi-Preneel construction — structurally closer to Whirlpool than to SHA-3's sponge design. Та сама ідея — AES-подібна перестановка всередині конструкції Miyaguchi-Preneel — структурно ближче до Whirlpool, ніж до губчастої конструкції SHA-3. ~1.5-2.1x slower — same optimization tier on both sides, no hardware-acceleration asterisk needed. ~1.5-2.1x повільніше — обидві сторони одного рівня оптимізації, без застереги про апаратне прискорення.
Strumok / Струмок stream cipherпотоковий шифр ChaCha20 (same job) · SNOW 2.0 / SNOW 3G (same design) ChaCha20 (та сама роль) · SNOW 2.0 / SNOW 3G (та сама конструкція) ChaCha20 is a wholly different internal design (ARX, no LFSR) — it matches Strumok's job, not its machinery. SNOW is the real architectural relative (LFSR + FSM). ChaCha20 має цілком іншу внутрішню будову (ARX, без LFSR) — збігається лише роллю, не механікою. SNOW — справжній архітектурний родич (LFSR + FSM). ~1.6-1.7x slower than AVX2-accelerated ChaCha20. ~1.6-1.7x повільніше за ChaCha20 з AVX2-прискоренням.
DSTU 4145 digital signatureцифровий підпис ECDSA Over a binary-field elliptic curve, not Edwards. The deterministic, Kupyna-KMAC-derived nonce is this project's own design choice — the same idea as RFC 6979 for plain ECDSA, not something the standard itself mandates. На еліптичній кривій у двійковому полі, не Едвардса. Детермінований nonce (похідний від Kupyna-KMAC) — власне рішення проєкту, та сама ідея, що й RFC 6979 для звичайного ECDSA, а не вимога самого стандарту. ~7.9x slower signing, ~5.2x slower verifying than OpenSSL's `nistb163` (same binary-field curve family, fairer than the P-256 comparison) — an algorithmic gap (no precomputed-table windowing yet), not a hardware asterisk. ~7.9x повільніше підписування, ~5.2x повільніше перевірка за OpenSSL's `nistb163` (та сама родина кривих у двійковому полі, чесніше порівняння, ніж P-256) — алгоритмічний розрив (ще без вікна з попередньо обчисленою таблицею), а не апаратна застережка.
DSTU 9041 asymmetric encryptionасиметричне шифрування crypto_box_seal (libsodium) A twisted Edwards curve with its own field, not Curve25519 — and a KEM-then-symmetric composition this project designed itself (D-169), since the standard only defines the asymmetric wrap. Скручена крива Едвардса з власним полем, не Curve25519 — і композиція «KEM, потім симетричне шифрування», спроєктована власне цим проєктом (D-169), бо стандарт визначає лише асиметричну обгортку. ~3.3-4.2x slower sealing/opening than OpenSSL's own hybrid envelope (CMS + EC) — the raw elliptic-curve math alone is close to parity with a field-size-matched OpenSSL curve; the gap is mostly the symmetric layer, not chased further yet. ~3.3-4.2x повільніше запечатування/розпечатування за власний гібридний конверт OpenSSL (CMS + EC) — сама еліптична математика близька до паритету з кривою OpenSSL того ж розміру поля; розрив переважно в симетричному шарі, поки не досліджено глибше.

Full numbers and methodology (same dev machine, both directions where they exist, every caveat above stated in detail): docs/PERFORMANCE.md. Повні цифри й методологія (та сама dev-машина, обидва напрями де вони є, кожна застерога вище — розгорнуто): docs/PERFORMANCE.md.

Discipline Дисципліна

Verification, not vibes

Passing self-consistent unit tests is not treated as evidence of correctness for security-critical code. Every primitive in this project goes through the same gauntlet:

Верифікація, а не відчуття

Проходження власних unit-тестів не вважається доказом коректності для критичного до безпеки коду. Кожен примітив проходить один і той самий набір перевірок:

Dual-oracle verification

Подвійний оракул

Official DSTU test vectors and cross-checked against two real, independent reference implementations: Bouncy Castle (via actual Java and .NET oracle harnesses — not a vendored clone) and UAPKI (the C reference). Need Kalyna/ Kupyna/Strumok in Java or .NET instead of Rust? Bouncy Castle already has them. Need C? UAPKI does.

Офіційні тестові вектори ДСТУ і звірка з двома реальними, незалежними референсними реалізаціями: Bouncy Castle (через справжні Java- та .NET-гарнеси, а не вендорений клон) і UAPKI (референс на C). Потрібні Калина/ Купина/Струмок на Java чи .NET замість Rust? Вони вже є в Bouncy Castle. Потрібен C? Це UAPKI.

cargo miri

Undefined-behavior detection, required in CI, not optional tooling.

Виявлення undefined behavior, обов'язково в CI, а не опційний інструмент.

cargo kani

Bounded model checking. Currently proves DSTU 4145's field-reduction step correct for all 2384 possible inputs — not a sampled test, an exhaustive proof.

Обмежена перевірка моделей. Наразі доводить коректність кроку редукції поля ДСТУ 4145 для всіх 2384 можливих входів — це не вибіркові тести, а вичерпний доказ.

cargo fuzz

Every parser of untrusted input bytes, fuzzed, not just hand-picked edge cases.

Кожен парсер недовірених вхідних байтів — під фазингом, а не лише на вручну підібраних граничних випадках.

Constant-time discipline

Дисципліна сталого часу

No secret-dependent branching; subtle::ConstantTimeEq for secret comparisons; all key material is Zeroize/ZeroizeOnDrop.

Жодного гілкування, залежного від секрету; subtle::ConstantTimeEq для порівнянь секретних даних; увесь ключовий матеріал — Zeroize/ ZeroizeOnDrop.

Supply chain

Ланцюг залежностей

cargo audit (advisory database) and cargo deny (license/dependency policy) as required CI layers, same standing as miri and fuzz.

cargo audit (база вразливостей) і cargo deny (політика ліцензій і залежностей) — обов'язкові шари CI, нарівні з miri та fuzz.

What this project does not claim: resistance to hardware side-channel attacks (SPA/DPA — that needs a dedicated hardware audit this project hasn't had), or any form of state certification.

Чого цей проєкт не стверджує: стійкості до апаратних атак побічними каналами (SPA/DPA — для цього потрібен окремий апаратний аудит, якого не було), і жодної форми державної сертифікації.

Portability Портованість

Runs everywhere, by construction

dstu-core is no_std-compatible from day one — feature-gated std/alloc/no_std builds, confirmed cross-compiling to real embedded targets: thumbv7em-none-eabihf (STM32 Cortex-M) and riscv32imc-unknown-none-elf (ESP32-C3-class RISC-V). Two build profiles trade speed for flash footprint: fused (fast, table-heavy, default) and small-tables (flash-constrained MCUs).

Compiling for a target is not the same claim as validating on it. The non-embedded ARM64/Linux path is checked on real hardware (a Raspberry Pi); bare-metal STM32/ESP32 hardware validation is a separate, not-yet-done phase — and neither is a claim of side-channel resistance.

Працює всюди — за задумом

dstu-core є no_std-сумісним з першого дня — збірки за feature-флагами std/alloc/no_std, підтверджено крос-компіляцію на реальні embedded-цілі: thumbv7em-none-eabihf (STM32 Cortex-M) і riscv32imc-unknown-none-elf (клас ESP32-C3, RISC-V). Два профілі збірки міняють швидкість на розмір прошивки: fused (швидкий, з великими таблицями, за замовчуванням) і small-tables (для MCU з обмеженою пам'яттю).

Компіляція під ціль — не те саме, що валідація на ній. Неembedded шлях ARM64/Linux перевірено на реальному залізі (Raspberry Pi); валідація на реальних STM32/ESP32 — окремий, ще не пройдений етап — і жодне з цього не є заявою про стійкість до атак побічними каналами.

Try it Спробувати

Every verb the CLI has — still nothing to misconfigure

Mode, nonce, and algorithm are hardcoded — there's nothing left to misconfigure.

Усі дієслова CLI — і досі нічого не можна неправильно налаштувати

Режим, nonce і алгоритм зашиті наглухо — налаштовувати нічого.

cargo build -p uacrypt --release

uacrypt keygen  --out key.bin
uacrypt encrypt --key key.bin --in message.bin --out sealed.bin
uacrypt decrypt --key key.bin --in sealed.bin  --out message.bin
uacrypt hash    --in file.bin --out digest.bin

uacrypt sign-keygen --out signing.key
uacrypt sign-pubkey --key signing.key --out verifying.key
uacrypt sign         --key signing.key   --in message.bin --out message.bin.sig
uacrypt verify       --key verifying.key --in message.bin --sig message.bin.sig

uacrypt box-keygen --out box.key
uacrypt box-pubkey --key box.key --out box.pub
uacrypt box-seal   --key box.pub  --in message.bin --out sealed.box
uacrypt box-open   --key box.key  --in sealed.box   --out message.bin

box-* (DSTU 9041 / crypto_box) is on master, not yet in a tagged release — see the version note above.

box-* (ДСТУ 9041 / crypto_box) є на master, ще не увійшло до жодного тегованого релізу — див. примітку про версію вище.

encrypt/decrypt stream the file in fixed-size chunks — no message-length cap, no whole-file memory buffer. Prebuilt binaries for Windows, Linux, and macOS (Apple Silicon) ship on every GitHub Release.

encrypt/decrypt читають і пишуть файл потоково, фіксованими блоками — без обмеження на довжину повідомлення, без буфера на весь файл у пам'яті. Готові бінарники для Windows, Linux і macOS (Apple Silicon) додаються до кожного GitHub Release.

Bindings Байндінги

Eight languages, one C ABI

The full crypto_* surface, idiomatic errors and secretstream I/O, and the same correctness/rejection/misuse test suite per language — not a thin, partial wrapper. Python, Node.js, and Ruby are published (PyPI/npm/RubyGems); the rest aren't yet (Packagist/NuGet/Maven Central) — build those from source, same as the Rust crate itself before crates.io. Each card below links the README (full docs, every binding) and the package registry where one exists (the actual install command).

Вісім мов, один C ABI

Повна поверхня crypto_*, ідіоматичні помилки та I/O для secretstream, той самий набір тестів на коректність/відхилення/некоректне використання для кожної мови — не тонка, часткова обгортка. Python, Node.js і Ruby опубліковані (PyPI/npm/RubyGems); решта — ще ні (Packagist/NuGet/Maven Central) — для них поки що збірка з джерела, так само як і сам Rust-крейт до crates.io. Кожна картка нижче веде на README (повна документація, для всіх мов) і на реєстр пакетів там, де він є (реальна команда встановлення).

Python

PyO3, direct Rust binding — bindings/python (docs) · PyPI (install).

PyO3, прямий Rust-байндінг — bindings/python (документація) · PyPI (встановлення).

Node.js

napi-rs, direct Rust binding — bindings/nodejs (docs) · npm (install).

napi-rs, прямий Rust-байндінг — bindings/nodejs (документація) · npm (встановлення).

Ruby

magnus/rb-sys, direct Rust binding — bindings/ruby.

magnus/rb-sys, прямий Rust-байндінг — bindings/ruby.

PHP

ext-php-rs, direct Rust binding — bindings/php.

ext-php-rs, прямий Rust-байндінг — bindings/php.

.NET (C#)

.NET (C#)

P/Invoke over the C ABI — bindings/dotnet.

P/Invoke поверх C ABI — bindings/dotnet.

Java

jni crate, direct Rust binding — bindings/java.

крейт jni, прямий Rust-байндінг — bindings/java.

Go

cgo over the C ABI — bindings/go.

cgo поверх C ABI — bindings/go.

C++

Header-only RAII wrapper over the C ABI — bindings/cpp.

Header-only RAII-обгортка поверх C ABI — bindings/cpp.

The C ABI itself (crates/dstu-core-capi, opaque handles, cbindgen-generated header) is what the .NET, Go, and C++ bindings above link against directly — usable from any language with a C FFI, not just those three.

Сам C ABI (crates/dstu-core-capi, непрозорі хендли, заголовок згенерований cbindgen) — це те, з чим напряму лінкуються байндінги для .NET, Go і C++ вище — придатний для будь-якої мови з C FFI, а не лише для цих трьох.

Status Статус

Where this stands, and what's next

dstu-core/uacrypt are published to crates.io, PyPI, and npm — see docs/CHANGELOG.md for what changed each release, and the status note above for the current per-registry detail. The phase-by-phase backlog lives in docs/TASKS.md, the full gap analysis against a libsodium-equivalent 1.0 in docs/release-readiness.md, and every architectural decision — including the ones this page simplifies — in docs/DECISIONS.md. Dual-licensed MIT / Apache-2.0, the Rust ecosystem default.

Де зараз проєкт і що далі

dstu-core/uacrypt опубліковані на crates.io, PyPI та npm — див. docs/CHANGELOG.md щодо змін у кожному релізі, і статус-банер вище — щодо деталей по кожному реєстру. Беклог по фазах — у docs/TASKS.md, повний аналіз розриву до рівня, еквівалентного libsodium 1.0, — у docs/release-readiness.md, а кожне архітектурне рішення — зокрема ті, які ця сторінка спрощує, — у docs/DECISIONS.md. Подвійна ліцензія MIT / Apache-2.0 — стандарт для екосистеми Rust.