@lifeready/core 1.0.0 → 1.0.1
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 +62 -62
- package/karma.conf.js +32 -0
- package/ng-package.json +26 -0
- package/package.json +21 -29
- package/src/lib/_common/ast.ts +75 -0
- package/src/lib/_common/deferred-promise.ts +35 -0
- package/src/lib/_common/exceptions.ts +189 -0
- package/src/lib/_common/queries.gql.ts +200 -0
- package/src/lib/_common/run-outside-angular.ts +125 -0
- package/src/lib/_common/tests.ts +82 -0
- package/{lib/_common/types.d.ts → src/lib/_common/types.ts} +13 -10
- package/src/lib/_common/utils.ts +57 -0
- package/src/lib/api/api-mutation.spec.ts +547 -0
- package/src/lib/api/api-query.spec.ts +40 -0
- package/src/lib/api/contact-card.gql.ts +85 -0
- package/src/lib/api/contact-card.service.spec.ts +249 -0
- package/src/lib/api/contact-card.service.ts +228 -0
- package/src/lib/api/contact-card2.gql.ts +93 -0
- package/src/lib/api/contact-card2.service.spec.ts +297 -0
- package/src/lib/api/contact-card2.service.ts +139 -0
- package/src/lib/api/file.service.spec.ts +14 -0
- package/src/lib/api/file.service.ts +81 -0
- package/src/lib/api/item2.gql.ts +211 -0
- package/src/lib/api/item2.service.spec.ts +1043 -0
- package/src/lib/api/item2.service.ts +481 -0
- package/src/lib/api/key-exchange.gql.ts +196 -0
- package/src/lib/api/key-exchange.service.spec.ts +470 -0
- package/src/lib/api/key-exchange.service.ts +731 -0
- package/src/lib/api/key-exchange.types.ts +235 -0
- package/src/lib/api/key-exchange2.gql.ts +310 -0
- package/src/lib/api/key-exchange2.service.spec.ts +892 -0
- package/src/lib/api/key-exchange2.service.ts +875 -0
- package/src/lib/api/lock.gql.ts +67 -0
- package/src/lib/api/lock.service.spec.ts +549 -0
- package/src/lib/api/lock.service.ts +57 -0
- package/src/lib/api/lr-apollo.service.spec.ts +27 -0
- package/src/lib/api/lr-apollo.service.ts +43 -0
- package/{lib/api/lr-graphql/index.d.ts → src/lib/api/lr-graphql/index.ts} +5 -5
- package/src/lib/api/lr-graphql/lr-graphql.service.ts +313 -0
- package/src/lib/api/lr-graphql/lr-merged-mutation.ts +377 -0
- package/src/lib/api/lr-graphql/lr-mutation-base.ts +67 -0
- package/src/lib/api/lr-graphql/lr-mutation.ts +74 -0
- package/src/lib/api/lr-graphql/lr.service.ts +28 -0
- package/src/lib/api/message.service.spec.ts +20 -0
- package/src/lib/api/message.service.ts +210 -0
- package/src/lib/api/persist.service.spec.ts +209 -0
- package/src/lib/api/persist.service.ts +220 -0
- package/src/lib/api/query-processor/common-processors.service.ts +148 -0
- package/{lib/api/query-processor/index.d.ts → src/lib/api/query-processor/index.ts} +2 -2
- package/src/lib/api/query-processor/query-processor.service.ts +240 -0
- package/src/lib/api/query-processor/tp-password-reset-processor.service.ts +177 -0
- package/src/lib/api/shared-contact-card.service.ts +156 -0
- package/src/lib/api/shared-contact-card2.gql.ts +76 -0
- package/src/lib/api/shared-contact-card2.service.ts +154 -0
- package/src/lib/api/time.service.spec.ts +48 -0
- package/src/lib/api/time.service.ts +155 -0
- package/src/lib/api/types/graphql.types.ts +48 -0
- package/{lib/api/types/index.d.ts → src/lib/api/types/index.ts} +2 -2
- package/src/lib/api/types/lr-graphql.types.ts +467 -0
- package/src/lib/auth/auth.config.ts +83 -0
- package/src/lib/auth/auth.gql.ts +62 -0
- package/src/lib/auth/auth.types.ts +79 -0
- package/src/lib/auth/idle.service.spec.ts +119 -0
- package/src/lib/auth/idle.service.ts +208 -0
- package/src/lib/auth/idle.types.ts +11 -0
- package/src/lib/auth/lbop.service.spec.ts +56 -0
- package/src/lib/auth/lbop.service.ts +539 -0
- package/src/lib/auth/life-ready-auth.service.spec.ts +70 -0
- package/src/lib/auth/life-ready-auth.service.ts +454 -0
- package/src/lib/auth/password.service.spec.ts +51 -0
- package/src/lib/auth/password.service.ts +438 -0
- package/src/lib/auth/register.service.spec.ts +31 -0
- package/src/lib/auth/register.service.ts +181 -0
- package/src/lib/auth/two-factor.service.spec.ts +21 -0
- package/src/lib/auth/two-factor.service.ts +69 -0
- package/src/lib/category/category-meta.service.spec.ts +28 -0
- package/src/lib/category/category-meta.service.ts +125 -0
- package/src/lib/category/category.gql.ts +449 -0
- package/src/lib/category/category.service.spec.ts +26 -0
- package/src/lib/category/category.service.ts +498 -0
- package/src/lib/category/category.types.ts +89 -0
- package/src/lib/cryptography/cryptography.types.ts +108 -0
- package/src/lib/cryptography/encryption.service.spec.ts +125 -0
- package/src/lib/cryptography/encryption.service.ts +243 -0
- package/src/lib/cryptography/key-factory.service.spec.ts +15 -0
- package/src/lib/cryptography/key-factory.service.ts +303 -0
- package/src/lib/cryptography/key-graph.service.spec.ts +16 -0
- package/src/lib/cryptography/key-graph.service.ts +354 -0
- package/src/lib/cryptography/key-meta.service.spec.ts +40 -0
- package/src/lib/cryptography/key-meta.service.ts +254 -0
- package/src/lib/cryptography/key.service.spec.ts +16 -0
- package/src/lib/cryptography/key.service.ts +154 -0
- package/src/lib/cryptography/slip39.service.spec.ts +44 -0
- package/src/lib/cryptography/slip39.service.ts +204 -0
- package/src/lib/cryptography/web-crypto.service.ts +22 -0
- package/src/lib/life-ready.config.ts +127 -0
- package/src/lib/life-ready.module.ts +81 -0
- package/src/lib/plan/plan.gql.ts +133 -0
- package/src/lib/plan/plan.service.spec.ts +294 -0
- package/src/lib/plan/plan.service.ts +198 -0
- package/src/lib/plan/plan.types.ts +37 -0
- package/src/lib/record/record-attachment.service.spec.ts +31 -0
- package/src/lib/record/record-attachment.service.ts +101 -0
- package/src/lib/record/record.gql.ts +192 -0
- package/src/lib/record/record.service.spec.ts +598 -0
- package/src/lib/record/record.service.ts +236 -0
- package/src/lib/record/record.types.ts +86 -0
- package/src/lib/record-type/record-type.service.spec.ts +16 -0
- package/src/lib/record-type/record-type.service.ts +71 -0
- package/src/lib/record-type/record-type.types.ts +58 -0
- package/src/lib/scenario/approvals/scenario-approval.gql.ts +112 -0
- package/src/lib/scenario/approvals/scenario-approval.types.ts +85 -0
- package/src/lib/scenario/approvals/scenario-approver.service.spec.ts +16 -0
- package/src/lib/scenario/approvals/scenario-approver.service.ts +422 -0
- package/src/lib/scenario/claimants/scenario-claimant.gql.ts +56 -0
- package/src/lib/scenario/claimants/scenario-claimant.service.spec.ts +16 -0
- package/src/lib/scenario/claimants/scenario-claimant.service.ts +100 -0
- package/src/lib/scenario/claimants/scenario-claimant.types.ts +21 -0
- package/src/lib/scenario/receivers/scenario-receiver.gql.ts +157 -0
- package/src/lib/scenario/receivers/scenario-receiver.service.spec.ts +16 -0
- package/src/lib/scenario/receivers/scenario-receiver.service.ts +278 -0
- package/src/lib/scenario/receivers/scenario-receiver.types.ts +66 -0
- package/src/lib/scenario/scenario-setup.service.spec.ts +22 -0
- package/src/lib/scenario/scenario-setup.service.ts +369 -0
- package/src/lib/scenario/scenario.gql.ts +404 -0
- package/src/lib/scenario/scenario.service.spec.ts +1586 -0
- package/src/lib/scenario/scenario.service.ts +811 -0
- package/src/lib/scenario/scenario.types.ts +258 -0
- package/src/lib/search/search.gql.ts +62 -0
- package/src/lib/search/search.service.spec.ts +57 -0
- package/src/lib/search/search.service.ts +174 -0
- package/src/lib/search/search.types.ts +24 -0
- package/src/lib/trusted-parties/tp-password-reset-request.service.ts +140 -0
- package/src/lib/trusted-parties/tp-password-reset-user.service.ts +359 -0
- package/src/lib/trusted-parties/tp-password-reset.gql.ts +453 -0
- package/src/lib/trusted-parties/tp-password-reset.service.spec.ts +602 -0
- package/src/lib/trusted-parties/tp-password-reset.service.ts +482 -0
- package/src/lib/trusted-parties/trusted-party.gql.ts +159 -0
- package/src/lib/trusted-parties/trusted-party.service.spec.ts +1008 -0
- package/src/lib/trusted-parties/trusted-party.service.ts +394 -0
- package/src/lib/trusted-parties/trusted-party.types.ts +119 -0
- package/src/lib/trusted-parties/trusted-party2.gql.ts +165 -0
- package/src/lib/trusted-parties/trusted-party2.service.spec.ts +1782 -0
- package/src/lib/trusted-parties/trusted-party2.service.ts +272 -0
- package/src/lib/users/profile-details.service.spec.ts +45 -0
- package/src/lib/users/profile-details.service.ts +278 -0
- package/src/lib/users/profile.gql.ts +108 -0
- package/src/lib/users/profile.service.spec.ts +97 -0
- package/src/lib/users/profile.service.ts +224 -0
- package/src/lib/users/profile.types.ts +101 -0
- package/src/lib/users/user.gql.ts +69 -0
- package/src/lib/users/user.service.spec.ts +161 -0
- package/src/lib/users/user.service.ts +72 -0
- package/src/lib/users/user.types.ts +27 -0
- package/{public-api.d.ts → src/public-api.ts} +96 -77
- package/src/test.ts +21 -0
- package/tsconfig.lib.json +21 -0
- package/tsconfig.lib.prod.json +6 -0
- package/tsconfig.spec.json +10 -0
- package/tslint.json +17 -0
- package/bundles/lifeready-core.umd.js +0 -15876
- package/bundles/lifeready-core.umd.js.map +0 -1
- package/bundles/lifeready-core.umd.min.js +0 -16
- package/bundles/lifeready-core.umd.min.js.map +0 -1
- package/esm2015/lib/_common/ast.js +0 -40
- package/esm2015/lib/_common/deferred-promise.js +0 -24
- package/esm2015/lib/_common/exceptions.js +0 -157
- package/esm2015/lib/_common/queries.gql.js +0 -190
- package/esm2015/lib/_common/run-outside-angular.js +0 -79
- package/esm2015/lib/_common/types.js +0 -1
- package/esm2015/lib/_common/utils.js +0 -44
- package/esm2015/lib/api/contact-card.gql.js +0 -79
- package/esm2015/lib/api/contact-card.service.js +0 -154
- package/esm2015/lib/api/contact-card2.gql.js +0 -60
- package/esm2015/lib/api/contact-card2.service.js +0 -103
- package/esm2015/lib/api/file.service.js +0 -74
- package/esm2015/lib/api/item2.gql.js +0 -110
- package/esm2015/lib/api/item2.service.js +0 -311
- package/esm2015/lib/api/key-exchange.gql.js +0 -188
- package/esm2015/lib/api/key-exchange.service.js +0 -442
- package/esm2015/lib/api/key-exchange.types.js +0 -18
- package/esm2015/lib/api/key-exchange2.gql.js +0 -171
- package/esm2015/lib/api/key-exchange2.service.js +0 -479
- package/esm2015/lib/api/lock.gql.js +0 -40
- package/esm2015/lib/api/lock.service.js +0 -64
- package/esm2015/lib/api/lr-apollo.service.js +0 -46
- package/esm2015/lib/api/lr-graphql/index.js +0 -6
- package/esm2015/lib/api/lr-graphql/lr-graphql.service.js +0 -155
- package/esm2015/lib/api/lr-graphql/lr-merged-mutation.js +0 -213
- package/esm2015/lib/api/lr-graphql/lr-mutation-base.js +0 -51
- package/esm2015/lib/api/lr-graphql/lr-mutation.js +0 -48
- package/esm2015/lib/api/lr-graphql/lr.service.js +0 -18
- package/esm2015/lib/api/message.service.js +0 -138
- package/esm2015/lib/api/persist.service.js +0 -181
- package/esm2015/lib/api/query-processor/common-processors.service.js +0 -93
- package/esm2015/lib/api/query-processor/index.js +0 -3
- package/esm2015/lib/api/query-processor/query-processor.service.js +0 -192
- package/esm2015/lib/api/query-processor/tp-password-reset-processor.service.js +0 -109
- package/esm2015/lib/api/shared-contact-card.service.js +0 -119
- package/esm2015/lib/api/shared-contact-card2.gql.js +0 -41
- package/esm2015/lib/api/shared-contact-card2.service.js +0 -117
- package/esm2015/lib/api/time.service.js +0 -146
- package/esm2015/lib/api/types/graphql.types.js +0 -7
- package/esm2015/lib/api/types/index.js +0 -3
- package/esm2015/lib/api/types/lr-graphql.types.js +0 -71
- package/esm2015/lib/auth/auth.config.js +0 -57
- package/esm2015/lib/auth/auth.gql.js +0 -48
- package/esm2015/lib/auth/auth.types.js +0 -27
- package/esm2015/lib/auth/idle.service.js +0 -168
- package/esm2015/lib/auth/idle.types.js +0 -7
- package/esm2015/lib/auth/lbop.service.js +0 -355
- package/esm2015/lib/auth/life-ready-auth.service.js +0 -333
- package/esm2015/lib/auth/password.service.js +0 -320
- package/esm2015/lib/auth/register.service.js +0 -172
- package/esm2015/lib/auth/two-factor.service.js +0 -74
- package/esm2015/lib/category/category-meta.service.js +0 -99
- package/esm2015/lib/category/category.gql.js +0 -406
- package/esm2015/lib/category/category.service.js +0 -390
- package/esm2015/lib/category/category.types.js +0 -29
- package/esm2015/lib/cryptography/cryptography.types.js +0 -11
- package/esm2015/lib/cryptography/encryption.service.js +0 -189
- package/esm2015/lib/cryptography/key-factory.service.js +0 -237
- package/esm2015/lib/cryptography/key-graph.service.js +0 -280
- package/esm2015/lib/cryptography/key-meta.service.js +0 -200
- package/esm2015/lib/cryptography/key.service.js +0 -124
- package/esm2015/lib/cryptography/slip39.service.js +0 -169
- package/esm2015/lib/cryptography/web-crypto.service.js +0 -29
- package/esm2015/lib/life-ready.config.js +0 -84
- package/esm2015/lib/life-ready.module.js +0 -74
- package/esm2015/lib/plan/plan.gql.js +0 -123
- package/esm2015/lib/plan/plan.service.js +0 -149
- package/esm2015/lib/plan/plan.types.js +0 -11
- package/esm2015/lib/record/record-attachment.service.js +0 -101
- package/esm2015/lib/record/record.gql.js +0 -179
- package/esm2015/lib/record/record.service.js +0 -206
- package/esm2015/lib/record/record.types.js +0 -15
- package/esm2015/lib/record-type/record-type.service.js +0 -75
- package/esm2015/lib/record-type/record-type.types.js +0 -28
- package/esm2015/lib/scenario/approvals/scenario-approval.gql.js +0 -105
- package/esm2015/lib/scenario/approvals/scenario-approval.types.js +0 -1
- package/esm2015/lib/scenario/approvals/scenario-approver.service.js +0 -300
- package/esm2015/lib/scenario/claimants/scenario-claimant.gql.js +0 -52
- package/esm2015/lib/scenario/claimants/scenario-claimant.service.js +0 -97
- package/esm2015/lib/scenario/claimants/scenario-claimant.types.js +0 -1
- package/esm2015/lib/scenario/receivers/scenario-receiver.gql.js +0 -150
- package/esm2015/lib/scenario/receivers/scenario-receiver.service.js +0 -229
- package/esm2015/lib/scenario/receivers/scenario-receiver.types.js +0 -1
- package/esm2015/lib/scenario/scenario-setup.service.js +0 -269
- package/esm2015/lib/scenario/scenario.gql.js +0 -368
- package/esm2015/lib/scenario/scenario.service.js +0 -611
- package/esm2015/lib/scenario/scenario.types.js +0 -64
- package/esm2015/lib/search/search.gql.js +0 -62
- package/esm2015/lib/search/search.service.js +0 -156
- package/esm2015/lib/search/search.types.js +0 -6
- package/esm2015/lib/trusted-parties/tp-password-reset-request.service.js +0 -112
- package/esm2015/lib/trusted-parties/tp-password-reset-user.service.js +0 -266
- package/esm2015/lib/trusted-parties/tp-password-reset.gql.js +0 -232
- package/esm2015/lib/trusted-parties/tp-password-reset.service.js +0 -300
- package/esm2015/lib/trusted-parties/trusted-party.gql.js +0 -148
- package/esm2015/lib/trusted-parties/trusted-party.service.js +0 -326
- package/esm2015/lib/trusted-parties/trusted-party.types.js +0 -41
- package/esm2015/lib/trusted-parties/trusted-party2.gql.js +0 -87
- package/esm2015/lib/trusted-parties/trusted-party2.service.js +0 -215
- package/esm2015/lib/users/profile-details.service.js +0 -214
- package/esm2015/lib/users/profile.gql.js +0 -97
- package/esm2015/lib/users/profile.service.js +0 -169
- package/esm2015/lib/users/profile.types.js +0 -34
- package/esm2015/lib/users/user.gql.js +0 -60
- package/esm2015/lib/users/user.service.js +0 -79
- package/esm2015/lib/users/user.types.js +0 -5
- package/esm2015/lifeready-core.js +0 -10
- package/esm2015/public-api.js +0 -81
- package/fesm2015/lifeready-core.js +0 -13282
- package/fesm2015/lifeready-core.js.map +0 -1
- package/lib/_common/ast.d.ts +0 -11
- package/lib/_common/deferred-promise.d.ts +0 -12
- package/lib/_common/exceptions.d.ts +0 -109
- package/lib/_common/queries.gql.d.ts +0 -10
- package/lib/_common/run-outside-angular.d.ts +0 -14
- package/lib/_common/utils.d.ts +0 -3
- package/lib/api/contact-card.gql.d.ts +0 -7
- package/lib/api/contact-card.service.d.ts +0 -52
- package/lib/api/contact-card2.gql.d.ts +0 -34
- package/lib/api/contact-card2.service.d.ts +0 -49
- package/lib/api/file.service.d.ts +0 -18
- package/lib/api/item2.gql.d.ts +0 -96
- package/lib/api/item2.service.d.ts +0 -177
- package/lib/api/key-exchange.gql.d.ts +0 -9
- package/lib/api/key-exchange.service.d.ts +0 -39
- package/lib/api/key-exchange.types.d.ts +0 -196
- package/lib/api/key-exchange2.gql.d.ts +0 -125
- package/lib/api/key-exchange2.service.d.ts +0 -187
- package/lib/api/lock.gql.d.ts +0 -27
- package/lib/api/lock.service.d.ts +0 -25
- package/lib/api/lr-apollo.service.d.ts +0 -15
- package/lib/api/lr-graphql/lr-graphql.service.d.ts +0 -60
- package/lib/api/lr-graphql/lr-merged-mutation.d.ts +0 -27
- package/lib/api/lr-graphql/lr-mutation-base.d.ts +0 -28
- package/lib/api/lr-graphql/lr-mutation.d.ts +0 -8
- package/lib/api/lr-graphql/lr.service.d.ts +0 -9
- package/lib/api/message.service.d.ts +0 -58
- package/lib/api/persist.service.d.ts +0 -31
- package/lib/api/query-processor/common-processors.service.d.ts +0 -36
- package/lib/api/query-processor/query-processor.service.d.ts +0 -18
- package/lib/api/query-processor/tp-password-reset-processor.service.d.ts +0 -15
- package/lib/api/shared-contact-card.service.d.ts +0 -33
- package/lib/api/shared-contact-card2.gql.d.ts +0 -36
- package/lib/api/shared-contact-card2.service.d.ts +0 -45
- package/lib/api/time.service.d.ts +0 -16
- package/lib/api/types/graphql.types.d.ts +0 -29
- package/lib/api/types/lr-graphql.types.d.ts +0 -385
- package/lib/auth/auth.config.d.ts +0 -5
- package/lib/auth/auth.gql.d.ts +0 -15
- package/lib/auth/auth.types.d.ts +0 -66
- package/lib/auth/idle.service.d.ts +0 -40
- package/lib/auth/idle.types.d.ts +0 -10
- package/lib/auth/lbop.service.d.ts +0 -91
- package/lib/auth/life-ready-auth.service.d.ts +0 -46
- package/lib/auth/password.service.d.ts +0 -78
- package/lib/auth/register.service.d.ts +0 -25
- package/lib/auth/two-factor.service.d.ts +0 -15
- package/lib/category/category-meta.service.d.ts +0 -23
- package/lib/category/category.gql.d.ts +0 -45
- package/lib/category/category.service.d.ts +0 -67
- package/lib/category/category.types.d.ts +0 -79
- package/lib/cryptography/cryptography.types.d.ts +0 -83
- package/lib/cryptography/encryption.service.d.ts +0 -41
- package/lib/cryptography/key-factory.service.d.ts +0 -38
- package/lib/cryptography/key-graph.service.d.ts +0 -33
- package/lib/cryptography/key-meta.service.d.ts +0 -44
- package/lib/cryptography/key.service.d.ts +0 -36
- package/lib/cryptography/slip39.service.d.ts +0 -43
- package/lib/cryptography/web-crypto.service.d.ts +0 -5
- package/lib/life-ready.config.d.ts +0 -14
- package/lib/life-ready.module.d.ts +0 -5
- package/lib/plan/plan.gql.d.ts +0 -11
- package/lib/plan/plan.service.d.ts +0 -33
- package/lib/plan/plan.types.d.ts +0 -31
- package/lib/record/record-attachment.service.d.ts +0 -16
- package/lib/record/record.gql.d.ts +0 -14
- package/lib/record/record.service.d.ts +0 -25
- package/lib/record/record.types.d.ts +0 -57
- package/lib/record-type/record-type.service.d.ts +0 -11
- package/lib/record-type/record-type.types.d.ts +0 -50
- package/lib/scenario/approvals/scenario-approval.gql.d.ts +0 -7
- package/lib/scenario/approvals/scenario-approval.types.d.ts +0 -63
- package/lib/scenario/approvals/scenario-approver.service.d.ts +0 -32
- package/lib/scenario/claimants/scenario-claimant.gql.d.ts +0 -5
- package/lib/scenario/claimants/scenario-claimant.service.d.ts +0 -17
- package/lib/scenario/claimants/scenario-claimant.types.d.ts +0 -18
- package/lib/scenario/receivers/scenario-receiver.gql.d.ts +0 -8
- package/lib/scenario/receivers/scenario-receiver.service.d.ts +0 -30
- package/lib/scenario/receivers/scenario-receiver.types.d.ts +0 -54
- package/lib/scenario/scenario-setup.service.d.ts +0 -22
- package/lib/scenario/scenario.gql.d.ts +0 -34
- package/lib/scenario/scenario.service.d.ts +0 -58
- package/lib/scenario/scenario.types.d.ts +0 -217
- package/lib/search/search.gql.d.ts +0 -1
- package/lib/search/search.service.d.ts +0 -25
- package/lib/search/search.types.d.ts +0 -20
- package/lib/trusted-parties/tp-password-reset-request.service.d.ts +0 -20
- package/lib/trusted-parties/tp-password-reset-user.service.d.ts +0 -41
- package/lib/trusted-parties/tp-password-reset.gql.d.ts +0 -218
- package/lib/trusted-parties/tp-password-reset.service.d.ts +0 -131
- package/lib/trusted-parties/trusted-party.gql.d.ts +0 -9
- package/lib/trusted-parties/trusted-party.service.d.ts +0 -44
- package/lib/trusted-parties/trusted-party.types.d.ts +0 -102
- package/lib/trusted-parties/trusted-party2.gql.d.ts +0 -79
- package/lib/trusted-parties/trusted-party2.service.d.ts +0 -114
- package/lib/users/profile-details.service.d.ts +0 -21
- package/lib/users/profile.gql.d.ts +0 -11
- package/lib/users/profile.service.d.ts +0 -35
- package/lib/users/profile.types.d.ts +0 -96
- package/lib/users/user.gql.d.ts +0 -9
- package/lib/users/user.service.d.ts +0 -12
- package/lib/users/user.types.d.ts +0 -23
- package/lifeready-core.d.ts +0 -9
- package/lifeready-core.metadata.json +0 -1
|
@@ -0,0 +1,875 @@
|
|
|
1
|
+
import { Injectable, NgZone } from '@angular/core';
|
|
2
|
+
import { JWK } from 'node-jose';
|
|
3
|
+
import {
|
|
4
|
+
EncryptionService,
|
|
5
|
+
JoseSerialization,
|
|
6
|
+
} from '../cryptography/encryption.service';
|
|
7
|
+
import { KeyFactoryService } from '../cryptography/key-factory.service';
|
|
8
|
+
import { KeyGraphService } from '../cryptography/key-graph.service';
|
|
9
|
+
import { KeyService } from '../cryptography/key.service';
|
|
10
|
+
import { LrCodeMismatchException } from '../_common/exceptions';
|
|
11
|
+
import { RunOutsideAngular } from '../_common/run-outside-angular';
|
|
12
|
+
import { UserService } from './../users/user.service';
|
|
13
|
+
import { OwnerPlainDataJson } from './contact-card2.service';
|
|
14
|
+
import {
|
|
15
|
+
CancelKeyExchangeMutation,
|
|
16
|
+
CompleteKeyExchangeOtkMutation,
|
|
17
|
+
CurrentUserSharedKeyQuery2,
|
|
18
|
+
DeclineKeyExchangeMutation,
|
|
19
|
+
InitiateKeyExchangeOtkMutation,
|
|
20
|
+
KeyExchangeFragment,
|
|
21
|
+
KeyExchangeQuery2,
|
|
22
|
+
KeyExchangesQuery2,
|
|
23
|
+
KeyExchangeState2,
|
|
24
|
+
KeyExchangeTokenQuery2,
|
|
25
|
+
RespondKeyExchangeOtkMutation,
|
|
26
|
+
} from './key-exchange2.gql';
|
|
27
|
+
import { LrGraphQLService, LrMutation } from './lr-graphql';
|
|
28
|
+
import { ContactCardSharedCipherData, OtKeyCipherClearJson2 } from './types';
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* The decrypted content of the one-time key cipher;
|
|
32
|
+
* When user supplies this information the lib doesn't need to do another API call
|
|
33
|
+
* to fetch the key exchange node. And since the typical use case is to display
|
|
34
|
+
* some information to the user, the key exchange node would already have been
|
|
35
|
+
* fetched and decrypted.
|
|
36
|
+
*/
|
|
37
|
+
export interface DecryptedOtk2 {
|
|
38
|
+
otKeyCipherClearJson: OtKeyCipherClearJson2;
|
|
39
|
+
otKey: JWK.Key; // The one-time key
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export interface ContactCardReceiverCipherData {
|
|
43
|
+
// The receiver of the contact card keeps a copy
|
|
44
|
+
// of the owner's contact card information, encrypted using the receiver's keys. So that when
|
|
45
|
+
// the owner decides to update their shared contact card at a later date, the receiver can
|
|
46
|
+
// compare against the original contact card sent during key exchange. This way, the owner
|
|
47
|
+
// can't unilaterally update their shared contact card without the receiver knowing about it.
|
|
48
|
+
receiverCipherDataClearJson: any;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export interface ContactCardOwnerPlainData {
|
|
52
|
+
// Accessible by the server and the owner. Server side notification emails need to know some
|
|
53
|
+
// information about the owner.
|
|
54
|
+
// The owner could either be the initiator or the responder.
|
|
55
|
+
ownerPlainDataJson: OwnerPlainDataJson;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export interface ContactCardOwnerCipherData {
|
|
59
|
+
// Owner only access to this data
|
|
60
|
+
ownerCipherDataClearJson: any;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Sending contact card information from the owner to the receiver.
|
|
65
|
+
*/
|
|
66
|
+
export type SendContactCardInput = ContactCardOwnerPlainData &
|
|
67
|
+
ContactCardOwnerCipherData &
|
|
68
|
+
ContactCardSharedCipherData;
|
|
69
|
+
|
|
70
|
+
export interface InitiateOtkInput2 {
|
|
71
|
+
// Note that if neither email nor responderUsername are given, the one-time key
|
|
72
|
+
// can still be sent to the responder via OOB
|
|
73
|
+
email?: string;
|
|
74
|
+
message?: any;
|
|
75
|
+
contactCard?: SendContactCardInput;
|
|
76
|
+
// If True, to upgrade an email invite to an existing user invite if the email
|
|
77
|
+
// is already associated with an existing user.
|
|
78
|
+
upgrade?: boolean;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export interface RespondOtkInput2 {
|
|
82
|
+
keyExchangeId: string;
|
|
83
|
+
token: string;
|
|
84
|
+
decryptedOtk: DecryptedOtk2;
|
|
85
|
+
message?: any;
|
|
86
|
+
// The initiator is the owner fo the initiatorContactCard, the responder
|
|
87
|
+
// is the receiver.
|
|
88
|
+
initiatorContactCard?: ContactCardReceiverCipherData;
|
|
89
|
+
responderContactCard?: SendContactCardInput;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export interface CompleteOtkInput2 {
|
|
93
|
+
keyExchangeId: string;
|
|
94
|
+
// This is a part of the key exchange data. It's encrypted using the root key
|
|
95
|
+
initiatorRootKeyCipher: string;
|
|
96
|
+
// This is a part of the key exchange data. It's encrypted using the one-time key.
|
|
97
|
+
initiatorOneTimePbkCipher: string;
|
|
98
|
+
// The responder is the owner fo the responderContactCard, the initiator
|
|
99
|
+
// is the receiver.
|
|
100
|
+
responderContactCard?: ContactCardReceiverCipherData;
|
|
101
|
+
// The initiator can update the cipher data that are only visible to them. It makes
|
|
102
|
+
// less sense to update the shared data because the responder would have already seen
|
|
103
|
+
// the shared data and accepted that it's legit.
|
|
104
|
+
// But in any case, the initiator can update the shared contact card info at any time.
|
|
105
|
+
initiatorContactCard?: ContactCardOwnerCipherData;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export interface InitiatorRootKeyCipherClearJson2 {
|
|
109
|
+
nonce: string;
|
|
110
|
+
oneTimePrk: object; // one-time public encryption key responder use to send data back to initiator
|
|
111
|
+
otKey: object; // one-time symmetric key that needs to be shared OOB
|
|
112
|
+
initiatorContactCard?: ContactCardOwnerCipherData &
|
|
113
|
+
ContactCardSharedCipherData;
|
|
114
|
+
initiator: {
|
|
115
|
+
message?: any;
|
|
116
|
+
contactCard?: ContactCardSharedCipherData;
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export interface InitiatorOneTimePbkCipherClearJson {
|
|
121
|
+
nonce: string;
|
|
122
|
+
sharedKey: object;
|
|
123
|
+
mkSharedKey: object;
|
|
124
|
+
responder: {
|
|
125
|
+
pbk: object;
|
|
126
|
+
sigPbk: object;
|
|
127
|
+
message?: any;
|
|
128
|
+
contactCard?: ContactCardSharedCipherData & {
|
|
129
|
+
// Note that this is _not_ the same key as the sharedKey. The sharedKey wraps
|
|
130
|
+
// this key in the key graph. But because this key has not been entered into
|
|
131
|
+
// the key graph when the responder calls the API, we pass the JWK directly here.
|
|
132
|
+
sharedCipherKey: object;
|
|
133
|
+
};
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
export interface GetKeyExchangeOptions2 {
|
|
138
|
+
// The otKey as a raw string. i.e. key.toJSON(true).k
|
|
139
|
+
otKeyK?: string;
|
|
140
|
+
// User need the token if they have not responded to the key exchange yet.
|
|
141
|
+
// Once they've responded (hence proven they have the OOB Key) they become
|
|
142
|
+
// the "responder" of this exchange, and can access it when signed in.
|
|
143
|
+
token?: string;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
@RunOutsideAngular({
|
|
147
|
+
ngZoneName: 'ngZone',
|
|
148
|
+
})
|
|
149
|
+
@Injectable({
|
|
150
|
+
providedIn: 'root',
|
|
151
|
+
})
|
|
152
|
+
export class KeyExchange2Service {
|
|
153
|
+
private readonly CLIENT_NONCE_LENGTH = 32;
|
|
154
|
+
|
|
155
|
+
constructor(
|
|
156
|
+
private ngZone: NgZone,
|
|
157
|
+
private keyFactory: KeyFactoryService,
|
|
158
|
+
private keyService: KeyService,
|
|
159
|
+
private encryptionService: EncryptionService,
|
|
160
|
+
private userService: UserService,
|
|
161
|
+
private keyGraph: KeyGraphService,
|
|
162
|
+
private lrGraphQL: LrGraphQLService
|
|
163
|
+
) {}
|
|
164
|
+
|
|
165
|
+
private async getOtKey(
|
|
166
|
+
keyExchange: KeyExchangeFragment,
|
|
167
|
+
otKeyK?: string
|
|
168
|
+
): Promise<JWK.Key> {
|
|
169
|
+
if (otKeyK) {
|
|
170
|
+
return await KeyFactoryService.asKey({
|
|
171
|
+
...JSON.parse(keyExchange.otk.otKeyParams),
|
|
172
|
+
k: otKeyK,
|
|
173
|
+
});
|
|
174
|
+
} else if (
|
|
175
|
+
keyExchange.otk.state === 'OTK_INITIATED' &&
|
|
176
|
+
!keyExchange.isInitiator &&
|
|
177
|
+
keyExchange.otk.responderPbkCipher
|
|
178
|
+
) {
|
|
179
|
+
// Assuming existing user getting invited where OTK is wrapped in responder's public key.
|
|
180
|
+
const prk = await this.keyService.getCurrentPxk();
|
|
181
|
+
const decryptedCipher: any = await this.encryptionService.decrypt(
|
|
182
|
+
prk.jwk,
|
|
183
|
+
JSON.parse(keyExchange.otk.responderPbkCipher),
|
|
184
|
+
{
|
|
185
|
+
serializations: [JoseSerialization.COMPACT],
|
|
186
|
+
}
|
|
187
|
+
);
|
|
188
|
+
if (decryptedCipher.otKey) {
|
|
189
|
+
return await KeyFactoryService.asKey(decryptedCipher.otKey);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
return null;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
private async decryptOtk(
|
|
196
|
+
keyExchange: KeyExchangeFragment,
|
|
197
|
+
otKeyK?: string
|
|
198
|
+
): Promise<KeyExchangeFragment> {
|
|
199
|
+
const otKey = await this.getOtKey(keyExchange, otKeyK);
|
|
200
|
+
|
|
201
|
+
let otk = keyExchange.otk;
|
|
202
|
+
|
|
203
|
+
if (otKey && otk.otKeyCipher) {
|
|
204
|
+
otk = {
|
|
205
|
+
...otk,
|
|
206
|
+
otKey,
|
|
207
|
+
otKeyCipherClearJson: await this.encryptionService.decrypt(
|
|
208
|
+
otKey,
|
|
209
|
+
keyExchange.otk.otKeyCipher
|
|
210
|
+
),
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
return {
|
|
215
|
+
...keyExchange,
|
|
216
|
+
otk,
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
private async decryptResponseCipher(
|
|
221
|
+
otKey: JWK.Key,
|
|
222
|
+
otPrk: JWK.Key,
|
|
223
|
+
content: any
|
|
224
|
+
): Promise<InitiatorOneTimePbkCipherClearJson> {
|
|
225
|
+
// The response could be wrapped by the OtK in addition to the OtPbk
|
|
226
|
+
try {
|
|
227
|
+
content = await this.encryptionService.decrypt(otKey, content);
|
|
228
|
+
} catch (error) {
|
|
229
|
+
if (error.message !== 'no key found') {
|
|
230
|
+
throw error;
|
|
231
|
+
}
|
|
232
|
+
// Do nothing to support older versions where message is not wrapped with otk.
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
// The Prk is single-use and only used to send information from the responder back to the initiator.
|
|
236
|
+
return await this.encryptionService.decrypt(otPrk, content);
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
private async decryptKeyExchangeAsInitiator(
|
|
240
|
+
keyExchange: KeyExchangeFragment
|
|
241
|
+
): Promise<KeyExchangeFragment> {
|
|
242
|
+
const rootKey = await this.keyService.getCurrentRootKey();
|
|
243
|
+
|
|
244
|
+
// Decrypt using the root key to get the Prk
|
|
245
|
+
const initiatorRootKeyCipherClearJson = (await this.encryptionService.decrypt(
|
|
246
|
+
rootKey.jwk,
|
|
247
|
+
keyExchange.initiatorRootKeyCipher
|
|
248
|
+
)) as InitiatorRootKeyCipherClearJson2;
|
|
249
|
+
|
|
250
|
+
const otKey = await KeyFactoryService.asKey(
|
|
251
|
+
initiatorRootKeyCipherClearJson.otKey
|
|
252
|
+
);
|
|
253
|
+
|
|
254
|
+
keyExchange = {
|
|
255
|
+
...keyExchange,
|
|
256
|
+
initiatorRootKeyCipherClearJson,
|
|
257
|
+
};
|
|
258
|
+
|
|
259
|
+
let otk = keyExchange.otk;
|
|
260
|
+
|
|
261
|
+
if (otk.initiatorOneTimePbkCipher) {
|
|
262
|
+
otk = {
|
|
263
|
+
...otk,
|
|
264
|
+
initiatorOneTimePbkCipherClearJson: await this.decryptResponseCipher(
|
|
265
|
+
otKey,
|
|
266
|
+
await KeyFactoryService.asKey(
|
|
267
|
+
initiatorRootKeyCipherClearJson.oneTimePrk
|
|
268
|
+
),
|
|
269
|
+
otk.initiatorOneTimePbkCipher
|
|
270
|
+
),
|
|
271
|
+
};
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
if (otk.otKeyCipher) {
|
|
275
|
+
otk.otKeyCipherClearJson = await this.encryptionService.decrypt(
|
|
276
|
+
otKey,
|
|
277
|
+
otk.otKeyCipher
|
|
278
|
+
);
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
return {
|
|
282
|
+
...keyExchange,
|
|
283
|
+
otk,
|
|
284
|
+
};
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
private async decryptKeyExchangeAsResponder(
|
|
288
|
+
keyExchange: KeyExchangeFragment,
|
|
289
|
+
otKeyK?: string
|
|
290
|
+
) {
|
|
291
|
+
return this.decryptOtk(keyExchange, otKeyK);
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
async decryptKeyExchange(keyExchange: KeyExchangeFragment, otKeyK?: string) {
|
|
295
|
+
if (keyExchange.isInitiator) {
|
|
296
|
+
return this.decryptKeyExchangeAsInitiator(keyExchange);
|
|
297
|
+
} else {
|
|
298
|
+
return this.decryptKeyExchangeAsResponder(keyExchange, otKeyK);
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
async getKeyExchanges({ state }: { state?: KeyExchangeState2 } = {}) {
|
|
303
|
+
const { keyExchanges } = await this.lrGraphQL.query({
|
|
304
|
+
query: KeyExchangesQuery2,
|
|
305
|
+
variables: {
|
|
306
|
+
state,
|
|
307
|
+
},
|
|
308
|
+
});
|
|
309
|
+
|
|
310
|
+
return Promise.all(
|
|
311
|
+
keyExchanges.edges.map((edge) => this.decryptKeyExchange(edge.node))
|
|
312
|
+
);
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
/**
|
|
316
|
+
* @param id If the current user can responder the key exchange if they are either the initiator or the receiver.
|
|
317
|
+
* @param token If not signed in, or not the initiator or responder, 'token' must be given.
|
|
318
|
+
* @param otKeyK Is the raw one-time key (string). If the responder is explicitly specified at time of initiation, then
|
|
319
|
+
* it's possible to have the otKey wrapped by the public key of the responder. In which case, the otKeyK is not needed.
|
|
320
|
+
*/
|
|
321
|
+
async getKeyExchange(
|
|
322
|
+
id: string,
|
|
323
|
+
{ otKeyK, token }: GetKeyExchangeOptions2 = {}
|
|
324
|
+
) {
|
|
325
|
+
const res = await this.lrGraphQL.query({
|
|
326
|
+
query: token ? KeyExchangeTokenQuery2 : KeyExchangeQuery2,
|
|
327
|
+
variables: {
|
|
328
|
+
id,
|
|
329
|
+
token,
|
|
330
|
+
},
|
|
331
|
+
includeKeyGraph: !token, // if !token then we are post auth, so can fetch keyGraph
|
|
332
|
+
});
|
|
333
|
+
return this.decryptKeyExchange(res.keyExchange, otKeyK);
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
public async getCurrentUserSharedKey(input: {
|
|
337
|
+
username?: string;
|
|
338
|
+
userId?: string;
|
|
339
|
+
}) {
|
|
340
|
+
return this.lrGraphQL.query({
|
|
341
|
+
query: CurrentUserSharedKeyQuery2,
|
|
342
|
+
variables: {
|
|
343
|
+
username: input.username,
|
|
344
|
+
userId: input.userId,
|
|
345
|
+
},
|
|
346
|
+
});
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
// TODO: deprecate this
|
|
350
|
+
async cancelKeyExchange(id: string) {
|
|
351
|
+
return this.cancelKeyExchangeMutation(id);
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
cancelKeyExchangeMutation(id: string) {
|
|
355
|
+
return new LrMutation({
|
|
356
|
+
mutation: CancelKeyExchangeMutation,
|
|
357
|
+
variables: {
|
|
358
|
+
input: {
|
|
359
|
+
id,
|
|
360
|
+
},
|
|
361
|
+
},
|
|
362
|
+
});
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
// TODO: deprecate this
|
|
366
|
+
async declineKeyExchange(id: string, token: string) {
|
|
367
|
+
return this.declineKeyExchangeMutation(id, token);
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
declineKeyExchangeMutation(id: string, token: string) {
|
|
371
|
+
return new LrMutation({
|
|
372
|
+
mutation: DeclineKeyExchangeMutation,
|
|
373
|
+
variables: {
|
|
374
|
+
input: {
|
|
375
|
+
id,
|
|
376
|
+
token,
|
|
377
|
+
},
|
|
378
|
+
},
|
|
379
|
+
});
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
async initiateOtk({
|
|
383
|
+
message,
|
|
384
|
+
email,
|
|
385
|
+
contactCard,
|
|
386
|
+
upgrade,
|
|
387
|
+
}: InitiateOtkInput2 = {}) {
|
|
388
|
+
const otKey = await this.keyFactory.createKey();
|
|
389
|
+
const nonce = this.keyFactory.randomString(this.CLIENT_NONCE_LENGTH);
|
|
390
|
+
|
|
391
|
+
// New PKC key for encryption. This key is used only once when the responder sends
|
|
392
|
+
// back their signing public key.
|
|
393
|
+
const initiatorOneTimePrk = await this.keyFactory.createPkcKey();
|
|
394
|
+
|
|
395
|
+
// Option 1: New PKC key for signing
|
|
396
|
+
// const initiatorSigPrk = await this.keyService.createPkcSignKey();
|
|
397
|
+
|
|
398
|
+
// Option 2: Use the user's global signing key.
|
|
399
|
+
// This key is used to prove the initiator's identity.
|
|
400
|
+
const initiatorPrk = await this.keyService.getCurrentPxk();
|
|
401
|
+
const initiatorSigPrk = await this.keyService.getCurrentSigPxk();
|
|
402
|
+
|
|
403
|
+
let initiatorPlainDataSig: string = null;
|
|
404
|
+
|
|
405
|
+
if (contactCard && contactCard.ownerPlainDataJson) {
|
|
406
|
+
initiatorPlainDataSig = await this.encryptionService.signToString(
|
|
407
|
+
initiatorSigPrk.jwk,
|
|
408
|
+
contactCard.ownerPlainDataJson
|
|
409
|
+
);
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
const initiator = {
|
|
413
|
+
message,
|
|
414
|
+
contactCard: contactCard && {
|
|
415
|
+
sharedCipherDataClearJson: contactCard.sharedCipherDataClearJson,
|
|
416
|
+
},
|
|
417
|
+
};
|
|
418
|
+
|
|
419
|
+
// Content to be encrypted using the OTK.
|
|
420
|
+
const plainOtKeyCipher: OtKeyCipherClearJson2 = {
|
|
421
|
+
// TODO Make sure we also put the OOB code in here as well since the OOB code is the
|
|
422
|
+
// _only_ information the KC server does not have access to. The server may have
|
|
423
|
+
// access to OTK and hence the nonce here. It's good to have both the nonce and OOB code
|
|
424
|
+
// since the user may not be using the OOB code. And it's simple to always include
|
|
425
|
+
// the nonce, so why not.
|
|
426
|
+
nonce,
|
|
427
|
+
initiator: {
|
|
428
|
+
...initiator,
|
|
429
|
+
oneTimePbk: initiatorOneTimePrk.toJSON(), // one-time public encryption key responder use to send data back to initiator
|
|
430
|
+
pbk: initiatorPrk.jwk.toJSON(), // public encryption key
|
|
431
|
+
sigPbk: initiatorSigPrk.jwk.toJSON(), // public signing key
|
|
432
|
+
},
|
|
433
|
+
};
|
|
434
|
+
|
|
435
|
+
const otKeyCipher = await this.keyGraph.encryptToString(
|
|
436
|
+
otKey,
|
|
437
|
+
plainOtKeyCipher
|
|
438
|
+
);
|
|
439
|
+
|
|
440
|
+
// Content to be encrypted using the initiator's root key.
|
|
441
|
+
const initiatorRootKeyCipherClearJson: InitiatorRootKeyCipherClearJson2 = {
|
|
442
|
+
nonce,
|
|
443
|
+
oneTimePrk: initiatorOneTimePrk.toJSON(true),
|
|
444
|
+
// Should not need to keep this encrypted since we are using the global signing key.
|
|
445
|
+
// sigPrk: initiatorSigPrk.toJSON(true),
|
|
446
|
+
|
|
447
|
+
// Save it in case the initiator want to decode the otKeyCipher.
|
|
448
|
+
// Since the otKey is only used once, and that otKeyCipher contains only
|
|
449
|
+
// the public key of the initiator, it's safe just leave the otKey stored here.
|
|
450
|
+
otKey: otKey.toJSON(true),
|
|
451
|
+
// These should be storing information such as how the fields of the shared contact card is
|
|
452
|
+
// derived from the master contact card.
|
|
453
|
+
initiatorContactCard: contactCard,
|
|
454
|
+
initiator,
|
|
455
|
+
};
|
|
456
|
+
|
|
457
|
+
const rootKey = await this.keyService.getCurrentRootKey();
|
|
458
|
+
const initiatorRootKeyCipher = await this.keyGraph.encryptToString(
|
|
459
|
+
rootKey.jwk,
|
|
460
|
+
initiatorRootKeyCipherClearJson
|
|
461
|
+
);
|
|
462
|
+
|
|
463
|
+
// The raw OTK
|
|
464
|
+
const otKeyK: string = (otKey.toJSON(true) as any).k;
|
|
465
|
+
|
|
466
|
+
// API call
|
|
467
|
+
const lrMutation = new LrMutation({
|
|
468
|
+
mutation: InitiateKeyExchangeOtkMutation,
|
|
469
|
+
variables: {
|
|
470
|
+
input: {
|
|
471
|
+
// These will be stored on the server
|
|
472
|
+
initiatorRootKeyCipher,
|
|
473
|
+
initiatorPxkId: initiatorPrk.id,
|
|
474
|
+
initiatorSigPxkId: initiatorSigPrk.id,
|
|
475
|
+
// These will be sent to the responder
|
|
476
|
+
otKeyParams: JSON.stringify(otKey.toJSON()),
|
|
477
|
+
otKeyCipher,
|
|
478
|
+
sendEmail: email && {
|
|
479
|
+
email,
|
|
480
|
+
rawOtKey: otKeyK,
|
|
481
|
+
},
|
|
482
|
+
createTp: true,
|
|
483
|
+
initiatorPlainDataSig,
|
|
484
|
+
upgrade,
|
|
485
|
+
},
|
|
486
|
+
},
|
|
487
|
+
});
|
|
488
|
+
|
|
489
|
+
return { lrMutation, otKeyK };
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
async respondOtk({
|
|
493
|
+
keyExchangeId,
|
|
494
|
+
token,
|
|
495
|
+
decryptedOtk,
|
|
496
|
+
message,
|
|
497
|
+
initiatorContactCard,
|
|
498
|
+
responderContactCard,
|
|
499
|
+
}: RespondOtkInput2) {
|
|
500
|
+
const rootKey = await this.keyService.getCurrentRootKey();
|
|
501
|
+
|
|
502
|
+
const masterKeyId = this.keyService.getCurrentMasterKey().id;
|
|
503
|
+
const masterKey = await this.keyService.getCurrentMasterKey();
|
|
504
|
+
|
|
505
|
+
const sharedKey = await this.keyFactory.createKey();
|
|
506
|
+
const mkSharedKey = await this.keyFactory.createKey();
|
|
507
|
+
|
|
508
|
+
const rkWrappedSharedKey = await this.encryptionService.encrypt(
|
|
509
|
+
rootKey.jwk,
|
|
510
|
+
sharedKey.toJSON(true)
|
|
511
|
+
);
|
|
512
|
+
const mkWrappedMkSharedKey = await this.encryptionService.encrypt(
|
|
513
|
+
masterKey.jwk,
|
|
514
|
+
mkSharedKey.toJSON(true)
|
|
515
|
+
);
|
|
516
|
+
|
|
517
|
+
const initiatorOneTimePbk = await KeyFactoryService.asKey(
|
|
518
|
+
decryptedOtk.otKeyCipherClearJson.initiator.oneTimePbk
|
|
519
|
+
);
|
|
520
|
+
|
|
521
|
+
const initiatorPbk = await KeyFactoryService.asKey(
|
|
522
|
+
decryptedOtk.otKeyCipherClearJson.initiator.pbk
|
|
523
|
+
);
|
|
524
|
+
const initiatorSigPbk = await KeyFactoryService.asKey(
|
|
525
|
+
decryptedOtk.otKeyCipherClearJson.initiator.sigPbk
|
|
526
|
+
);
|
|
527
|
+
|
|
528
|
+
// Option 1: Using new Prk for each TP pair
|
|
529
|
+
// Create a new public signing key for the responder.
|
|
530
|
+
// const responderSigPrk = await this.keyService.createPkcSignKey()
|
|
531
|
+
// const rkWrappedResponderSigPrk = await this.encrypt(rootKey, responderSigPrk.toJSON(true));
|
|
532
|
+
|
|
533
|
+
// Option 2: Responder already has a signing Prk
|
|
534
|
+
const responderPrk = await this.keyService.getCurrentPxk();
|
|
535
|
+
const responderSigPrk = await this.keyService.getCurrentSigPxk();
|
|
536
|
+
|
|
537
|
+
const signedInitiatorPbk = await this.encryptionService.sign(
|
|
538
|
+
responderSigPrk.jwk,
|
|
539
|
+
initiatorPbk.toJSON()
|
|
540
|
+
);
|
|
541
|
+
const signedInitiatorSigPbk = await this.encryptionService.sign(
|
|
542
|
+
responderSigPrk.jwk,
|
|
543
|
+
initiatorSigPbk.toJSON()
|
|
544
|
+
);
|
|
545
|
+
|
|
546
|
+
const initiatorOneTimePbkCipherClearJson: InitiatorOneTimePbkCipherClearJson = {
|
|
547
|
+
nonce: decryptedOtk.otKeyCipherClearJson.nonce,
|
|
548
|
+
sharedKey: sharedKey.toJSON(true),
|
|
549
|
+
mkSharedKey: mkSharedKey.toJSON(true),
|
|
550
|
+
responder: {
|
|
551
|
+
pbk: responderPrk.jwk.toJSON(), // public key
|
|
552
|
+
sigPbk: responderSigPrk.jwk.toJSON(), // public key
|
|
553
|
+
message,
|
|
554
|
+
},
|
|
555
|
+
};
|
|
556
|
+
|
|
557
|
+
let receivedCardInput;
|
|
558
|
+
if (decryptedOtk.otKeyCipherClearJson.initiator.contactCard) {
|
|
559
|
+
// Set the info about the initiator to be the ones sent by the initiator. We need th responder to do the encryption here
|
|
560
|
+
// because the initiator does not have the shared key yet, and we want the responder to have a functional contact card after
|
|
561
|
+
// this exchange. The initiator can double check the contact details are correct and sign it when it completes the exchange.
|
|
562
|
+
const sharedCipherDataClearJson =
|
|
563
|
+
decryptedOtk.otKeyCipherClearJson.initiator.contactCard
|
|
564
|
+
.sharedCipherDataClearJson;
|
|
565
|
+
|
|
566
|
+
// Create keys
|
|
567
|
+
const receiverKey = await this.keyFactory.createKey();
|
|
568
|
+
const ccSharedKey = await this.keyFactory.createKey();
|
|
569
|
+
const sigPxk = await this.keyService.getCurrentSigPxk();
|
|
570
|
+
|
|
571
|
+
receivedCardInput = {
|
|
572
|
+
receiverWrappedKey: JSON.stringify(
|
|
573
|
+
await this.encryptionService.encrypt(
|
|
574
|
+
rootKey.jwk,
|
|
575
|
+
receiverKey.toJSON(true)
|
|
576
|
+
)
|
|
577
|
+
),
|
|
578
|
+
receiverWrappingKeyId: rootKey.id,
|
|
579
|
+
receiverCipherData: initiatorContactCard
|
|
580
|
+
? JSON.stringify(
|
|
581
|
+
await this.encryptionService.encrypt(
|
|
582
|
+
receiverKey,
|
|
583
|
+
initiatorContactCard.receiverCipherDataClearJson
|
|
584
|
+
)
|
|
585
|
+
)
|
|
586
|
+
: '',
|
|
587
|
+
sharedWrappedKey: JSON.stringify(
|
|
588
|
+
await this.encryptionService.encrypt(
|
|
589
|
+
sharedKey,
|
|
590
|
+
ccSharedKey.toJSON(true)
|
|
591
|
+
)
|
|
592
|
+
),
|
|
593
|
+
};
|
|
594
|
+
|
|
595
|
+
const sharedCipherData = await this.encryptionService.encrypt(
|
|
596
|
+
ccSharedKey,
|
|
597
|
+
sharedCipherDataClearJson
|
|
598
|
+
);
|
|
599
|
+
receivedCardInput.sharedCipherDataSig = JSON.stringify(
|
|
600
|
+
await this.encryptionService.sign(sigPxk.jwk, sharedCipherData)
|
|
601
|
+
);
|
|
602
|
+
receivedCardInput.sigPxkId = sigPxk.id;
|
|
603
|
+
|
|
604
|
+
initiatorOneTimePbkCipherClearJson.responder.contactCard = {
|
|
605
|
+
...initiatorOneTimePbkCipherClearJson.responder.contactCard,
|
|
606
|
+
sharedCipherKey: ccSharedKey.toJSON(true),
|
|
607
|
+
};
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
let responderCardInput;
|
|
611
|
+
if (responderContactCard) {
|
|
612
|
+
// Create keys
|
|
613
|
+
const ownerKey = await this.keyFactory.createKey();
|
|
614
|
+
const ccSharedKey = await this.keyFactory.createKey();
|
|
615
|
+
const sigPxk = await this.keyService.getCurrentSigPxk();
|
|
616
|
+
|
|
617
|
+
responderCardInput = {
|
|
618
|
+
ownerWrappedKey: JSON.stringify(
|
|
619
|
+
await this.encryptionService.encrypt(
|
|
620
|
+
rootKey.jwk,
|
|
621
|
+
ownerKey.toJSON(true)
|
|
622
|
+
)
|
|
623
|
+
),
|
|
624
|
+
ownerWrappingKeyId: rootKey.id,
|
|
625
|
+
ownerCipherData: responderContactCard.ownerCipherDataClearJson
|
|
626
|
+
? JSON.stringify(
|
|
627
|
+
await this.encryptionService.encrypt(
|
|
628
|
+
ownerKey,
|
|
629
|
+
responderContactCard.ownerCipherDataClearJson
|
|
630
|
+
)
|
|
631
|
+
)
|
|
632
|
+
: '',
|
|
633
|
+
|
|
634
|
+
sharedWrappedKey: JSON.stringify(
|
|
635
|
+
await this.encryptionService.encrypt(
|
|
636
|
+
sharedKey,
|
|
637
|
+
ccSharedKey.toJSON(true)
|
|
638
|
+
)
|
|
639
|
+
),
|
|
640
|
+
};
|
|
641
|
+
|
|
642
|
+
const sharedCipherData = await this.encryptionService.encrypt(
|
|
643
|
+
ccSharedKey,
|
|
644
|
+
responderContactCard.sharedCipherDataClearJson
|
|
645
|
+
);
|
|
646
|
+
responderCardInput.sharedCipherDataSig = JSON.stringify(
|
|
647
|
+
await this.encryptionService.sign(sigPxk.jwk, sharedCipherData)
|
|
648
|
+
);
|
|
649
|
+
responderCardInput.sigPxkId = sigPxk.id;
|
|
650
|
+
|
|
651
|
+
if (responderContactCard.ownerPlainDataJson) {
|
|
652
|
+
responderCardInput.ownerPlainDataSig = JSON.stringify(
|
|
653
|
+
await this.encryptionService.sign(
|
|
654
|
+
responderSigPrk.jwk,
|
|
655
|
+
responderContactCard.ownerPlainDataJson
|
|
656
|
+
)
|
|
657
|
+
);
|
|
658
|
+
}
|
|
659
|
+
|
|
660
|
+
// Contact card info readable by the initiator
|
|
661
|
+
initiatorOneTimePbkCipherClearJson.responder.contactCard = {
|
|
662
|
+
...initiatorOneTimePbkCipherClearJson.responder.contactCard,
|
|
663
|
+
sharedCipherDataClearJson:
|
|
664
|
+
responderContactCard.sharedCipherDataClearJson,
|
|
665
|
+
};
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
// Encrypt with one-time public key
|
|
669
|
+
let initiatorOneTimePbkCipher = await this.encryptionService.encrypt(
|
|
670
|
+
initiatorOneTimePbk,
|
|
671
|
+
initiatorOneTimePbkCipherClearJson
|
|
672
|
+
);
|
|
673
|
+
|
|
674
|
+
// Encrypt with the otk again to keep use of asymmetric keys to a minimum.
|
|
675
|
+
initiatorOneTimePbkCipher = await this.encryptionService.encrypt(
|
|
676
|
+
decryptedOtk.otKey,
|
|
677
|
+
initiatorOneTimePbkCipher
|
|
678
|
+
);
|
|
679
|
+
|
|
680
|
+
return new LrMutation({
|
|
681
|
+
mutation: RespondKeyExchangeOtkMutation,
|
|
682
|
+
variables: {
|
|
683
|
+
input: {
|
|
684
|
+
keyExchangeId,
|
|
685
|
+
keyExchangeToken: token,
|
|
686
|
+
rootKeyId: rootKey.id,
|
|
687
|
+
masterKeyId,
|
|
688
|
+
// These will be stored on the server
|
|
689
|
+
responderPxkId: responderPrk.id,
|
|
690
|
+
responderSigPxkId: responderSigPrk.id,
|
|
691
|
+
signedInitiatorPbk: JSON.stringify(signedInitiatorPbk),
|
|
692
|
+
signedInitiatorSigPbk: JSON.stringify(signedInitiatorSigPbk),
|
|
693
|
+
// rkWrappedInitiatorSigPbk: JSON.stringify(rkWrappedInitiatorSigPbk),
|
|
694
|
+
|
|
695
|
+
// Option 1: Using new Prk for each TP pair
|
|
696
|
+
// rkWrappedResponderSigPrk: JSON.stringify(rkWrappedResponderSigPrk),
|
|
697
|
+
rkWrappedSharedKey: JSON.stringify(rkWrappedSharedKey),
|
|
698
|
+
mkWrappedMkSharedKey: JSON.stringify(mkWrappedMkSharedKey),
|
|
699
|
+
// These will be sent to the initiator
|
|
700
|
+
initiatorOneTimePbkCipher: JSON.stringify(initiatorOneTimePbkCipher),
|
|
701
|
+
initiatorContactCard: receivedCardInput,
|
|
702
|
+
responderContactCard: responderCardInput,
|
|
703
|
+
},
|
|
704
|
+
},
|
|
705
|
+
});
|
|
706
|
+
}
|
|
707
|
+
|
|
708
|
+
async completeOtk({
|
|
709
|
+
keyExchangeId,
|
|
710
|
+
initiatorRootKeyCipher,
|
|
711
|
+
initiatorOneTimePbkCipher,
|
|
712
|
+
responderContactCard,
|
|
713
|
+
initiatorContactCard,
|
|
714
|
+
}: CompleteOtkInput2) {
|
|
715
|
+
const rootKey = await this.keyService.getCurrentRootKey();
|
|
716
|
+
const masterKey = await this.keyService.getCurrentMasterKey();
|
|
717
|
+
|
|
718
|
+
// Decrypt using the root key to get the Prk
|
|
719
|
+
const initiatorRootKeyCipherClearJson = (await this.encryptionService.decrypt(
|
|
720
|
+
rootKey.jwk,
|
|
721
|
+
initiatorRootKeyCipher
|
|
722
|
+
)) as InitiatorRootKeyCipherClearJson2;
|
|
723
|
+
|
|
724
|
+
// The Prk is single-use and only used to send information from the responder back to the initiator.
|
|
725
|
+
const plainInitiatorOneTimePbkCipher = await this.decryptResponseCipher(
|
|
726
|
+
await KeyFactoryService.asKey(initiatorRootKeyCipherClearJson.otKey),
|
|
727
|
+
await KeyFactoryService.asKey(initiatorRootKeyCipherClearJson.oneTimePrk),
|
|
728
|
+
initiatorOneTimePbkCipher
|
|
729
|
+
);
|
|
730
|
+
|
|
731
|
+
// Check the nonce match to ensure the responder was the one holding the OTK
|
|
732
|
+
if (
|
|
733
|
+
initiatorRootKeyCipherClearJson.nonce !==
|
|
734
|
+
plainInitiatorOneTimePbkCipher.nonce
|
|
735
|
+
) {
|
|
736
|
+
throw new LrCodeMismatchException(
|
|
737
|
+
'The nonce returned by responder does not match with the one created by the initiator.'
|
|
738
|
+
);
|
|
739
|
+
}
|
|
740
|
+
|
|
741
|
+
// Option 1: Assuming the signing key is unique between users.
|
|
742
|
+
// const initiatorSigPrk = await KFS.asKey(ke.plainInitiatorRootKeyCipher.sigPrk);
|
|
743
|
+
// const rkWrappedInitiatorSigPrk = await this.encrypt(rootKey, initiatorSigPrk.toJSON(true));
|
|
744
|
+
|
|
745
|
+
// Option 2: Use the user's global signing key.
|
|
746
|
+
// In this case the initiatorSigPrk is already a part of the key graph.
|
|
747
|
+
// So there's nothing to do here.
|
|
748
|
+
|
|
749
|
+
// Protected the signing public key of the responder.
|
|
750
|
+
const initiatorSigPrk = await this.keyService.getCurrentSigPxk();
|
|
751
|
+
const responderSigPbk = await KeyFactoryService.asKey(
|
|
752
|
+
plainInitiatorOneTimePbkCipher.responder.sigPbk
|
|
753
|
+
);
|
|
754
|
+
const responderPbk = await KeyFactoryService.asKey(
|
|
755
|
+
plainInitiatorOneTimePbkCipher.responder.pbk
|
|
756
|
+
);
|
|
757
|
+
|
|
758
|
+
const signedResponderPbk = await this.encryptionService.sign(
|
|
759
|
+
initiatorSigPrk.jwk,
|
|
760
|
+
responderPbk.toJSON()
|
|
761
|
+
);
|
|
762
|
+
const signedResponderSigPbk = await this.encryptionService.sign(
|
|
763
|
+
initiatorSigPrk.jwk,
|
|
764
|
+
responderSigPbk.toJSON()
|
|
765
|
+
);
|
|
766
|
+
|
|
767
|
+
const sharedKey = await KeyFactoryService.asKey(
|
|
768
|
+
plainInitiatorOneTimePbkCipher.sharedKey
|
|
769
|
+
);
|
|
770
|
+
const rkWrappedSharedKey = await this.encryptionService.encrypt(
|
|
771
|
+
rootKey.jwk,
|
|
772
|
+
sharedKey.toJSON(true)
|
|
773
|
+
);
|
|
774
|
+
|
|
775
|
+
const mkSharedKey = await KeyFactoryService.asKey(
|
|
776
|
+
plainInitiatorOneTimePbkCipher.mkSharedKey
|
|
777
|
+
);
|
|
778
|
+
const mkWrappedMkSharedKey = await this.encryptionService.encrypt(
|
|
779
|
+
masterKey.jwk,
|
|
780
|
+
mkSharedKey.toJSON(true)
|
|
781
|
+
);
|
|
782
|
+
|
|
783
|
+
let responderContactCardCipherInput;
|
|
784
|
+
if (responderContactCard) {
|
|
785
|
+
// Create key
|
|
786
|
+
const receiverKey = await this.keyFactory.createKey();
|
|
787
|
+
|
|
788
|
+
responderContactCardCipherInput = {
|
|
789
|
+
receiverWrappedKey: JSON.stringify(
|
|
790
|
+
await this.encryptionService.encrypt(
|
|
791
|
+
rootKey.jwk,
|
|
792
|
+
receiverKey.toJSON(true)
|
|
793
|
+
)
|
|
794
|
+
),
|
|
795
|
+
receiverWrappingKeyId: rootKey.id,
|
|
796
|
+
receiverCipherData: JSON.stringify(
|
|
797
|
+
await this.encryptionService.encrypt(
|
|
798
|
+
receiverKey,
|
|
799
|
+
responderContactCard.receiverCipherDataClearJson
|
|
800
|
+
)
|
|
801
|
+
),
|
|
802
|
+
};
|
|
803
|
+
}
|
|
804
|
+
|
|
805
|
+
// Get the data needed from the initiator's cipher data.
|
|
806
|
+
let initiatorContactCardCipherInput;
|
|
807
|
+
let initiatorContactCardSharedCipherInput;
|
|
808
|
+
if (initiatorRootKeyCipherClearJson.initiatorContactCard) {
|
|
809
|
+
// The initiatorContactCard created during the creation of the invite and encrypted using the initiator's
|
|
810
|
+
// root key
|
|
811
|
+
const initiatorContactCardFromInit =
|
|
812
|
+
initiatorRootKeyCipherClearJson.initiatorContactCard;
|
|
813
|
+
const ownerKey = await this.keyFactory.createKey();
|
|
814
|
+
const sharedCipherKey = await KeyFactoryService.asKey(
|
|
815
|
+
plainInitiatorOneTimePbkCipher.responder.contactCard.sharedCipherKey
|
|
816
|
+
);
|
|
817
|
+
|
|
818
|
+
const ownerWrappedKey = JSON.stringify(
|
|
819
|
+
await this.encryptionService.encrypt(rootKey.jwk, ownerKey.toJSON(true))
|
|
820
|
+
);
|
|
821
|
+
|
|
822
|
+
// Allow the initiatorContactCard parameter to override
|
|
823
|
+
const ownerCipherDataClearJson =
|
|
824
|
+
initiatorContactCard?.ownerCipherDataClearJson ||
|
|
825
|
+
initiatorContactCardFromInit.ownerCipherDataClearJson;
|
|
826
|
+
|
|
827
|
+
const ownerCipherData = ownerCipherDataClearJson
|
|
828
|
+
? await this.keyGraph.encryptToString(
|
|
829
|
+
ownerKey,
|
|
830
|
+
ownerCipherDataClearJson
|
|
831
|
+
)
|
|
832
|
+
: '';
|
|
833
|
+
|
|
834
|
+
initiatorContactCardCipherInput = {
|
|
835
|
+
ownerWrappedKey,
|
|
836
|
+
ownerWrappingKeyId: rootKey.id,
|
|
837
|
+
ownerCipherData,
|
|
838
|
+
};
|
|
839
|
+
|
|
840
|
+
initiatorContactCardSharedCipherInput = {
|
|
841
|
+
sigPxkId: initiatorSigPrk.id,
|
|
842
|
+
};
|
|
843
|
+
|
|
844
|
+
const sharedCipherData = await this.encryptionService.encrypt(
|
|
845
|
+
sharedCipherKey,
|
|
846
|
+
initiatorContactCardFromInit.sharedCipherDataClearJson
|
|
847
|
+
);
|
|
848
|
+
initiatorContactCardSharedCipherInput.sharedCipherDataSig = JSON.stringify(
|
|
849
|
+
await this.encryptionService.sign(initiatorSigPrk.jwk, sharedCipherData)
|
|
850
|
+
);
|
|
851
|
+
}
|
|
852
|
+
|
|
853
|
+
// TODO ideally we update the shared data in the contact card sent to the responder as well since that
|
|
854
|
+
// CC was created by the responder.
|
|
855
|
+
|
|
856
|
+
return new LrMutation({
|
|
857
|
+
mutation: CompleteKeyExchangeOtkMutation,
|
|
858
|
+
variables: {
|
|
859
|
+
input: {
|
|
860
|
+
keyExchangeId,
|
|
861
|
+
rootKeyId: rootKey.id,
|
|
862
|
+
masterKeyId: masterKey.id,
|
|
863
|
+
initiatorSigPxkId: initiatorSigPrk.id,
|
|
864
|
+
signedResponderPbk: JSON.stringify(signedResponderPbk),
|
|
865
|
+
signedResponderSigPbk: JSON.stringify(signedResponderSigPbk),
|
|
866
|
+
rkWrappedSharedKey: JSON.stringify(rkWrappedSharedKey),
|
|
867
|
+
mkWrappedMkSharedKey: JSON.stringify(mkWrappedMkSharedKey),
|
|
868
|
+
responderContactCardCipher: responderContactCardCipherInput,
|
|
869
|
+
initiatorContactCardCipher: initiatorContactCardCipherInput,
|
|
870
|
+
initiatorContactCardSharedCipher: initiatorContactCardSharedCipherInput,
|
|
871
|
+
},
|
|
872
|
+
},
|
|
873
|
+
});
|
|
874
|
+
}
|
|
875
|
+
}
|