-
Notifications
You must be signed in to change notification settings - Fork 0
cal integration #36
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Closed
Closed
cal integration #36
Changes from all commits
Commits
Show all changes
32 commits
Select commit
Hold shift + click to select a range
4faea8e
Feature/crypto layer secret key handle (#33)
WyvernIXTL 817f9bb
Merge branch 'main' into feature/cal-integration
jkoenig134 50bd8bb
Merge branch 'main' into feature/cal-integration
jkoenig134 b058a83
Cleanup cal branch (#37)
jkoenig134 2cac5b7
Merge branch 'main' into feature/cal-integration
jkoenig134 45df57f
Remove serialization for derived key handles, remove keySpec property…
WyvernIXTL 8d46218
Merge branch 'main' into feature/cal-integration
jkoenig134 72a9d97
feat: cal provider scope
WyvernIXTL 8f589f4
refactor!: changed crypto layer init
WyvernIXTL 781824f
chore: bump rs-crypto-types to v0.11.0 and rs-crypto-node to v0.14.0
WyvernIXTL 781f5a7
feat: implemented provider initialization that is reproducable via a …
WyvernIXTL 9eafe2c
feat: added clear providers function
WyvernIXTL 9f97815
fix: wrong imports
WyvernIXTL 54114d3
fix: wrong import in tests
WyvernIXTL 6428fa7
feat!: handle provider creation
WyvernIXTL 5461a91
fix: eslint error due to not exhaustive switch
WyvernIXTL 9389086
test: signature key pair creation and loading
WyvernIXTL fc8f36d
test: provider creation
WyvernIXTL 6aa68d0
fix: providers to be initialized wrong serialize implementation
WyvernIXTL 7ebdc59
refactor!: renamed CryptoLayerProviderToBeInitialized to ProviderInit…
WyvernIXTL 7ddd32d
fix!: replaced key handles with custom serializable in providers to b…
WyvernIXTL 491036e
feat: added functions to retreive stored key count and metadata of a …
WyvernIXTL 399fdc0
removed!: AES CBC algorithm
WyvernIXTL 41cf83c
refactor!: clarified config classes, variable names and provider init…
WyvernIXTL 3f1a4c6
docs: added comment regarding the use of mocks for testing provider i…
WyvernIXTL 884f835
removed!: ChaCha20 algorithm
WyvernIXTL 7a68ce7
chore: merge main into feature/cal-integration
WyvernIXTL 69d236b
chore: pruned package lock via npm prune
WyvernIXTL 748d6c1
fix: eslint error due to console log in test setup
WyvernIXTL 29ee192
fix: update dependencies with vulnerabilities
WyvernIXTL 47681f3
fix: remove comment in webpack.test.config.js
WyvernIXTL daa96b2
chore: removed dependency override and updated dependencies
WyvernIXTL File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -8,3 +8,7 @@ dist | |
| dist-test | ||
| lib-web | ||
| lib-esm | ||
| test_cal_db | ||
| .nyc_output | ||
| .nycrc | ||
| coverage | ||
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,168 @@ | ||
| /* eslint-disable @typescript-eslint/naming-convention */ | ||
| import { KDF, KeySpec } from "@nmshd/rs-crypto-types"; | ||
| import { CoreBuffer, ICoreBuffer } from "../CoreBuffer"; | ||
| import { CryptoDerivationAlgorithm } from "../CryptoDerivation"; | ||
| import { CryptoError } from "../CryptoError"; | ||
| import { CryptoErrorCode } from "../CryptoErrorCode"; | ||
| import { CryptoValidation } from "../CryptoValidation"; | ||
| import { CryptoEncryptionAlgorithm } from "../encryption/CryptoEncryption"; | ||
| import { CryptoHashAlgorithm } from "../hash/CryptoHash"; | ||
| import { CryptoLayerProviderIdentifier } from "./CryptoLayerConfig"; | ||
| import { getProvider } from "./CryptoLayerProviders"; | ||
| import { CryptoLayerUtils } from "./CryptoLayerUtils"; | ||
| import { BaseDerivedKeyHandle } from "./encryption/BaseDerivedKeyHandle"; | ||
| import { BaseKeyHandle } from "./encryption/BaseKeyHandle"; | ||
| import { CryptoEncryptionHandle } from "./encryption/CryptoEncryptionHandle"; | ||
| import { DeviceBoundDerivedKeyHandle } from "./encryption/DeviceBoundDerivedKeyHandle"; | ||
| import { DeviceBoundKeyHandle } from "./encryption/DeviceBoundKeyHandle"; | ||
| import { PortableDerivedKeyHandle } from "./encryption/PortableDerivedKeyHandle"; | ||
| import { PortableKeyHandle } from "./encryption/PortableKeyHandle"; | ||
|
|
||
| export interface DeriveKeyHandleFromPasswordParameters { | ||
| providerIdent: CryptoLayerProviderIdentifier; | ||
| password: ICoreBuffer; | ||
| salt: ICoreBuffer; | ||
| resultingKeyEncryptionAlgorithm: CryptoEncryptionAlgorithm; | ||
| resultingKeyHashAlgorithm: CryptoHashAlgorithm; | ||
| derivationAlgorithm: CryptoDerivationAlgorithm; | ||
| derivationIterations: number; | ||
| derivationMemoryLimit: number; | ||
| derivationParallelism: number; | ||
| } | ||
|
|
||
| export class CryptoDerivationHandle { | ||
| private static async deriveKeyHandleFromPassword<T extends BaseDerivedKeyHandle>( | ||
| constructor: new () => T, | ||
| derivationParameters: DeriveKeyHandleFromPasswordParameters, | ||
| keySpecOfResultingKey: KeySpec | ||
| ): Promise<T> { | ||
| CryptoValidation.checkBuffer(new CoreBuffer(derivationParameters.salt), 8, 64, "salt", true); | ||
|
|
||
| const provider = getProvider(derivationParameters.providerIdent); | ||
|
|
||
| const kdfParameters: KDF = CryptoLayerUtils.kdfFromCryptoDerivation( | ||
| derivationParameters.derivationAlgorithm, | ||
| derivationParameters.derivationIterations, | ||
| derivationParameters.derivationMemoryLimit, | ||
| derivationParameters.derivationParallelism | ||
| ); | ||
|
|
||
| let keyHandle; | ||
| try { | ||
| keyHandle = await provider.deriveKeyFromPassword( | ||
| derivationParameters.password.toUtf8(), | ||
| derivationParameters.salt.buffer, | ||
| keySpecOfResultingKey, | ||
| kdfParameters | ||
| ); | ||
| } catch (e) { | ||
| throw new CryptoError( | ||
| CryptoErrorCode.CalKeyDerivation, | ||
| `Provider ${await provider.providerName()} failed to derive key from password.`, | ||
| undefined, | ||
| e as Error, | ||
| CryptoDerivationHandle.deriveKeyHandleFromPassword | ||
| ); | ||
| } | ||
|
|
||
| return await CryptoEncryptionHandle._keyHandleFromProviderAndCalKeyHandle(constructor, provider, keyHandle); | ||
| } | ||
|
|
||
| /** | ||
| * Derive an ephemeral {@link DeviceBoundDerivedKeyHandle} from a password. | ||
| */ | ||
| public static async deriveDeviceBoundKeyHandleFromPassword( | ||
| parameters: DeriveKeyHandleFromPasswordParameters | ||
| ): Promise<DeviceBoundDerivedKeyHandle> { | ||
| const keySpec: KeySpec = { | ||
| cipher: CryptoLayerUtils.cipherFromCryptoEncryptionAlgorithm(parameters.resultingKeyEncryptionAlgorithm), | ||
| signing_hash: CryptoLayerUtils.cryptoHashFromCryptoHashAlgorithm(parameters.resultingKeyHashAlgorithm), | ||
| ephemeral: true, | ||
| non_exportable: true | ||
| }; | ||
|
|
||
| return await CryptoDerivationHandle.deriveKeyHandleFromPassword<DeviceBoundDerivedKeyHandle>( | ||
| DeviceBoundDerivedKeyHandle, | ||
| parameters, | ||
| keySpec | ||
| ); | ||
| } | ||
|
|
||
| /** | ||
| * Derive an ephemeral {@link PortableDerivedKeyHandle} from a password. | ||
| */ | ||
| public static async derivePortableKeyHandleFromPassword( | ||
| parameters: DeriveKeyHandleFromPasswordParameters | ||
| ): Promise<PortableDerivedKeyHandle> { | ||
| const keySpec: KeySpec = { | ||
| cipher: CryptoLayerUtils.cipherFromCryptoEncryptionAlgorithm(parameters.resultingKeyEncryptionAlgorithm), | ||
| signing_hash: CryptoLayerUtils.cryptoHashFromCryptoHashAlgorithm(parameters.resultingKeyHashAlgorithm), | ||
| ephemeral: true, | ||
| non_exportable: false | ||
| }; | ||
|
|
||
| return await CryptoDerivationHandle.deriveKeyHandleFromPassword<PortableDerivedKeyHandle>( | ||
| PortableDerivedKeyHandle, | ||
| parameters, | ||
| keySpec | ||
| ); | ||
| } | ||
|
|
||
| private static async deriveKeyFromBaseKeyHandle<T extends BaseKeyHandle, R extends BaseDerivedKeyHandle>( | ||
| constructor: new () => R, | ||
| baseKey: T, | ||
| keyId: number, | ||
| context: string | ||
| ): Promise<R> { | ||
| const bytes = CoreBuffer.fromUtf8(`id:${keyId};ctx:${context}`); | ||
|
|
||
| let keyHandle; | ||
| try { | ||
| keyHandle = await baseKey.keyHandle.deriveKey(bytes.buffer); | ||
| } catch (e) { | ||
| throw new CryptoError( | ||
| CryptoErrorCode.CalKeyDerivation, | ||
| `Failed to derive key from base key.`, | ||
| undefined, | ||
| e as Error, | ||
| CryptoDerivationHandle.deriveKeyFromBaseKeyHandle | ||
| ); | ||
| } | ||
|
|
||
| return await CryptoEncryptionHandle._keyHandleFromProviderAndCalKeyHandle( | ||
| constructor, | ||
| baseKey.provider, | ||
| keyHandle | ||
| ); | ||
| } | ||
|
|
||
| /** | ||
| * Derive an ephemeral {@link DeviceBoundDerivedKeyHandle} from a {@link DeviceBoundKeyHandle} with the same algorithms. | ||
| */ | ||
| public static async deriveDeviceBoundKeyHandle( | ||
| baseKey: DeviceBoundKeyHandle, | ||
| keyId: number, | ||
| context: string | ||
| ): Promise<DeviceBoundDerivedKeyHandle> { | ||
| return await CryptoDerivationHandle.deriveKeyFromBaseKeyHandle< | ||
| DeviceBoundKeyHandle, | ||
| DeviceBoundDerivedKeyHandle | ||
| >(DeviceBoundDerivedKeyHandle, baseKey, keyId, context); | ||
| } | ||
|
|
||
| /** | ||
| * Derive an ephemeral {@link PortableDerivedKeyHandle} from a {@link PortableKeyHandle} with the same algorithms. | ||
| */ | ||
| public static async derivePortableKeyHandle( | ||
| baseKey: PortableKeyHandle, | ||
| keyId: number, | ||
| context: string | ||
| ): Promise<PortableDerivedKeyHandle> { | ||
| return await CryptoDerivationHandle.deriveKeyFromBaseKeyHandle<PortableKeyHandle, PortableDerivedKeyHandle>( | ||
| PortableDerivedKeyHandle, | ||
| baseKey, | ||
| keyId, | ||
| context | ||
| ); | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,142 @@ | ||
| import { serialize, type, validate } from "@js-soft/ts-serval"; | ||
| import { AdditionalConfig, KeyHandle, KeyPairHandle, SecurityLevel } from "@nmshd/rs-crypto-types"; | ||
| import { CryptoSerializable } from "../CryptoSerializable"; | ||
| import { CryptoEncryptionAlgorithm } from "../encryption/CryptoEncryption"; | ||
| import { CryptoHashAlgorithm } from "../hash/CryptoHash"; | ||
| import { CryptoSignatureAlgorithm } from "../signature/CryptoSignatureAlgorithm"; | ||
| import { getProvider } from "./CryptoLayerProviders"; | ||
| import { DeviceBoundKeyHandle } from "./encryption/DeviceBoundKeyHandle"; | ||
| import { DeviceBoundKeyPairHandle } from "./signature/DeviceBoundKeyPairHandle"; | ||
|
|
||
| type KeyHandleType = "symmetric" | "asymmetric"; | ||
|
|
||
| interface IProviderInitConfigKeyHandle { | ||
| type: KeyHandleType; | ||
| keyId: string; | ||
| providerName: string; | ||
| } | ||
|
|
||
| /** | ||
| * Configuration for loading a key handle from a provider without loading on deserialization. | ||
| */ | ||
| @type("ProviderInitConfigKeyHandle") | ||
| export class ProviderInitConfigKeyHandle extends CryptoSerializable { | ||
| @validate() | ||
| @serialize() | ||
| public type: KeyHandleType; | ||
|
|
||
| @validate() | ||
| @serialize() | ||
| public keyId: string; | ||
|
|
||
| @validate() | ||
| @serialize() | ||
| public providerName: string; | ||
|
|
||
| public static from(value: IProviderInitConfigKeyHandle): ProviderInitConfigKeyHandle { | ||
| return ProviderInitConfigKeyHandle.fromAny(value); | ||
| } | ||
|
|
||
| public static fromDeviceBoundHandle( | ||
| handle: DeviceBoundKeyHandle | DeviceBoundKeyPairHandle | ||
| ): ProviderInitConfigKeyHandle { | ||
| return ProviderInitConfigKeyHandle.from({ | ||
| type: handle instanceof DeviceBoundKeyHandle ? "symmetric" : "asymmetric", | ||
| keyId: handle.id, | ||
| providerName: handle.providerName | ||
| }); | ||
| } | ||
|
|
||
| public async loadKeyHandle(): Promise<KeyHandle | KeyPairHandle> { | ||
| const provider = getProvider({ providerName: this.providerName }); | ||
|
|
||
| switch (this.type) { | ||
| case "asymmetric": | ||
| return await provider.loadKeyPair(this.keyId); | ||
| case "symmetric": | ||
| return await provider.loadKey(this.keyId); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| interface IProviderInitConfig { | ||
| providerName: string; | ||
| masterEncryptionKeyHandle?: ProviderInitConfigKeyHandle; | ||
| masterSignatureKeyHandle?: ProviderInitConfigKeyHandle; | ||
| requiredProvider?: ProviderInitConfig; | ||
| } | ||
|
|
||
| /** | ||
| * Recursive configuration used to load providers and their dependencies. | ||
| */ | ||
| @type("ProviderInitConfig") | ||
| export class ProviderInitConfig extends CryptoSerializable { | ||
| @validate() | ||
| @serialize() | ||
| public providerName: string; | ||
|
|
||
| @validate({ nullable: true }) | ||
| @serialize() | ||
| public masterEncryptionKeyHandle?: ProviderInitConfigKeyHandle; | ||
|
|
||
| @validate({ nullable: true }) | ||
| @serialize() | ||
| public masterSignatureKeyHandle?: ProviderInitConfigKeyHandle; | ||
|
|
||
| @validate({ nullable: true }) | ||
| @serialize() | ||
| public requiredProvider?: ProviderInitConfig; | ||
|
|
||
| public static from(value: IProviderInitConfig): ProviderInitConfig { | ||
| return ProviderInitConfig.fromAny(value); | ||
| } | ||
| } | ||
|
|
||
| // eslint-disable-next-line @typescript-eslint/naming-convention | ||
| export type StorageConfig = Extract<AdditionalConfig, { KVStoreConfig: any } | { FileStoreConfig: any }>; | ||
|
|
||
| export type CryptoLayerProviderIdentifier = | ||
| | { | ||
| providerName: string; | ||
| } | ||
| | { | ||
| securityLevel: SecurityLevel; | ||
| }; | ||
|
|
||
| export type StorageSecuritySpec = | ||
| | { | ||
| type: "asymmetric"; | ||
| asymmetricKeyAlgorithm: CryptoSignatureAlgorithm; | ||
| encryptionAlgorithm: CryptoEncryptionAlgorithm | undefined; | ||
| hashingAlgorithm: CryptoHashAlgorithm; | ||
| } | ||
| | { | ||
| type: "symmetric"; | ||
| encryptionAlgorithm: CryptoEncryptionAlgorithm; | ||
| hashingAlgorithm: CryptoHashAlgorithm; | ||
| }; | ||
|
|
||
| export interface StorageSecurityConfig { | ||
| name: string; | ||
| signature: StorageSecuritySpec; | ||
| encryption: StorageSecuritySpec; | ||
| } | ||
|
|
||
| export type KeyMetadata = | ||
| | { | ||
| id: string; | ||
| type: "symmetric"; | ||
| encryptionAlgorithm: CryptoEncryptionAlgorithm; | ||
| hashAlgorithm: CryptoHashAlgorithm; | ||
| deviceBound: boolean; | ||
| ephemeral: boolean; | ||
| } | ||
| | { | ||
| id: string; | ||
| type: "asymmetric"; | ||
| asymmetricKeyAlgorithm: CryptoSignatureAlgorithm; | ||
| encryptionAlgorithm?: CryptoEncryptionAlgorithm; | ||
| hashAlgorithm: CryptoHashAlgorithm; | ||
| deviceBound: boolean; | ||
| ephemeral: boolean; | ||
| }; |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.