Welcome to WASM PNA
What is PNA?
Portable Network Archive (PNA) is a flexible, secure, and cross-platform archive format inspired by the PNG data structure. Like PNG, PNA uses a chunk-based structure where each piece of data is self-contained with its own type, length, and checksum. This enables individual file access without full decompression, robust error detection, and natural streaming support.
- Compression — Multiple algorithms (zlib, ZStandard, xz) for speed or size optimization
- Encryption — Industry-standard 256-bit AES and Camellia to protect sensitive data
- Integrity — Built-in error detection with chunk-based CRC validation
- Splitting — Divide large archives into smaller parts for easy distribution
This demo runs entirely in your browser via WebAssembly — no files are uploaded to any server.
Why PNA?
Portability
Works seamlessly across Windows, Linux, macOS, and FreeBSD. Combines the strengths of TAR and ZIP formats.
Compression Flexibility
Per-file and archive-wide compression options. Access individual files without decompressing the entire archive.
Native Encryption
Encryption is built into the format — not an afterthought. 256-bit AES and Camellia protect your data by default.
Streamability
Supports serial read/write operations, making it suitable for streaming processing — just like TAR.
Metadata-Free by Design
Everything except the entry name and body is optional. Create the smallest possible archives with no metadata leakage.
Extensible
Designed for future extensions and private add-ons while maintaining backward compatibility with the base format.
Try it now
Get Started
PNA is available as a command-line tool and as a Rust library.
Command-Line Tool
Install
cargo install portable-network-archiveUsage
# Create an archive
pna create -f archive.pna file1.txt file2.txt
# Extract an archive
pna extract -f archive.pna
# List archive contents
pna list -f archive.pnaRust Library
Install
cargo add libpnaExample
use libpna::{Archive, EntryBuilder, WriteOptions};
use std::io::Write;
let file = std::fs::File::create("archive.pna")?;
let mut archive = Archive::write_header(file)?;
let mut entry = EntryBuilder::new_file(
"hello.txt".into(),
WriteOptions::builder().build(),
)?;
entry.write_all(b"Hello, world!")?;
archive.add_entry(entry.build()?)?;
archive.finalize()?;