Expand description
§A simple archiving format, designed for storing assets in compact secure containers
vach
is an archiving and resource transmission format.
It was built to be secure, contained and protected. A big benefit of vach
is the fine grained control it grants it’s users, as it allows for per-entry independent configuration.
vach
also has in-built support for multiple compression schemes (LZ4, Snappy and Brolti), data signing, leaf bitflags, encryption and some degree of archive customization.
Check out the
vach
spec at spec.txt.
§👄 Terminologies
- Archive: Any source of data, for example a file or TCP stream, that is a valid
vach
data source. - Leaf: Any actual data endpoint within an archive, what
tar
calls archive members, for examplefootstep1.wav
insounds.vach
. - Entry: Some data in the registry section of a
vach
source on an corresponding leaf. For example,{ id: footstep.wav, location: 45, offset: 2345, flags: 0b0000_0000_0000_0000u16 }
.
§🔫 Cargo Features
archive
andbuilder
(default): Turning them off turns off their respective modules. For example a game only needs thearchive
feature but a tool for packing assets would only need thebuilder
feature.multithreaded
: RunsBuilder::dump(---)
on multiple threads. Number of threads can be set manually usingBuilderConfig::num_threads
compression
: Pullssnap
,lz4_flex
andbrotli
as dependencies and allows for compression invach
archives.crypto
: Enables encryption and authentication functionality by pulling theed25519_dalek
andaes_gcm
cratesdefault
: Enables thearchive
andbuilder
features.all
: Enables all the features listed above
§🀄 Show me some code dang it!
§> Building a basic unsigned .vach
file
ⓘ
use std::{io::Cursor, fs::File};
use vach::prelude::{Builder, BuilderConfig};
let config = BuilderConfig::default();
let mut builder = Builder::default();
// Use `Builder::add( reader, ID )` to add data to the write queue
// Adds any data that implements `io::Read`
builder.add(File::open("test_data/background.wav")?, "ambient").unwrap();
builder.add(&[12, 23, 34, 45, 56, 67, 78, 90, 69], "ftstep").unwrap();
builder.add(b"Hello, Cassandra!", "hello").unwrap();
// let mut target = File::create("sounds.vach")?;
let mut target = Cursor::new(Vec::new());
// The number of bytes written to the file
let size = builder.dump(&mut target, &config).unwrap();
§> Loading resources from an unsigned .vach
file
ⓘ
use std::fs::File;
use vach::prelude::{Archive, Resource, Flags};
let target = File::open("sounds.vach")?;
let mut archive = Archive::new(target)?;
let resource: Resource = archive.fetch_mut("ambient")?;
// By default all resources are flagged as NOT authenticated
println!("{}", Sound::new(&resource.data)?);
assert!(!resource.authenticated);
let resource = archive.fetch_mut("ftstep")?;
§> Build a signed .vach
file
ⓘ
use std::{io::Cursor, fs::File};
use vach::prelude::{Builder, BuilderConfig, Keypair};
use vach::crypto_utils::gen_keypair;
let keypair: Keypair = gen_keypair();
let config: BuilderConfig = BuilderConfig::default().keypair(keypair);
let mut builder = Builder::default();
// Use `Builder::add( reader, ID )` to add data to the write queue
builder.add(File::open("test_data/background.wav")?, "ambient").unwrap();
builder.add(vec![12, 23, 34, 45, 56, 67, 78], "ftstep").unwrap();
builder.add(b"Hello, Cassandra!" as &[u8], "hello").unwrap();
let mut target = File::create("sounds.vach")?;
builder.dump(&mut target, &config).unwrap();
let mut target = Cursor::new(Vec::new());
builder.dump(&mut target, &config).unwrap();
§> Load resources from a signed .vach
source
ⓘ
// Load public_key
let mut public_key = File::open(PUBLIC_KEY)?;
let mut public_key_bytes: [u8; crate::PUBLIC_KEY_LENGTH];
public_key.read_exact(&mut public_key_bytes)?;
// Build the Loader config
let mut config = ArchiveConfig::default().key(PublicKey::from_bytes(&public_key_bytes)?);
let target = File::open("sounds.vach")?;
let archive = Archive::with_config(target, &config)?;
// Resources are marked as secure (=true) if the signatures match the data
let mut resource = archive.fetch_mut("ambient")?;
println!("{}", Sound::new(&resource.data)?);
assert!(resource.authenticated);
§> Serialize and de-serialize a Keypair
, SecretKey
and PublicKey
As SigningKey
, SecretKey
and VerifyingKey
are reflected from ed25519_dalek, you could refer to their docs to read further about them. These are needed for any cryptography related procedures,
Re-exports§
pub use rand;
crypto
Modules§
- archive
archive
Loader-based logic and data-structures - builder
builder
Builder
related data structures and logic - crypto
crypto
Import keypairs and signatures from here, mirrors fromed25519_dalek
- crypto_utils
crypto
Some utility functions to keep you happy - Consolidated import for crate logic; This module stores all
structs
associated with this crate. Constants can be accesses directly withcrate::<CONSTANT>
Constants§
- The default MAGIC used by
vach
- The standard size of any MAGIC entry in bytes
- Maximum size for any ID
- Size of a public key
- Size of a secret key
- Size of a signature
- Current
vach
spec version. increments by ten with every spec change