Skip to content
File

Blob: src/node/internal/crypto_util.ts

typescript134 lines
1// Copyright (c) 2017-2023 Cloudflare, Inc.
2// Licensed under the Apache 2.0 license found in the LICENSE file or at:
3// https://opensource.org/licenses/Apache-2.0
4//
5// Copyright Joyent, Inc. and other Node contributors.
6//
7// Permission is hereby granted, free of charge, to any person obtaining a
8// copy of this software and associated documentation files (the
9// "Software"), to deal in the Software without restriction, including
10// without limitation the rights to use, copy, modify, merge, publish,
11// distribute, sublicense, and/or sell copies of the Software, and to permit
12// persons to whom the Software is furnished to do so, subject to the
13// following conditions:
14//
15// The above copyright notice and this permission notice shall be included
16// in all copies or substantial portions of the Software.
17//
18// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
21// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
22// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
23// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
24// USE OR OTHER DEALINGS IN THE SOFTWARE.
25 
26import { Buffer } from 'node-internal:internal_buffer';
27 
28import {
29 isAnyArrayBuffer,
30 isArrayBufferView,
31} from 'node-internal:internal_types';
32 
33import { ERR_INVALID_ARG_TYPE } from 'node-internal:internal_errors';
34 
35import { validateString } from 'node-internal:validators';
36 
37import { default as cryptoImpl } from 'node-internal:crypto';
38type ArrayLike = cryptoImpl.ArrayLike;
39 
40export const kHandle = Symbol('kHandle');
41export const kFinalized = Symbol('kFinalized');
42export const kState = Symbol('kState');
43 
44// eslint-disable-next-line @typescript-eslint/no-explicit-any
45export function getStringOption(options: any, key: string): string | undefined {
46 let value: string | undefined;
47 // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition,@typescript-eslint/no-unsafe-member-access
48 if (options && (value = options[key] as string) != null)
49 validateString(value, `options.${key}`);
50 return value;
51}
52 
53export function getArrayBufferOrView(
54 buffer: CryptoKey | Buffer | ArrayBuffer | ArrayBufferView | string,
55 name: string,
56 encoding?: string
57): Buffer | ArrayBuffer | ArrayBufferView {
58 if (isAnyArrayBuffer(buffer)) return buffer;
59 if (typeof buffer === 'string') {
60 if (encoding === undefined || encoding === 'buffer') {
61 encoding = 'utf8';
62 }
63 return Buffer.from(buffer, encoding);
64 }
65 if (!isArrayBufferView(buffer)) {
66 throw new ERR_INVALID_ARG_TYPE(
67 name,
68 ['string', 'ArrayBuffer', 'Buffer', 'TypedArray', 'DataView'],
69 buffer
70 );
71 }
72 return buffer;
73}
74 
75/**
76 * 48 is the ASCII code for '0', 97 is the ASCII code for 'a'.
77 * @param {number} number An integer between 0 and 15.
78 * @returns {number} corresponding to the ASCII code of the hex representation
79 * of the parameter.
80 */
81export const numberToHexCharCode = (number: number): number =>
82 (number < 10 ? 48 : 87) + number;
83 
84/**
85 * @param {ArrayBuffer} buf An ArrayBuffer.
86 * @return {bigint}
87 */
88export function arrayBufferToUnsignedBigInt(buf: ArrayBuffer): bigint {
89 const length = buf.byteLength;
90 const chars = new Array<number>(length * 2);
91 const view = new DataView(buf);
92 
93 for (let i = 0; i < length; i++) {
94 const val = view.getUint8(i);
95 chars[2 * i] = numberToHexCharCode(val >> 4);
96 chars[2 * i + 1] = numberToHexCharCode(val & 0xf);
97 }
98 
99 return BigInt(`0x${String.fromCharCode.apply(null, chars)}`);
100}
101 
102// This is here because many functions accepted binary strings without
103// any explicit encoding in older versions of node, and we don't want
104// to break them unnecessarily.
105export function toBuf(
106 val: ArrayLike,
107 encoding?: string
108): Buffer | ArrayBuffer | ArrayBufferView {
109 if (typeof val === 'string') {
110 if (encoding === 'buffer') {
111 encoding = 'utf8';
112 }
113 return Buffer.from(val, encoding);
114 }
115 return val;
116}
117 
118export function validateByteSource(
119 val: ArrayLike,
120 name: string
121): Buffer | ArrayBuffer | ArrayBufferView {
122 val = toBuf(val);
123 
124 if (isAnyArrayBuffer(val) || isArrayBufferView(val)) {
125 return val;
126 }
127 
128 throw new ERR_INVALID_ARG_TYPE(
129 name,
130 ['string', 'ArrayBuffer', 'TypedArray', 'DataView', 'Buffer'],
131 val
132 );
133}