AtClientSecretSharing class

Ready-made composition of the same-atSign secret-sharing mixins, for apps that don't want to mix them into their own classes.

final sharing = AtClientSecretSharing.forClient(atClient);
await sharing.register();
await sharing.startListening();
sharing.receivedSecrets.listen((r) => ...);

Prefer AtClientSecretSharing.forClient over the plain constructor: a secret-sharing instance is this APKAM keypair's recipient identity (its X-Wing enc keypair, registered key package, and envelope listener) plus its SecretStore. Reusing one instance per AtClient lets every consumer (the app and SDK-internal ones, e.g. a future CryptoProvider that distributes its keys as secrets) share a single store and a single registration rather than minting duplicate enc keypairs. (Correctness does not depend on it — kpid-addressed envelopes converge idempotently via SecretStore.putIfNewer — but a single instance avoids redundant registration and double delivery.)

⚠ Not yet suitable for production secrets. The recipient key package a sender seals to is discovered via the gated enroll:listns verb and is not yet APKAM-signed or verified, so sealing currently trusts the atServer to return the genuine key package — a tampering atServer could substitute the encapsulation target and read the secret. This caveat lifts once advertised key packages are signed by their generating enrollment and verified against its _apsk before sealing.

Mixed-in types
Annotations
  • @experimental

Constructors

AtClientSecretSharing(AtClient atClient, {({Duration cacheExpiry, bool resetOnLookup})? publicKeyCacheSettings = (cacheExpiry: Duration(minutes: 5), resetOnLookup: true)})
Direct construction creates an independent instance with its own enc keypair. Use forClient unless that is what you want (tests, custom compositions).
AtClientSecretSharing.forClient(AtClient atClient, {SecretStorePersistence? persistence, ({Duration cacheExpiry, bool resetOnLookup})? publicKeyCacheSettings = (cacheExpiry: Duration(minutes: 5), resetOnLookup: true)})
The shared secret-sharing instance for atClient, created on first call. persistence and publicKeyCacheSettings take effect only on the creating call; later calls return the cached instance unchanged (one SecretStorePersistence per APKAM keypair — see SecretStore.persistence).
factory

Properties

answerSecretRequests SecretRequestPolicy?
Optional app override for the kind:'request' answer decision. Null = the default policy (answer any requester that resolves to an authorized key package of the request's namespace).
getter/setter pairinherited
atClient AtClient
final
directory EnrollmentDirectory
The atServer-backed key-package directory. Defaults to a verb-backed implementation; tests assign a fake.
getter/setter pairinherited
enrollmentId String
no setterinherited
envelopeTtl Duration
How long an unconsumed envelope lives on the atServer.
getter/setter pairinherited
hashCode int
The hash code for this object.
no setterinherited
isRegistered bool
no setterinherited
kpid String
This key package's addressing id (KeyPackage.kpid) — the SHA-256 prefix of the X-Wing public key. Throws StateError until register completes.
no setterinherited
loadApkamKeys Future<PersistedApkamKeys?> Function()?
Supply to give this APKAM keypair a stable enc keypair across restarts. Called once, before generating a fresh one; return null to generate fresh.
getter/setter pairinherited
logger → AtSignLogger
final
myKeyPackage KeyPackage
This APKAM keypair's key package (the one registered for discovery). Throws StateError until register has generated the enc keypair.
no setterinherited
privateSigningKey String
the private key used to sign things this application sends
no setterinherited
pubKeyCache Map<String, (String, Timer)>
finalinherited
publicKeyCacheSettings → ({Duration cacheExpiry, bool resetOnLookup})?
How to handle caching of public keys used for verification
final
publicSigningKey String
the public key which can be used to verify signatures made using privateSigningKey
no setterinherited
publicSigningKeyUri String
the uri (e.g. public:apsk.<enrollment_id>.__wa@atsign) of the publicSigningKey
no setterinherited
receivedEnvelopes Stream<ReceivedEnvelope>
Decrypted, verified payloads addressed to this client. Listen, then call startListening.
no setterinherited
receivedSecrets Stream<ReceivedSecret>
Secrets shared with this client by other APKAM keypairs (already verified, decrypted, and stored in secretStore). Listen, then call startListening.
no setterinherited
requestAnswerMinInterval Duration
Anti-storm floor: the same (requester, secret-name) is answered at most once per this interval. A burst of duplicate requests collapses to one share.
getter/setter pairinherited
runtimeType Type
A representation of the runtime type of the object.
no setterinherited
saveApkamKeys Future<void> Function(PersistedApkamKeys keys)?
Supply to persist a freshly generated enc keypair (e.g. to the keyfile / platform keystore — the app's concern).
getter/setter pairinherited
secretStore SecretStore
The secrets this client holds: what it created via SecretStore.putSecret, plus what other APKAM keypairs shared with it (received secrets are stored automatically, newest wins).
finalinherited
sendWakeUpNotification bool
Whether sendEnvelope also fires a best-effort wake-up notification (default on) after the put. Clients that run sync receive envelopes via sync without it; sync-less clients rely on it (their startListening monitors for it and does a remote sweep). It is best-effort: the envelope is already durably stored, so a failed wake-up never fails the send. A future atServer enhancement will emit this notification itself on a put to an __ssenv key, at which point senders can leave it off.
getter/setter pairinherited
sweepInterval Duration
How often startListening sweeps the local store for envelopes, in addition to sweeping when sync delivers one.
getter/setter pairinherited
xWingPublicKey Uint8List
This APKAM keypair's X-Wing public key (raw bytes). Throws StateError until register has completed.
no setterinherited
xWingSeed Uint8List
This APKAM keypair's X-Wing secret seed — for decapsulation by composing mixins, not for application use.
no setterinherited

Methods

cachePubKey(String atSign, String enrollmentId, String pubKey) → void
inherited
getApkamPublicKey(String atSign, String enrollmentId) Future<String>
Fetch the APKAM public signing key which enrollmentId of atSign has published in its per-enrollment namespace. See ApkamSigning.publicSigningKeyUri.
inherited
lookupPubKey(String atSign, String enrollmentId) String?
inherited
noSuchMethod(Invocation invocation) → dynamic
Invoked when a nonexistent method or property is accessed.
inherited
publishPublicSigningKey() Future
inherited
pushSecretToNamespaceMembers(Secret secret, {Set<String> excludeEnrollmentIds = const {}}) Future<int>
Pushes one secret to every key package registered for its namespace (minus this client). This is the mint/rotation push: it enumerates the namespace's members via the directory, seals once per key package, and puts the kpid-addressed envelope. excludeEnrollmentIds drops revoked enrollments. Returns the number of key packages it was pushed to.
inherited
register() Future<KeyPackage>
Generates (or loads, via loadApkamKeys) this APKAM keypair's X-Wing enc keypair and publishes its APKAM signing key (so peers can verify its envelopes), then returns this client's KeyPackage. Idempotent.
inherited
requestSecret(String namespace, String name, {Duration timeout = const Duration(seconds: 30), Set<String> excludeEnrollmentIds = const {}}) Future<Secret>
Requests a single named secret from the holders in namespace, then resolves when it arrives (waitForSecret).
inherited
requestSecretsFromNamespace(String namespace, {List<String>? names, String? namePrefix, Set<String> excludeEnrollmentIds = const {}}) Future<int>
Broadcasts a pull request for held secrets to every key package registered for namespace (minus this client). Holders that pass the answer policy reply by sharing the matching secrets; the caller typically then waitForSecrets. Filter the request by exact names and/or a namePrefix (e.g. __rk. for epoch keys). excludeEnrollmentIds drops revoked enrollments. Returns the number of key packages the request was sent to.
inherited
sendEnvelope(KeyPackage to, String appNamespace, Map<String, dynamic> payload) Future<void>
Encrypts payload to to's key package and stores it for delivery, addressed through appNamespace.
inherited
shareAllSecretsWith(KeyPackage to, {Map<String, dynamic>? approvedNamespaces, Set<String>? excludeEnrollmentIds}) Future<int>
Shares every secret in secretStore with to, filtered — when approvedNamespaces is given — to secrets whose namespace that enrollment is authorized for (SecretStore.namespaceAuthorizes).
inherited
shareAllSecretsWithEnrollment(String enrollmentId, Map<String, dynamic> approvedNamespaces, {Set<String>? excludeEnrollmentIds}) Future<int>
For use by an enrollment approver, after approving enrollmentId with approvedNamespaces (both available from the enrollment request): shares with each of the newly-approved enrollment's key packages every held secret the enrollment's namespaces authorize.
inherited
shareSecretWith(KeyPackage to, Secret secret) Future<void>
Shares one secret with one key package.
inherited
startListening() Future<void>
Starts watching for envelopes addressed to this client: sweeps the local store now, after every sync that delivers an envelope key, and every sweepInterval; and subscribes to wake-up notifications, doing a remote sweep on each (which is how a sync-less client receives envelopes at all). Requires register to have completed.
inherited
stopListening() → void
Stops watching. The receivedEnvelopes stream stays open; a later startListening resumes.
inherited
sweepOnce({bool fromRemote = false}) Future<int>
Scans for envelopes addressed to this client; verifies, decrypts, emits and deletes each. Returns how many envelopes were consumed. Safe to call concurrently with the periodic sweep, a sync-triggered sweep, and a wake-up sweep — each envelope key is claimed synchronously before any await, so the same payload is never emitted twice.
inherited
toString() String
A string representation of this object.
inherited
verifyEnvelopeSignature(Map envelope, {required String signerAtSign}) Future<void>
Verify an envelope created by wrapAndSign or wrapAndSignAndJsonEncode.
inherited
waitForSecret(String namespace, String name, {Duration timeout = const Duration(seconds: 30)}) Future<Secret>
Returns the secret (namespace, name) as soon as this client holds it: immediately from secretStore when already present, otherwise the first matching arrival on receivedSecrets — subscription is set up before the store check, so an arrival between the two cannot be missed. startListening must be active for arrivals to be observed.
inherited
wrapAndSign(Object? payload, {Object? toEncodable(Object? nonEncodable)?}) FutureOr<Map<String, Object?>>
Create a json envelope around payload in a format that can be verified by verifyEnvelopeSignature.
inherited
wrapAndSignAndJsonEncode(Object? payload, {Object? toEncodable(Object? nonEncodable)?}) FutureOr<String>
Same as wrapAndSign but we also call jsonEncode for you :)
inherited

Operators

operator ==(Object other) bool
The equality operator.
inherited