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:listnsverb 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_apskbefore 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.persistenceandpublicKeyCacheSettingstake 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 publicSigningKeyno 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
__ssenvkey, 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
enrollmentIdofatSignhas 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
secretto 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.excludeEnrollmentIdsdrops 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 exactnamesand/or anamePrefix(e.g.__rk.for epoch keys).excludeEnrollmentIdsdrops 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
payloadtoto's key package and stores it for delivery, addressed throughappNamespace.inherited -
Shares every secret in secretStore with
to, filtered — whenapprovedNamespacesis given — to secrets whose namespace that enrollment is authorized for (SecretStore.namespaceAuthorizes).inherited -
For use by an enrollment approver, after approving
enrollmentIdwithapprovedNamespaces(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 -
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
payloadin 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