Skip to content

Commit 79cd9ba

Browse files
committed
refactor!: put crypto layer additions into separate folder and rewrote getProvider function
BREAKING CHANGE: `getProvider` takes `ProviderIdentifier` type.
1 parent ac92ca3 commit 79cd9ba

8 files changed

+178
-198
lines changed

src/CryptoLayerKeyPair.ts

Lines changed: 0 additions & 158 deletions
This file was deleted.

src/CryptoPrivateKeyHandle.ts renamed to src/crypto-layer/CryptoAsymmetricKeyHandle.ts

Lines changed: 7 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,12 @@
11
import { serialize, type, validate } from "@js-soft/ts-serval";
22
import { KeyPairHandle, KeyPairSpec, Provider } from "@nmshd/rs-crypto-types";
3-
import { CryptoError } from "./CryptoError";
4-
import { CryptoErrorCode } from "./CryptoErrorCode";
3+
import { CryptoError } from "../CryptoError";
4+
import { CryptoErrorCode } from "../CryptoErrorCode";
5+
import { CryptoSerializable } from "../CryptoSerializable";
56
import { getProvider } from "./CryptoLayerProviders";
6-
import { CryptoSerializable } from "./CryptoSerializable";
77

8-
export interface ICryptoPrivateKeyHandle {
9-
keyPairHandle: KeyPairHandle;
10-
spec: KeyPairSpec;
11-
}
12-
13-
export interface ICryptoPrivateKeyHandleStatic {
14-
new (): ICryptoPrivateKeyHandle;
15-
fromNativeKey(key: any, spec: KeyPairSpec): Promise<ICryptoPrivateKeyHandle>;
16-
}
17-
18-
@type("CryptoPrivateKeyHandle")
19-
export class CryptoPrivateKeyHandle extends CryptoSerializable implements ICryptoPrivateKeyHandle {
8+
@type("CryptoAsymmetricKeyHandle")
9+
export class CryptoAsymmetricKeyHandle extends CryptoSerializable {
2010
@validate()
2111
@serialize()
2212
public spec: KeyPairSpec;
@@ -33,11 +23,11 @@ export class CryptoPrivateKeyHandle extends CryptoSerializable implements ICrypt
3323

3424
public keyPairHandle: KeyPairHandle;
3525

36-
public static from(value: any): CryptoPrivateKeyHandle {
26+
public static from(value: any): CryptoAsymmetricKeyHandle {
3727
return this.fromAny(value);
3828
}
3929

40-
public static override async postFrom(value: CryptoPrivateKeyHandle): Promise<CryptoPrivateKeyHandle> {
30+
public static override async postFrom(value: CryptoAsymmetricKeyHandle): Promise<CryptoAsymmetricKeyHandle> {
4131
const provider = getProvider(value.providerName);
4232
if (!provider) {
4333
throw new CryptoError(
File renamed without changes.

src/CryptoLayerProviders.ts renamed to src/crypto-layer/CryptoLayerProviders.ts

Lines changed: 19 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ import {
88
} from "@nmshd/rs-crypto-types";
99

1010
import { defaults } from "lodash";
11-
import { CryptoError } from "./CryptoError";
12-
import { CryptoErrorCode } from "./CryptoErrorCode";
11+
import { CryptoError } from "../CryptoError";
12+
import { CryptoErrorCode } from "../CryptoErrorCode";
1313
import { CryptoLayerConfig, CryptoLayerProviderFilter } from "./CryptoLayerConfig";
1414

1515
let PROVIDERS_BY_SECURITY: Map<SecurityLevel, Provider[]> | undefined = undefined;
@@ -110,37 +110,35 @@ export async function initCryptoLayerProviders(config: CryptoLayerConfig): Promi
110110
PROVIDERS_BY_SECURITY = await providerBySecurityMapFromProviderByNameMap(PROVIDERS_BY_NAME);
111111
}
112112

113-
function isSecurityLevel(value: string): value is SecurityLevel {
114-
const securityLevels = ["Hardware", "Network", "Software", "Unsafe"];
115-
return securityLevels.includes(value);
116-
}
113+
export type ProviderIdentifier = Exclude<CryptoLayerProviderFilter, { providerConfig: any }>;
117114

118115
/**
119116
* Returns an initialized provider with the given name or security level if possible.
120117
*
121-
* This function is structured in a way that if `initCryptoLayerProviders()` was never called it always returns undefined.
122-
*
123-
* @param key Name of a provider or security level.
124-
* @returns `Provider` with security level or name if providers are initialized (with `initCryptoLayerProviders`).
125-
* `undefined` if providers where not initialized or if key is undefined.
126-
*
127-
* @throws `CryptoError` with `CryptoErrorCode.WrongParameters` if provider name or security level could not be matched to any provider
128-
* if providers have been initialized.
118+
* Returns `undefined` if providers are not initialized or provider asked for was not initialized by `initCryptoLayerProviders`.
129119
*/
130-
export function getProvider(key: string | SecurityLevel | undefined): Provider | undefined {
131-
if (!key) {
120+
export function getProvider(identifier: ProviderIdentifier): Provider | undefined {
121+
if (!PROVIDERS_BY_NAME || !PROVIDERS_BY_SECURITY) {
132122
return undefined;
133123
}
134124

135-
if (!PROVIDERS_BY_NAME || !PROVIDERS_BY_SECURITY) {
136-
return undefined;
125+
if ("providerName" in identifier) {
126+
return PROVIDERS_BY_NAME.get(identifier.providerName);
127+
}
128+
if ("securityLevel" in identifier) {
129+
return PROVIDERS_BY_SECURITY.get(identifier.securityLevel)?.[0];
137130
}
138131

139-
const provider = isSecurityLevel(key) ? PROVIDERS_BY_SECURITY.get(key)?.[0] : PROVIDERS_BY_NAME.get(key);
132+
throw new CryptoError(CryptoErrorCode.WrongParameters);
133+
}
140134

135+
export function getProviderOrThrow(identifier: ProviderIdentifier): Provider {
136+
const provider = getProvider(identifier);
141137
if (!provider) {
142-
throw new CryptoError(CryptoErrorCode.WrongParameters, `No such provider with name or security level: ${key}`);
138+
throw new CryptoError(
139+
CryptoErrorCode.WrongParameters,
140+
`Failed finding provider with name or security level ${identifier}`
141+
);
143142
}
144-
145143
return provider;
146144
}

src/crypto-layer/CryptoLayerUtils.ts

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
/* eslint-disable @typescript-eslint/naming-convention */
2+
import { AsymmetricKeySpec, CryptoHash, KeyPairHandle, KeyPairSpec, Provider } from "@nmshd/rs-crypto-types";
3+
import { defaults } from "lodash";
4+
import { CoreBuffer } from "../CoreBuffer";
5+
import { CryptoError } from "../CryptoError";
6+
import { CryptoErrorCode } from "../CryptoErrorCode";
7+
import { CryptoExchangeAlgorithm } from "../exchange/CryptoExchange";
8+
import { CryptoHashAlgorithm } from "../hash/CryptoHash";
9+
import { CryptoSignatureAlgorithm } from "../signature/CryptoSignatureAlgorithm";
10+
import { getProviderOrThrow, ProviderIdentifier } from "./CryptoLayerProviders";
11+
12+
export const DEFAULT_KEY_PAIR_SPEC: KeyPairSpec = {
13+
asym_spec: "P256",
14+
cipher: "AesGcm256",
15+
signing_hash: "Sha2_512",
16+
ephemeral: false,
17+
non_exportable: false
18+
};
19+
20+
export function asymSpecFromCryptoAlgorithm(
21+
algorithm: CryptoExchangeAlgorithm | CryptoSignatureAlgorithm
22+
): AsymmetricKeySpec {
23+
switch (algorithm) {
24+
case CryptoExchangeAlgorithm.ECDH_P256:
25+
return "P256";
26+
case CryptoExchangeAlgorithm.ECDH_P521:
27+
return "P521";
28+
case CryptoExchangeAlgorithm.ECDH_X25519:
29+
return "Curve25519";
30+
case CryptoSignatureAlgorithm.ECDSA_P256:
31+
return "P256";
32+
case CryptoSignatureAlgorithm.ECDSA_P521:
33+
return "P521";
34+
case CryptoSignatureAlgorithm.ECDSA_ED25519:
35+
return "Curve25519";
36+
}
37+
}
38+
39+
export function cryptoHashFromCryptoHashAlgorithm(algorithm: CryptoHashAlgorithm): CryptoHash {
40+
switch (algorithm) {
41+
case CryptoHashAlgorithm.SHA256:
42+
return "Sha2_256";
43+
case CryptoHashAlgorithm.SHA512:
44+
return "Sha2_512";
45+
case CryptoHashAlgorithm.BLAKE2B:
46+
throw new CryptoError(CryptoErrorCode.CalUnsupportedAlgorithm);
47+
}
48+
}
49+
50+
export class CryptoLayerUtils {
51+
/**
52+
* Returns a provider and a key pair handle from default key spec and a raw private key.
53+
*
54+
* @param providerIdent An identifier of an initialized provider.
55+
* @param privateKeyBuffer The raw private key.
56+
* @param specOverride Override default key pair spec.
57+
* @returns Tuple with provider and handle to key pair.
58+
*
59+
* @throws `CryptoErrorCode.WrongParameters` if providerIdent does not match any initialized providers or if provider cannot import key pair.
60+
*/
61+
public static async providerAndKeyPairFromPrivateBuffer(
62+
providerIdent: ProviderIdentifier,
63+
privateKeyBuffer: CoreBuffer,
64+
specOverride: Partial<KeyPairSpec>
65+
): Promise<[Provider, KeyPairHandle]> {
66+
const provider = getProviderOrThrow(providerIdent);
67+
const spec = defaults(specOverride, DEFAULT_KEY_PAIR_SPEC);
68+
const keyPair = await provider.importKeyPair(spec, new Uint8Array(0), privateKeyBuffer.buffer);
69+
return [provider, keyPair];
70+
}
71+
72+
public static async providerAndKeyPairFromPrivateBufferWithAlgorithm(
73+
providerIdent: ProviderIdentifier,
74+
privateKeyBuffer: CoreBuffer,
75+
asymmetricAlgorithm?: CryptoExchangeAlgorithm | CryptoSignatureAlgorithm,
76+
hashAlgorithm?: CryptoHashAlgorithm
77+
): Promise<[Provider, KeyPairHandle]> {
78+
const override: Partial<KeyPairSpec> = {
79+
asym_spec: asymmetricAlgorithm ? asymSpecFromCryptoAlgorithm(asymmetricAlgorithm) : undefined,
80+
signing_hash: hashAlgorithm ? cryptoHashFromCryptoHashAlgorithm(hashAlgorithm) : undefined
81+
};
82+
return await this.providerAndKeyPairFromPrivateBuffer(providerIdent, privateKeyBuffer, override);
83+
}
84+
85+
/**
86+
* Returns a provider and a key pair handle from default key spec and a raw public key.
87+
*
88+
* @param providerIdent An identifier of an initialized provider.
89+
* @param privateKeyBuffer The raw public key.
90+
* @param specOverride Override default key pair spec.
91+
* @returns Tuple with provider and handle to key pair.
92+
*
93+
* @throws `CryptoErrorCode.WrongParameters` if providerIdent does not match any initialized providers or if provider cannot import key pair.
94+
*/
95+
public static async providerAndKeyPairFromPublicBuffer(
96+
providerIdent: ProviderIdentifier,
97+
publicKeyBuffer: CoreBuffer,
98+
specOverride: Partial<KeyPairSpec>
99+
): Promise<[Provider, KeyPairHandle]> {
100+
const provider = getProviderOrThrow(providerIdent);
101+
const spec = defaults(specOverride, DEFAULT_KEY_PAIR_SPEC);
102+
const keyPair = await provider.importPublicKey(spec, publicKeyBuffer.buffer);
103+
return [provider, keyPair];
104+
}
105+
106+
public static async providerAndKeyPairFromPublicBufferWithAlgorithm(
107+
providerIdent: ProviderIdentifier,
108+
privateKeyBuffer: CoreBuffer,
109+
asymmetricAlgorithm?: CryptoExchangeAlgorithm | CryptoSignatureAlgorithm,
110+
hashAlgorithm?: CryptoHashAlgorithm
111+
): Promise<CryptoLayerUtils> {
112+
const override: Partial<KeyPairSpec> = {
113+
asym_spec: asymmetricAlgorithm ? asymSpecFromCryptoAlgorithm(asymmetricAlgorithm) : undefined,
114+
signing_hash: hashAlgorithm ? cryptoHashFromCryptoHashAlgorithm(hashAlgorithm) : undefined
115+
};
116+
return await this.providerAndKeyPairFromPublicBuffer(providerIdent, privateKeyBuffer, override);
117+
}
118+
}

0 commit comments

Comments
 (0)