Concrete crypto providers for the CryptoProvider capability protocols
defined in swift-p2p-core. Ships two interchangeable
backends — vendored BoringSSL for non-Apple and Embedded Swift targets, and
Apple's swift-crypto / CryptoKit on Apple targets — behind one umbrella that
selects from the actual compilation destination,
operating over the stack's [UInt8] / Span<UInt8> byte currency.
Release status. Current release:
0.2.0.
- Swift 6.4 development snapshot
2026-07-23(tools version6.2) - macOS 26+ / iOS 26+
Add swift-p2p-crypto to your Package.swift:
.package(url: "https://github.com/1amageek/swift-p2p-crypto.git", from: "0.2.0")| Product | Provider | Backend |
|---|---|---|
P2PCrypto |
DefaultCryptoProvider (typealias) |
Foundation on Apple; BoringSSL on non-Apple and Embedded targets |
BoringSSLCryptoProvider and FoundationEssentialsCryptoProvider are public enums
that conform to CryptoProvider and the independent
AESCounterModeProvider. They wire each capability associated type (AES-CTR,
AEAD, hash, HKDF, HMAC, ECDH, signatures, random, clock, header protection) to
a backend-specific implementation. AES-CTR remains outside the aggregate so a
consumer such as SRTP can require only AESCounterModeProvider & MACProvider.
P2PCrypto exposes DefaultCryptoProvider, a typealias chosen at compile
time:
#if P2P_CRYPTO_DEFAULT_BORINGSSL
public typealias DefaultCryptoProvider = BoringSSLCryptoProvider
#elseif P2P_CRYPTO_DEFAULT_FOUNDATION
public typealias DefaultCryptoProvider = FoundationEssentialsCryptoProvider
#elseif canImport(Darwin)
public typealias DefaultCryptoProvider = FoundationEssentialsCryptoProvider
#else
public typealias DefaultCryptoProvider = BoringSSLCryptoProvider
#endifThe automatic manifest configuration includes both source sets because a
SwiftPM manifest executes on the build host, which may differ from a
cross-compilation destination. The Swift source condition above is evaluated
for the destination, so a macOS host cross-compiling to Linux or WASI does not
accidentally select the Apple backend. P2P_CRYPTO_BACKEND=foundation and
P2P_CRYPTO_BACKEND=boringssl remain explicit build-time overrides.
Depend on P2PCrypto and use DefaultCryptoProvider to get the destination's
default backend automatically.
The Embedded backend uses a vendored BoringSSL under vendor/p2p-boringssl
(do not edit; it is upstream-derived). It is wired as local C targets
CP2PBoringSSL and CP2PBoringSSLShims. Symbols carry a
CP2PBoringSSL_* prefix so the library can coexist in the same binary with
the BoringSSL embedded inside Apple's swift-crypto without duplicate-symbol
collisions. Because BoringSSL is C++, BoringSSL builds link libc++.
Both providers expose a reusable AES-128-CTR context through
AESCounterModeProvider. The operation accepts a caller-owned inout [UInt8],
a validated Range<Int>, and a borrowed 16-byte counter. Only the selected
range is mutated; the payload is never converted to Data or another array.
| Backend | Keyed state | Per-call state | Synchronization |
|---|---|---|---|
| BoringSSL | immutable expanded AES_KEY |
scoped counter, keystream block, offset | none; keyed state is read-only |
| FoundationEssentials | CCCryptorRef |
reset counter | Mutex around CCCryptorReset + CCCryptorUpdate |
Incremental HMAC-SHA1/256/384 follows the same payload rule. Each update(Span)
borrows the Span directly into the backend hash state rather than buffering or
materializing the media payload. Only the fixed-size final authentication code
is allocated.
| Dependency | Reference | Used by |
|---|---|---|
swift-p2p-core |
from: "0.3.0" |
both backends (P2PCoreCrypto, P2PCoreBytes) |
| vendored BoringSSL | local C targets under vendor/p2p-boringssl |
BoringSSL backend |
swift-crypto |
"3.12.3"..<"5.0.0" |
FoundationEssentials backend |
The swift-crypto range deliberately spans into the 4.x line: in the wider
swift-libp2p graph this package is resolved transitively alongside
swift-tls and swift-webrtc, which require swift-crypto >= 4.2.0.
Both backends are exercised against known-answer tests (KATs), and the two are checked for cross-provider byte-equivalence so a build can swap backends without changing wire output:
- BoringSSL tests — AEAD (RFC 8439 ChaCha20-Poly1305, NIST AES-GCM), NIST AES-128-CTR, hash/HKDF/HMAC, key agreement, signatures, header protection, QUIC vectors.
- FoundationEssentials tests — KAT / RFC vectors for the host backend.
- Equivalence tests — AES-CTR, AEAD seal output, hashes, HKDF, and incremental HMAC MUST be byte-identical across BoringSSL and swift-crypto, with cross-open interop. Signatures and ECDH are cross-verified rather than byte-compared, since both backends sign non-deterministically.
Gated on the P2P_CRYPTO_EMBEDDED environment variable; the Lifetimes
feature is always on (the core's Span surface requires it):
# Apple host build (default): swift-crypto / CryptoKit backend
swift build
# Embedded build: BoringSSL backend + Embedded feature + WMO
P2P_CRYPTO_EMBEDDED=1 swift build
# Host BoringSSL backend build
P2P_CRYPTO_BACKEND=boringssl swift build
# Normal WASM build: BoringSSL is selected from the destination automatically
swift build --swift-sdk <swift-6.4-wasm-sdk>
# Host equivalence test build with both backends present
P2P_CRYPTO_BACKEND=all xcodebuild test \
-scheme swift-p2p-crypto \
-destination 'platform=macOS' \
-maximum-test-execution-time-allowance 60The KAT, RFC-vector, and cross-provider equivalence suites listed under Security run on the host with the default toolchain:
P2P_CRYPTO_BACKEND=all xcodebuild test \
-scheme swift-p2p-crypto \
-destination 'platform=macOS' \
-maximum-test-execution-time-allowance 60