๐ฆ asx-rs
Async-native, memory-safe AS2 + AS4 EDI transport library for Rust.
asx-rs implements the AS2 (RFC 4130) and
AS4 (OASIS ebMS3 + eDelivery)
protocols โ the wire formats used by PEPPOL, CEF eDelivery, BDEW, and tens of thousands of
EDI trading partner connections worldwide.
โจ Features
๐จ AS2 (RFC 4130 / RFC 5751)
- Send and receive signed payloads (CMS/S/MIME, RSA-SHA256)
- Synchronous and asynchronous MDN (Message Disposition Notification)
- MIC computation for end-to-end integrity verification
- Payload compression (RFC 5402 / zlib,
compressionfeature) - Configurable interop mode: strict vs. relaxed for legacy partners
- Retry classification (
SuccessConfirmed/Indeterminate/AcceptedPendingVerification)
๐ฌ AS4 (ebMS3 + OASIS eDelivery AS4 v1.15)
- One-Way/Push send and receive (SOAP 1.1 and 1.2)
- One-Way/Pull with bounded in-memory pull store per MPC partition
- WS-Security XMLDSig signing โ RSA-SHA256 and ECDSA-SHA256; algorithm is auto-detected from the signing certificate key type. Works with NIST P-256/P-384/P-521 and BSI BrainpoolP256r1/P384r1 (required by BDEW AS4-Profil ยง2.2.6.2.1 / BSI TR-03116-3 ยง9.1).
- XML Encryption (XMLenc11) โ auto-dispatches on recipient certificate key type:
- RSA recipient โ RSA-OAEP (SHA-256/MGF1-SHA-256) โ PEPPOL / CEF eDelivery
- EC recipient โ ECDH-ES + ConcatKDF (NIST SP 800-56A ยง5.8.1) + AES-128 Key Wrap (RFC 3394) โ BDEW AS4-Profil ยง2.2.6.2.2 / BSI TR-03116-3 ยง9.2
X509PKIPathv1BST token type (WsSecOutboundKeyInfoProfile::X509PKIPathv1)require_encrypted_inboundpolicy field โ rejects unencrypted push messages at the policy layer (symmetric torequire_signed_push)- Streaming receive path with bounded memory; conversation-ordered delivery gate
- P-Mode registry for per-partner MEP/security configuration
- SBDH 1.3 envelope wrap/unwrap for PEPPOL and CEF eDelivery
๐ Security & Reliability
- Type-state lifecycle machine โ compiler enforces
UntrustedBytes โ StructurallyParsed โ CryptographicallyVerified โ ContentDecrypted โ DomainReady; payloads cannot reach application code without every gate passing - OCSP stapling + responder-based revocation checking (
async-ocspfeature) - PKIX certificate chain validation (fail-closed on empty trust store)
TtlDedupStorage/BoundedFifoDedupStorageprevents replay attacks- Reconciliation hooks for async delivery confirmation
๐ HTTP Transport
- Axum server integration (
serverfeature) โ drop-inRouterfor AS2 and AS4 ingress - Async HTTP egress via
reqwest(clientfeature) - Inbound endpoint governance against unexpected sources
๐ Observability
EventBuswith fan-out broadcast and ordered mpsc audit channelDurableAuditSinktrait for pluggable persistent audit backendsEventBusMetricswith lock-freeAtomicU64counters- Optional Prometheus/OpenMetrics sink (
prometheusfeature)
๐งฉ Interop
- Profile stacking with regional packs and per-partner overlays
interop-strict(default) andinterop-relaxedfeature-gated modes- Exception policies (
InteropExceptionPolicy) for well-known deviations
๐งช Testing (testing feature โ never enable in production)
InsecureBypassAs4Verifierโ skips all WS-Security verification; parity withInsecureBypassTrustVerifieron the AS2 sideMockAs4Endpoint(testing + server) โ local HTTP AS4 server that accepts any push (signed, unsigned, encrypted, or plain), records messages in an async channel, and returns synchronous AS4 receipts. Configure decryption viaMockAs4Endpoint::builder().with_decryption_key_pem(key_pem).bind(addr).await?EventBus::new_for_testing()โ zero-configBestEffortbus; never fails on emit when no subscriber is active โ no morenew_with_config_and_mode(...)boilerplateDurableInMemoryDedupBackendโ in-memory dedup withis_durable() = true; passes the strict durable-backend guard without a real persistent storeAs4HttpTransport::new_for_localhost_testing()โ plain-HTTP transport for integration tests againstMockAs4Endpointonhttp://127.0.0.1:โฆ; SSRF guards disabled for the test binary onlygenerate_self_signed_ec_keypair(cn, curve)โ self-signed EC cert+key (P-256 through BrainpoolP512r1); no openssl/rcgen dev-dependency needed in downstream cratesgenerate_self_signed_rsa_keypair(cn, bits)โ same for RSAverifier_sealโ re-export of theAs4Verifiersealed trait; allows downstream crates to write custom verifiers (recording, fault-injection, etc.)
๐ Quick Start
[]
# AS4 โ PEPPOL / CEF eDelivery (RSA) or BDEW (EC/ECDH-ES) โ same code, key type decides
= { = "0.8", = ["as4", "client", "server", "async-ocsp"] }
# AS2 + AS4 with compression
= { = "0.8", = ["as2", "as4", "compression", "client", "server", "async-ocsp"] }
[]
# Testing without PKI certificates (MockAs4Endpoint, bypass verifier, keypair generators)
= { = "0.8", = ["as4", "testing", "server"] }
as2andas4are not in the default feature set โ add them explicitly. Thetestingfeature is compile-error-guarded against release profile builds.
๐ Examples
AS4 โ Send a signed push message
The signing algorithm is chosen automatically from the key type โ no configuration needed:
- RSA certificate โ RSA-SHA256 (PEPPOL / CEF eDelivery)
- EC certificate (P-256, BrainpoolP256r1, โฆ) โ ECDSA-SHA256 (BDEW, BSI TR-03116-3 ยง9.1)
use ;
use SessionContextBuilder;
use EventBus;
// Session with trust anchor + signing material โ one fluent chain:
let session = new
.with_signing_material
.with_trust_anchor_pem
.with_fingerprint_sha256 // optional hard pin
.build?;
// RSA or EC signing key โ auto-detected:
let = new
.action
.service
.signing_cert_pem // RSA or EC
.signing_key_pem
.recipient_cert_pem // RSA โ RSA-OAEP; EC โ ECDH-ES
.encrypt
.build?;
let bus = new?;
let output = send_async.await?;
// output.soap_envelope.body โ multipart/related bytes to POST
// output.http_content_type โ HTTP Content-Type header value
AS4 โ Receive push with encryption enforcement
use ;
use Arc;
let policy = new
.inbound_decryption_key_pem
.require_encrypted_inbound // fail-closed: reject any unencrypted message
.build?;
let outcome = receive_push_with_dedup_async.await?;
AS4 โ Testing without PKI certificates
use MockAs4Endpoint;
use EventBus;
use ;
// Plain receive: bind to a random port โ no cert, no WIRK, no PEPPOL test PKI needed
let endpoint = bind.await?;
// Receive encrypted messages: configure decryption key via builder
let endpoint = builder
.with_decryption_key_pem
.bind
.await?;
let url = endpoint.local_url; // "http://127.0.0.1:PORT/as4/inbox"
// Test EventBus: zero-config, never fails on emit (BestEffort)
let bus = new_for_testing; // requires `testing` feature
// Wait for the first message (returns None if the endpoint is dropped).
let msg = timeout
.await??;
assert_eq!;
assert!;
// from_party_ids contains the sender GLN; to_party_ids the receiver GLN
AS4 โ Generate EC or RSA test keypairs
use ;
// BrainpoolP256r1 โ required by BDEW AS4-Profil ยง2.2.6.2.1
let = generate_self_signed_ec_keypair;
// P-256 โ standard for PEPPOL Access Points
let = generate_self_signed_ec_keypair;
// RSA-2048 โ classic PEPPOL style
let = generate_self_signed_rsa_keypair;
AS4 โ Custom verifier (testing feature)
use ;
use ;
AS2 โ Send a signed message
use ;
use SessionContext;
use EventBus;
let policy = As2SendPolicy ;
let creds = As2SendCredentials ;
let session = new?;
let bus = new?;
let output = send_async.await?;
Strict production startup
use ;
use ;
use Arc;
let bus = strict_production_event_bus?;
let _token = issue_strict_runtime_bootstrap_token_with_as4_topology?;
// _token must be passed to session_with_strict_runtime_bootstrap_token()
// before any protocol entry point is called
SBDH โ PEPPOL / CEF eDelivery
use ;
let wrapped = StandardBusinessDocument .wrap?;
๐๏ธ Feature Flags
| Flag | Enables | Default |
|---|---|---|
as2 |
AS2 send/receive (as2::send_sync/async, as2::receive_sync/async) |
โ |
as4 |
AS4 send/receive, pull store, WS-Security, ECDH-ES + ECDSA support | โ |
client |
HTTP egress via reqwest |
โ |
server |
Axum router integration (as2_router, as4_router) |
โ |
compression |
Zlib/GZIP payload compression (RFC 5402) | โ |
async-ocsp |
Async OCSP responder fetching | โ |
interop-strict |
Strict interop mode as compile-time default | โ |
interop-relaxed |
Relaxed mode helpers for legacy partners | โ |
trace |
tracing instrumentation on hot paths |
โ |
prometheus |
Built-in Prometheus/OpenMetrics MetricsSink |
โ |
postgres-storage |
PostgreSQL-backed durable cluster-safe storage | โ |
testing |
InsecureBypassAs4Verifier, DurableInMemoryDedupBackend, keypair generators, verifier_seal, interop matrix executor, EventBus::new_for_testing() |
โ |
testing + server |
Also: MockAs4Endpoint (with builder().with_decryption_key_pem()) |
โ |
Security: The
testingfeature triggers acompile_error!in release profile builds. It must never appear in production binaries.
๐๏ธ Architecture
asx-rs
โโโ as2/ AS2 send, receive, MDN handling
โโโ as4/ AS4 push/pull, P-Mode registry, pull store, conversation gate
โ โโโ pmode.rs P-Mode registry + resolution
โ โโโ parser.rs ebMS3 UserMessage XML parser
โ โโโ pull_store/ Bounded in-memory pull queue (per-MPC)
โ โโโ mock_endpoint/ In-process test endpoint (testing + server)
โโโ crypto/
โ โโโ as2_smime CMS/S/MIME signing + verification
โ โโโ wssec/ WS-Security (XMLDSig, XMLenc11, OCSP, Exc-C14N)
โ โ โโโ xmlenc AES-GCM + (RSA-OAEP | ECDH-ES + ConcatKDF + AES-KW)
โ โโโ soap_builder SOAP envelope construction
โโโ transport/
โ โโโ ingress HTTP request normalisation + validation
โ โโโ egress HTTP send with endpoint governance
โ โโโ server Axum router builders (server feature)
โโโ lifecycle Type-state trust transition machine
โโโ reliability Retry classification, dedup, reconciliation
โโโ storage/ DedupStorage + ReconciliationStorage traits + in-memory impls
โโโ observability/ EventBus, audit sink, back-pressure policy
โโโ interop Profile stacks, regional packs, exception policies
โโโ sbdh UN/CEFACT SBDH 1.3 wrap/unwrap
โโโ wire Bounded stream reading, MIME utilities
โโโ core Error types, SessionContext, shared utilities
๐ Trust lifecycle
UntrustedBytes
โ structural parse (MIME / SOAP envelope)
โผ
StructurallyParsed
โ cryptographic verify (S/MIME or XMLDSig)
โผ
CryptographicallyVerified
โ decrypt (S/MIME EnvelopedData or XMLenc11)
โผ
ContentDecrypted
โ dedup check + domain validation
โผ
DomainReady โ your application code starts here
๐ XML Encryption: automatic key transport selection
encrypt_payload_xmlenc inspects the recipient certificate's key type at call time:
| Recipient cert key | Key transport | Key reference | Profiles |
|---|---|---|---|
| RSA | RSA-OAEP (SHA-256 / MGF1-SHA-256) | BinarySecurityToken |
PEPPOL, CEF eDelivery |
| EC (any named curve) | ECDH-ES ephemeral + ConcatKDF (NIST SP 800-56A) + AES-128-KW (RFC 3394) | X509SKI |
BDEW AS4-Profil ยง2.2.6.2.2, BSI TR-03116-3 ยง9.2 |
No configuration knob is needed โ pass the recipient's certificate and the right algorithm follows from the key type.
๐ Security Notes
InsecureBypassAs4Verifier/InsecureBypassTrustVerifierbypass all cryptographic checks. They are strictly limited to thetestingfeature, which is blocked in release builds viacompile_error!.- PKIX chain validation is fail-closed: an empty
trust_anchor_pemsstore withrequire_chain_validation = truerejects every certificate. - OCSP is disabled by default (
OcspMode::Disabled). SetOcspMode::ResponderOnlyorOcspMode::StapledAndResponderin production. - Outbound HTTP egress validates URL scheme and blocks private / link-local targets.
๐ Status
asx-rs is beta quality. Core AS2 and AS4 push/pull flows are implemented, tested
(887+ tests across unit + integration suites), and exercised in production integrations.
- โ AS2 send/receive (signed, encrypted, compressed, sync + async)
- โ AS4 push send/receive (signed, encrypted, dedup, fragment reassembly)
- โ AS4 pull (with reliability classification)
- โ WS-Security (RSA-SHA256, ECDSA-SHA256, ECDH-ES + ConcatKDF + AES-KW, XMLenc11)
- โ OCSP + PKIX chain validation
- โ Strict-mode production validation gate
- โ Comprehensive testing infrastructure (bypass verifier, mock endpoint, keypair generators)
- โ ๏ธ Persistent storage backends (dedup/reconciliation) are trait-defined but not shipped in-tree; deployers provide their own Redis/PostgreSQL/DynamoDB implementations.
๐ License
Licensed under either of:
at your option.
โจ Features
๐จ AS2 (RFC 4130 / RFC 5751)
- Send and receive signed payloads (CMS/S/MIME, RSA-SHA256)
- Synchronous and asynchronous MDN (Message Disposition Notification)
- MIC computation for end-to-end integrity verification
- Payload compression (RFC 5402 / zlib, enabled by default via
compression) - Configurable interop mode: strict vs. relaxed for legacy partners
- Retry classification (
SuccessConfirmed/Indeterminate/AcceptedPendingVerification)
๐ฌ AS4 (ebMS3 + OASIS eDelivery)
- One-Way/Push send and receive
- One-Way/Pull with bounded in-memory pull store per MPC partition
- WS-Security XMLDSig signing (RSA-SHA256, Exc-C14N) and verification
- XML encryption / decryption (XMLenc11 AES-GCM + RSA-OAEP)
- Streaming receive path with bounded memory
- P-Mode registry for per-partner MEP/security configuration
- SBDH 1.3 envelope wrap/unwrap for PEPPOL and CEF eDelivery
๐ Security & Reliability
- Type-state lifecycle machine โ compiler enforces the full trust chain:
UntrustedBytes โ StructurallyParsed โ CryptographicallyVerified โ ContentDecrypted โ DomainReady. Payload bytes cannot reach application code without every gate passing. - OCSP stapling + responder-based revocation checking (
async-ocspfeature) - PKIX certificate chain validation (fail-closed on empty trust store)
- Dedup storage (
InMemoryDedupStorage,TtlDedupStorage) prevents replay - Reconciliation hooks for async delivery confirmation
๐ HTTP Transport
- Axum server integration (
serverfeature) โ drop-inRouterfor AS2 and AS4 ingress - Async HTTP egress via
reqwest(clientfeature) - Inbound endpoint governance (
HttpEndpointPolicy) against unexpected sources
๐ Observability
EventBuswith fan-out broadcast and ordered mpsc audit channelDurableAuditSinktrait for pluggable audit backends- Configurable back-pressure policy (
BackpressurePolicy) EventBusMetricswith lock-freeAtomicU64counters- Optional built-in Prometheus/OpenMetrics text sink (
prometheusfeature)
๐งฉ Interop
- Profile stacking with regional packs and per-partner overlays
interop-strict(default) andinterop-relaxedfeature-gated modes- Exception policies (
InteropExceptionPolicy) for well-known deviations - Interop matrix executor (
testingfeature) โ built-in fixture-based conformance runner
๐ Quick Start
Add to Cargo.toml:
[]
# AS2 client + server with OCSP
= { = "0.8", = ["as2", "client", "server", "async-ocsp"] }
# AS4 only
= { = "0.8", = ["as4", "client", "server", "async-ocsp"] }
# Both protocols with compression (default)
= { = "0.8", = ["as2", "as4", "compression", "client", "server", "async-ocsp"] }
as2andas4are not enabled by default โ add them explicitly.
๐ Examples
AS2 โ Send a signed message
use ;
use SessionContext;
use ;
let policy = As2SendPolicy ;
let creds = As2SendCredentials ;
let session = new?;
let bus = new_with_config_and_mode?;
let output = send_sync?;
// output.mime.body โ body bytes to POST to partner's AS2 URL
// output.mime.content_type โ HTTP Content-Type header value
// output.http_headers โ required AS2 HTTP headers (AS2-From, AS2-To, etc.)
AS2 โ Receive and verify
use ;
use SessionContext;
let session = new?;
let verifier = CmsSmimeTrustVerifier;
let trusted = receive_sync?;
println!;
AS4 โ Send a push message
use ;
use SessionContext;
use ;
let = new
.signing_cert_pem
.signing_key_pem
.build?;
let session = new?;
let bus = new_with_config_and_mode?;
let output = send_sync?;
// output.soap_envelope.body -> multipart/related bytes ready to POST
AS4 โ Axum server (ingress)
use Arc;
use Router;
use async_trait;
use ;
use As4HttpIngress;
;
async
Strict production startup validation
use Arc;
use ;
use ;
use ;
In non-testing builds, strict interop protocol entry points fail closed unless
startup validation is bound to the session by explicitly applying
asx_rs::presets::session_with_strict_runtime_bootstrap_token(...).
For AS2 HTTP server flows, bind a strict session once with
session_with_strict_runtime_bootstrap_token(...) and then call
As2HttpIngress::receive_and_generate_mdn(...) or
As2HttpIngress::receive_and_generate_mdn_with_signing(...).
For AS4 HTTP server flows, bind a strict session once with
session_with_strict_runtime_bootstrap_token(...) and then call
As4HttpIngress::receive_push_with_dedup_sync(...) with an optional receipt payload.
SBDH โ PEPPOL / CEF eDelivery envelope
use ;
let doc = StandardBusinessDocument ;
let wrapped = doc.wrap?;
// wrapped โ send via AS4 push to PEPPOL access point
๐๏ธ Feature Flags
| Flag | Enables | Default |
|---|---|---|
as2 |
AS2 send/receive free functions (as2::send_sync, as2::receive_sync) |
โ |
as4 |
AS4 send/receive free functions (as4::send_sync, as4::receive_push_with_dedup_sync) and As4PullStore |
โ |
client |
HTTP egress via reqwest (As2HttpTransport, As4HttpTransport) |
โ |
server |
Axum router integration (as2_router, as4_router) |
โ |
compression |
Zlib/GZIP compression via flate2 |
โ |
async-ocsp |
Async OCSP responder fetching via reqwest |
โ |
interop-strict |
Strict interop mode as default | โ |
interop-relaxed |
Relaxed mode helpers for legacy partners | โ |
trace |
tracing instrumentation stubs |
โ |
prometheus |
Built-in PrometheusMetricsSink adapter for MetricsSink |
โ |
postgres-storage |
PostgreSQL-backed durable, cluster-safe dedup/reconciliation storage | โ |
testing |
Exposes fixture catalog and matrix executor | โ |
๐๏ธ Architecture
asx-rs
โโโ as2/ AS2 send, receive, MDN handling
โโโ as4/ AS4 push/pull, P-Mode registry, pull store
โ โโโ pmode.rs P-Mode registry + resolution
โ โโโ parser.rs ebMS3 UserMessage XML parser
โ โโโ pull_store Bounded in-memory pull queue
โโโ crypto/
โ โโโ as2_smime CMS/S/MIME signing + verification
โ โโโ wssec WS-Security (XMLDSig, XMLenc, OCSP, Exc-C14N)
โ โโโ soap_builder SOAP envelope construction
โโโ transport/
โ โโโ ingress HTTP request normalisation
โ โโโ egress HTTP send with endpoint governance
โ โโโ server Axum router builders (server feature)
โโโ lifecycle Type-state trust transition machine
โโโ reliability Retry classification, dedup, reconciliation
โโโ storage/ DedupStorage + ReconciliationStorage traits + in-memory impls
โโโ observability/ EventBus, audit sink, back-pressure policy
โโโ interop Profile stacks, regional packs, exception policies
โโโ sbdh UN/CEFACT SBDH 1.3 wrap/unwrap
โโโ wire Bounded stream reading, MIME utilities
โโโ core Error types, SessionContext, shared utilities
๐ Trust lifecycle
Every inbound byte travels a compiler-enforced path before reaching your application:
UntrustedBytes
โ structural parse (MIME / SOAP envelope)
โผ
StructurallyParsed
โ cryptographic verify (S/MIME or XMLDSig)
โผ
CryptographicallyVerified
โ decrypt (S/MIME EnvelopedData or XMLenc)
โผ
ContentDecrypted
โ dedup check + domain validation
โผ
DomainReady โ your application code starts here
๐ Security Notes
InsecureBypassTrustVerifierskips all cryptographic verification. It is intended exclusively for testing. Never use it in production.- PKIX chain validation is fail-closed: an empty
trust_anchor_pemsstore rejects every certificate. - OCSP checking is opt-in via
OcspModeinCertHandle. The default isOcspMode::Disabledโ setOcspMode::ResponderOnlyorOcspMode::StapledAndResponderin production. - Outbound HTTP egress validates URL scheme and blocks private/loopback/link-local targets (including DNS-rebinding to private addresses).
๐ Status
asx-rs is alpha quality. Core AS2 send/receive and AS4 push/pull flows are implemented and tested, but the crate is not yet production-hardened.
Current constraints to evaluate before production rollout:
- Core send/receive entry points are synchronous, but async-safe wrappers are now available (
as2::send_async,as2::receive_async,as4::send_async,as4::receive_push_with_dedup_async) to isolate blocking work on Tokio blocking threads. - Production persistence adapters (Redis/PostgreSQL/DynamoDB) are trait-based and not yet shipped in-tree; deployers must provide backend implementations.
๐ License
Licensed under either of:
at your option.