Quick Start Guide
Side-channel claim limit. Nothing on this page claims constant-time behaviour or side-channel resistance for any target: the side-channel harness covers nothing (finding A48) and no measurement exists. The Rust and C cores are designed for constant time and unmeasured; managed runtimes (JIT, GC, bounds checks) make no timing claim. Where this page names constant-time or side-channel techniques, in prose or in code, they are design intent or recommendations, not measured properties.
One post-quantum round trip per language, through the package each target
ships. Every snippet on this page was run against a locally built candidate
of the 1.0.0-rc.7 tree (the runs are recorded in the source repository’s
documents/public-release/evidence/229-documentation.md); the coordinates
are the decided public names, which resolve nowhere until the launch
publishes them. See the Installation Guide
for building from source. A Korean draft of this page, awaiting owner review, is at
빠른 시작.
Profiles are explicit: ml-kem-768, ml-dsa-65, falcon-512.r3-padded and
the other catalog identifiers name one algorithm, one parameter set and one
wire encoding each, and a family name (ml-dsa) is refused rather than
substituted. ML-DSA, SLH-DSA, HAETAE and AIMer sign under a context string
of at most 255 bytes; a signature made under one context does not verify
under another.
Rust
[dependencies]
metamui-crypto = "1.0.0-rc.7"
rand = "0.8"
use metamui_crypto::{falcon512, mldsa65, mlkem768, Profile};
fn main() -> Result<(), metamui_crypto::Error> {
let mut rng = rand::rngs::OsRng;
let kp = falcon512::generate_keypair(&mut rng)?;
let sig = falcon512::sign_padded(&kp.secret_key, b"hello", &mut rng)?;
falcon512::verify_padded(&kp.public_key, b"hello", &sig)?;
let kem = mlkem768::generate_keypair(&mut rng)?;
let (ct, ss) = mlkem768::encapsulate(&kem.encapsulation_key, &mut rng)?;
assert_eq!(mlkem768::decapsulate(&kem.decapsulation_key, &ct)?, ss);
let dsa = mldsa65::generate_keypair(&mut rng)?;
let sig = mldsa65::sign(&dsa.secret_key, b"hello", b"my-protocol/v1", &mut rng)?;
mldsa65::verify(&dsa.public_key, b"hello", b"my-protocol/v1", &sig)?;
assert!(mldsa65::verify(&dsa.public_key, b"hello", b"", &sig).is_err()); // another context
assert!(Profile::parse("haetae").is_err()); // a family is not a profile
Ok(())
}
Python
pip install metamui-crypto==1.0.0rc7
from metamui_crypto.facade import profile
sig = profile("ml-dsa-65")
keys = sig.generate_keypair()
signature = sig.sign(keys.secret_key, b"message", context=b"my-app")
sig.verify(keys.public_key, b"message", signature, context=b"my-app") # raises InvalidSignatureError on failure
kem = profile("ml-kem-768")
ek, dk = kem.generate_keypair()
ct, ss = kem.encapsulate(ek)
assert kem.decapsulate(dk, ct) == ss
TypeScript
npm install @metamui/crypto@1.0.0-rc.7
import { falcon512, mldsa65, mlkem768, init } from '@metamui/crypto';
await init(); // optional: compiles the WebAssembly up front
const message = new TextEncoder().encode('hello');
const signer = await falcon512.generateKeyPair();
const signature = await falcon512.signPadded(signer.secretKey, message);
await falcon512.verifyPadded(signer.publicKey, message, signature); // throws InvalidSignatureError if wrong
const ctx = new TextEncoder().encode('metamui/example/v1');
const dsa = await mldsa65.generateKeyPair();
const sig = await mldsa65.sign(dsa.secretKey, message, ctx);
await mldsa65.verify(dsa.publicKey, message, ctx, sig);
const receiver = await mlkem768.generateKeyPair();
const { ciphertext, sharedSecret } = await mlkem768.encapsulate(receiver.encapsulationKey);
const same = await mlkem768.decapsulate(receiver.decapsulationKey, ciphertext);
Swift
// Package.swift
dependencies: [
.package(url: "https://github.com/SovereignWallet-Network/metamui-crypto", exact: "1.0.0-rc.7")
],
targets: [
.executableTarget(name: "app", dependencies: [.product(name: "MetaMUICrypto", package: "metamui-crypto")])
]
import Foundation
import MetaMUICrypto
let message = Data("hello".utf8)
let profile = try Profile.parse("ml-dsa-65") // exact id; "ml-dsa" is refused
let dsa = profile.contextSignature! // nil for a KEM profile
let keys = try dsa.generateKeyPair()
let context = Data("my-protocol/v1".utf8) // required: "" is the empty context
let signature = try dsa.sign(message: message, context: context, secretKey: keys.secretKey)
try dsa.verify(message: message, context: context, signature: signature, publicKey: keys.publicKey)
let kem = try Profile.parse("ml-kem-768").kem!
let pair = try kem.generateKeyPair()
let enc = try kem.encapsulate(publicKey: pair.publicKey)
let shared = try kem.decapsulate(secretKey: pair.secretKey, ciphertext: enc.ciphertext)
assert(shared == enc.sharedSecret)
Go
go get github.com/SovereignWallet-Network/metamui-crypto/metamui-crypto-go@v1.0.0-rc.7
package main
import (
"bytes"
"fmt"
"github.com/SovereignWallet-Network/metamui-crypto/metamui-crypto-go/mlkem"
)
func main() {
kem := mlkem.New(mlkem.MLKEM768)
pk, sk, err := kem.GenerateKeyPair()
if err != nil {
panic(err)
}
ct, ss, err := kem.Encapsulate(pk)
if err != nil {
panic(err)
}
ss2, err := kem.Decapsulate(sk, ct)
if err != nil {
panic(err)
}
fmt.Println(bytes.Equal(ss, ss2))
}
Java
<dependency>
<groupId>id.metamui.crypto</groupId>
<artifactId>metamui-pqc</artifactId>
<version>1.0.0-rc7</version> <!-- what the reactor builds; not on Maven Central yet -->
</dependency>
import id.metamui.crypto.mlkem.MLKem;
import id.metamui.crypto.mlkem.MLKem768;
public class App {
public static void main(String[] args) {
MLKem kem = new MLKem768();
MLKem.KeyPair keys = kem.generateKeyPair();
MLKem.EncapsulationResult enc = kem.encapsulate(keys.getPublicKey());
byte[] shared = kem.decapsulate(keys.getSecretKey(), enc.getCiphertext());
System.out.println(java.util.Arrays.equals(shared, enc.getSharedSecret()));
}
}
Kotlin
dependencies {
implementation("id.metamui.crypto:metamui-crypto-kotlin:1.0.0-rc7") // what the build publishes; not on Maven Central yet
}
import id.metamui.crypto.mlkem.MLKem768
fun main() {
val kem = MLKem768()
val keys = kem.generateKeypair()
val (ciphertext, shared) = kem.encapsulate(keys.publicKey)
val recovered = kem.decapsulate(keys.privateKey, ciphertext)
println(recovered == shared)
}
C#
dotnet add package MetaMUI.Crypto.MLKEM --version 1.0.0-rc.7
using MetaMUI.Crypto.MLKEM;
var kem = new MLKEM768(); // ML-KEM-768 (FIPS 203)
(byte[] publicKey, byte[] privateKey) = kem.GenerateKeyPair();
(byte[] ciphertext, byte[] sharedSecret) = kem.Encapsulate(publicKey);
byte[] recovered = kem.Decapsulate(ciphertext, privateKey);
Console.WriteLine(sharedSecret.AsSpan().SequenceEqual(recovered));
C
The C API reference carries the build,
install and linking recipe and compiled examples for each module; its code
blocks are quoted from files the C tree compiles and runs under ctest.
What these examples do not show
- Every randomized operation draws from the operating system; there is no seeded or deterministic entry point in the public packages.
- Constant-time behaviour and side-channel resistance are not claimed for any target: the side-channel axis is unmeasured (finding A48). The Rust and C cores are designed for constant time; managed runtimes make no timing claim.
- No package wraps an external cryptography library; each is MetaMUI’s own implementation, validated against the algorithm’s upstream test vectors.
What’s next?
- Supported algorithms — the catalog’s 49 profiles in 16 families
- Platform guides
- API reference
- Security scope
Need help?
- Report issues on GitHub
- Support level: best effort, no commercial support through the repository (
SUPPORT.md); security reports to security@metamui.id