@enbox/dwn-sdk-js 0.4.6 → 0.4.8
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 +3 -1
- package/dist/browser.mjs +19 -78
- package/dist/browser.mjs.map +4 -4
- package/dist/esm/generated/precompiled-validators.js +2324 -1525
- package/dist/esm/generated/precompiled-validators.js.map +1 -1
- package/dist/esm/src/core/constants.js +50 -0
- package/dist/esm/src/core/constants.js.map +1 -1
- package/dist/esm/src/core/dwn-error.js +29 -11
- package/dist/esm/src/core/dwn-error.js.map +1 -1
- package/dist/esm/src/core/encryption-control.js +785 -0
- package/dist/esm/src/core/encryption-control.js.map +1 -0
- package/dist/esm/src/core/message.js +6 -0
- package/dist/esm/src/core/message.js.map +1 -1
- package/dist/esm/src/core/messages-grant-authorization.js +36 -5
- package/dist/esm/src/core/messages-grant-authorization.js.map +1 -1
- package/dist/esm/src/core/protocol-authorization-action.js +3 -12
- package/dist/esm/src/core/protocol-authorization-action.js.map +1 -1
- package/dist/esm/src/core/protocol-authorization-validation.js +31 -30
- package/dist/esm/src/core/protocol-authorization-validation.js.map +1 -1
- package/dist/esm/src/core/protocol-authorization.js +6 -0
- package/dist/esm/src/core/protocol-authorization.js.map +1 -1
- package/dist/esm/src/core/recording-validation-state-reader.js +3 -3
- package/dist/esm/src/core/recording-validation-state-reader.js.map +1 -1
- package/dist/esm/src/core/replication-apply.js +62 -108
- package/dist/esm/src/core/replication-apply.js.map +1 -1
- package/dist/esm/src/core/validation-state-reader.js +5 -6
- package/dist/esm/src/core/validation-state-reader.js.map +1 -1
- package/dist/esm/src/dwn.js +1 -2
- package/dist/esm/src/dwn.js.map +1 -1
- package/dist/esm/src/event-stream/event-emitter-wake-publisher.js +11 -11
- package/dist/esm/src/event-stream/event-emitter-wake-publisher.js.map +1 -1
- package/dist/esm/src/handlers/messages-query.js +6 -16
- package/dist/esm/src/handlers/messages-query.js.map +1 -1
- package/dist/esm/src/handlers/messages-read.js +4 -3
- package/dist/esm/src/handlers/messages-read.js.map +1 -1
- package/dist/esm/src/handlers/messages-subscribe.js +26 -30
- package/dist/esm/src/handlers/messages-subscribe.js.map +1 -1
- package/dist/esm/src/handlers/protocols-configure.js +6 -4
- package/dist/esm/src/handlers/protocols-configure.js.map +1 -1
- package/dist/esm/src/handlers/records-count.js +85 -10
- package/dist/esm/src/handlers/records-count.js.map +1 -1
- package/dist/esm/src/handlers/records-delete.js +11 -0
- package/dist/esm/src/handlers/records-delete.js.map +1 -1
- package/dist/esm/src/handlers/records-query.js +140 -18
- package/dist/esm/src/handlers/records-query.js.map +1 -1
- package/dist/esm/src/handlers/records-read.js +20 -4
- package/dist/esm/src/handlers/records-read.js.map +1 -1
- package/dist/esm/src/handlers/records-subscribe.js +127 -11
- package/dist/esm/src/handlers/records-subscribe.js.map +1 -1
- package/dist/esm/src/handlers/records-write.js +15 -0
- package/dist/esm/src/handlers/records-write.js.map +1 -1
- package/dist/esm/src/index.js +8 -11
- package/dist/esm/src/index.js.map +1 -1
- package/dist/esm/src/interfaces/protocols-configure.js +66 -9
- package/dist/esm/src/interfaces/protocols-configure.js.map +1 -1
- package/dist/esm/src/interfaces/records-write.js +43 -36
- package/dist/esm/src/interfaces/records-write.js.map +1 -1
- package/dist/esm/src/jose/algorithms/signing/ed25519.js +5 -5
- package/dist/esm/src/jose/algorithms/signing/ed25519.js.map +1 -1
- package/dist/esm/src/jose/jws/general/verifier.js +1 -1
- package/dist/esm/src/jose/jws/general/verifier.js.map +1 -1
- package/dist/esm/src/protocols/encryption.js +60 -270
- package/dist/esm/src/protocols/encryption.js.map +1 -1
- package/dist/esm/src/store/blockstore-level.js +14 -23
- package/dist/esm/src/store/blockstore-level.js.map +1 -1
- package/dist/esm/src/store/blockstore-mock.js +10 -27
- package/dist/esm/src/store/blockstore-mock.js.map +1 -1
- package/dist/esm/src/store/blockstore-utils.js +45 -0
- package/dist/esm/src/store/blockstore-utils.js.map +1 -0
- package/dist/esm/src/store/blockstore.js +2 -0
- package/dist/esm/src/store/blockstore.js.map +1 -0
- package/dist/esm/src/store/data-store-level.js +4 -12
- package/dist/esm/src/store/data-store-level.js.map +1 -1
- package/dist/esm/src/store/level.js +7 -0
- package/dist/esm/src/store/level.js.map +1 -0
- package/dist/esm/src/types/encryption-types.js +4 -1
- package/dist/esm/src/types/encryption-types.js.map +1 -1
- package/dist/esm/src/utils/data-stream.js +25 -0
- package/dist/esm/src/utils/data-stream.js.map +1 -1
- package/dist/esm/src/utils/encryption.js +107 -19
- package/dist/esm/src/utils/encryption.js.map +1 -1
- package/dist/esm/src/utils/grant-key-coverage.js +180 -0
- package/dist/esm/src/utils/grant-key-coverage.js.map +1 -0
- package/dist/esm/src/utils/hd-key.js +1 -2
- package/dist/esm/src/utils/hd-key.js.map +1 -1
- package/dist/esm/src/utils/jws.js +7 -1
- package/dist/esm/src/utils/jws.js.map +1 -1
- package/dist/esm/src/utils/memory-cache.js +29 -8
- package/dist/esm/src/utils/memory-cache.js.map +1 -1
- package/dist/esm/src/utils/protocols.js +27 -0
- package/dist/esm/src/utils/protocols.js.map +1 -1
- package/dist/esm/src/utils/record-limit-occupancy.js +23 -3
- package/dist/esm/src/utils/record-limit-occupancy.js.map +1 -1
- package/dist/esm/src/utils/records.js +29 -0
- package/dist/esm/src/utils/records.js.map +1 -1
- package/dist/esm/src/utils/secp256k1.js +12 -11
- package/dist/esm/src/utils/secp256k1.js.map +1 -1
- package/dist/esm/src/utils/secp256r1.js +12 -20
- package/dist/esm/src/utils/secp256r1.js.map +1 -1
- package/dist/esm/src/utils/time.js +103 -25
- package/dist/esm/src/utils/time.js.map +1 -1
- package/dist/esm/tests/core/constants.spec.js +35 -0
- package/dist/esm/tests/core/constants.spec.js.map +1 -0
- package/dist/esm/tests/core/encryption-control.spec.js +100 -0
- package/dist/esm/tests/core/encryption-control.spec.js.map +1 -0
- package/dist/esm/tests/core/message.spec.js +35 -0
- package/dist/esm/tests/core/message.spec.js.map +1 -1
- package/dist/esm/tests/core/protocol-authorization.spec.js +1 -1
- package/dist/esm/tests/core/protocol-authorization.spec.js.map +1 -1
- package/dist/esm/tests/core/replication-apply.spec.js +157 -74
- package/dist/esm/tests/core/replication-apply.spec.js.map +1 -1
- package/dist/esm/tests/core/replication-replay-property.spec.js +2 -1
- package/dist/esm/tests/core/replication-replay-property.spec.js.map +1 -1
- package/dist/esm/tests/core/validation-read-closure.spec.js +14 -28
- package/dist/esm/tests/core/validation-read-closure.spec.js.map +1 -1
- package/dist/esm/tests/core/validation-state-reader.spec.js +19 -23
- package/dist/esm/tests/core/validation-state-reader.spec.js.map +1 -1
- package/dist/esm/tests/dwn.spec.js +2 -1
- package/dist/esm/tests/dwn.spec.js.map +1 -1
- package/dist/esm/tests/event-emitter-wake-publisher.spec.js +51 -0
- package/dist/esm/tests/event-emitter-wake-publisher.spec.js.map +1 -0
- package/dist/esm/tests/features/protocol-composition.spec.js +1 -1
- package/dist/esm/tests/features/protocol-composition.spec.js.map +1 -1
- package/dist/esm/tests/features/records-record-limit.spec.js +1 -1
- package/dist/esm/tests/features/records-record-limit.spec.js.map +1 -1
- package/dist/esm/tests/fuzz/encryption.fuzz.spec.js +9 -1
- package/dist/esm/tests/fuzz/encryption.fuzz.spec.js.map +1 -1
- package/dist/esm/tests/fuzz/process-message.fuzz.spec.js +1 -1
- package/dist/esm/tests/fuzz/process-message.fuzz.spec.js.map +1 -1
- package/dist/esm/tests/fuzz/protocols-utils.fuzz.spec.js +29 -1
- package/dist/esm/tests/fuzz/protocols-utils.fuzz.spec.js.map +1 -1
- package/dist/esm/tests/fuzz/secp256k1.fuzz.spec.js +2 -2
- package/dist/esm/tests/fuzz/secp256k1.fuzz.spec.js.map +1 -1
- package/dist/esm/tests/fuzz/time.fuzz.spec.js +7 -1
- package/dist/esm/tests/fuzz/time.fuzz.spec.js.map +1 -1
- package/dist/esm/tests/handlers/messages-query.spec.js +123 -11
- package/dist/esm/tests/handlers/messages-query.spec.js.map +1 -1
- package/dist/esm/tests/handlers/messages-read.spec.js +95 -0
- package/dist/esm/tests/handlers/messages-read.spec.js.map +1 -1
- package/dist/esm/tests/handlers/messages-subscribe.spec.js +90 -0
- package/dist/esm/tests/handlers/messages-subscribe.spec.js.map +1 -1
- package/dist/esm/tests/handlers/protocols-configure.spec.js +66 -0
- package/dist/esm/tests/handlers/protocols-configure.spec.js.map +1 -1
- package/dist/esm/tests/handlers/records-count.spec.js +370 -0
- package/dist/esm/tests/handlers/records-count.spec.js.map +1 -1
- package/dist/esm/tests/handlers/records-delete.spec.js +70 -1
- package/dist/esm/tests/handlers/records-delete.spec.js.map +1 -1
- package/dist/esm/tests/handlers/records-query.spec.js +562 -1
- package/dist/esm/tests/handlers/records-query.spec.js.map +1 -1
- package/dist/esm/tests/handlers/records-read.spec.js +140 -2
- package/dist/esm/tests/handlers/records-read.spec.js.map +1 -1
- package/dist/esm/tests/handlers/records-subscribe.spec.js +241 -1
- package/dist/esm/tests/handlers/records-subscribe.spec.js.map +1 -1
- package/dist/esm/tests/handlers/records-write.spec.js +1187 -29
- package/dist/esm/tests/handlers/records-write.spec.js.map +1 -1
- package/dist/esm/tests/interfaces/protocols-configure.spec.js +290 -2
- package/dist/esm/tests/interfaces/protocols-configure.spec.js.map +1 -1
- package/dist/esm/tests/interfaces/records-write.spec.js +47 -5
- package/dist/esm/tests/interfaces/records-write.spec.js.map +1 -1
- package/dist/esm/tests/protocols/encryption.spec.js +187 -452
- package/dist/esm/tests/protocols/encryption.spec.js.map +1 -1
- package/dist/esm/tests/scenarios/end-to-end-tests.spec.js +13 -27
- package/dist/esm/tests/scenarios/end-to-end-tests.spec.js.map +1 -1
- package/dist/esm/tests/store/blockstore-level.spec.js +33 -10
- package/dist/esm/tests/store/blockstore-level.spec.js.map +1 -1
- package/dist/esm/tests/store/blockstore-mock.spec.js +31 -7
- package/dist/esm/tests/store/blockstore-mock.spec.js.map +1 -1
- package/dist/esm/tests/store/blockstore-utils.spec.js +115 -0
- package/dist/esm/tests/store/blockstore-utils.spec.js.map +1 -0
- package/dist/esm/tests/store/index-level.spec.js +3 -3
- package/dist/esm/tests/store/index-level.spec.js.map +1 -1
- package/dist/esm/tests/test-stores.js +2 -1
- package/dist/esm/tests/test-stores.js.map +1 -1
- package/dist/esm/tests/utils/cid.spec.js +15 -0
- package/dist/esm/tests/utils/cid.spec.js.map +1 -1
- package/dist/esm/tests/utils/data-stream.spec.js +30 -0
- package/dist/esm/tests/utils/data-stream.spec.js.map +1 -1
- package/dist/esm/tests/utils/encryption-control-test-utils.js +111 -0
- package/dist/esm/tests/utils/encryption-control-test-utils.js.map +1 -0
- package/dist/esm/tests/utils/encryption.spec.js +198 -5
- package/dist/esm/tests/utils/encryption.spec.js.map +1 -1
- package/dist/esm/tests/utils/grant-key-coverage.spec.js +262 -0
- package/dist/esm/tests/utils/grant-key-coverage.spec.js.map +1 -0
- package/dist/esm/tests/utils/memory-cache.spec.js +12 -0
- package/dist/esm/tests/utils/memory-cache.spec.js.map +1 -1
- package/dist/esm/tests/utils/secp256r1.spec.js +2 -2
- package/dist/esm/tests/utils/secp256r1.spec.js.map +1 -1
- package/dist/esm/tests/utils/test-data-generator.js +2 -1
- package/dist/esm/tests/utils/test-data-generator.js.map +1 -1
- package/dist/esm/tests/utils/test-validation-state-reader.js +1 -1
- package/dist/esm/tests/utils/test-validation-state-reader.js.map +1 -1
- package/dist/esm/tests/utils/time.spec.js +26 -0
- package/dist/esm/tests/utils/time.spec.js.map +1 -1
- package/dist/esm/tests/validation/json-schemas/encryption/audience.spec.js +45 -0
- package/dist/esm/tests/validation/json-schemas/encryption/audience.spec.js.map +1 -0
- package/dist/esm/tests/validation/json-schemas/encryption/delivery.spec.js +47 -0
- package/dist/esm/tests/validation/json-schemas/encryption/delivery.spec.js.map +1 -0
- package/dist/esm/tests/validation/json-schemas/encryption/wrapped-grant-key-envelope.spec.js +43 -0
- package/dist/esm/tests/validation/json-schemas/encryption/wrapped-grant-key-envelope.spec.js.map +1 -0
- package/dist/esm/tests/validation/json-schemas/protocols/protocols-configure.spec.js +152 -0
- package/dist/esm/tests/validation/json-schemas/protocols/protocols-configure.spec.js.map +1 -1
- package/dist/esm/tests/validation/json-schemas/records/records-write.spec.js +46 -1
- package/dist/esm/tests/validation/json-schemas/records/records-write.spec.js.map +1 -1
- package/dist/types/generated/precompiled-validators.d.ts +20 -4
- package/dist/types/generated/precompiled-validators.d.ts.map +1 -1
- package/dist/types/src/core/constants.d.ts +39 -0
- package/dist/types/src/core/constants.d.ts.map +1 -1
- package/dist/types/src/core/dwn-error.d.ts +29 -11
- package/dist/types/src/core/dwn-error.d.ts.map +1 -1
- package/dist/types/src/core/encryption-control.d.ts +128 -0
- package/dist/types/src/core/encryption-control.d.ts.map +1 -0
- package/dist/types/src/core/message.d.ts +4 -0
- package/dist/types/src/core/message.d.ts.map +1 -1
- package/dist/types/src/core/messages-grant-authorization.d.ts +11 -0
- package/dist/types/src/core/messages-grant-authorization.d.ts.map +1 -1
- package/dist/types/src/core/protocol-authorization-action.d.ts.map +1 -1
- package/dist/types/src/core/protocol-authorization-validation.d.ts.map +1 -1
- package/dist/types/src/core/protocol-authorization.d.ts.map +1 -1
- package/dist/types/src/core/recording-validation-state-reader.d.ts +2 -3
- package/dist/types/src/core/recording-validation-state-reader.d.ts.map +1 -1
- package/dist/types/src/core/replication-apply.d.ts +10 -1
- package/dist/types/src/core/replication-apply.d.ts.map +1 -1
- package/dist/types/src/core/validation-state-reader.d.ts +2 -3
- package/dist/types/src/core/validation-state-reader.d.ts.map +1 -1
- package/dist/types/src/dwn.d.ts.map +1 -1
- package/dist/types/src/event-stream/event-emitter-wake-publisher.d.ts +1 -1
- package/dist/types/src/event-stream/event-emitter-wake-publisher.d.ts.map +1 -1
- package/dist/types/src/handlers/messages-query.d.ts.map +1 -1
- package/dist/types/src/handlers/messages-read.d.ts.map +1 -1
- package/dist/types/src/handlers/messages-subscribe.d.ts.map +1 -1
- package/dist/types/src/handlers/protocols-configure.d.ts +1 -0
- package/dist/types/src/handlers/protocols-configure.d.ts.map +1 -1
- package/dist/types/src/handlers/records-count.d.ts +2 -0
- package/dist/types/src/handlers/records-count.d.ts.map +1 -1
- package/dist/types/src/handlers/records-delete.d.ts.map +1 -1
- package/dist/types/src/handlers/records-query.d.ts +3 -0
- package/dist/types/src/handlers/records-query.d.ts.map +1 -1
- package/dist/types/src/handlers/records-read.d.ts.map +1 -1
- package/dist/types/src/handlers/records-subscribe.d.ts +2 -0
- package/dist/types/src/handlers/records-subscribe.d.ts.map +1 -1
- package/dist/types/src/handlers/records-write.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +12 -18
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/interfaces/protocols-configure.d.ts +13 -1
- package/dist/types/src/interfaces/protocols-configure.d.ts.map +1 -1
- package/dist/types/src/interfaces/records-write.d.ts +5 -1
- package/dist/types/src/interfaces/records-write.d.ts.map +1 -1
- package/dist/types/src/jose/algorithms/signing/ed25519.d.ts.map +1 -1
- package/dist/types/src/protocols/encryption.d.ts +15 -19
- package/dist/types/src/protocols/encryption.d.ts.map +1 -1
- package/dist/types/src/store/blockstore-level.d.ts +11 -11
- package/dist/types/src/store/blockstore-level.d.ts.map +1 -1
- package/dist/types/src/store/blockstore-mock.d.ts +12 -12
- package/dist/types/src/store/blockstore-mock.d.ts.map +1 -1
- package/dist/types/src/store/blockstore-utils.d.ts +23 -0
- package/dist/types/src/store/blockstore-utils.d.ts.map +1 -0
- package/dist/types/src/store/blockstore.d.ts +3 -0
- package/dist/types/src/store/blockstore.d.ts.map +1 -0
- package/dist/types/src/store/data-store-level.d.ts.map +1 -1
- package/dist/types/src/store/level.d.ts +13 -0
- package/dist/types/src/store/level.d.ts.map +1 -0
- package/dist/types/src/types/cache.d.ts +2 -2
- package/dist/types/src/types/cache.d.ts.map +1 -1
- package/dist/types/src/types/encryption-types.d.ts +31 -2
- package/dist/types/src/types/encryption-types.d.ts.map +1 -1
- package/dist/types/src/types/validation-state-reader.d.ts +3 -5
- package/dist/types/src/types/validation-state-reader.d.ts.map +1 -1
- package/dist/types/src/utils/data-stream.d.ts +5 -0
- package/dist/types/src/utils/data-stream.d.ts.map +1 -1
- package/dist/types/src/utils/encryption.d.ts +53 -24
- package/dist/types/src/utils/encryption.d.ts.map +1 -1
- package/dist/types/src/utils/grant-key-coverage.d.ts +36 -0
- package/dist/types/src/utils/grant-key-coverage.d.ts.map +1 -0
- package/dist/types/src/utils/hd-key.d.ts.map +1 -1
- package/dist/types/src/utils/jws.d.ts.map +1 -1
- package/dist/types/src/utils/memory-cache.d.ts +4 -2
- package/dist/types/src/utils/memory-cache.d.ts.map +1 -1
- package/dist/types/src/utils/protocols.d.ts +11 -0
- package/dist/types/src/utils/protocols.d.ts.map +1 -1
- package/dist/types/src/utils/record-limit-occupancy.d.ts +7 -0
- package/dist/types/src/utils/record-limit-occupancy.d.ts.map +1 -1
- package/dist/types/src/utils/records.d.ts +2 -0
- package/dist/types/src/utils/records.d.ts.map +1 -1
- package/dist/types/src/utils/secp256k1.d.ts.map +1 -1
- package/dist/types/src/utils/secp256r1.d.ts.map +1 -1
- package/dist/types/src/utils/time.d.ts +21 -13
- package/dist/types/src/utils/time.d.ts.map +1 -1
- package/dist/types/tests/core/constants.spec.d.ts +2 -0
- package/dist/types/tests/core/constants.spec.d.ts.map +1 -0
- package/dist/types/tests/core/encryption-control.spec.d.ts +2 -0
- package/dist/types/tests/core/encryption-control.spec.d.ts.map +1 -0
- package/dist/types/tests/dwn.spec.d.ts.map +1 -1
- package/dist/types/tests/event-emitter-wake-publisher.spec.d.ts +2 -0
- package/dist/types/tests/event-emitter-wake-publisher.spec.d.ts.map +1 -0
- package/dist/types/tests/handlers/messages-query.spec.d.ts.map +1 -1
- package/dist/types/tests/handlers/messages-read.spec.d.ts.map +1 -1
- package/dist/types/tests/handlers/messages-subscribe.spec.d.ts.map +1 -1
- package/dist/types/tests/handlers/protocols-configure.spec.d.ts.map +1 -1
- package/dist/types/tests/handlers/records-count.spec.d.ts.map +1 -1
- package/dist/types/tests/handlers/records-delete.spec.d.ts.map +1 -1
- package/dist/types/tests/handlers/records-query.spec.d.ts.map +1 -1
- package/dist/types/tests/handlers/records-read.spec.d.ts.map +1 -1
- package/dist/types/tests/handlers/records-subscribe.spec.d.ts.map +1 -1
- package/dist/types/tests/handlers/records-write.spec.d.ts.map +1 -1
- package/dist/types/tests/scenarios/end-to-end-tests.spec.d.ts.map +1 -1
- package/dist/types/tests/store/blockstore-utils.spec.d.ts +2 -0
- package/dist/types/tests/store/blockstore-utils.spec.d.ts.map +1 -0
- package/dist/types/tests/test-stores.d.ts.map +1 -1
- package/dist/types/tests/utils/encryption-control-test-utils.d.ts +46 -0
- package/dist/types/tests/utils/encryption-control-test-utils.d.ts.map +1 -0
- package/dist/types/tests/utils/grant-key-coverage.spec.d.ts +2 -0
- package/dist/types/tests/utils/grant-key-coverage.spec.d.ts.map +1 -0
- package/dist/types/tests/utils/test-data-generator.d.ts.map +1 -1
- package/dist/types/tests/validation/json-schemas/encryption/audience.spec.d.ts +2 -0
- package/dist/types/tests/validation/json-schemas/encryption/audience.spec.d.ts.map +1 -0
- package/dist/types/tests/validation/json-schemas/encryption/delivery.spec.d.ts +2 -0
- package/dist/types/tests/validation/json-schemas/encryption/delivery.spec.d.ts.map +1 -0
- package/dist/types/tests/validation/json-schemas/encryption/wrapped-grant-key-envelope.spec.d.ts +2 -0
- package/dist/types/tests/validation/json-schemas/encryption/wrapped-grant-key-envelope.spec.d.ts.map +1 -0
- package/package.json +47 -28
- package/src/core/constants.ts +61 -0
- package/src/core/dwn-error.ts +29 -11
- package/src/core/encryption-control.ts +1249 -0
- package/src/core/message.ts +7 -0
- package/src/core/messages-grant-authorization.ts +60 -9
- package/src/core/protocol-authorization-action.ts +3 -13
- package/src/core/protocol-authorization-validation.ts +66 -46
- package/src/core/protocol-authorization.ts +7 -0
- package/src/core/recording-validation-state-reader.ts +4 -5
- package/src/core/replication-apply.ts +77 -133
- package/src/core/validation-state-reader.ts +6 -8
- package/src/dwn.ts +1 -2
- package/src/event-stream/event-emitter-wake-publisher.ts +10 -14
- package/src/handlers/messages-query.ts +6 -22
- package/src/handlers/messages-read.ts +4 -3
- package/src/handlers/messages-subscribe.ts +34 -30
- package/src/handlers/protocols-configure.ts +7 -4
- package/src/handlers/records-count.ts +111 -10
- package/src/handlers/records-delete.ts +15 -0
- package/src/handlers/records-query.ts +176 -20
- package/src/handlers/records-read.ts +19 -6
- package/src/handlers/records-subscribe.ts +158 -8
- package/src/handlers/records-write.ts +19 -0
- package/src/index.ts +50 -22
- package/src/interfaces/protocols-configure.ts +102 -11
- package/src/interfaces/records-write.ts +49 -43
- package/src/jose/algorithms/signing/ed25519.ts +7 -6
- package/src/jose/jws/general/verifier.ts +3 -3
- package/src/protocols/encryption.ts +94 -411
- package/src/store/blockstore-level.ts +33 -37
- package/src/store/blockstore-mock.ts +24 -38
- package/src/store/blockstore-utils.ts +85 -0
- package/src/store/blockstore.ts +8 -0
- package/src/store/data-store-level.ts +5 -12
- package/src/store/level.ts +19 -0
- package/src/types/cache.ts +3 -3
- package/src/types/encryption-types.ts +39 -2
- package/src/types/validation-state-reader.ts +3 -5
- package/src/utils/data-stream.ts +29 -1
- package/src/utils/encryption.ts +190 -60
- package/src/utils/grant-key-coverage.ts +303 -0
- package/src/utils/hd-key.ts +1 -2
- package/src/utils/jws.ts +8 -2
- package/src/utils/memory-cache.ts +42 -11
- package/src/utils/protocols.ts +32 -0
- package/src/utils/record-limit-occupancy.ts +34 -5
- package/src/utils/records.ts +36 -2
- package/src/utils/secp256k1.ts +12 -12
- package/src/utils/secp256r1.ts +12 -22
- package/src/utils/time.ts +145 -27
- package/dist/esm/tests/validation/json-schemas/encryption/audience-key.spec.js +0 -40
- package/dist/esm/tests/validation/json-schemas/encryption/audience-key.spec.js.map +0 -1
- package/dist/types/tests/validation/json-schemas/encryption/audience-key.spec.d.ts +0 -2
- package/dist/types/tests/validation/json-schemas/encryption/audience-key.spec.d.ts.map +0 -1
- package/src/types/mitt.d.ts +0 -28
package/src/utils/encryption.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import type { Jwk } from '@enbox/crypto';
|
|
2
2
|
import type { PublicKeyJwk } from '../types/jose-types.js';
|
|
3
3
|
|
|
4
|
-
import { concatBytes } from '@noble/ciphers/utils';
|
|
5
4
|
import { AesCtr, AesKw, computeJwkThumbprint, Hkdf, X25519 } from '@enbox/crypto';
|
|
6
5
|
|
|
7
6
|
import { Encoder } from './encoder.js';
|
|
@@ -17,73 +16,128 @@ export enum KeyAgreementAlgorithm {
|
|
|
17
16
|
}
|
|
18
17
|
|
|
19
18
|
export const ROLE_AUDIENCE_DERIVATION_SCHEME = 'roleAudience';
|
|
19
|
+
export const SEAL_DERIVATION_SCHEME = 'seal';
|
|
20
20
|
|
|
21
21
|
const AES_256_KEY_LENGTH_BYTES = 32;
|
|
22
22
|
const AES_CTR_COUNTER_LENGTH_BYTES = 16;
|
|
23
23
|
const AES_CTR_COUNTER_LENGTH_BITS = 128;
|
|
24
24
|
const KEK_INFO_PREFIX = KeyAgreementAlgorithm.X25519HkdfSha256A256Kw;
|
|
25
25
|
|
|
26
|
-
|
|
26
|
+
function concatBytes(...arrays: Uint8Array[]): Uint8Array {
|
|
27
|
+
const byteLength = arrays.reduce((total, array): number => total + array.byteLength, 0);
|
|
28
|
+
const result = new Uint8Array(byteLength);
|
|
29
|
+
let offset = 0;
|
|
30
|
+
|
|
31
|
+
for (const array of arrays) {
|
|
32
|
+
result.set(array, offset);
|
|
33
|
+
offset += array.byteLength;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return result;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export type X25519KeyEncryptionBase = {
|
|
27
40
|
algorithm: KeyAgreementAlgorithm.X25519HkdfSha256A256Kw;
|
|
28
41
|
keyId: string;
|
|
29
|
-
derivationScheme: KeyDerivationScheme.ProtocolPath;
|
|
30
42
|
ephemeralPublicKey: PublicKeyJwk;
|
|
31
43
|
encryptedKey: string;
|
|
32
44
|
};
|
|
33
45
|
|
|
34
|
-
export type
|
|
35
|
-
|
|
36
|
-
|
|
46
|
+
export type ProtocolPathKeyEncryption = X25519KeyEncryptionBase & {
|
|
47
|
+
derivationScheme: KeyDerivationScheme.ProtocolPath;
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
export type SourceRoleAudienceKeyEncryption = X25519KeyEncryptionBase & {
|
|
37
51
|
derivationScheme: typeof ROLE_AUDIENCE_DERIVATION_SCHEME;
|
|
38
52
|
protocol: string;
|
|
39
|
-
|
|
40
|
-
epoch: number;
|
|
41
|
-
ephemeralPublicKey: PublicKeyJwk;
|
|
42
|
-
encryptedKey: string;
|
|
53
|
+
rolePath: string;
|
|
43
54
|
};
|
|
44
55
|
|
|
45
|
-
export type
|
|
56
|
+
export type X25519KeyEncryption = ProtocolPathKeyEncryption | SourceRoleAudienceKeyEncryption;
|
|
46
57
|
|
|
47
|
-
export type
|
|
58
|
+
export type SealKeyWrap = X25519KeyEncryptionBase & {
|
|
59
|
+
derivationScheme: typeof SEAL_DERIVATION_SCHEME;
|
|
60
|
+
};
|
|
48
61
|
|
|
49
62
|
export type DwnEncryption = {
|
|
50
63
|
algorithm: ContentEncryptionAlgorithm.A256CTR;
|
|
51
64
|
initializationVector: string;
|
|
52
|
-
keyEncryption:
|
|
65
|
+
keyEncryption: X25519KeyEncryption[];
|
|
53
66
|
};
|
|
54
67
|
|
|
55
|
-
export type
|
|
68
|
+
export type X25519KeyEncryptionInputBase = {
|
|
69
|
+
algorithm: KeyAgreementAlgorithm.X25519HkdfSha256A256Kw;
|
|
56
70
|
keyId: string;
|
|
57
71
|
publicKey: PublicKeyJwk;
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
export type ProtocolPathKeyEncryptionInput = X25519KeyEncryptionInputBase & {
|
|
58
75
|
derivationScheme: KeyDerivationScheme.ProtocolPath;
|
|
59
76
|
};
|
|
60
77
|
|
|
61
|
-
export type
|
|
62
|
-
keyId: string;
|
|
63
|
-
publicKey: PublicKeyJwk;
|
|
78
|
+
export type SourceRoleAudienceKeyEncryptionInput = X25519KeyEncryptionInputBase & {
|
|
64
79
|
derivationScheme: typeof ROLE_AUDIENCE_DERIVATION_SCHEME;
|
|
65
80
|
protocol: string;
|
|
66
|
-
|
|
67
|
-
epoch: number;
|
|
81
|
+
rolePath: string;
|
|
68
82
|
};
|
|
69
83
|
|
|
70
|
-
export type
|
|
84
|
+
export type X25519KeyEncryptionInput = ProtocolPathKeyEncryptionInput | SourceRoleAudienceKeyEncryptionInput;
|
|
71
85
|
|
|
72
|
-
export type
|
|
86
|
+
export type SealKeyWrapInput = X25519KeyEncryptionInputBase & {
|
|
87
|
+
derivationScheme: typeof SEAL_DERIVATION_SCHEME;
|
|
88
|
+
protocol: string;
|
|
89
|
+
rolePath: string;
|
|
90
|
+
contextId: string;
|
|
91
|
+
audienceKeyId: string;
|
|
92
|
+
};
|
|
73
93
|
|
|
74
94
|
export type EncryptionInput = {
|
|
75
95
|
algorithm?: ContentEncryptionAlgorithm;
|
|
76
96
|
key: Uint8Array;
|
|
77
97
|
initializationVector: Uint8Array;
|
|
78
|
-
keyEncryptionInputs:
|
|
98
|
+
keyEncryptionInputs: X25519KeyEncryptionInput[];
|
|
79
99
|
};
|
|
80
100
|
|
|
81
101
|
export type KeyUnwrapPayload = {
|
|
82
102
|
encryptedKey: Uint8Array;
|
|
83
103
|
ephemeralPublicKey: PublicKeyJwk;
|
|
84
|
-
keyEncryption:
|
|
104
|
+
keyEncryption: X25519KeyEncryption;
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
export type X25519KeyWrapInput = {
|
|
108
|
+
cek: Uint8Array;
|
|
109
|
+
keyInput: X25519KeyEncryptionInput;
|
|
110
|
+
ephemeralPrivateKey?: Jwk;
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
export type SealWrapInput = {
|
|
114
|
+
privateKeyBytes: Uint8Array;
|
|
115
|
+
keyInput: SealKeyWrapInput;
|
|
116
|
+
ephemeralPrivateKey?: Jwk;
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
export type SealUnwrapInput = {
|
|
120
|
+
seal: SealKeyWrap;
|
|
121
|
+
recipientPrivateKey: Jwk;
|
|
122
|
+
protocol: string;
|
|
123
|
+
rolePath: string;
|
|
124
|
+
contextId: string;
|
|
125
|
+
audienceKeyId: string;
|
|
85
126
|
};
|
|
86
127
|
|
|
128
|
+
type SealKeyUnwrapInfo = SealKeyWrap & {
|
|
129
|
+
protocol: string;
|
|
130
|
+
rolePath: string;
|
|
131
|
+
contextId: string;
|
|
132
|
+
audienceKeyId: string;
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
type X25519KekDerivationInput =
|
|
136
|
+
| X25519KeyEncryptionInput
|
|
137
|
+
| X25519KeyEncryption
|
|
138
|
+
| SealKeyWrapInput
|
|
139
|
+
| SealKeyUnwrapInfo;
|
|
140
|
+
|
|
87
141
|
export class Encryption {
|
|
88
142
|
public static async encrypt(
|
|
89
143
|
algorithm: ContentEncryptionAlgorithm,
|
|
@@ -137,31 +191,54 @@ export class Encryption {
|
|
|
137
191
|
return Encryption.toStream(plaintext);
|
|
138
192
|
}
|
|
139
193
|
|
|
140
|
-
public static async wrapKey(
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
return Encryption.wrapX25519Key(recipientPublicKey, cek, keyInput, ephemeralPrivateKey);
|
|
194
|
+
public static async wrapKey(input: X25519KeyWrapInput): Promise<{ encryptedKey: Uint8Array; ephemeralPublicKey: PublicKeyJwk }> {
|
|
195
|
+
if (Encryption.isX25519KeyAgreementAlgorithm(input.keyInput.algorithm)) {
|
|
196
|
+
return Encryption.wrapX25519Key(input);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
throw new Error(Encryption.unsupportedKeyAgreementAlgorithmMessage(input.keyInput.algorithm));
|
|
147
200
|
}
|
|
148
201
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
202
|
+
public static async wrapSeal(input: SealWrapInput): Promise<SealKeyWrap> {
|
|
203
|
+
if (!Encryption.isX25519KeyAgreementAlgorithm(input.keyInput.algorithm)) {
|
|
204
|
+
throw new Error(Encryption.unsupportedKeyAgreementAlgorithmMessage(input.keyInput.algorithm));
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
Encryption.validateContentEncryptionKey(input.privateKeyBytes);
|
|
208
|
+
|
|
209
|
+
const privateKey = input.ephemeralPrivateKey ?? await X25519.generateKey();
|
|
210
|
+
const publicKey = await X25519.getPublicKey({ key: privateKey }) as PublicKeyJwk;
|
|
211
|
+
const sharedSecret = await X25519.sharedSecret({
|
|
212
|
+
privateKeyA : privateKey,
|
|
213
|
+
publicKeyB : input.keyInput.publicKey as Jwk,
|
|
214
|
+
});
|
|
215
|
+
const kek = await Encryption.deriveKek(sharedSecret, input.keyInput);
|
|
216
|
+
const unwrappedKey = await AesKw.bytesToPrivateKey({ privateKeyBytes: input.privateKeyBytes });
|
|
217
|
+
const encryptedKey = await AesKw.wrapKey({
|
|
218
|
+
encryptionKey: Encryption.toA256KwJwk(kek),
|
|
219
|
+
unwrappedKey,
|
|
220
|
+
});
|
|
156
221
|
|
|
157
|
-
|
|
222
|
+
return {
|
|
223
|
+
algorithm : input.keyInput.algorithm,
|
|
224
|
+
derivationScheme : SEAL_DERIVATION_SCHEME,
|
|
225
|
+
encryptedKey : Encoder.bytesToBase64Url(encryptedKey),
|
|
226
|
+
ephemeralPublicKey : publicKey,
|
|
227
|
+
keyId : input.keyInput.keyId,
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
private static async wrapX25519Key(input: X25519KeyWrapInput): Promise<{ encryptedKey: Uint8Array; ephemeralPublicKey: PublicKeyJwk }> {
|
|
232
|
+
Encryption.validateContentEncryptionKey(input.cek);
|
|
233
|
+
|
|
234
|
+
const privateKey = input.ephemeralPrivateKey ?? await X25519.generateKey();
|
|
158
235
|
const publicKey = await X25519.getPublicKey({ key: privateKey }) as PublicKeyJwk;
|
|
159
236
|
const sharedSecret = await X25519.sharedSecret({
|
|
160
237
|
privateKeyA : privateKey,
|
|
161
|
-
publicKeyB :
|
|
238
|
+
publicKeyB : input.keyInput.publicKey as Jwk,
|
|
162
239
|
});
|
|
163
|
-
const kek = await Encryption.deriveKek(sharedSecret, keyInput);
|
|
164
|
-
const cekJwk = Encryption.toA256CtrJwk(cek);
|
|
240
|
+
const kek = await Encryption.deriveKek(sharedSecret, input.keyInput);
|
|
241
|
+
const cekJwk = Encryption.toA256CtrJwk(input.cek);
|
|
165
242
|
const kekJwk: Jwk = { alg: 'A256KW', k: Encoder.bytesToBase64Url(kek), kty: 'oct' };
|
|
166
243
|
const encryptedKey = await AesKw.wrapKey({ encryptionKey: kekJwk, unwrappedKey: cekJwk });
|
|
167
244
|
|
|
@@ -170,13 +247,39 @@ export class Encryption {
|
|
|
170
247
|
|
|
171
248
|
public static async unwrapKey(
|
|
172
249
|
recipientPrivateKey: Jwk,
|
|
173
|
-
keyEncryption:
|
|
250
|
+
keyEncryption: X25519KeyEncryption,
|
|
174
251
|
): Promise<Uint8Array> {
|
|
175
|
-
if (keyEncryption.algorithm
|
|
252
|
+
if (Encryption.isX25519KeyAgreementAlgorithm(keyEncryption.algorithm)) {
|
|
176
253
|
return Encryption.unwrapX25519Key(recipientPrivateKey, keyEncryption);
|
|
177
254
|
}
|
|
178
255
|
|
|
179
|
-
throw new Error(
|
|
256
|
+
throw new Error(Encryption.unsupportedKeyAgreementAlgorithmMessage(keyEncryption.algorithm));
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
public static async unwrapSeal(input: SealUnwrapInput): Promise<Uint8Array> {
|
|
260
|
+
if (!Encryption.isX25519KeyAgreementAlgorithm(input.seal.algorithm)) {
|
|
261
|
+
throw new Error(Encryption.unsupportedKeyAgreementAlgorithmMessage(input.seal.algorithm));
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
const keyEncryption: SealKeyUnwrapInfo = {
|
|
265
|
+
...input.seal,
|
|
266
|
+
audienceKeyId : input.audienceKeyId,
|
|
267
|
+
contextId : input.contextId,
|
|
268
|
+
protocol : input.protocol,
|
|
269
|
+
rolePath : input.rolePath,
|
|
270
|
+
};
|
|
271
|
+
const sharedSecret = await X25519.sharedSecret({
|
|
272
|
+
privateKeyA : input.recipientPrivateKey,
|
|
273
|
+
publicKeyB : input.seal.ephemeralPublicKey as Jwk,
|
|
274
|
+
});
|
|
275
|
+
const kek = await Encryption.deriveKek(sharedSecret, keyEncryption);
|
|
276
|
+
const unwrappedKey = await AesKw.unwrapKey({
|
|
277
|
+
decryptionKey : Encryption.toA256KwJwk(kek),
|
|
278
|
+
wrappedKeyAlgorithm : 'A256KW',
|
|
279
|
+
wrappedKeyBytes : Encoder.base64UrlToBytes(input.seal.encryptedKey),
|
|
280
|
+
});
|
|
281
|
+
|
|
282
|
+
return AesKw.privateKeyToBytes({ privateKey: unwrappedKey });
|
|
180
283
|
}
|
|
181
284
|
|
|
182
285
|
private static async unwrapX25519Key(
|
|
@@ -204,7 +307,7 @@ export class Encryption {
|
|
|
204
307
|
const algorithm = encryptionInput.algorithm ?? ContentEncryptionAlgorithm.A256CTR;
|
|
205
308
|
Encryption.validateContentEncryptionParameters(algorithm, encryptionInput.key, encryptionInput.initializationVector);
|
|
206
309
|
|
|
207
|
-
const keyEncryption:
|
|
310
|
+
const keyEncryption: X25519KeyEncryption[] = [];
|
|
208
311
|
for (const keyInput of encryptionInput.keyEncryptionInputs) {
|
|
209
312
|
keyEncryption.push(await Encryption.buildKeyEncryptionEntry(encryptionInput.key, keyInput));
|
|
210
313
|
}
|
|
@@ -236,15 +339,14 @@ export class Encryption {
|
|
|
236
339
|
|
|
237
340
|
private static async buildKeyEncryptionEntry(
|
|
238
341
|
cek: Uint8Array,
|
|
239
|
-
keyInput:
|
|
240
|
-
): Promise<
|
|
241
|
-
const { encryptedKey, ephemeralPublicKey } = await Encryption.wrapKey(
|
|
242
|
-
keyInput.publicKey,
|
|
342
|
+
keyInput: X25519KeyEncryptionInput,
|
|
343
|
+
): Promise<X25519KeyEncryption> {
|
|
344
|
+
const { encryptedKey, ephemeralPublicKey } = await Encryption.wrapKey({
|
|
243
345
|
cek,
|
|
244
346
|
keyInput,
|
|
245
|
-
);
|
|
347
|
+
});
|
|
246
348
|
const common = {
|
|
247
|
-
algorithm :
|
|
349
|
+
algorithm : keyInput.algorithm,
|
|
248
350
|
encryptedKey : Encoder.bytesToBase64Url(encryptedKey),
|
|
249
351
|
ephemeralPublicKey,
|
|
250
352
|
keyId : keyInput.keyId,
|
|
@@ -260,21 +362,20 @@ export class Encryption {
|
|
|
260
362
|
return {
|
|
261
363
|
...common,
|
|
262
364
|
derivationScheme : ROLE_AUDIENCE_DERIVATION_SCHEME,
|
|
263
|
-
epoch : keyInput.epoch,
|
|
264
365
|
protocol : keyInput.protocol,
|
|
265
|
-
|
|
366
|
+
rolePath : keyInput.rolePath,
|
|
266
367
|
};
|
|
267
368
|
}
|
|
268
369
|
|
|
269
|
-
private static validateKeyEncryptionEntry(entry:
|
|
270
|
-
if (entry.algorithm
|
|
370
|
+
private static validateKeyEncryptionEntry(entry: X25519KeyEncryption): void {
|
|
371
|
+
if (Encryption.isX25519KeyAgreementAlgorithm(entry.algorithm)) {
|
|
271
372
|
Encryption.validateX25519KeyEncryptionEntry(entry);
|
|
272
373
|
return;
|
|
273
374
|
}
|
|
274
375
|
|
|
275
376
|
throw new DwnError(
|
|
276
377
|
DwnErrorCode.RecordsWriteValidateIntegrityEncryptionEphemeralPublicKeyInvalid,
|
|
277
|
-
|
|
378
|
+
Encryption.unsupportedKeyAgreementAlgorithmMessage(entry.algorithm)
|
|
278
379
|
);
|
|
279
380
|
}
|
|
280
381
|
|
|
@@ -289,7 +390,7 @@ export class Encryption {
|
|
|
289
390
|
|
|
290
391
|
private static async deriveKek(
|
|
291
392
|
sharedSecret: Uint8Array,
|
|
292
|
-
keyEncryption:
|
|
393
|
+
keyEncryption: X25519KekDerivationInput,
|
|
293
394
|
): Promise<Uint8Array> {
|
|
294
395
|
Encryption.validateSharedSecret(sharedSecret);
|
|
295
396
|
const info = Encryption.getKekInfo(keyEncryption);
|
|
@@ -302,12 +403,29 @@ export class Encryption {
|
|
|
302
403
|
});
|
|
303
404
|
}
|
|
304
405
|
|
|
305
|
-
private static getKekInfo(keyEncryption:
|
|
406
|
+
private static getKekInfo(keyEncryption: X25519KekDerivationInput): string {
|
|
407
|
+
if (keyEncryption.derivationScheme === SEAL_DERIVATION_SCHEME) {
|
|
408
|
+
return JSON.stringify([
|
|
409
|
+
KEK_INFO_PREFIX,
|
|
410
|
+
SEAL_DERIVATION_SCHEME,
|
|
411
|
+
keyEncryption.protocol,
|
|
412
|
+
keyEncryption.rolePath,
|
|
413
|
+
keyEncryption.contextId,
|
|
414
|
+
keyEncryption.audienceKeyId,
|
|
415
|
+
]);
|
|
416
|
+
}
|
|
417
|
+
|
|
306
418
|
if (keyEncryption.derivationScheme === ROLE_AUDIENCE_DERIVATION_SCHEME) {
|
|
307
|
-
return
|
|
419
|
+
return JSON.stringify([
|
|
420
|
+
KEK_INFO_PREFIX,
|
|
421
|
+
ROLE_AUDIENCE_DERIVATION_SCHEME,
|
|
422
|
+
keyEncryption.protocol,
|
|
423
|
+
keyEncryption.rolePath,
|
|
424
|
+
keyEncryption.keyId,
|
|
425
|
+
]);
|
|
308
426
|
}
|
|
309
427
|
|
|
310
|
-
return
|
|
428
|
+
return JSON.stringify([KEK_INFO_PREFIX, KeyDerivationScheme.ProtocolPath, keyEncryption.keyId]);
|
|
311
429
|
}
|
|
312
430
|
|
|
313
431
|
private static validateContentEncryptionParameters(
|
|
@@ -338,10 +456,22 @@ export class Encryption {
|
|
|
338
456
|
}
|
|
339
457
|
}
|
|
340
458
|
|
|
459
|
+
private static isX25519KeyAgreementAlgorithm(algorithm: unknown): algorithm is KeyAgreementAlgorithm.X25519HkdfSha256A256Kw {
|
|
460
|
+
return algorithm === KeyAgreementAlgorithm.X25519HkdfSha256A256Kw;
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
private static unsupportedKeyAgreementAlgorithmMessage(algorithm: unknown): string {
|
|
464
|
+
return `Unsupported key agreement algorithm: ${String(algorithm)}`;
|
|
465
|
+
}
|
|
466
|
+
|
|
341
467
|
private static toA256CtrJwk(keyBytes: Uint8Array): Jwk {
|
|
342
468
|
return { alg: ContentEncryptionAlgorithm.A256CTR, k: Encoder.bytesToBase64Url(keyBytes), kty: 'oct' };
|
|
343
469
|
}
|
|
344
470
|
|
|
471
|
+
private static toA256KwJwk(keyBytes: Uint8Array): Jwk {
|
|
472
|
+
return { alg: 'A256KW', k: Encoder.bytesToBase64Url(keyBytes), kty: 'oct' };
|
|
473
|
+
}
|
|
474
|
+
|
|
345
475
|
private static async readStream(stream: ReadableStream<Uint8Array>): Promise<Uint8Array> {
|
|
346
476
|
const reader = stream.getReader();
|
|
347
477
|
const chunks: Uint8Array[] = [];
|
|
@@ -0,0 +1,303 @@
|
|
|
1
|
+
import type { PermissionScope, RecordsPermissionScope } from '../types/permission-types.js';
|
|
2
|
+
import type { ProtocolDefinition, ProtocolRuleSet } from '../types/protocols-types.js';
|
|
3
|
+
|
|
4
|
+
import { KeyDerivationScheme } from './hd-key.js';
|
|
5
|
+
import { ProtocolAction } from '../types/protocols-types.js';
|
|
6
|
+
import { DwnInterfaceName, DwnMethodName } from '../enums/dwn-interface-method.js';
|
|
7
|
+
import { getRuleSetAtPath, parseCrossProtocolRef } from './protocols.js';
|
|
8
|
+
|
|
9
|
+
type GrantKeyRecordsScopeBase = RecordsPermissionScope & {
|
|
10
|
+
interface: typeof DwnInterfaceName.Records;
|
|
11
|
+
protocol: string;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export type GrantKeyRecordsScope = GrantKeyRecordsScopeBase & {
|
|
15
|
+
method: typeof DwnMethodName.Read | typeof DwnMethodName.Write;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export type GrantKeyReadRecordsScope = GrantKeyRecordsScopeBase & {
|
|
19
|
+
contextId?: undefined;
|
|
20
|
+
method: typeof DwnMethodName.Read;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export type GrantKeyWriteRecordsScope = GrantKeyRecordsScopeBase & {
|
|
24
|
+
contextId?: undefined;
|
|
25
|
+
method: typeof DwnMethodName.Write;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export type GrantKeyEligibleRecordsScope = GrantKeyReadRecordsScope | GrantKeyWriteRecordsScope;
|
|
29
|
+
|
|
30
|
+
export type GrantKeyProtocolPathScope = {
|
|
31
|
+
scheme: typeof KeyDerivationScheme.ProtocolPath;
|
|
32
|
+
protocol: string;
|
|
33
|
+
protocolPath?: string;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
type GrantKeyDeliveryScopeBuilder = (
|
|
37
|
+
grantScope: GrantKeyEligibleRecordsScope,
|
|
38
|
+
protocolDefinition?: ProtocolDefinition,
|
|
39
|
+
) => GrantKeyProtocolPathScope[];
|
|
40
|
+
|
|
41
|
+
type GrantKeyCoveragePredicate = (
|
|
42
|
+
input: {
|
|
43
|
+
grantScope: GrantKeyEligibleRecordsScope;
|
|
44
|
+
deliveredScope: Pick<GrantKeyProtocolPathScope, 'protocol' | 'protocolPath'>;
|
|
45
|
+
protocolDefinition?: ProtocolDefinition;
|
|
46
|
+
},
|
|
47
|
+
) => boolean;
|
|
48
|
+
|
|
49
|
+
const grantKeyRecordsMethods = new Set<string>([
|
|
50
|
+
DwnMethodName.Read,
|
|
51
|
+
DwnMethodName.Write,
|
|
52
|
+
]);
|
|
53
|
+
|
|
54
|
+
const grantKeyDeliveryScopeBuilders: Record<GrantKeyRecordsScope['method'], GrantKeyDeliveryScopeBuilder> = {
|
|
55
|
+
[DwnMethodName.Read] : getReadGrantKeyDeliveryScopes,
|
|
56
|
+
[DwnMethodName.Write] : getWriteGrantKeyDeliveryScopes,
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
const grantKeyCoveragePredicates: Record<GrantKeyRecordsScope['method'], GrantKeyCoveragePredicate> = {
|
|
60
|
+
[DwnMethodName.Read] : readGrantKeyScopeCoversDeliveredScope,
|
|
61
|
+
[DwnMethodName.Write] : writeGrantKeyScopeCoversDeliveredScope,
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
export function isGrantKeyRecordsScope(scope: PermissionScope): scope is GrantKeyRecordsScope {
|
|
65
|
+
const maybeProtocol = (scope as { protocol?: unknown }).protocol;
|
|
66
|
+
return [
|
|
67
|
+
scope.interface === DwnInterfaceName.Records,
|
|
68
|
+
grantKeyRecordsMethods.has(scope.method),
|
|
69
|
+
typeof maybeProtocol === 'string',
|
|
70
|
+
].every(Boolean);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export function isGrantKeyEligibleRecordsScope(scope: PermissionScope): scope is GrantKeyEligibleRecordsScope {
|
|
74
|
+
return isGrantKeyRecordsScope(scope) &&
|
|
75
|
+
!('contextId' in scope && scope.contextId !== undefined);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export function getGrantKeyDeliveryScopes(
|
|
79
|
+
grantScope: GrantKeyReadRecordsScope,
|
|
80
|
+
protocolDefinition?: ProtocolDefinition,
|
|
81
|
+
): GrantKeyProtocolPathScope[];
|
|
82
|
+
|
|
83
|
+
export function getGrantKeyDeliveryScopes(
|
|
84
|
+
grantScope: GrantKeyWriteRecordsScope,
|
|
85
|
+
protocolDefinition: ProtocolDefinition,
|
|
86
|
+
): GrantKeyProtocolPathScope[];
|
|
87
|
+
|
|
88
|
+
export function getGrantKeyDeliveryScopes(
|
|
89
|
+
grantScope: GrantKeyEligibleRecordsScope,
|
|
90
|
+
protocolDefinition?: ProtocolDefinition,
|
|
91
|
+
): GrantKeyProtocolPathScope[] {
|
|
92
|
+
return uniqueGrantKeyScopes(grantKeyDeliveryScopeBuilders[grantScope.method](grantScope, protocolDefinition));
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export function grantKeyScopeCoversDeliveredScope(input: {
|
|
96
|
+
grantScope: GrantKeyEligibleRecordsScope;
|
|
97
|
+
deliveredScope: Pick<GrantKeyProtocolPathScope, 'protocol' | 'protocolPath'>;
|
|
98
|
+
protocolDefinition?: ProtocolDefinition;
|
|
99
|
+
}): boolean {
|
|
100
|
+
const { grantScope, deliveredScope, protocolDefinition } = input;
|
|
101
|
+
if (grantScope.protocol !== deliveredScope.protocol) {
|
|
102
|
+
return false;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
return grantKeyCoveragePredicates[grantScope.method]({ grantScope, deliveredScope, protocolDefinition });
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function getReadGrantKeyDeliveryScopes(
|
|
109
|
+
grantScope: GrantKeyEligibleRecordsScope,
|
|
110
|
+
protocolDefinition?: ProtocolDefinition,
|
|
111
|
+
): GrantKeyProtocolPathScope[] {
|
|
112
|
+
if (grantScope.protocolPath === undefined) {
|
|
113
|
+
return [createProtocolGrantKeyScope(grantScope.protocol)];
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
const scopes = [
|
|
117
|
+
createProtocolPathGrantKeyScope(grantScope.protocol, grantScope.protocolPath),
|
|
118
|
+
];
|
|
119
|
+
|
|
120
|
+
if (protocolDefinition === undefined) {
|
|
121
|
+
return scopes;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
for (const rolePath of getGrantKeyReadRolePathsForScope(protocolDefinition, grantScope.protocolPath)) {
|
|
125
|
+
scopes.push(createProtocolPathGrantKeyScope(grantScope.protocol, rolePath));
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
return scopes;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
function getWriteGrantKeyDeliveryScopes(
|
|
132
|
+
grantScope: GrantKeyEligibleRecordsScope,
|
|
133
|
+
protocolDefinition?: ProtocolDefinition,
|
|
134
|
+
): GrantKeyProtocolPathScope[] {
|
|
135
|
+
if (protocolDefinition === undefined) {
|
|
136
|
+
throw new Error('getGrantKeyDeliveryScopes: write grants require a protocol definition.');
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
return getGrantKeyRolePathsCoveredByScope(protocolDefinition, grantScope.protocolPath)
|
|
140
|
+
.map((rolePath) => createProtocolPathGrantKeyScope(grantScope.protocol, rolePath));
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
function createProtocolGrantKeyScope(protocol: string): GrantKeyProtocolPathScope {
|
|
144
|
+
return {
|
|
145
|
+
scheme: KeyDerivationScheme.ProtocolPath,
|
|
146
|
+
protocol,
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
function createProtocolPathGrantKeyScope(protocol: string, protocolPath: string): GrantKeyProtocolPathScope {
|
|
151
|
+
return {
|
|
152
|
+
scheme: KeyDerivationScheme.ProtocolPath,
|
|
153
|
+
protocol,
|
|
154
|
+
protocolPath,
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
function readGrantKeyScopeCoversDeliveredScope(input: {
|
|
159
|
+
grantScope: GrantKeyEligibleRecordsScope;
|
|
160
|
+
deliveredScope: Pick<GrantKeyProtocolPathScope, 'protocol' | 'protocolPath'>;
|
|
161
|
+
protocolDefinition?: ProtocolDefinition;
|
|
162
|
+
}): boolean {
|
|
163
|
+
const { grantScope, deliveredScope, protocolDefinition } = input;
|
|
164
|
+
const grantProtocolPath = grantScope.protocolPath;
|
|
165
|
+
if (grantProtocolPath === undefined) {
|
|
166
|
+
return true;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
const deliveredProtocolPath = deliveredScope.protocolPath;
|
|
170
|
+
if (deliveredProtocolPath === undefined) {
|
|
171
|
+
return false;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
if (isBoundaryAwareSubtree(grantProtocolPath, deliveredProtocolPath)) {
|
|
175
|
+
return true;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
if (protocolDefinition === undefined) {
|
|
179
|
+
return false;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
return grantKeyReadScopeReferencesRolePath(protocolDefinition, grantProtocolPath, deliveredProtocolPath);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
function writeGrantKeyScopeCoversDeliveredScope(input: {
|
|
186
|
+
grantScope: GrantKeyEligibleRecordsScope;
|
|
187
|
+
deliveredScope: Pick<GrantKeyProtocolPathScope, 'protocol' | 'protocolPath'>;
|
|
188
|
+
protocolDefinition?: ProtocolDefinition;
|
|
189
|
+
}): boolean {
|
|
190
|
+
const { grantScope, deliveredScope, protocolDefinition } = input;
|
|
191
|
+
const deliveredProtocolPath = deliveredScope.protocolPath;
|
|
192
|
+
if (deliveredProtocolPath === undefined) {
|
|
193
|
+
return false;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
if (protocolDefinition === undefined) {
|
|
197
|
+
return false;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
if (!isGrantKeyLocalRolePath(protocolDefinition, deliveredProtocolPath)) {
|
|
201
|
+
return false;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
const grantProtocolPath = grantScope.protocolPath;
|
|
205
|
+
if (grantProtocolPath === undefined) {
|
|
206
|
+
return true;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
return isBoundaryAwareSubtree(grantProtocolPath, deliveredProtocolPath);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
function getGrantKeyReadRolePathsForScope(protocolDefinition: ProtocolDefinition, scopeProtocolPath: string): string[] {
|
|
213
|
+
const scopedRuleSet = getRuleSetAtPath(scopeProtocolPath, protocolDefinition.structure);
|
|
214
|
+
if (scopedRuleSet === undefined) {
|
|
215
|
+
return [];
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
return [...collectReadRolePaths(protocolDefinition, scopedRuleSet)];
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
function grantKeyReadScopeReferencesRolePath(
|
|
222
|
+
protocolDefinition: ProtocolDefinition,
|
|
223
|
+
scopeProtocolPath: string,
|
|
224
|
+
rolePath: string,
|
|
225
|
+
): boolean {
|
|
226
|
+
if (!isGrantKeyLocalRolePath(protocolDefinition, rolePath)) {
|
|
227
|
+
return false;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
return getGrantKeyReadRolePathsForScope(protocolDefinition, scopeProtocolPath).includes(rolePath);
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
function collectReadRolePaths(protocolDefinition: ProtocolDefinition, ruleSet: ProtocolRuleSet): Set<string> {
|
|
234
|
+
const rolePaths = new Set<string>();
|
|
235
|
+
|
|
236
|
+
for (const actionRule of ruleSet.$actions ?? []) {
|
|
237
|
+
if (!actionRule.can.includes(ProtocolAction.Read) || actionRule.role === undefined || parseCrossProtocolRef(actionRule.role) !== undefined) {
|
|
238
|
+
continue;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
if (isGrantKeyLocalRolePath(protocolDefinition, actionRule.role)) {
|
|
242
|
+
rolePaths.add(actionRule.role);
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
for (const [key, value] of Object.entries(ruleSet)) {
|
|
247
|
+
if (key.startsWith('$')) {
|
|
248
|
+
continue;
|
|
249
|
+
}
|
|
250
|
+
for (const rolePath of collectReadRolePaths(protocolDefinition, value as ProtocolRuleSet)) {
|
|
251
|
+
rolePaths.add(rolePath);
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
return rolePaths;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
function getGrantKeyRolePathsCoveredByScope(protocolDefinition: ProtocolDefinition, scopeProtocolPath?: string): string[] {
|
|
259
|
+
return collectRolePaths(protocolDefinition, protocolDefinition.structure as ProtocolRuleSet)
|
|
260
|
+
.filter((rolePath) => scopeProtocolPath === undefined || isBoundaryAwareSubtree(scopeProtocolPath, rolePath));
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
function collectRolePaths(protocolDefinition: ProtocolDefinition, ruleSet: ProtocolRuleSet, parentPath: string[] = []): string[] {
|
|
264
|
+
const rolePaths: string[] = [];
|
|
265
|
+
|
|
266
|
+
for (const [key, value] of Object.entries(ruleSet)) {
|
|
267
|
+
if (key.startsWith('$')) {
|
|
268
|
+
continue;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
const path = [...parentPath, key];
|
|
272
|
+
const protocolPath = path.join('/');
|
|
273
|
+
const childRuleSet = value as ProtocolRuleSet;
|
|
274
|
+
if (isGrantKeyLocalRolePath(protocolDefinition, protocolPath)) {
|
|
275
|
+
rolePaths.push(protocolPath);
|
|
276
|
+
}
|
|
277
|
+
rolePaths.push(...collectRolePaths(protocolDefinition, childRuleSet, path));
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
return rolePaths;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
function isGrantKeyLocalRolePath(protocolDefinition: ProtocolDefinition, protocolPath: string): boolean {
|
|
284
|
+
const ruleSet = getRuleSetAtPath(protocolPath, protocolDefinition.structure);
|
|
285
|
+
return ruleSet?.$role === true && ruleSet.$keyAgreement !== undefined;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
function isBoundaryAwareSubtree(scopePath: string, candidatePath: string): boolean {
|
|
289
|
+
return `${candidatePath}/`.startsWith(`${scopePath}/`);
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
function getGrantKeyScopeCacheKey(scope: GrantKeyProtocolPathScope): string {
|
|
293
|
+
return JSON.stringify([scope.protocol, scope.protocolPath]);
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
function uniqueGrantKeyScopes(scopes: GrantKeyProtocolPathScope[]): GrantKeyProtocolPathScope[] {
|
|
297
|
+
const deliveredScopes = new Map<string, GrantKeyProtocolPathScope>();
|
|
298
|
+
for (const scope of scopes) {
|
|
299
|
+
deliveredScopes.set(getGrantKeyScopeCacheKey(scope), scope);
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
return [...deliveredScopes.values()];
|
|
303
|
+
}
|