Skip to content

reallyme/crypto

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

33 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

reallyme-crypto

Code Checks reallyme-crypto npm Maven Central Security Policy License

ReallyMe Crypto is a cross-platform cryptography workspace for Rust, Swift, Kotlin, Android, and TypeScript. It provides one typed operation contract, explicit provider routing, and shared conformance evidence across server, mobile, browser, and WASM environments.

The protobuf schema is the source of truth for executable structured requests, responses, algorithm identifiers, and wire errors. Generated bindings feed a single Rust operation boundary; native SDK facades provide ergonomic APIs over the same semantics. provider_manifest.json fixes the provider selected for each SDK lane, and positive and negative vectors prove the byte and failure contract. Missing providers and unsupported algorithms fail closed. The canonical contract is not mechanically generated from one language API.

Why

Modern cryptography APIs differ across platforms. Algorithms are exposed differently, key formats vary, providers have different capabilities, and error behavior is inconsistent.

ReallyMe Crypto makes those differences explicit. Applications use consistent algorithm identifiers, encodings, errors, and verification semantics wherever a lane is supported. Provider selection is deterministic, verification fails closed, and an unavailable route returns a typed error instead of switching implementations.

Packages

Language Package Notes
Rust reallyme-crypto Umbrella crate for cryptographic APIs.
Swift ReallyMeCrypto Swift Package at the repository root, with native Apple providers and Rust C ABI routes where needed.
Kotlin/JVM me.really:crypto JVM package with explicit JCA/JCE, BouncyCastle, and Rust-backed routes.
Android me.really:crypto-android Android AAR with jniLibs Rust provider packaging and the published me.really:codec-android dependency.
TypeScript @reallyme/crypto npm package for Node, browsers, and WASM-backed primitives.
Protobuf reallyme/crypto/v1/crypto.proto Canonical structured operation, algorithm identifier, and typed wire-error contract.

General-purpose encoding, serialization, and multiformat codec APIs live in github.com/reallyme/codec.

Supported Algorithms

Category Algorithms
AEAD and key wrap AES-128/192/256-GCM, AES-256-GCM-SIV, AES-128/192/256-KW, ChaCha20-Poly1305, XChaCha20-Poly1305
Hash, MAC, and KDF SHA-2, SHA-3, HMAC-SHA-256/384/512, HKDF-SHA256/384, KMAC256 KDF, JWA Concat KDF (ECDH-ES), PBKDF2-HMAC-SHA-256/512, Argon2id
Signatures Ed25519, ECDSA P-256/P-384/P-521, secp256k1 ECDSA, BIP-340 Schnorr, RSA verification, ML-DSA-44/65/87, SLH-DSA-SHA2-128s
Key agreement and KEM X25519, X448 (standalone Rust crate and HPKE component only), P-256/P-384/P-521/secp256k1 ECDH, ML-KEM-512/768/1024, X-Wing-768
Protocols HPKE
Key and wire envelopes JWK and public-key multikey bindings used by the crypto facades

X-Wing-768 follows the IETF CFRG Internet-Draft draft-connolly-cfrg-xwing-kem, which defines a hybrid KEM built from X25519 and ML-KEM-768.

Availability varies by SDK lane. The exact provider and support map lives in PROVIDER_POLICY.md. For each language lane, an algorithm is either handled by its declared provider or rejected with a typed unsupported-algorithm error.

X448 is not an umbrella-crate or SDK-facade algorithm. It is available through the standalone reallyme-crypto-x448 Rust crate and as an internal HPKE KEM component. It is therefore intentionally absent from the package provider manifest and exact cross-language support map.

HPKE Profiles

The cross-platform SDK facade exposes two RFC 9180 Base-mode profiles:

Profile KEM KDF AEAD Swift Kotlin/JVM and Android TypeScript
DHKEM-P256-HKDF-SHA256-HKDF-SHA256-AES-256-GCM DHKEM(P-256, HKDF-SHA256) HKDF-SHA256 AES-256-GCM Rust C ABI provider BouncyCastle Rust WASM provider
DHKEM-X25519-HKDF-SHA256-HKDF-SHA256-CHACHA20-POLY1305 DHKEM(X25519, HKDF-SHA256) HKDF-SHA256 ChaCha20-Poly1305 Rust C ABI provider BouncyCastle Rust WASM provider

Swift requires an explicit Rust C ABI provider for these profiles. Missing or unavailable providers fail closed. The Rust native operation contract also supports reviewed classical, post-quantum, and hybrid HPKE components; see docs/protobuf.md for the executable component set and operation-level constraints.

The Rust HPKE surface includes split PSK sender setup for OpenMLS targeted messages, arbitrary-length IKM key derivation through each KEM's registered DeriveKeyPair construction, and named aliases for the MLS 192/256-bit ML-KEM-1024 and MLKEM1024-P384 draft profiles. Live sender contexts remain in-process, non-exportable state and are not exposed through protobuf or SDK transport adapters. Raw Rust derivation accepts the selected KEM's non-empty input contract; operation and serialized SDK boundaries require at least 32 bytes of caller-owned high-entropy IKM.

Every provider route must implement identical input validation and normalization, output encodings, typed failure semantics, and edge-case behavior. Security-sensitive composition, canonical serialization, deterministic signatures, post-quantum primitives, memory-hard KDFs, and provider-ambiguous algorithms default to the ReallyMe Rust implementation through FFI, JNI, or WASM unless a native route is explicitly proven equivalent.

RSA support is intentionally verification-only for historical X.509 and eMRTD PKI interoperability. The package does not generate RSA keys, sign with RSA private keys, or provide RSA encryption/decryption APIs.

Install

Rust

cargo add reallyme-crypto --features native,dispatch,ed25519

The Rust crates require Rust 1.96.0 or newer. That MSRV is intentional: ReallyMe Crypto tracks current stable Rust so the public packages can use the compiler, dependency, lint, and target support expected by the conformance wall.

When default features are disabled, enable one backend lane and each algorithm surface your crate calls:

reallyme-crypto = { version = "0.3.3", default-features = false, features = [
  "native",
  "ed25519",
  "p256",
  "secp256k1",
  "sha2",
] }

Messaging-focused consumers can use the narrow primitive bundle instead of the default feature set:

reallyme-crypto = { version = "0.3.3", default-features = false, features = [
  "native",
  "messaging-primitives",
] }

messaging-primitives enables only ChaCha20-Poly1305/XChaCha20-Poly1305, HKDF, HMAC, ML-KEM-768, SHA-2, and X25519. The ML-KEM-768 and X25519 algorithm features require the typed router, so this bundle also enables dispatch; it does not enable signer.

OpenMLS adapters can select the narrow HPKE profile without enabling the full HPKE compatibility surface:

reallyme-crypto = { version = "0.3.3", default-features = false, features = [
  "native",
  "hpke-openmls",
] }

hpke-openmls enables ML-KEM-1024, ML-KEM-1024/P-384, X-Wing, HKDF-SHA256, HKDF-SHA384, AES-256-GCM, and ChaCha20-Poly1305. It does not enable the SHAKE256 HPKE KDF or unrelated HPKE KEMs. Direct reallyme-crypto-hpke consumers can compose its granular kem-*, kdf-*, and aead-* features when an even narrower profile is required.

Dispatch and signer surfaces are feature-gated by algorithm, so enabling the router does not pull in unrelated primitives unless the matching algorithm feature is also selected.

The native and wasm features select the Rust backend lane. They do not, by themselves, enable every primitive. Algorithm features such as ed25519, p256, or sha2 enable the root modules and re-exports. This keeps no-default consumers from pulling unused cryptography while still forwarding the selected backend into every enabled primitive crate. The wasm lane is for wasm32 builds; host builds should use native.

Some Rust helper APIs are intentionally lane-scoped. P-256 raw scalar import is available in both native and wasm lanes through p256::generate_p256_keypair_from_secret_key; it validates an existing private scalar and is not random key generation. P-384 and P-521 ECDH are native Rust APIs today; the Swift, Kotlin, and TypeScript package facades expose their own provider-backed P-384/P-521 ECDH surfaces.

The Swift package also includes a P-256 ECDH Secure Enclave / Keychain API for applications that need non-exportable private-key residency, such as JOSE/JWE decryption with platform-held keys. That API uses explicit handles and is separate from raw private-key bytes.

Swift

.package(
    url: "https://github.com/reallyme/crypto",
    from: "0.3.3"
)
.product(name: "ReallyMeCrypto", package: "crypto")

Kotlin

dependencies {
    implementation("me.really:crypto:0.3.3")
}

TypeScript

npm install @reallyme/crypto

For production deployments, pin exact package versions, release tags, or Git revisions so cryptographic behavior and conformance vectors remain identical across all language lanes.

Quick Start

Rust:

use reallyme_crypto::Algorithm;
use reallyme_crypto::dispatch::{generate_keypair, sign, verify};

let (public_key, secret_key) = generate_keypair(Algorithm::Ed25519)?;
let signature = sign(Algorithm::Ed25519, &secret_key, b"message")?;
verify(Algorithm::Ed25519, &public_key, b"message", &signature)?;
# Ok::<(), reallyme_crypto::dispatch::AlgorithmError>(())

Swift:

import ReallyMeCrypto

let digest = try ReallyMeCrypto.hash(.sha2_256, Array("abc".utf8))

Kotlin:

import me.really.crypto.ReallyMeCrypto
import me.really.crypto.ReallyMeHashAlgorithm

val digest = ReallyMeCrypto.hash(ReallyMeHashAlgorithm.SHA2_256, "abc".toByteArray())

TypeScript:

import { ReallyMeCrypto } from "@reallyme/crypto";

const digest = ReallyMeCrypto.hash("SHA2-256", new TextEncoder().encode("abc"));

Signature verification fails closed: an invalid signature returns an error rather than a boolean that can be accidentally ignored.

Protobuf

The canonical structured wire contract lives at crates/proto/proto/reallyme/crypto/v1/crypto.proto. Service, application, and storage protos can import it when they need the structured operation boundary, stable algorithm identifiers, or typed errors.

ReallyMe Crypto uses raw bytes for single primitive outputs, protobuf bytes for fixed multi-field boundary results, and strict proto-JSON for Connect JSON, CLI, browser-adapter, and conformance boundaries that require JSON. Proto-JSON is available for operation requests, but it is not a casual JSON crypto facade and is not the preferred representation for secret-bearing payloads. JSON convenience shapes remain limited to public metadata such as JWK/JWKS.

For example, a JSON-only client can express a SHA2-256 hash request as strict proto-JSON:

{
  "hash": {
    "algorithm": {
      "hash": "HASH_ALGORITHM_SHA2_256"
    },
    "input": "YWJj"
  }
}

See docs/proto-json.md for operation-family examples and the security notes for secret-bearing JSON payloads.

Rust adapters can enable the operation-response feature and call reallyme_crypto::operation_contract::process_operation_response(request_bytes) with one encoded CryptoOperationRequest: serialized request bytes in, binary CryptoOperationResponse bytes out, with either a generated CryptoOperationResult or generated CryptoError outcome. The ProtoJSON entrypoint accepts the generated JSON representation of the same request and still returns binary protobuf. TypeScript exposes processOperationResponse and processOperationResponseJson; Swift and Kotlin expose the same method names on ReallyMeCrypto. Every structured adapter returns the generated operation response directly. Native SDK methods remain the primary ergonomic application API.

The generated proto adapters are available through:

Language Proto surface
Rust reallyme-crypto-proto
Swift ReallyMeCryptoProto and ReallyMeCryptoProtoAdapters
Kotlin me.really.crypto.v1 and me.really.crypto.proto
TypeScript @reallyme/crypto/proto

See docs/protobuf.md for the boundary rules and adapter policy.

Documentation

Security Rules

This repository is security-sensitive code. The project policy is:

  • no panics, unwraps, or generic string errors in production paths;
  • typed errors only;
  • zeroizing owners for secret material;
  • checked arithmetic for buffer sizes and offsets;
  • negative tests and conformance vectors for every primitive;
  • no silent platform fallback in release platform lanes.

Conformance

Shared vectors live in vectors. The generator and platform verifiers live in crates/conformance. External third-party vector coverage is documented in External conformance vectors.

The everyday all-feature Rust check is:

cargo nextest run --workspace --all-features

The full release wall is documented in docs/conformance.md.

About

Cross-platform cryptography primitives, FFI, conformance vectors, and SDK facades for Rust, Swift, Kotlin, and TypeScript/WASM.

Topics

Resources

License

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Packages

 
 
 

Contributors