generated from TBD54566975/tbd-project-template
-
Notifications
You must be signed in to change notification settings - Fork 57
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
70 changed files
with
8,001 additions
and
5,255 deletions.
There are no files selected for viewing
This file contains 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
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains 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 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 |
---|---|---|
@@ -1,49 +1,64 @@ | ||
import { universalTypeOf } from '@web5/common'; | ||
|
||
import type { Web5Crypto } from '../../types/web5-crypto.js'; | ||
import type { JwkOperation, PrivateKeyJwk } from '../../jose.js'; | ||
|
||
import { Jose } from '../../jose.js'; | ||
import { InvalidAccessError } from '../errors.js'; | ||
import { checkRequiredProperty } from '../../utils.js'; | ||
import { CryptoAlgorithm } from '../crypto-algorithm.js'; | ||
import { InvalidAccessError, OperationError } from '../errors.js'; | ||
|
||
export abstract class BaseAesAlgorithm extends CryptoAlgorithm { | ||
|
||
public checkGenerateKey(options: { | ||
public checkGenerateKeyOptions(options: { | ||
algorithm: Web5Crypto.AesGenerateKeyOptions, | ||
keyUsages: Web5Crypto.KeyUsage[] | ||
keyOperations: JwkOperation[] | ||
}): void { | ||
const { algorithm, keyUsages } = options; | ||
const { algorithm, keyOperations } = options; | ||
|
||
// Algorithm specified in the operation must match the algorithm implementation processing the operation. | ||
this.checkAlgorithmName({ algorithmName: algorithm.name }); | ||
// The algorithm object must contain a length property. | ||
checkRequiredProperty({ property: 'length', inObject: algorithm }); | ||
// The length specified must be a number. | ||
if (universalTypeOf(algorithm.length) !== 'Number') { | ||
throw new TypeError(`Algorithm 'length' is not of type: Number.`); | ||
|
||
// If specified, key operations must be permitted by the algorithm implementation processing the operation. | ||
if (keyOperations) { | ||
this.checkKeyOperations({ keyOperations, allowedKeyOperations: this.keyOperations }); | ||
} | ||
// The length specified must be one of the allowed bit lengths for AES. | ||
if (![128, 192, 256].includes(algorithm.length)) { | ||
throw new OperationError(`Algorithm 'length' must be 128, 192, or 256.`); | ||
} | ||
|
||
public checkSecretKey(options: { | ||
key: PrivateKeyJwk | ||
}): void { | ||
const { key } = options; | ||
|
||
// The options object must contain a key property. | ||
checkRequiredProperty({ property: 'key', inObject: options }); | ||
|
||
// The key object must be a JSON Web key (JWK). | ||
this.checkJwk({ key }); | ||
|
||
// The key object must be an octet sequence (oct) private key in JWK format. | ||
if (!Jose.isOctPrivateKeyJwk(key)) { | ||
throw new InvalidAccessError('Requested operation is only valid for oct private keys.'); | ||
} | ||
|
||
// If specified, the key's algorithm must match the algorithm implementation processing the operation. | ||
if (key.alg) { | ||
this.checkKeyAlgorithm({ keyAlgorithmName: key.alg }); | ||
} | ||
// The key usages specified must be permitted by the algorithm implementation processing the operation. | ||
this.checkKeyUsages({ keyUsages, allowedKeyUsages: this.keyUsages }); | ||
} | ||
|
||
public abstract generateKey(options: { | ||
algorithm: Web5Crypto.AesGenerateKeyOptions, | ||
extractable: boolean, | ||
keyUsages: Web5Crypto.KeyUsage[] | ||
}): Promise<Web5Crypto.CryptoKey>; | ||
keyOperations: JwkOperation[] | ||
}): Promise<PrivateKeyJwk>; | ||
|
||
public override async deriveBits(): Promise<Uint8Array> { | ||
throw new InvalidAccessError(`Requested operation 'deriveBits' is not valid for ${this.name} keys.`); | ||
throw new InvalidAccessError(`Requested operation 'deriveBits' is not valid for AES algorithm.`); | ||
} | ||
|
||
public override async sign(): Promise<Uint8Array> { | ||
throw new InvalidAccessError(`Requested operation 'sign' is not valid for ${this.name} keys.`); | ||
throw new InvalidAccessError(`Requested operation 'sign' is not valid for AES algorithm.`); | ||
} | ||
|
||
public override async verify(): Promise<boolean> { | ||
throw new InvalidAccessError(`Requested operation 'verify' is not valid for ${this.name} keys.`); | ||
throw new InvalidAccessError(`Requested operation 'verify' is not valid for AES algorithm.`); | ||
} | ||
} |
This file contains 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 |
---|---|---|
@@ -1,51 +1,96 @@ | ||
import { universalTypeOf } from '@web5/common'; | ||
|
||
import type { Web5Crypto } from '../../types/web5-crypto.js'; | ||
import type { JwkOperation, PrivateKeyJwk } from '../../jose.js'; | ||
|
||
import { BaseAesAlgorithm } from './base.js'; | ||
import { OperationError } from '../errors.js'; | ||
import { checkRequiredProperty } from '../../utils.js'; | ||
|
||
export abstract class BaseAesCtrAlgorithm extends BaseAesAlgorithm { | ||
|
||
public readonly name = 'AES-CTR'; | ||
|
||
public readonly keyUsages: Web5Crypto.KeyUsage[] = ['encrypt', 'decrypt', 'wrapKey', 'unwrapKey']; | ||
public readonly keyOperations: JwkOperation[] = ['encrypt', 'decrypt', 'wrapKey', 'unwrapKey']; | ||
|
||
public checkAlgorithmOptions(options: { | ||
algorithm: Web5Crypto.AesCtrOptions, | ||
key: Web5Crypto.CryptoKey | ||
algorithm: Web5Crypto.AesCtrOptions | ||
}): void { | ||
const { algorithm, key } = options; | ||
const { algorithm } = options; | ||
|
||
// Algorithm specified in the operation must match the algorithm implementation processing the operation. | ||
this.checkAlgorithmName({ algorithmName: algorithm.name }); | ||
|
||
// The algorithm object must contain a counter property. | ||
checkRequiredProperty({ property: 'counter', inObject: algorithm }); | ||
|
||
// The counter must a Uint8Array. | ||
if (!(universalTypeOf(algorithm.counter) === 'Uint8Array')) { | ||
throw new TypeError(`Algorithm 'counter' is not of type: Uint8Array.`); | ||
} | ||
|
||
// The initial value of the counter block must be 16 bytes long (the AES block size). | ||
if (algorithm.counter.byteLength !== 16) { | ||
throw new OperationError(`Algorithm 'counter' must have length: 16 bytes.`); | ||
} | ||
|
||
// The algorithm object must contain a length property. | ||
checkRequiredProperty({ property: 'length', inObject: algorithm }); | ||
|
||
// The length specified must be a number. | ||
if (universalTypeOf(algorithm.length) !== 'Number') { | ||
throw new TypeError(`Algorithm 'length' is not of type: Number.`); | ||
} | ||
|
||
// The length specified must be between 1 and 128. | ||
if ((algorithm.length < 1 || algorithm.length > 128)) { | ||
throw new OperationError(`Algorithm 'length' should be in the range: 1 to 128.`); | ||
} | ||
// The options object must contain a key property. | ||
checkRequiredProperty({ property: 'key', inObject: options }); | ||
// The key object must be a CryptoKey. | ||
this.checkCryptoKey({ key }); | ||
// The key algorithm must match the algorithm implementation processing the operation. | ||
this.checkKeyAlgorithm({ keyAlgorithmName: key.algorithm.name }); | ||
// The CryptoKey object must be a secret key. | ||
this.checkKeyType({ keyType: key.type, allowedKeyType: 'secret' }); | ||
} | ||
|
||
public checkDecryptOptions(options: { | ||
algorithm: Web5Crypto.AesCtrOptions, | ||
key: PrivateKeyJwk, | ||
data: Uint8Array | ||
}): void { | ||
const { algorithm, key, data } = options; | ||
|
||
// Validate the algorithm input parameters. | ||
this.checkAlgorithmOptions({ algorithm }); | ||
|
||
// Validate the secret key. | ||
this.checkSecretKey({ key }); | ||
|
||
// If specified, the secret key must be allowed to be used for 'decrypt' operations. | ||
if (key.key_ops) { | ||
this.checkKeyOperations({ keyOperations: ['decrypt'], allowedKeyOperations: key.key_ops }); | ||
} | ||
|
||
// The data must be a Uint8Array. | ||
if (universalTypeOf(data) !== 'Uint8Array') { | ||
throw new TypeError('The data must be of type Uint8Array.'); | ||
} | ||
} | ||
|
||
public checkEncryptOptions(options: { | ||
algorithm: Web5Crypto.AesCtrOptions, | ||
key: PrivateKeyJwk, | ||
data: Uint8Array | ||
}): void { | ||
const { algorithm, key, data } = options; | ||
|
||
// Validate the algorithm and key input parameters. | ||
this.checkAlgorithmOptions({ algorithm }); | ||
|
||
// Validate the secret key. | ||
this.checkSecretKey({ key }); | ||
|
||
// If specified, the secret key must be allowed to be used for 'encrypt' operations. | ||
if (key.key_ops) { | ||
this.checkKeyOperations({ keyOperations: ['encrypt'], allowedKeyOperations: key.key_ops }); | ||
} | ||
|
||
// The data must be a Uint8Array. | ||
if (universalTypeOf(data) !== 'Uint8Array') { | ||
throw new TypeError('The data must be of type Uint8Array.'); | ||
} | ||
} | ||
} |
Oops, something went wrong.