• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

microsoft / botbuilder-js / 12258997087

10 Dec 2024 03:08PM UTC coverage: 84.277% (-0.4%) from 84.686%
12258997087

push

github

web-flow
feat: Add support for Node 22 (#4808)

* Use tsup to compile ESM-only filenamify package

* Update yamls to include node 22

* Throw error on crypto.createDecipher for node 22

* Add NODE_NO_WARNINGS flag to bf dialogs:merge exec

* Apply feedback

* Update unit tests

8149 of 10821 branches covered (75.31%)

Branch coverage included in aggregate %.

8 of 12 new or added lines in 3 files covered. (66.67%)

17 existing lines in 1 file now uncovered.

20431 of 23091 relevant lines covered (88.48%)

3465.04 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

88.71
/libraries/botframework-config/src/encrypt.ts
1
/**
2
 * @module botframework-config
3
 *
4
 * Copyright(c) Microsoft Corporation.All rights reserved.
5
 * Licensed under the MIT License.
6
 */
7

8
import crypto from 'crypto';
1✔
9
import { version as nodeVersion } from 'process';
1✔
10

11
/**
12
 * @private
13
 * @deprecated
14
 */
15
export function generateKey(): string {
1✔
16
    // Generates 32 byte cryptographically strong pseudo-random data as a base64 encoded string
17
    // https://nodejs.org/api/crypto.html#crypto_crypto_randombytes_size_callback
18
    return crypto.randomBytes(32).toString('base64');
8✔
19
}
20

21
/**
22
 * @private
23
 * @deprecated
24
 * Encrypt a string using standardized encyryption of AES256
25
 * @param plainText value to encrypt
26
 * @param secret secret to use
27
 */
28
export function encryptString(plainText: string, secret: string): string {
1✔
29
    if (!plainText || plainText.length === 0) {
95✔
30
        return plainText;
3✔
31
    }
32

33
    if (!secret || secret.length === 0) {
92✔
34
        throw new Error('you must pass a secret');
1✔
35
    }
36

37
    const keyBytes: Buffer = Buffer.from(secret, 'base64');
91✔
38

39
    // Generates 16 byte cryptographically strong pseudo-random data as IV
40
    // https://nodejs.org/api/crypto.html#crypto_crypto_randombytes_size_callback
41
    const ivBytes: Buffer = crypto.randomBytes(16);
91✔
42
    const ivText: string = ivBytes.toString('base64');
91✔
43

44
    // encrypt using aes256 iv + key + plainText = encryptedText
45
    const cipher: crypto.Cipher = crypto.createCipheriv('aes-256-cbc', keyBytes, ivBytes);
91✔
46
    let encryptedValue: string = cipher.update(plainText, 'utf8', 'base64');
91✔
47
    encryptedValue += cipher.final('base64');
91✔
48

49
    // store base64(ivBytes)!base64(encryptedValue)
50
    return `${ivText}!${encryptedValue}`;
91✔
51
}
52

53
/**
54
 * @private
55
 * @deprecated
56
 * Decrypt a string using standardized encyryption of AES256
57
 * @param enryptedValue value to decrypt
58
 * @param secret secret to use
59
 */
60
export function decryptString(encryptedValue: string, secret: string): string {
1✔
61
    if (!encryptedValue || encryptedValue.length === 0) {
152✔
62
        return encryptedValue;
3✔
63
    }
64

65
    if (!secret || secret.length === 0) {
149✔
66
        throw new Error('you must pass a secret');
1✔
67
    }
68

69
    // enrypted value = base64(ivBytes)!base64(encryptedValue)
70
    const parts: string[] = encryptedValue.split('!');
148✔
71
    if (parts.length !== 2) {
148✔
72
        throw new Error('The encrypted value is not a valid format');
1✔
73
    }
74

75
    const ivText: string = parts[0];
147✔
76
    const encryptedText: string = parts[1];
147✔
77

78
    const ivBytes: Buffer = Buffer.from(ivText, 'base64');
147✔
79
    const keyBytes: Buffer = Buffer.from(secret, 'base64');
147✔
80

81
    if (ivBytes.length !== 16) {
147!
82
        throw new Error('The encrypted value is not a valid format');
×
83
    }
84

85
    if (keyBytes.length !== 32) {
147✔
86
        throw new Error('The secret is not valid format');
1✔
87
    }
88

89
    // decrypt using aes256 iv + key + encryptedText = decryptedText
90
    const decipher: crypto.Decipher = crypto.createDecipheriv('aes-256-cbc', keyBytes, ivBytes);
146✔
91
    let value: string = decipher.update(encryptedText, 'base64', 'utf8');
146✔
92
    value += decipher.final('utf8');
146✔
93

94
    return value;
145✔
95
}
96

97
/**
98
 * @private
99
 * @deprecated
100
 * @param encryptedValue
101
 * @param secret
102
 */
103
export function legacyDecrypt(encryptedValue: string, secret: string): string {
1✔
104
    const UNSUPPORTED_VERSION = 'v22.0.0';
2✔
105
    if (!isNodeCompatible(nodeVersion, UNSUPPORTED_VERSION)) {
2!
106
        throw new Error(`This method is not available for Node.js versions over ${UNSUPPORTED_VERSION}.`);
2✔
107
    } else {
108
        // LEGACY for pre standardized SHA256 encryption, this uses some undocumented nodejs MD5 hash internally and is deprecated
NEW
109
        const decipher: crypto.Decipher = crypto.createDecipher('aes192', secret);
×
NEW
110
        let value: string = decipher.update(encryptedValue, 'hex', 'utf8');
×
NEW
111
        value += decipher.final('utf8');
×
112

NEW
113
        return value;
×
114
    }
115
}
116

117
/**
118
 * private
119
 *
120
 * @param currentVersion The current version of Node.js.
121
 * @param minVersion The minimum unsupported version.
122
 * @returns true if the current version of Node is lower than the unsupported version.
123
 */
124
function isNodeCompatible(currentVersion: string, minVersion: string): boolean {
125
    return minVersion.localeCompare(currentVersion) > 0;
2✔
126
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc