@weaveprotocol/core 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1106 -0
- package/dist/elements/auth-styles.d.ts +18 -0
- package/dist/elements/auth-styles.d.ts.map +1 -0
- package/dist/elements/auth-styles.js +150 -0
- package/dist/elements/auth-styles.js.map +1 -0
- package/dist/elements/dom.d.ts +28 -0
- package/dist/elements/dom.d.ts.map +1 -0
- package/dist/elements/dom.js +74 -0
- package/dist/elements/dom.js.map +1 -0
- package/dist/elements/index.d.ts +13 -0
- package/dist/elements/index.d.ts.map +1 -0
- package/dist/elements/index.js +11 -0
- package/dist/elements/index.js.map +1 -0
- package/dist/elements/weave-auth.d.ts +52 -0
- package/dist/elements/weave-auth.d.ts.map +1 -0
- package/dist/elements/weave-auth.js +427 -0
- package/dist/elements/weave-auth.js.map +1 -0
- package/dist/identity/account-store.d.ts +113 -0
- package/dist/identity/account-store.d.ts.map +1 -0
- package/dist/identity/account-store.js +305 -0
- package/dist/identity/account-store.js.map +1 -0
- package/dist/identity/account-vault.d.ts +199 -0
- package/dist/identity/account-vault.d.ts.map +1 -0
- package/dist/identity/account-vault.js +251 -0
- package/dist/identity/account-vault.js.map +1 -0
- package/dist/identity/agent-note.d.ts +19 -0
- package/dist/identity/agent-note.d.ts.map +1 -0
- package/dist/identity/agent-note.js +29 -0
- package/dist/identity/agent-note.js.map +1 -0
- package/dist/identity/crypto-p256.d.ts +7 -0
- package/dist/identity/crypto-p256.d.ts.map +1 -0
- package/dist/identity/crypto-p256.js +84 -0
- package/dist/identity/crypto-p256.js.map +1 -0
- package/dist/identity/device-key.d.ts +60 -0
- package/dist/identity/device-key.d.ts.map +1 -0
- package/dist/identity/device-key.js +103 -0
- package/dist/identity/device-key.js.map +1 -0
- package/dist/identity/did.d.ts +22 -0
- package/dist/identity/did.d.ts.map +1 -0
- package/dist/identity/did.js +37 -0
- package/dist/identity/did.js.map +1 -0
- package/dist/identity/folder-account.d.ts +65 -0
- package/dist/identity/folder-account.d.ts.map +1 -0
- package/dist/identity/folder-account.js +115 -0
- package/dist/identity/folder-account.js.map +1 -0
- package/dist/identity/identity-manager.d.ts +36 -0
- package/dist/identity/identity-manager.d.ts.map +1 -0
- package/dist/identity/identity-manager.js +115 -0
- package/dist/identity/identity-manager.js.map +1 -0
- package/dist/identity/index.d.ts +10 -0
- package/dist/identity/index.d.ts.map +1 -0
- package/dist/identity/index.js +10 -0
- package/dist/identity/index.js.map +1 -0
- package/dist/identity/keys.d.ts +24 -0
- package/dist/identity/keys.d.ts.map +1 -0
- package/dist/identity/keys.js +38 -0
- package/dist/identity/keys.js.map +1 -0
- package/dist/identity/pairing.d.ts +83 -0
- package/dist/identity/pairing.d.ts.map +1 -0
- package/dist/identity/pairing.js +120 -0
- package/dist/identity/pairing.js.map +1 -0
- package/dist/identity/passkey-diagnostics.d.ts +54 -0
- package/dist/identity/passkey-diagnostics.d.ts.map +1 -0
- package/dist/identity/passkey-diagnostics.js +178 -0
- package/dist/identity/passkey-diagnostics.js.map +1 -0
- package/dist/identity/recovery-code.d.ts +50 -0
- package/dist/identity/recovery-code.d.ts.map +1 -0
- package/dist/identity/recovery-code.js +116 -0
- package/dist/identity/recovery-code.js.map +1 -0
- package/dist/identity/root-signer.d.ts +59 -0
- package/dist/identity/root-signer.d.ts.map +1 -0
- package/dist/identity/root-signer.js +44 -0
- package/dist/identity/root-signer.js.map +1 -0
- package/dist/identity/ucan.d.ts +164 -0
- package/dist/identity/ucan.d.ts.map +1 -0
- package/dist/identity/ucan.js +273 -0
- package/dist/identity/ucan.js.map +1 -0
- package/dist/identity/webauthn.d.ts +87 -0
- package/dist/identity/webauthn.d.ts.map +1 -0
- package/dist/identity/webauthn.js +155 -0
- package/dist/identity/webauthn.js.map +1 -0
- package/dist/index.d.ts +116 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +85 -0
- package/dist/index.js.map +1 -0
- package/dist/network/index.d.ts +17 -0
- package/dist/network/index.d.ts.map +1 -0
- package/dist/network/index.js +10 -0
- package/dist/network/index.js.map +1 -0
- package/dist/network/introductions.d.ts +85 -0
- package/dist/network/introductions.d.ts.map +1 -0
- package/dist/network/introductions.js +94 -0
- package/dist/network/introductions.js.map +1 -0
- package/dist/network/local-transport.d.ts +22 -0
- package/dist/network/local-transport.d.ts.map +1 -0
- package/dist/network/local-transport.js +55 -0
- package/dist/network/local-transport.js.map +1 -0
- package/dist/network/mesh.d.ts +31 -0
- package/dist/network/mesh.d.ts.map +1 -0
- package/dist/network/mesh.js +332 -0
- package/dist/network/mesh.js.map +1 -0
- package/dist/network/multi-signaling.d.ts +29 -0
- package/dist/network/multi-signaling.d.ts.map +1 -0
- package/dist/network/multi-signaling.js +125 -0
- package/dist/network/multi-signaling.js.map +1 -0
- package/dist/network/network-manager.d.ts +37 -0
- package/dist/network/network-manager.d.ts.map +1 -0
- package/dist/network/network-manager.js +64 -0
- package/dist/network/network-manager.js.map +1 -0
- package/dist/network/peer-auth.d.ts +98 -0
- package/dist/network/peer-auth.d.ts.map +1 -0
- package/dist/network/peer-auth.js +86 -0
- package/dist/network/peer-auth.js.map +1 -0
- package/dist/network/rtc-transport.d.ts +18 -0
- package/dist/network/rtc-transport.d.ts.map +1 -0
- package/dist/network/rtc-transport.js +149 -0
- package/dist/network/rtc-transport.js.map +1 -0
- package/dist/network/signaling.d.ts +40 -0
- package/dist/network/signaling.d.ts.map +1 -0
- package/dist/network/signaling.js +124 -0
- package/dist/network/signaling.js.map +1 -0
- package/dist/network/transport.d.ts +50 -0
- package/dist/network/transport.d.ts.map +1 -0
- package/dist/network/transport.js +13 -0
- package/dist/network/transport.js.map +1 -0
- package/dist/network/ws-transport.d.ts +42 -0
- package/dist/network/ws-transport.d.ts.map +1 -0
- package/dist/network/ws-transport.js +194 -0
- package/dist/network/ws-transport.js.map +1 -0
- package/dist/node/actions.d.ts +62 -0
- package/dist/node/actions.d.ts.map +1 -0
- package/dist/node/actions.js +500 -0
- package/dist/node/actions.js.map +1 -0
- package/dist/node/carrier.d.ts +85 -0
- package/dist/node/carrier.d.ts.map +1 -0
- package/dist/node/carrier.js +192 -0
- package/dist/node/carrier.js.map +1 -0
- package/dist/node/copy.d.ts +38 -0
- package/dist/node/copy.d.ts.map +1 -0
- package/dist/node/copy.js +53 -0
- package/dist/node/copy.js.map +1 -0
- package/dist/node/index.d.ts +16 -0
- package/dist/node/index.d.ts.map +1 -0
- package/dist/node/index.js +11 -0
- package/dist/node/index.js.map +1 -0
- package/dist/node/node.d.ts +12 -0
- package/dist/node/node.d.ts.map +1 -0
- package/dist/node/node.js +872 -0
- package/dist/node/node.js.map +1 -0
- package/dist/node/space-runtime.d.ts +144 -0
- package/dist/node/space-runtime.d.ts.map +1 -0
- package/dist/node/space-runtime.js +1221 -0
- package/dist/node/space-runtime.js.map +1 -0
- package/dist/node/stores.d.ts +45 -0
- package/dist/node/stores.d.ts.map +1 -0
- package/dist/node/stores.js +31 -0
- package/dist/node/stores.js.map +1 -0
- package/dist/node/types.d.ts +508 -0
- package/dist/node/types.d.ts.map +1 -0
- package/dist/node/types.js +2 -0
- package/dist/node/types.js.map +1 -0
- package/dist/privacy/index.d.ts +4 -0
- package/dist/privacy/index.d.ts.map +1 -0
- package/dist/privacy/index.js +4 -0
- package/dist/privacy/index.js.map +1 -0
- package/dist/privacy/key-distribution.d.ts +42 -0
- package/dist/privacy/key-distribution.d.ts.map +1 -0
- package/dist/privacy/key-distribution.js +50 -0
- package/dist/privacy/key-distribution.js.map +1 -0
- package/dist/privacy/privacy-guard.d.ts +24 -0
- package/dist/privacy/privacy-guard.d.ts.map +1 -0
- package/dist/privacy/privacy-guard.js +87 -0
- package/dist/privacy/privacy-guard.js.map +1 -0
- package/dist/privacy/space-encryption.d.ts +48 -0
- package/dist/privacy/space-encryption.d.ts.map +1 -0
- package/dist/privacy/space-encryption.js +61 -0
- package/dist/privacy/space-encryption.js.map +1 -0
- package/dist/query/engine.d.ts +27 -0
- package/dist/query/engine.d.ts.map +1 -0
- package/dist/query/engine.js +84 -0
- package/dist/query/engine.js.map +1 -0
- package/dist/query/filter.d.ts +15 -0
- package/dist/query/filter.d.ts.map +1 -0
- package/dist/query/filter.js +207 -0
- package/dist/query/filter.js.map +1 -0
- package/dist/query/types.d.ts +144 -0
- package/dist/query/types.d.ts.map +1 -0
- package/dist/query/types.js +22 -0
- package/dist/query/types.js.map +1 -0
- package/dist/react/context.d.ts +81 -0
- package/dist/react/context.d.ts.map +1 -0
- package/dist/react/context.js +95 -0
- package/dist/react/context.js.map +1 -0
- package/dist/react/index.d.ts +40 -0
- package/dist/react/index.d.ts.map +1 -0
- package/dist/react/index.js +36 -0
- package/dist/react/index.js.map +1 -0
- package/dist/react/use-live.d.ts +16 -0
- package/dist/react/use-live.d.ts.map +1 -0
- package/dist/react/use-live.js +55 -0
- package/dist/react/use-live.js.map +1 -0
- package/dist/react/use-query.d.ts +17 -0
- package/dist/react/use-query.d.ts.map +1 -0
- package/dist/react/use-query.js +23 -0
- package/dist/react/use-query.js.map +1 -0
- package/dist/react/use-space.d.ts +29 -0
- package/dist/react/use-space.d.ts.map +1 -0
- package/dist/react/use-space.js +48 -0
- package/dist/react/use-space.js.map +1 -0
- package/dist/react/use-spaces.d.ts +19 -0
- package/dist/react/use-spaces.d.ts.map +1 -0
- package/dist/react/use-spaces.js +55 -0
- package/dist/react/use-spaces.js.map +1 -0
- package/dist/react/use-weave-auth.d.ts +10 -0
- package/dist/react/use-weave-auth.d.ts.map +1 -0
- package/dist/react/use-weave-auth.js +15 -0
- package/dist/react/use-weave-auth.js.map +1 -0
- package/dist/react/weave-auth.d.ts +17 -0
- package/dist/react/weave-auth.d.ts.map +1 -0
- package/dist/react/weave-auth.js +38 -0
- package/dist/react/weave-auth.js.map +1 -0
- package/dist/records/describe.d.ts +38 -0
- package/dist/records/describe.d.ts.map +1 -0
- package/dist/records/describe.js +101 -0
- package/dist/records/describe.js.map +1 -0
- package/dist/records/links.d.ts +14 -0
- package/dist/records/links.d.ts.map +1 -0
- package/dist/records/links.js +25 -0
- package/dist/records/links.js.map +1 -0
- package/dist/records/rules.d.ts +59 -0
- package/dist/records/rules.d.ts.map +1 -0
- package/dist/records/rules.js +118 -0
- package/dist/records/rules.js.map +1 -0
- package/dist/records/version.d.ts +54 -0
- package/dist/records/version.d.ts.map +1 -0
- package/dist/records/version.js +70 -0
- package/dist/records/version.js.map +1 -0
- package/dist/schema/collection-def.d.ts +96 -0
- package/dist/schema/collection-def.d.ts.map +1 -0
- package/dist/schema/collection-def.js +272 -0
- package/dist/schema/collection-def.js.map +1 -0
- package/dist/schema/expression.d.ts +69 -0
- package/dist/schema/expression.d.ts.map +1 -0
- package/dist/schema/expression.js +92 -0
- package/dist/schema/expression.js.map +1 -0
- package/dist/schema/index.d.ts +4 -0
- package/dist/schema/index.d.ts.map +1 -0
- package/dist/schema/index.js +4 -0
- package/dist/schema/index.js.map +1 -0
- package/dist/schema/schema-engine.d.ts +42 -0
- package/dist/schema/schema-engine.d.ts.map +1 -0
- package/dist/schema/schema-engine.js +36 -0
- package/dist/schema/schema-engine.js.map +1 -0
- package/dist/schema/signer.d.ts +27 -0
- package/dist/schema/signer.d.ts.map +1 -0
- package/dist/schema/signer.js +36 -0
- package/dist/schema/signer.js.map +1 -0
- package/dist/schemas/apps.d.ts +88 -0
- package/dist/schemas/apps.d.ts.map +1 -0
- package/dist/schemas/apps.js +168 -0
- package/dist/schemas/apps.js.map +1 -0
- package/dist/schemas/index.d.ts +410 -0
- package/dist/schemas/index.d.ts.map +1 -0
- package/dist/schemas/index.js +208 -0
- package/dist/schemas/index.js.map +1 -0
- package/dist/schemas/screens.d.ts +67 -0
- package/dist/schemas/screens.d.ts.map +1 -0
- package/dist/schemas/screens.js +242 -0
- package/dist/schemas/screens.js.map +1 -0
- package/dist/session/agent-link.d.ts +79 -0
- package/dist/session/agent-link.d.ts.map +1 -0
- package/dist/session/agent-link.js +251 -0
- package/dist/session/agent-link.js.map +1 -0
- package/dist/session/auth.d.ts +233 -0
- package/dist/session/auth.d.ts.map +1 -0
- package/dist/session/auth.js +783 -0
- package/dist/session/auth.js.map +1 -0
- package/dist/session/connect.d.ts +211 -0
- package/dist/session/connect.d.ts.map +1 -0
- package/dist/session/connect.js +355 -0
- package/dist/session/connect.js.map +1 -0
- package/dist/session/connection.d.ts +70 -0
- package/dist/session/connection.d.ts.map +1 -0
- package/dist/session/connection.js +120 -0
- package/dist/session/connection.js.map +1 -0
- package/dist/session/credentials.d.ts +44 -0
- package/dist/session/credentials.d.ts.map +1 -0
- package/dist/session/credentials.js +60 -0
- package/dist/session/credentials.js.map +1 -0
- package/dist/session/index.d.ts +25 -0
- package/dist/session/index.d.ts.map +1 -0
- package/dist/session/index.js +18 -0
- package/dist/session/index.js.map +1 -0
- package/dist/session/pairing.d.ts +59 -0
- package/dist/session/pairing.d.ts.map +1 -0
- package/dist/session/pairing.js +144 -0
- package/dist/session/pairing.js.map +1 -0
- package/dist/session/places.d.ts +62 -0
- package/dist/session/places.d.ts.map +1 -0
- package/dist/session/places.js +101 -0
- package/dist/session/places.js.map +1 -0
- package/dist/session/stay-signed-in.d.ts +37 -0
- package/dist/session/stay-signed-in.d.ts.map +1 -0
- package/dist/session/stay-signed-in.js +124 -0
- package/dist/session/stay-signed-in.js.map +1 -0
- package/dist/space/account-registry.d.ts +64 -0
- package/dist/space/account-registry.d.ts.map +1 -0
- package/dist/space/account-registry.js +66 -0
- package/dist/space/account-registry.js.map +1 -0
- package/dist/space/index.d.ts +3 -0
- package/dist/space/index.d.ts.map +1 -0
- package/dist/space/index.js +3 -0
- package/dist/space/index.js.map +1 -0
- package/dist/space/pass.d.ts +63 -0
- package/dist/space/pass.d.ts.map +1 -0
- package/dist/space/pass.js +54 -0
- package/dist/space/pass.js.map +1 -0
- package/dist/space/presets.d.ts +31 -0
- package/dist/space/presets.d.ts.map +1 -0
- package/dist/space/presets.js +24 -0
- package/dist/space/presets.js.map +1 -0
- package/dist/space/roles.d.ts +186 -0
- package/dist/space/roles.d.ts.map +1 -0
- package/dist/space/roles.js +500 -0
- package/dist/space/roles.js.map +1 -0
- package/dist/space/space-access.d.ts +80 -0
- package/dist/space/space-access.d.ts.map +1 -0
- package/dist/space/space-access.js +135 -0
- package/dist/space/space-access.js.map +1 -0
- package/dist/space/space-manager.d.ts +87 -0
- package/dist/space/space-manager.d.ts.map +1 -0
- package/dist/space/space-manager.js +187 -0
- package/dist/space/space-manager.js.map +1 -0
- package/dist/storage/directory-access.d.ts +78 -0
- package/dist/storage/directory-access.d.ts.map +1 -0
- package/dist/storage/directory-access.js +164 -0
- package/dist/storage/directory-access.js.map +1 -0
- package/dist/storage/encrypted-adapter.d.ts +49 -0
- package/dist/storage/encrypted-adapter.d.ts.map +1 -0
- package/dist/storage/encrypted-adapter.js +106 -0
- package/dist/storage/encrypted-adapter.js.map +1 -0
- package/dist/storage/folder-adapter.d.ts +105 -0
- package/dist/storage/folder-adapter.d.ts.map +1 -0
- package/dist/storage/folder-adapter.js +280 -0
- package/dist/storage/folder-adapter.js.map +1 -0
- package/dist/storage/folder-reconcile.d.ts +53 -0
- package/dist/storage/folder-reconcile.d.ts.map +1 -0
- package/dist/storage/folder-reconcile.js +65 -0
- package/dist/storage/folder-reconcile.js.map +1 -0
- package/dist/storage/index.d.ts +10 -0
- package/dist/storage/index.d.ts.map +1 -0
- package/dist/storage/index.js +9 -0
- package/dist/storage/index.js.map +1 -0
- package/dist/storage/indexeddb-adapter.d.ts +12 -0
- package/dist/storage/indexeddb-adapter.d.ts.map +1 -0
- package/dist/storage/indexeddb-adapter.js +190 -0
- package/dist/storage/indexeddb-adapter.js.map +1 -0
- package/dist/storage/mst.d.ts +121 -0
- package/dist/storage/mst.d.ts.map +1 -0
- package/dist/storage/mst.js +402 -0
- package/dist/storage/mst.js.map +1 -0
- package/dist/storage/storage-provider.d.ts +85 -0
- package/dist/storage/storage-provider.d.ts.map +1 -0
- package/dist/storage/storage-provider.js +220 -0
- package/dist/storage/storage-provider.js.map +1 -0
- package/dist/sync/anti-entropy.d.ts +49 -0
- package/dist/sync/anti-entropy.d.ts.map +1 -0
- package/dist/sync/anti-entropy.js +62 -0
- package/dist/sync/anti-entropy.js.map +1 -0
- package/dist/sync/index.d.ts +4 -0
- package/dist/sync/index.d.ts.map +1 -0
- package/dist/sync/index.js +4 -0
- package/dist/sync/index.js.map +1 -0
- package/dist/sync/sync-engine.d.ts +71 -0
- package/dist/sync/sync-engine.d.ts.map +1 -0
- package/dist/sync/sync-engine.js +309 -0
- package/dist/sync/sync-engine.js.map +1 -0
- package/dist/sync/sync-messages.d.ts +75 -0
- package/dist/sync/sync-messages.d.ts.map +1 -0
- package/dist/sync/sync-messages.js +12 -0
- package/dist/sync/sync-messages.js.map +1 -0
- package/dist/types.d.ts +243 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +7 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/encoding.d.ts +63 -0
- package/dist/utils/encoding.d.ts.map +1 -0
- package/dist/utils/encoding.js +130 -0
- package/dist/utils/encoding.js.map +1 -0
- package/dist/utils/errors.d.ts +43 -0
- package/dist/utils/errors.d.ts.map +1 -0
- package/dist/utils/errors.js +28 -0
- package/dist/utils/errors.js.map +1 -0
- package/dist/utils/events.d.ts +19 -0
- package/dist/utils/events.d.ts.map +1 -0
- package/dist/utils/events.js +27 -0
- package/dist/utils/events.js.map +1 -0
- package/dist/utils/hash.d.ts +23 -0
- package/dist/utils/hash.d.ts.map +1 -0
- package/dist/utils/hash.js +49 -0
- package/dist/utils/hash.js.map +1 -0
- package/dist/utils/index.d.ts +9 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +9 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/validation/capability-gate.d.ts +50 -0
- package/dist/validation/capability-gate.d.ts.map +1 -0
- package/dist/validation/capability-gate.js +71 -0
- package/dist/validation/capability-gate.js.map +1 -0
- package/dist/validation/crypto-gate.d.ts +16 -0
- package/dist/validation/crypto-gate.d.ts.map +1 -0
- package/dist/validation/crypto-gate.js +37 -0
- package/dist/validation/crypto-gate.js.map +1 -0
- package/dist/validation/index.d.ts +6 -0
- package/dist/validation/index.d.ts.map +1 -0
- package/dist/validation/index.js +6 -0
- package/dist/validation/index.js.map +1 -0
- package/dist/validation/stateful-gate.d.ts +15 -0
- package/dist/validation/stateful-gate.d.ts.map +1 -0
- package/dist/validation/stateful-gate.js +50 -0
- package/dist/validation/stateful-gate.js.map +1 -0
- package/dist/validation/structural-gate.d.ts +18 -0
- package/dist/validation/structural-gate.d.ts.map +1 -0
- package/dist/validation/structural-gate.js +54 -0
- package/dist/validation/structural-gate.js.map +1 -0
- package/dist/validation/validation-engine.d.ts +28 -0
- package/dist/validation/validation-engine.d.ts.map +1 -0
- package/dist/validation/validation-engine.js +38 -0
- package/dist/validation/validation-engine.js.map +1 -0
- package/package.json +107 -0
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { base58 } from '@scure/base';
|
|
2
|
+
import { concatBytes } from '../utils/encoding.js';
|
|
3
|
+
/**
|
|
4
|
+
* Multicodec `p256-pub` (0x1200) as a varint. Per the did:key spec the key that
|
|
5
|
+
* follows is the 33-byte compressed point, which is why P-256 DIDs start `zDn`.
|
|
6
|
+
*/
|
|
7
|
+
export const P256_MULTICODEC = new Uint8Array([0x80, 0x24]);
|
|
8
|
+
/**
|
|
9
|
+
* Converts a public key to a did:key string.
|
|
10
|
+
* @param {Uint8Array} publicKeyBytes The public key bytes.
|
|
11
|
+
* @param {Uint8Array} multicodecPrefix The multicodec prefix for the key type.
|
|
12
|
+
* @returns {string} The formatted did:key string.
|
|
13
|
+
*/
|
|
14
|
+
export function publicKeyToDid(publicKeyBytes, multicodecPrefix) {
|
|
15
|
+
const prefixedKey = concatBytes(multicodecPrefix, publicKeyBytes);
|
|
16
|
+
return `did:key:z${base58.encode(prefixedKey)}`;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Parses a did:key string into its public key and multicodec prefix.
|
|
20
|
+
* @param {string} did The did:key string.
|
|
21
|
+
* @returns {{ publicKeyBytes: Uint8Array; multicodecPrefix: Uint8Array }} The parsed components.
|
|
22
|
+
*/
|
|
23
|
+
export function didToPublicKey(did) {
|
|
24
|
+
if (!did.startsWith('did:key:z')) {
|
|
25
|
+
throw new Error('Invalid did:key format');
|
|
26
|
+
}
|
|
27
|
+
const base58Str = did.slice(9);
|
|
28
|
+
const bytes = base58.decode(base58Str);
|
|
29
|
+
let prefixLen = 1;
|
|
30
|
+
while (prefixLen < bytes.length && (bytes[prefixLen - 1] & 0x80) !== 0) {
|
|
31
|
+
prefixLen++;
|
|
32
|
+
}
|
|
33
|
+
const multicodecPrefix = bytes.slice(0, prefixLen);
|
|
34
|
+
const publicKeyBytes = bytes.slice(prefixLen);
|
|
35
|
+
return { multicodecPrefix, publicKeyBytes };
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=did.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"did.js","sourceRoot":"","sources":["../../src/identity/did.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAEnD;;;GAGG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,IAAI,UAAU,CAAC,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;AAE5D;;;;;GAKG;AACH,MAAM,UAAU,cAAc,CAAC,cAA0B,EAAE,gBAA4B;IACrF,MAAM,WAAW,GAAG,WAAW,CAAC,gBAAgB,EAAE,cAAc,CAAC,CAAC;IAClE,OAAO,YAAY,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC;AAClD,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAAC,GAAW;IACxC,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;QACjC,MAAM,IAAI,KAAK,CAAC,wBAAwB,CAAC,CAAC;IAC5C,CAAC;IAED,MAAM,SAAS,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAC/B,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IAEvC,IAAI,SAAS,GAAG,CAAC,CAAC;IAClB,OAAO,SAAS,GAAG,KAAK,CAAC,MAAM,IAAI,CAAC,KAAK,CAAC,SAAS,GAAG,CAAC,CAAE,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QACxE,SAAS,EAAE,CAAC;IACd,CAAC;IAED,MAAM,gBAAgB,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC;IACnD,MAAM,cAAc,GAAG,KAAK,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;IAE9C,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,CAAC;AAC9C,CAAC"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module folder-account
|
|
3
|
+
* The account file at the root of a data folder.
|
|
4
|
+
*
|
|
5
|
+
* Once the folder is the store, the account belongs in it too — otherwise you
|
|
6
|
+
* have data that travels between origins and a key that does not, which is the
|
|
7
|
+
* problem the folder was meant to solve. Choosing the folder becomes most of
|
|
8
|
+
* signing in; unlocking it is the rest.
|
|
9
|
+
*
|
|
10
|
+
* The seed is never written in the clear. What the file holds is a set of
|
|
11
|
+
* wrapped copies of it, one per way of unlocking — see {@link module:account-vault},
|
|
12
|
+
* which owns the cryptography. This module owns the file: reading it, writing
|
|
13
|
+
* it, and recognising the older format that kept the seed in plain sight.
|
|
14
|
+
*/
|
|
15
|
+
import type { DirectoryHandleLike } from '../storage/folder-adapter.js';
|
|
16
|
+
import type { AccountVault, SeedWrap } from './account-vault.js';
|
|
17
|
+
export declare const ACCOUNT_FILE = "weave-account.json";
|
|
18
|
+
/** What a folder turned out to hold */
|
|
19
|
+
export interface FolderState {
|
|
20
|
+
/** The locked account, or null when the folder has no account yet */
|
|
21
|
+
readonly vault: AccountVault | null;
|
|
22
|
+
/**
|
|
23
|
+
* The seed, when the folder still uses the format that stored it in the clear.
|
|
24
|
+
*
|
|
25
|
+
* Present means the folder opens without asking for anything, which is the
|
|
26
|
+
* situation the vault exists to end: a caller that finds this should get the
|
|
27
|
+
* user to put a lock on it rather than carrying on quietly.
|
|
28
|
+
*/
|
|
29
|
+
readonly unlockedSeed: Uint8Array | null;
|
|
30
|
+
readonly label: string;
|
|
31
|
+
readonly did: string | null;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Reads whatever account a folder holds.
|
|
35
|
+
*
|
|
36
|
+
* @param dir The data folder
|
|
37
|
+
* @returns Its account, the legacy seed if it predates locking, or an empty state
|
|
38
|
+
*/
|
|
39
|
+
export declare function readFolderVault(dir: DirectoryHandleLike): Promise<FolderState>;
|
|
40
|
+
/**
|
|
41
|
+
* Writes the account file, replacing whatever was there.
|
|
42
|
+
*
|
|
43
|
+
* @param dir The data folder
|
|
44
|
+
* @param vault The locked account to record
|
|
45
|
+
*/
|
|
46
|
+
export declare function writeFolderVault(dir: DirectoryHandleLike, vault: AccountVault): Promise<void>;
|
|
47
|
+
/**
|
|
48
|
+
* Assembles a fresh locked account.
|
|
49
|
+
*
|
|
50
|
+
* Pure — it neither generates the seed nor touches the disk, so a caller stays
|
|
51
|
+
* in charge of both the entropy and when it lands.
|
|
52
|
+
*
|
|
53
|
+
* @param params.did The DID the seed derives
|
|
54
|
+
* @param params.wraps Shortcuts for getting in. May be empty: the account code
|
|
55
|
+
* is the seed written out, so it opens the account with nothing stored —
|
|
56
|
+
* which is exactly what a brand new account has.
|
|
57
|
+
* @param params.label What to call this account
|
|
58
|
+
* @returns The account, ready for {@link writeFolderVault}
|
|
59
|
+
*/
|
|
60
|
+
export declare function createVault(params: {
|
|
61
|
+
did: string;
|
|
62
|
+
wraps: ReadonlyArray<SeedWrap>;
|
|
63
|
+
label?: string;
|
|
64
|
+
}): AccountVault;
|
|
65
|
+
//# sourceMappingURL=folder-account.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"folder-account.d.ts","sourceRoot":"","sources":["../../src/identity/folder-account.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AAExE,OAAO,KAAK,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAKjE,eAAO,MAAM,YAAY,uBAAuB,CAAC;AA+BjD,uCAAuC;AACvC,MAAM,WAAW,WAAW;IAC1B,qEAAqE;IACrE,QAAQ,CAAC,KAAK,EAAE,YAAY,GAAG,IAAI,CAAC;IACpC;;;;;;OAMG;IACH,QAAQ,CAAC,YAAY,EAAE,UAAU,GAAG,IAAI,CAAC;IACzC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B;AAKD;;;;;GAKG;AACH,wBAAsB,eAAe,CAAC,GAAG,EAAE,mBAAmB,GAAG,OAAO,CAAC,WAAW,CAAC,CAoCpF;AAED;;;;;GAKG;AACH,wBAAsB,gBAAgB,CAAC,GAAG,EAAE,mBAAmB,EAAE,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAInG;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE;IAClC,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,aAAa,CAAC,QAAQ,CAAC,CAAC;IAC/B,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,GAAG,YAAY,CAQf"}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module folder-account
|
|
3
|
+
* The account file at the root of a data folder.
|
|
4
|
+
*
|
|
5
|
+
* Once the folder is the store, the account belongs in it too — otherwise you
|
|
6
|
+
* have data that travels between origins and a key that does not, which is the
|
|
7
|
+
* problem the folder was meant to solve. Choosing the folder becomes most of
|
|
8
|
+
* signing in; unlocking it is the rest.
|
|
9
|
+
*
|
|
10
|
+
* The seed is never written in the clear. What the file holds is a set of
|
|
11
|
+
* wrapped copies of it, one per way of unlocking — see {@link module:account-vault},
|
|
12
|
+
* which owns the cryptography. This module owns the file: reading it, writing
|
|
13
|
+
* it, and recognising the older format that kept the seed in plain sight.
|
|
14
|
+
*/
|
|
15
|
+
import { readFolderFile, writeFolderFile } from '../storage/folder-adapter.js';
|
|
16
|
+
import { isValidRecoveryCode, recoveryCodeToSeed } from './recovery-code.js';
|
|
17
|
+
import { utf8Encode, utf8Decode } from '../utils/encoding.js';
|
|
18
|
+
import { protocolError } from '../utils/errors.js';
|
|
19
|
+
export const ACCOUNT_FILE = 'weave-account.json';
|
|
20
|
+
const README_FILE = 'README.txt';
|
|
21
|
+
const README = `This folder is your data.
|
|
22
|
+
|
|
23
|
+
weave-account.json your identity, locked
|
|
24
|
+
stores/ your spaces, their contents, and the index over them
|
|
25
|
+
|
|
26
|
+
Any app that can open this folder — and unlock it — is a view on what is in it.
|
|
27
|
+
Point a second app at this same folder and it sees the same lists, signed by the
|
|
28
|
+
same key, with no account to create.
|
|
29
|
+
|
|
30
|
+
The account file does not contain your seed. It contains that seed encrypted,
|
|
31
|
+
once per way of unlocking it: under each app's passkey, and under your
|
|
32
|
+
passphrase if you set one. Adding an app adds an entry. Copying this folder
|
|
33
|
+
somewhere is not enough to read it; you need one of those too.
|
|
34
|
+
|
|
35
|
+
Your recovery code is the exception, and it is deliberately not in here. It is
|
|
36
|
+
the seed itself, written out, and it opens this folder anywhere — including on a
|
|
37
|
+
phone, or in Safari or Firefox, which cannot open folders at all. Keep it
|
|
38
|
+
somewhere you would keep a spare key.
|
|
39
|
+
|
|
40
|
+
Nothing here is a database. Every file under stores/*/expressions is one signed
|
|
41
|
+
record named after its own hash, so two copies of this folder merge by keeping
|
|
42
|
+
the union of their files.
|
|
43
|
+
|
|
44
|
+
What is not encrypted, so you know: the author, timestamp and collection of
|
|
45
|
+
every record, and the contents of any space you made public. Locking those too
|
|
46
|
+
would mean you could no longer open this folder and see what is in it.
|
|
47
|
+
`;
|
|
48
|
+
/** An empty folder, ready to have an account started in it. */
|
|
49
|
+
const EMPTY = { vault: null, unlockedSeed: null, label: 'My data', did: null };
|
|
50
|
+
/**
|
|
51
|
+
* Reads whatever account a folder holds.
|
|
52
|
+
*
|
|
53
|
+
* @param dir The data folder
|
|
54
|
+
* @returns Its account, the legacy seed if it predates locking, or an empty state
|
|
55
|
+
*/
|
|
56
|
+
export async function readFolderVault(dir) {
|
|
57
|
+
const bytes = await readFolderFile(dir, ACCOUNT_FILE);
|
|
58
|
+
if (!bytes)
|
|
59
|
+
return EMPTY;
|
|
60
|
+
// Deliberately loose: version 1 and version 2 are different shapes, and an
|
|
61
|
+
// intersection of the two is uninhabited. Narrowing happens below.
|
|
62
|
+
let parsed;
|
|
63
|
+
try {
|
|
64
|
+
parsed = JSON.parse(utf8Decode(bytes));
|
|
65
|
+
}
|
|
66
|
+
catch {
|
|
67
|
+
throw protocolError('FOLDER_ACCOUNT_UNREADABLE', `${ACCOUNT_FILE} in that folder is not valid JSON.`, 'Either the file was edited by hand, or this is not a data folder. Choose a ' +
|
|
68
|
+
'different folder, or move the broken file aside to start fresh.');
|
|
69
|
+
}
|
|
70
|
+
const label = typeof parsed.label === 'string' ? parsed.label : 'My data';
|
|
71
|
+
const did = typeof parsed.did === 'string' ? parsed.did : null;
|
|
72
|
+
if (parsed.version === 2 && Array.isArray(parsed.wraps)) {
|
|
73
|
+
return { vault: parsed, unlockedSeed: null, label, did };
|
|
74
|
+
}
|
|
75
|
+
// The first format kept the seed as a recovery code, in the clear.
|
|
76
|
+
if (typeof parsed.recoveryCode === 'string' && isValidRecoveryCode(parsed.recoveryCode)) {
|
|
77
|
+
return { vault: null, unlockedSeed: recoveryCodeToSeed(parsed.recoveryCode), label, did };
|
|
78
|
+
}
|
|
79
|
+
throw protocolError('FOLDER_ACCOUNT_UNREADABLE', `${ACCOUNT_FILE} in that folder is not an account this version understands.`, 'It may have been written by a newer build. Update the app, or move the file ' +
|
|
80
|
+
'aside and sign in with your recovery code to write a new one.');
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Writes the account file, replacing whatever was there.
|
|
84
|
+
*
|
|
85
|
+
* @param dir The data folder
|
|
86
|
+
* @param vault The locked account to record
|
|
87
|
+
*/
|
|
88
|
+
export async function writeFolderVault(dir, vault) {
|
|
89
|
+
await writeFolderFile(dir, ACCOUNT_FILE, utf8Encode(`${JSON.stringify(vault, null, 2)}\n`));
|
|
90
|
+
// Rewritten each time, so a folder that predates it picks it up on first save.
|
|
91
|
+
await writeFolderFile(dir, README_FILE, utf8Encode(README));
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Assembles a fresh locked account.
|
|
95
|
+
*
|
|
96
|
+
* Pure — it neither generates the seed nor touches the disk, so a caller stays
|
|
97
|
+
* in charge of both the entropy and when it lands.
|
|
98
|
+
*
|
|
99
|
+
* @param params.did The DID the seed derives
|
|
100
|
+
* @param params.wraps Shortcuts for getting in. May be empty: the account code
|
|
101
|
+
* is the seed written out, so it opens the account with nothing stored —
|
|
102
|
+
* which is exactly what a brand new account has.
|
|
103
|
+
* @param params.label What to call this account
|
|
104
|
+
* @returns The account, ready for {@link writeFolderVault}
|
|
105
|
+
*/
|
|
106
|
+
export function createVault(params) {
|
|
107
|
+
return {
|
|
108
|
+
version: 2,
|
|
109
|
+
label: params.label ?? 'My data',
|
|
110
|
+
did: params.did,
|
|
111
|
+
createdAt: new Date().toISOString(),
|
|
112
|
+
wraps: params.wraps,
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
//# sourceMappingURL=folder-account.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"folder-account.js","sourceRoot":"","sources":["../../src/identity/folder-account.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { CryptoProvider } from '../types.js';
|
|
2
|
+
export interface IdentityConfig {
|
|
3
|
+
readonly provider?: CryptoProvider;
|
|
4
|
+
readonly rpId?: string;
|
|
5
|
+
readonly rpName?: string;
|
|
6
|
+
}
|
|
7
|
+
export interface Identity {
|
|
8
|
+
readonly did: string;
|
|
9
|
+
readonly credentialId?: string;
|
|
10
|
+
readonly publicKey: CryptoKey;
|
|
11
|
+
readonly privateKey: CryptoKey;
|
|
12
|
+
readonly publicKeyBytes: Uint8Array;
|
|
13
|
+
}
|
|
14
|
+
/** How a passkey ceremony should be steered */
|
|
15
|
+
export interface CeremonyPreferences {
|
|
16
|
+
/** Favour the platform passkey over an installed credential manager */
|
|
17
|
+
readonly preferPlatform?: boolean;
|
|
18
|
+
}
|
|
19
|
+
export interface IdentityManager {
|
|
20
|
+
register(userName: string, preferences?: CeremonyPreferences): Promise<Identity>;
|
|
21
|
+
/** Signs in with a known passkey, or any discoverable one when no id is given. */
|
|
22
|
+
authenticate(credentialId?: string, preferences?: CeremonyPreferences): Promise<Identity>;
|
|
23
|
+
fromPassword(password: string, salt?: Uint8Array): Promise<Identity>;
|
|
24
|
+
/** Derives the root identity from a written-down recovery code (no passkey needed) */
|
|
25
|
+
fromRecoveryCode(code: string): Promise<Identity>;
|
|
26
|
+
/** Derives the root identity straight from seed bytes */
|
|
27
|
+
fromSeed(seed: Uint8Array): Promise<Identity>;
|
|
28
|
+
getProvider(): CryptoProvider;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Creates an IdentityManager instance.
|
|
32
|
+
* @param {IdentityConfig} [config] Configuration options.
|
|
33
|
+
* @returns {IdentityManager} The identity manager instance.
|
|
34
|
+
*/
|
|
35
|
+
export declare function createIdentityManager(config?: IdentityConfig): IdentityManager;
|
|
36
|
+
//# sourceMappingURL=identity-manager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"identity-manager.d.ts","sourceRoot":"","sources":["../../src/identity/identity-manager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAQ7C,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,QAAQ,CAAC,EAAE,cAAc,CAAC;IACnC,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAC;IAC9B,QAAQ,CAAC,UAAU,EAAE,SAAS,CAAC;IAC/B,QAAQ,CAAC,cAAc,EAAE,UAAU,CAAC;CACrC;AAED,+CAA+C;AAC/C,MAAM,WAAW,mBAAmB;IAClC,uEAAuE;IACvE,QAAQ,CAAC,cAAc,CAAC,EAAE,OAAO,CAAC;CACnC;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,mBAAmB,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;IACjF,kFAAkF;IAClF,YAAY,CAAC,YAAY,CAAC,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,mBAAmB,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC1F,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,UAAU,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;IACrE,sFAAsF;IACtF,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;IAClD,yDAAyD;IACzD,QAAQ,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC9C,WAAW,IAAI,cAAc,CAAC;CAC/B;AAmBD;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,CAAC,EAAE,cAAc,GAAG,eAAe,CA2G9E"}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { createP256Provider } from './crypto-p256.js';
|
|
2
|
+
import { registerPasskey, authenticatePasskey } from './webauthn.js';
|
|
3
|
+
import { deriveKeyPair, deriveKeyFromPassword } from './keys.js';
|
|
4
|
+
import { publicKeyToDid, P256_MULTICODEC } from './did.js';
|
|
5
|
+
import { protocolError } from '../utils/errors.js';
|
|
6
|
+
import { recoveryCodeToSeed } from './recovery-code.js';
|
|
7
|
+
/**
|
|
8
|
+
* The error raised when a passkey yields no PRF secret, with the remedies that
|
|
9
|
+
* actually help — a passkey only carries PRF if it was requested when the
|
|
10
|
+
* credential was created, so an older passkey cannot be upgraded in place.
|
|
11
|
+
* @returns A tagged PRF_UNSUPPORTED error
|
|
12
|
+
*/
|
|
13
|
+
function prfUnsupported() {
|
|
14
|
+
return protocolError('PRF_UNSUPPORTED', 'This passkey returned no PRF secret, so no identity key can be derived from it.', 'PRF has to be requested when a passkey is created, so one made before your ' +
|
|
15
|
+
'provider supported it will never return a secret — create a new passkey. ' +
|
|
16
|
+
'If it still fails, the authenticator itself lacks PRF (hmac-secret): try a ' +
|
|
17
|
+
'platform passkey (Touch ID, Windows Hello) or an up-to-date password manager.');
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Creates an IdentityManager instance.
|
|
21
|
+
* @param {IdentityConfig} [config] Configuration options.
|
|
22
|
+
* @returns {IdentityManager} The identity manager instance.
|
|
23
|
+
*/
|
|
24
|
+
export function createIdentityManager(config) {
|
|
25
|
+
const provider = config?.provider || createP256Provider();
|
|
26
|
+
// Use globalThis.location if available, fallback to localhost for Node/testing
|
|
27
|
+
const defaultRpId = typeof globalThis.location !== 'undefined' ? globalThis.location.hostname : 'localhost';
|
|
28
|
+
const rpId = config?.rpId || defaultRpId;
|
|
29
|
+
const rpName = config?.rpName || 'Weave';
|
|
30
|
+
return Object.freeze({
|
|
31
|
+
async register(userName, preferences) {
|
|
32
|
+
const platformOnly = preferences?.preferPlatform
|
|
33
|
+
? { hints: ['client-device'], attachment: 'platform' }
|
|
34
|
+
: {};
|
|
35
|
+
const registration = await registerPasskey({
|
|
36
|
+
rpId,
|
|
37
|
+
rpName,
|
|
38
|
+
userName,
|
|
39
|
+
...platformOnly
|
|
40
|
+
});
|
|
41
|
+
// Some authenticators return the PRF secret from the creation ceremony.
|
|
42
|
+
// The rest need an assertion to produce it — including providers that
|
|
43
|
+
// report nothing (or `enabled: false`) at creation and then evaluate PRF
|
|
44
|
+
// without complaint, so the declaration is never grounds to give up.
|
|
45
|
+
let prfOutput = registration.prfOutput;
|
|
46
|
+
if (!prfOutput) {
|
|
47
|
+
const auth = await authenticatePasskey(registration.credentialId, {
|
|
48
|
+
rpId,
|
|
49
|
+
...(preferences?.preferPlatform ? { hints: ['client-device'] } : {})
|
|
50
|
+
});
|
|
51
|
+
prfOutput = auth.prfOutput;
|
|
52
|
+
}
|
|
53
|
+
if (!prfOutput) {
|
|
54
|
+
throw prfUnsupported();
|
|
55
|
+
}
|
|
56
|
+
const keyPair = await deriveKeyPair(prfOutput, provider);
|
|
57
|
+
const did = publicKeyToDid(keyPair.publicKeyBytes, P256_MULTICODEC);
|
|
58
|
+
return Object.freeze({
|
|
59
|
+
did,
|
|
60
|
+
credentialId: registration.credentialId,
|
|
61
|
+
publicKey: keyPair.publicKey,
|
|
62
|
+
privateKey: keyPair.privateKey,
|
|
63
|
+
publicKeyBytes: keyPair.publicKeyBytes
|
|
64
|
+
});
|
|
65
|
+
},
|
|
66
|
+
async authenticate(credentialId, preferences) {
|
|
67
|
+
const auth = await authenticatePasskey(credentialId, {
|
|
68
|
+
rpId,
|
|
69
|
+
...(preferences?.preferPlatform ? { hints: ['client-device'] } : {})
|
|
70
|
+
});
|
|
71
|
+
if (!auth.prfOutput) {
|
|
72
|
+
throw prfUnsupported();
|
|
73
|
+
}
|
|
74
|
+
const keyPair = await deriveKeyPair(auth.prfOutput, provider);
|
|
75
|
+
const did = publicKeyToDid(keyPair.publicKeyBytes, P256_MULTICODEC);
|
|
76
|
+
return Object.freeze({
|
|
77
|
+
did,
|
|
78
|
+
credentialId: auth.credentialId,
|
|
79
|
+
publicKey: keyPair.publicKey,
|
|
80
|
+
privateKey: keyPair.privateKey,
|
|
81
|
+
publicKeyBytes: keyPair.publicKeyBytes
|
|
82
|
+
});
|
|
83
|
+
},
|
|
84
|
+
async fromPassword(password, salt) {
|
|
85
|
+
const actualSalt = salt || new TextEncoder().encode('default-weave-salt');
|
|
86
|
+
const keyPair = await deriveKeyFromPassword(password, actualSalt, provider);
|
|
87
|
+
const did = publicKeyToDid(keyPair.publicKeyBytes, P256_MULTICODEC);
|
|
88
|
+
return Object.freeze({
|
|
89
|
+
did,
|
|
90
|
+
publicKey: keyPair.publicKey,
|
|
91
|
+
privateKey: keyPair.privateKey,
|
|
92
|
+
publicKeyBytes: keyPair.publicKeyBytes
|
|
93
|
+
});
|
|
94
|
+
},
|
|
95
|
+
async fromRecoveryCode(code) {
|
|
96
|
+
return this.fromSeed(recoveryCodeToSeed(code));
|
|
97
|
+
},
|
|
98
|
+
async fromSeed(seed) {
|
|
99
|
+
// The seed already carries 128 bits of entropy, so it goes straight into
|
|
100
|
+
// HKDF — no password stretching to slow down what is not a password.
|
|
101
|
+
const keyPair = await deriveKeyPair(seed, provider);
|
|
102
|
+
const did = publicKeyToDid(keyPair.publicKeyBytes, P256_MULTICODEC);
|
|
103
|
+
return Object.freeze({
|
|
104
|
+
did,
|
|
105
|
+
publicKey: keyPair.publicKey,
|
|
106
|
+
privateKey: keyPair.privateKey,
|
|
107
|
+
publicKeyBytes: keyPair.publicKeyBytes
|
|
108
|
+
});
|
|
109
|
+
},
|
|
110
|
+
getProvider() {
|
|
111
|
+
return provider;
|
|
112
|
+
}
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
//# sourceMappingURL=identity-manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"identity-manager.js","sourceRoot":"","sources":["../../src/identity/identity-manager.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,eAAe,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AACrE,OAAO,EAAE,aAAa,EAAE,qBAAqB,EAAE,MAAM,WAAW,CAAC;AACjE,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAC3D,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAkCxD;;;;;GAKG;AACH,SAAS,cAAc;IACrB,OAAO,aAAa,CAClB,iBAAiB,EACjB,iFAAiF,EACjF,6EAA6E;QAC3E,2EAA2E;QAC3E,6EAA6E;QAC7E,+EAA+E,CAClF,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,qBAAqB,CAAC,MAAuB;IAC3D,MAAM,QAAQ,GAAG,MAAM,EAAE,QAAQ,IAAI,kBAAkB,EAAE,CAAC;IAE1D,+EAA+E;IAC/E,MAAM,WAAW,GAAG,OAAO,UAAU,CAAC,QAAQ,KAAK,WAAW,CAAC,CAAC,CAAC,UAAU,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,WAAW,CAAC;IAC5G,MAAM,IAAI,GAAG,MAAM,EAAE,IAAI,IAAI,WAAW,CAAC;IACzC,MAAM,MAAM,GAAG,MAAM,EAAE,MAAM,IAAI,OAAO,CAAC;IAEzC,OAAO,MAAM,CAAC,MAAM,CAAC;QACnB,KAAK,CAAC,QAAQ,CAAC,QAAgB,EAAE,WAAiC;YAChE,MAAM,YAAY,GAAG,WAAW,EAAE,cAAc;gBAC9C,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,eAAe,CAAU,EAAE,UAAU,EAAE,UAAmB,EAAE;gBACxE,CAAC,CAAC,EAAE,CAAC;YAEP,MAAM,YAAY,GAAG,MAAM,eAAe,CAAC;gBACzC,IAAI;gBACJ,MAAM;gBACN,QAAQ;gBACR,GAAG,YAAY;aAChB,CAAC,CAAC;YAEH,wEAAwE;YACxE,sEAAsE;YACtE,yEAAyE;YACzE,qEAAqE;YACrE,IAAI,SAAS,GAAG,YAAY,CAAC,SAAS,CAAC;YACvC,IAAI,CAAC,SAAS,EAAE,CAAC;gBACf,MAAM,IAAI,GAAG,MAAM,mBAAmB,CAAC,YAAY,CAAC,YAAY,EAAE;oBAChE,IAAI;oBACJ,GAAG,CAAC,WAAW,EAAE,cAAc,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,eAAe,CAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;iBAC9E,CAAC,CAAC;gBACH,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC;YAC7B,CAAC;YAED,IAAI,CAAC,SAAS,EAAE,CAAC;gBACf,MAAM,cAAc,EAAE,CAAC;YACzB,CAAC;YAED,MAAM,OAAO,GAAG,MAAM,aAAa,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;YACzD,MAAM,GAAG,GAAG,cAAc,CAAC,OAAO,CAAC,cAAc,EAAE,eAAe,CAAC,CAAC;YAEpE,OAAO,MAAM,CAAC,MAAM,CAAC;gBACnB,GAAG;gBACH,YAAY,EAAE,YAAY,CAAC,YAAY;gBACvC,SAAS,EAAE,OAAO,CAAC,SAAS;gBAC5B,UAAU,EAAE,OAAO,CAAC,UAAU;gBAC9B,cAAc,EAAE,OAAO,CAAC,cAAc;aACvC,CAAC,CAAC;QACL,CAAC;QAED,KAAK,CAAC,YAAY,CAAC,YAAqB,EAAE,WAAiC;YACzE,MAAM,IAAI,GAAG,MAAM,mBAAmB,CAAC,YAAY,EAAE;gBACnD,IAAI;gBACJ,GAAG,CAAC,WAAW,EAAE,cAAc,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,eAAe,CAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aAC9E,CAAC,CAAC;YAEH,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;gBACpB,MAAM,cAAc,EAAE,CAAC;YACzB,CAAC;YAED,MAAM,OAAO,GAAG,MAAM,aAAa,CAAC,IAAI,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;YAC9D,MAAM,GAAG,GAAG,cAAc,CAAC,OAAO,CAAC,cAAc,EAAE,eAAe,CAAC,CAAC;YAEpE,OAAO,MAAM,CAAC,MAAM,CAAC;gBACnB,GAAG;gBACH,YAAY,EAAE,IAAI,CAAC,YAAY;gBAC/B,SAAS,EAAE,OAAO,CAAC,SAAS;gBAC5B,UAAU,EAAE,OAAO,CAAC,UAAU;gBAC9B,cAAc,EAAE,OAAO,CAAC,cAAc;aACvC,CAAC,CAAC;QACL,CAAC;QAED,KAAK,CAAC,YAAY,CAAC,QAAgB,EAAE,IAAiB;YACpD,MAAM,UAAU,GAAG,IAAI,IAAI,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAC;YAC1E,MAAM,OAAO,GAAG,MAAM,qBAAqB,CAAC,QAAQ,EAAE,UAAU,EAAE,QAAQ,CAAC,CAAC;YAC5E,MAAM,GAAG,GAAG,cAAc,CAAC,OAAO,CAAC,cAAc,EAAE,eAAe,CAAC,CAAC;YAEpE,OAAO,MAAM,CAAC,MAAM,CAAC;gBACnB,GAAG;gBACH,SAAS,EAAE,OAAO,CAAC,SAAS;gBAC5B,UAAU,EAAE,OAAO,CAAC,UAAU;gBAC9B,cAAc,EAAE,OAAO,CAAC,cAAc;aACvC,CAAC,CAAC;QACL,CAAC;QAED,KAAK,CAAC,gBAAgB,CAAC,IAAY;YACjC,OAAO,IAAI,CAAC,QAAQ,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAC,CAAC;QACjD,CAAC;QAED,KAAK,CAAC,QAAQ,CAAC,IAAgB;YAC7B,yEAAyE;YACzE,qEAAqE;YACrE,MAAM,OAAO,GAAG,MAAM,aAAa,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;YACpD,MAAM,GAAG,GAAG,cAAc,CAAC,OAAO,CAAC,cAAc,EAAE,eAAe,CAAC,CAAC;YAEpE,OAAO,MAAM,CAAC,MAAM,CAAC;gBACnB,GAAG;gBACH,SAAS,EAAE,OAAO,CAAC,SAAS;gBAC5B,UAAU,EAAE,OAAO,CAAC,UAAU;gBAC9B,cAAc,EAAE,OAAO,CAAC,cAAc;aACvC,CAAC,CAAC;QACL,CAAC;QAED,WAAW;YACT,OAAO,QAAQ,CAAC;QAClB,CAAC;KACF,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export * from './crypto-p256.js';
|
|
2
|
+
export * from './webauthn.js';
|
|
3
|
+
export * from './keys.js';
|
|
4
|
+
export * from './did.js';
|
|
5
|
+
export * from './identity-manager.js';
|
|
6
|
+
export * from './ucan.js';
|
|
7
|
+
export * from './agent-note.js';
|
|
8
|
+
export * from './passkey-diagnostics.js';
|
|
9
|
+
export * from './recovery-code.js';
|
|
10
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/identity/index.ts"],"names":[],"mappings":"AAAA,cAAc,kBAAkB,CAAC;AACjC,cAAc,eAAe,CAAC;AAC9B,cAAc,WAAW,CAAC;AAC1B,cAAc,UAAU,CAAC;AACzB,cAAc,uBAAuB,CAAC;AACtC,cAAc,WAAW,CAAC;AAC1B,cAAc,iBAAiB,CAAC;AAChC,cAAc,0BAA0B,CAAC;AACzC,cAAc,oBAAoB,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export * from './crypto-p256.js';
|
|
2
|
+
export * from './webauthn.js';
|
|
3
|
+
export * from './keys.js';
|
|
4
|
+
export * from './did.js';
|
|
5
|
+
export * from './identity-manager.js';
|
|
6
|
+
export * from './ucan.js';
|
|
7
|
+
export * from './agent-note.js';
|
|
8
|
+
export * from './passkey-diagnostics.js';
|
|
9
|
+
export * from './recovery-code.js';
|
|
10
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/identity/index.ts"],"names":[],"mappings":"AAAA,cAAc,kBAAkB,CAAC;AACjC,cAAc,eAAe,CAAC;AAC9B,cAAc,WAAW,CAAC;AAC1B,cAAc,UAAU,CAAC;AACzB,cAAc,uBAAuB,CAAC;AACtC,cAAc,WAAW,CAAC;AAC1B,cAAc,iBAAiB,CAAC;AAChC,cAAc,0BAA0B,CAAC;AACzC,cAAc,oBAAoB,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { CryptoProvider } from '../types.js';
|
|
2
|
+
export interface DerivedKeyPair {
|
|
3
|
+
readonly publicKey: CryptoKey;
|
|
4
|
+
readonly privateKey: CryptoKey;
|
|
5
|
+
readonly publicKeyBytes: Uint8Array;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Derives a key pair from seed bytes: an account seed, a PRF output, or a
|
|
9
|
+
* stretched password. One KDF step, owned by the provider, since how many bytes
|
|
10
|
+
* a curve needs to reach a key without bias is a property of the curve.
|
|
11
|
+
* @param {Uint8Array} seed At least 16 uniformly random bytes.
|
|
12
|
+
* @param {CryptoProvider} provider The cryptography provider.
|
|
13
|
+
* @returns {Promise<DerivedKeyPair>} The derived key pair.
|
|
14
|
+
*/
|
|
15
|
+
export declare function deriveKeyPair(seed: Uint8Array, provider: CryptoProvider): Promise<DerivedKeyPair>;
|
|
16
|
+
/**
|
|
17
|
+
* Derives a key pair from a password and salt.
|
|
18
|
+
* @param {string} password The password.
|
|
19
|
+
* @param {Uint8Array} salt The salt.
|
|
20
|
+
* @param {CryptoProvider} provider The cryptography provider.
|
|
21
|
+
* @returns {Promise<DerivedKeyPair>} The derived key pair.
|
|
22
|
+
*/
|
|
23
|
+
export declare function deriveKeyFromPassword(password: string, salt: Uint8Array, provider: CryptoProvider): Promise<DerivedKeyPair>;
|
|
24
|
+
//# sourceMappingURL=keys.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"keys.d.ts","sourceRoot":"","sources":["../../src/identity/keys.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAE7C,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAC;IAC9B,QAAQ,CAAC,UAAU,EAAE,SAAS,CAAC;IAC/B,QAAQ,CAAC,cAAc,EAAE,UAAU,CAAC;CACrC;AAED;;;;;;;GAOG;AACH,wBAAsB,aAAa,CAAC,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,cAAc,GAAG,OAAO,CAAC,cAAc,CAAC,CAWvG;AAED;;;;;;GAMG;AACH,wBAAsB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,cAAc,GAAG,OAAO,CAAC,cAAc,CAAC,CAsBjI"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Derives a key pair from seed bytes: an account seed, a PRF output, or a
|
|
3
|
+
* stretched password. One KDF step, owned by the provider, since how many bytes
|
|
4
|
+
* a curve needs to reach a key without bias is a property of the curve.
|
|
5
|
+
* @param {Uint8Array} seed At least 16 uniformly random bytes.
|
|
6
|
+
* @param {CryptoProvider} provider The cryptography provider.
|
|
7
|
+
* @returns {Promise<DerivedKeyPair>} The derived key pair.
|
|
8
|
+
*/
|
|
9
|
+
export async function deriveKeyPair(seed, provider) {
|
|
10
|
+
// The provider turns the seed into a key pair whose public key genuinely
|
|
11
|
+
// matches the private one — that correspondence is what makes a DID verifiable.
|
|
12
|
+
const keyPair = await provider.deriveKeyPairFromSeed(seed);
|
|
13
|
+
const publicKeyBytes = await provider.exportPublicKey(keyPair.publicKey);
|
|
14
|
+
return Object.freeze({
|
|
15
|
+
publicKey: keyPair.publicKey,
|
|
16
|
+
privateKey: keyPair.privateKey,
|
|
17
|
+
publicKeyBytes
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Derives a key pair from a password and salt.
|
|
22
|
+
* @param {string} password The password.
|
|
23
|
+
* @param {Uint8Array} salt The salt.
|
|
24
|
+
* @param {CryptoProvider} provider The cryptography provider.
|
|
25
|
+
* @returns {Promise<DerivedKeyPair>} The derived key pair.
|
|
26
|
+
*/
|
|
27
|
+
export async function deriveKeyFromPassword(password, salt, provider) {
|
|
28
|
+
const encoder = new TextEncoder();
|
|
29
|
+
const passwordKey = await globalThis.crypto.subtle.importKey('raw', encoder.encode(password), { name: 'PBKDF2' }, false, ['deriveBits']);
|
|
30
|
+
const derivedBits = await globalThis.crypto.subtle.deriveBits({
|
|
31
|
+
name: 'PBKDF2',
|
|
32
|
+
hash: 'SHA-256',
|
|
33
|
+
salt: salt,
|
|
34
|
+
iterations: 100000
|
|
35
|
+
}, passwordKey, 256);
|
|
36
|
+
return deriveKeyPair(new Uint8Array(derivedBits), provider);
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=keys.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"keys.js","sourceRoot":"","sources":["../../src/identity/keys.ts"],"names":[],"mappings":"AAQA;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,IAAgB,EAAE,QAAwB;IAC5E,yEAAyE;IACzE,gFAAgF;IAChF,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,qBAAqB,CAAC,IAAI,CAAC,CAAC;IAC3D,MAAM,cAAc,GAAG,MAAM,QAAQ,CAAC,eAAe,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAEzE,OAAO,MAAM,CAAC,MAAM,CAAC;QACnB,SAAS,EAAE,OAAO,CAAC,SAAS;QAC5B,UAAU,EAAE,OAAO,CAAC,UAAU;QAC9B,cAAc;KACf,CAAC,CAAC;AACL,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAAC,QAAgB,EAAE,IAAgB,EAAE,QAAwB;IACtG,MAAM,OAAO,GAAG,IAAI,WAAW,EAAE,CAAC;IAClC,MAAM,WAAW,GAAG,MAAM,UAAU,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,CAC1D,KAAK,EACL,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,EACxB,EAAE,IAAI,EAAE,QAAQ,EAAE,EAClB,KAAK,EACL,CAAC,YAAY,CAAC,CACf,CAAC;IAEF,MAAM,WAAW,GAAG,MAAM,UAAU,CAAC,MAAM,CAAC,MAAM,CAAC,UAAU,CAC3D;QACE,IAAI,EAAE,QAAQ;QACd,IAAI,EAAE,SAAS;QACf,IAAI,EAAE,IAAoB;QAC1B,UAAU,EAAE,MAAM;KACnB,EACD,WAAW,EACX,GAAG,CACJ,CAAC;IAEF,OAAO,aAAa,CAAC,IAAI,UAAU,CAAC,WAAW,CAAC,EAAE,QAAQ,CAAC,CAAC;AAC9D,CAAC"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module pairing
|
|
3
|
+
* Handing an account to a phone.
|
|
4
|
+
*
|
|
5
|
+
* A phone cannot open a folder — no mobile browser has the File System Access
|
|
6
|
+
* API — so it keeps its own copy of the data, like any other peer. What it needs
|
|
7
|
+
* from the desktop is two things: who you are, and which lists exist.
|
|
8
|
+
*
|
|
9
|
+
* The first fits in a QR code. The second does not, and does not need to: once
|
|
10
|
+
* both sides know the seed they can each work out the same private meeting room
|
|
11
|
+
* and the same key, meet there over the ordinary peer connection, and hand the
|
|
12
|
+
* list of lists across encrypted. So the code stays small enough for a phone
|
|
13
|
+
* camera to read from across a desk.
|
|
14
|
+
*
|
|
15
|
+
* Deriving the room from the *seed* rather than from the DID matters. A DID
|
|
16
|
+
* appears in every expression the account has ever signed, so a room named after
|
|
17
|
+
* one would be a room anyone could find. A room named after the seed can only be
|
|
18
|
+
* found by someone who already has it.
|
|
19
|
+
*
|
|
20
|
+
* What this is not: the phone does not become a satellite of the desktop. It
|
|
21
|
+
* derives the same identity and becomes a full peer, syncing with anyone in the
|
|
22
|
+
* space. The desktop was a bootstrap, and can go offline immediately afterwards.
|
|
23
|
+
*/
|
|
24
|
+
/** What the QR code carries */
|
|
25
|
+
export interface PairingTicket {
|
|
26
|
+
readonly v: 1;
|
|
27
|
+
/** The recovery code — the seed, in the form that survives a camera */
|
|
28
|
+
readonly code: string;
|
|
29
|
+
/** Where to meet. Must be an address the phone can actually reach. */
|
|
30
|
+
readonly relay: string;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* The room both devices meet in.
|
|
34
|
+
*
|
|
35
|
+
* Derived from the seed, so finding it already requires the secret. Both sides
|
|
36
|
+
* compute it independently and neither has to send it.
|
|
37
|
+
*
|
|
38
|
+
* @param seed The account seed
|
|
39
|
+
* @returns An opaque room id for the signaling relay
|
|
40
|
+
*/
|
|
41
|
+
export declare function pairingRoomId(seed: Uint8Array): Promise<string>;
|
|
42
|
+
/**
|
|
43
|
+
* The key the handover is encrypted with.
|
|
44
|
+
*
|
|
45
|
+
* Separate from the vault key and from the signing key, so that a relay
|
|
46
|
+
* operator watching the room learns nothing but the size of the payload.
|
|
47
|
+
*
|
|
48
|
+
* @param seed The account seed
|
|
49
|
+
* @returns An AES-GCM key
|
|
50
|
+
*/
|
|
51
|
+
export declare function derivePairingKey(seed: Uint8Array): Promise<CryptoKey>;
|
|
52
|
+
/**
|
|
53
|
+
* Packs a ticket for a URL fragment.
|
|
54
|
+
*
|
|
55
|
+
* A fragment, because browsers never put one in a request — so the seed reaches
|
|
56
|
+
* the phone without passing through the server hosting the page, the same way a
|
|
57
|
+
* space invite carries its key.
|
|
58
|
+
*
|
|
59
|
+
* @param ticket What the phone needs to know
|
|
60
|
+
* @returns A compact string for after the `#`
|
|
61
|
+
*/
|
|
62
|
+
export declare function encodePairingTicket(ticket: PairingTicket): string;
|
|
63
|
+
/**
|
|
64
|
+
* Unpacks a ticket from a URL fragment.
|
|
65
|
+
* @param encoded The string after `#pair=`
|
|
66
|
+
* @returns The ticket it stands for
|
|
67
|
+
*/
|
|
68
|
+
export declare function decodePairingTicket(encoded: string): PairingTicket;
|
|
69
|
+
/**
|
|
70
|
+
* Encrypts the handover payload.
|
|
71
|
+
* @param plaintext What to send
|
|
72
|
+
* @param key From {@link derivePairingKey}
|
|
73
|
+
* @returns Nonce followed by ciphertext
|
|
74
|
+
*/
|
|
75
|
+
export declare function sealPairingPayload(plaintext: Uint8Array, key: CryptoKey): Promise<Uint8Array>;
|
|
76
|
+
/**
|
|
77
|
+
* Decrypts the handover payload.
|
|
78
|
+
* @param sealed What arrived
|
|
79
|
+
* @param key From {@link derivePairingKey}
|
|
80
|
+
* @returns The plaintext
|
|
81
|
+
*/
|
|
82
|
+
export declare function openPairingPayload(sealed: Uint8Array, key: CryptoKey): Promise<Uint8Array>;
|
|
83
|
+
//# sourceMappingURL=pairing.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pairing.d.ts","sourceRoot":"","sources":["../../src/identity/pairing.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAUH,+BAA+B;AAC/B,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC;IACd,uEAAuE;IACvE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,sEAAsE;IACtE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAED;;;;;;;;GAQG;AACH,wBAAsB,aAAa,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAErE;AAED;;;;;;;;GAQG;AACH,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,SAAS,CAAC,CAoB3E;AAED;;;;;;;;;GASG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,aAAa,GAAG,MAAM,CAEjE;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,aAAa,CAclE;AAED;;;;;GAKG;AACH,wBAAsB,kBAAkB,CAAC,SAAS,EAAE,UAAU,EAAE,GAAG,EAAE,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,CAQnG;AAED;;;;;GAKG;AACH,wBAAsB,kBAAkB,CAAC,MAAM,EAAE,UAAU,EAAE,GAAG,EAAE,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,CAmBhG"}
|