Skip to content

Commit

Permalink
types: improve cipher types (margelo#247)
Browse files Browse the repository at this point in the history
  • Loading branch information
shamilovtim authored Apr 15, 2024
1 parent 55f55c2 commit 07b14c5
Show file tree
Hide file tree
Showing 4 changed files with 108 additions and 63 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@
"@types/chai": "^4.3.4",
"@types/jest": "^29.5.11",
"@types/mocha": "^10.0.1",
"@types/node": "^17.0.31",
"@types/node": "^20.12.7",
"@types/react": "^18.0.33",
"@types/readable-stream": "^4.0.11",
"eslint": "^8.4.1",
Expand Down
151 changes: 94 additions & 57 deletions src/Cipher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,21 +13,23 @@ import {
validateString,
validateUint32,
validateInt32,
type BinaryLikeNode,
} from './Utils';
import { type InternalCipher, RSAKeyVariant } from './NativeQuickCrypto/Cipher';
// TODO(osp) re-enable type specific constructors
// They are nice to have but not absolutely necessary
// import type {
// CipherCCMOptions,
// CipherCCMTypes,
// CipherGCMTypes,
// CipherGCMOptions,
// // CipherKey,
// // KeyObject,
// // TODO(Szymon) This types seem to be missing? Where did you get this definitions from?
// // CipherOCBTypes,
// // CipherOCBOptions,
// } from 'crypto'; // Node crypto typings
import type {
CipherCCMOptions,
CipherCCMTypes,
CipherGCMTypes,
CipherGCMOptions,
CipherOCBOptions,
CipherOCBTypes,
DecipherGCM,
DecipherOCB,
DecipherCCM,
CipherCCM,
CipherOCB,
CipherGCM,
} from 'crypto'; // @types/node
import { StringDecoder } from 'string_decoder';
import { Buffer } from '@craftzdog/react-native-buffer';
import { Buffer as SBuffer } from 'safe-buffer';
Expand Down Expand Up @@ -106,7 +108,7 @@ class CipherCommon extends Stream.Transform {

constructor(
cipherType: string,
cipherKey: BinaryLike,
cipherKey: BinaryLikeNode,
isCipher: boolean,
options: Record<string, any> = {},
iv?: BinaryLike | null
Expand Down Expand Up @@ -217,7 +219,7 @@ class CipherCommon extends Stream.Transform {
class Cipher extends CipherCommon {
constructor(
cipherType: string,
cipherKey: BinaryLike,
cipherKey: BinaryLikeNode,
options: Record<string, any> = {},
iv?: BinaryLike | null
) {
Expand All @@ -231,7 +233,7 @@ class Cipher extends CipherCommon {
class Decipher extends CipherCommon {
constructor(
cipherType: string,
cipherKey: BinaryLike,
cipherKey: BinaryLikeNode,
options: Record<string, any> = {},
iv?: BinaryLike | null
) {
Expand All @@ -243,66 +245,101 @@ class Decipher extends CipherCommon {
}
}

// TODO(osp) This definitions cause typescript errors when using the API
// export function createDecipher(
// algorithm: CipherCCMTypes,
// password: BinaryLike,
// options: CipherCCMOptions
// ): Decipher;
// export function createDecipher(
// algorithm: CipherGCMTypes,
// password: BinaryLike,
// options?: CipherGCMOptions
// ): Decipher;
export function createDecipher(
algorithm: CipherCCMTypes,
password: BinaryLikeNode,
options: CipherCCMOptions
): DecipherCCM;
export function createDecipher(
algorithm: CipherGCMTypes,
password: BinaryLikeNode,
options?: CipherGCMOptions
): DecipherGCM;
export function createDecipher(
algorithm: string,
password: BinaryLike,
options?: Record<string, unknown> | Stream.TransformOptions
): Decipher {
password: BinaryLikeNode,
options?: CipherCCMOptions | CipherGCMOptions | Stream.TransformOptions
): DecipherCCM | DecipherGCM | Decipher {
return new Decipher(algorithm, password, options);
}

// function createDecipheriv(algorithm: CipherCCMTypes, key: CipherKey, iv: BinaryLike, options: CipherCCMOptions): DecipherCCM;
// function createDecipheriv(algorithm: CipherOCBTypes, key: CipherKey, iv: BinaryLike, options: CipherOCBOptions): DecipherOCB;
// function createDecipheriv(algorithm: CipherGCMTypes, key: CipherKey, iv: BinaryLike, options?: CipherGCMOptions): DecipherGCM;
export function createDecipheriv(
algorithm: CipherCCMTypes,
key: BinaryLikeNode,
iv: BinaryLike,
options: CipherCCMOptions
): DecipherCCM;
export function createDecipheriv(
algorithm: CipherOCBTypes,
key: BinaryLikeNode,
iv: BinaryLike,
options: CipherOCBOptions
): DecipherOCB;
export function createDecipheriv(
algorithm: CipherGCMTypes,
key: BinaryLikeNode,
iv: BinaryLike,
options?: CipherGCMOptions
): DecipherGCM;
export function createDecipheriv(
algorithm: string,
key: BinaryLike,
key: BinaryLikeNode,
iv: BinaryLike | null,
options?: Record<string, unknown> | Stream.TransformOptions
): Decipher {
options?:
| CipherCCMOptions
| CipherOCBOptions
| CipherGCMOptions
| Stream.TransformOptions
): DecipherCCM | DecipherOCB | DecipherGCM | Decipher {
return new Decipher(algorithm, key, options, iv);
}

// TODO(osp) This definitions cause typescript errors when using the API
// commenting them out for now
// export function createCipher(
// algorithm: CipherCCMTypes,
// password: BinaryLike,
// options: CipherCCMOptions
// ): Cipher;
// export function createCipher(
// algorithm: CipherGCMTypes,
// password: BinaryLike,
// options?: CipherGCMOptions
// ): Cipher;
export function createCipher(
algorithm: CipherCCMTypes,
password: BinaryLikeNode,
options: CipherCCMOptions
): CipherCCM;
export function createCipher(
algorithm: CipherGCMTypes,
password: BinaryLikeNode,
options?: CipherGCMOptions
): CipherGCM;
export function createCipher(
algorithm: string,
password: BinaryLike,
options?: Record<string, unknown> | Stream.TransformOptions
): Cipher {
password: BinaryLikeNode,
options?: CipherGCMOptions | CipherCCMOptions | Stream.TransformOptions
): CipherCCM | CipherGCM | Cipher {
return new Cipher(algorithm, password, options);
}

// export function createCipheriv(algorithm: CipherCCMTypes, key: CipherKey, iv: BinaryLike, options: CipherCCMOptions): CipherCCM;
// export function createCipheriv(algorithm: CipherOCBTypes, key: CipherKey, iv: BinaryLike, options: CipherOCBOptions): CipherOCB;
// export function createCipheriv(algorithm: CipherGCMTypes, key: CipherKey, iv: BinaryLike, options?: CipherGCMOptions): CipherGCM;
export function createCipheriv(
algorithm: CipherCCMTypes,
key: BinaryLikeNode,
iv: BinaryLike,
options: CipherCCMOptions
): CipherCCM;
export function createCipheriv(
algorithm: CipherOCBTypes,
key: BinaryLikeNode,
iv: BinaryLike,
options: CipherOCBOptions
): CipherOCB;
export function createCipheriv(
algorithm: CipherGCMTypes,
key: BinaryLikeNode,
iv: BinaryLike,
options?: CipherGCMOptions
): CipherGCM;
export function createCipheriv(
algorithm: string,
key: BinaryLike,
key: BinaryLikeNode,
iv: BinaryLike | null,
options?: Record<string, unknown> | Stream.TransformOptions
): Cipher {
options?:
| CipherCCMOptions
| CipherOCBOptions
| CipherGCMOptions
| Stream.TransformOptions
): CipherCCM | CipherOCB | CipherGCM | Cipher {
return new Cipher(algorithm, key, options, iv);
}

Expand Down
8 changes: 7 additions & 1 deletion src/Utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,11 @@ import type {
SignVerifyAlgorithm,
SubtleAlgorithm,
} from './keys';
import { type CipherKey } from 'crypto'; // @types/node

export type BufferLike = ArrayBuffer | Buffer | ArrayBufferView;
export type BinaryLike = string | ArrayBuffer | Buffer;
export type BinaryLikeNode = CipherKey | BinaryLike;

export type BinaryToTextEncoding = 'base64' | 'base64url' | 'hex' | 'binary';
export type CharacterEncoding = 'utf8' | 'utf-8' | 'utf16le' | 'latin1';
Expand Down Expand Up @@ -137,7 +139,7 @@ export function bufferLikeToArrayBuffer(buf: BufferLike): ArrayBuffer {
}

export function binaryLikeToArrayBuffer(
input: BinaryLike,
input: BinaryLikeNode, // CipherKey adds compat with node types
encoding: string = 'utf-8'
): ArrayBuffer {
if (typeof input === 'string') {
Expand Down Expand Up @@ -166,6 +168,8 @@ export function binaryLikeToArrayBuffer(

if (!(input instanceof ArrayBuffer)) {
try {
// this is a strange fallback case and input is unknown at this point
// @ts-expect-error
const buffer = Buffer.from(input);
return buffer.buffer.slice(
buffer.byteOffset,
Expand All @@ -176,6 +180,8 @@ export function binaryLikeToArrayBuffer(
}
}

// TODO: handle if input is KeyObject?

return input;
}

Expand Down
10 changes: 6 additions & 4 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2695,10 +2695,12 @@
dependencies:
undici-types "~5.26.4"

"@types/node@^17.0.31":
version "17.0.45"
resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.45.tgz#2c0fafd78705e7a18b7906b5201a522719dc5190"
integrity sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==
"@types/node@^20.12.7":
version "20.12.7"
resolved "https://registry.yarnpkg.com/@types/node/-/node-20.12.7.tgz#04080362fa3dd6c5822061aa3124f5c152cff384"
integrity sha512-wq0cICSkRLVaf3UGLMGItu/PtdY7oaXaI/RVU+xliKVOtRna3PRY57ZDfztpDL0n11vfymMUnXv8QwYCO7L1wg==
dependencies:
undici-types "~5.26.4"

"@types/normalize-package-data@^2.4.0":
version "2.4.4"
Expand Down

0 comments on commit 07b14c5

Please sign in to comment.