secrez 2.1.12 → 2.1.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -43,8 +43,6 @@ Secrez aims to provide a secure password management solution that is available e
43
43
 
44
44
  To achieve its goal, Secrez uses several strategies. First, any secret is a local file. Second, any file, whether it's a tree version, a directory, a text file, or a binary file, is immutable. Finally, any change can be pulled/pushed to a remote private repository. You can either create a private repository on GitHub, BitBucket, etc. or set up your own self-hosted Git server.
45
45
 
46
- In addition to functioning as a password manager, Secrez also includes an optional decentralized, surveillance-resistant, end-to-end encrypted messaging system. This provides an extra layer of security for your communications, ensuring that your messages cannot be intercepted or read by anyone other than the intended recipient.
47
-
48
46
  Overall, Secrez offers a powerful and secure solution for managing your passwords and secrets, all from the command line.
49
47
 
50
48
  ## The structure
@@ -370,6 +368,10 @@ Secrez is not intended to compete with password managers, so do not expect it to
370
368
 
371
369
  ## History
372
370
 
371
+ **2.1.12**
372
+
373
+ - enforce the usage of pnpm during global install. When that is not possible, for example with yarn, it blocks the execution asking the user to uninstall and install it again properly
374
+
373
375
  **2.1.11**
374
376
 
375
377
  - fix warning "(node:70960) [DEP0190] DeprecationWarning: Passing args to a child process with shell option true can lead to security vulnerabilities" caused by the Git checker
@@ -498,6 +500,10 @@ Secrez is not intended to compete with password managers, so do not expect it to
498
500
  - remove second factor authentication due to potentially critical issues with Python and the required libraries on macOS (2FA will be restored as soon as either a pure Javascript library is available or using external Python libraries is reliable again)
499
501
  - `Bash` has been renamed `Shell`
500
502
 
503
+ **0.11.0**
504
+
505
+ - removed support for FIDO2 second factor authentication due to potential critical issues with Python and the required libraries on MacOS (2FA may be restored if a pure Javascript library becomes available)
506
+
501
507
  **0.10.8**
502
508
 
503
509
  - expose a prompt mock to allow other software to run commands programmatically
@@ -886,30 +892,29 @@ Thank you for any contributions! 😉
886
892
  ## Test coverage
887
893
 
888
894
  ```
889
- 162 passing (1m)
890
- 1 pending
895
+ 162 passing (2m)
891
896
 
892
897
  --------------------|---------|----------|---------|---------|--------------------------------------
893
898
  File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
894
899
  --------------------|---------|----------|---------|---------|--------------------------------------
895
- All files | 80.07 | 67.69 | 80.91 | 79.96 |
900
+ All files | 81.62 | 68.94 | 83.57 | 81.53 |
896
901
  src | 57.62 | 53.75 | 55 | 58.11 |
897
902
  Command.js | 74.66 | 74.13 | 78.57 | 75.67 | ...5-62,73,80,93,127,164-172,179-182
898
903
  PreCommand.js | 8.82 | 0 | 0 | 8.82 | 6-97
899
904
  cliConfig.js | 100 | 100 | 100 | 100 |
900
- src/commands | 83.06 | 69.43 | 90.82 | 82.94 |
905
+ src/commands | 83.01 | 69.34 | 90.82 | 82.89 |
901
906
  Alias.js | 88.6 | 78.68 | 100 | 88.46 | 101,112,139,169,173,180,190,213-214
902
907
  Bash.js | 75 | 0 | 66.66 | 75 | 18-19
903
908
  Cat.js | 98.91 | 88.88 | 100 | 98.91 | 152
904
909
  Cd.js | 96.42 | 86.66 | 100 | 96.42 | 44
905
- Conf.js | 8.64 | 0 | 20 | 8.64 | 98-509
910
+ Conf.js | 8.64 | 0 | 20 | 8.64 | 47-216
906
911
  Contacts.js | 86.06 | 75.6 | 100 | 85.95 | ...5,165,172,184,237,250,260,268-269
907
912
  Copy.js | 91.2 | 71.92 | 100 | 91.11 | 115,166,183,205-210,225-226,253
908
913
  Ds.js | 90.27 | 82.6 | 100 | 90.14 | 99,108-113,125,147-148
909
914
  Edit.js | 12.94 | 0 | 40 | 12.94 | 88-222
910
915
  Export.js | 90.17 | 76.92 | 100 | 90.17 | ...3-198,209,227-231,236,248,257,260
911
916
  Find.js | 93.58 | 86.66 | 100 | 93.42 | 101,164,200-203,209
912
- Git.js | 96.15 | 75 | 100 | 96.15 | 61
917
+ Git.js | 92.3 | 66.66 | 100 | 92.3 | 40,61
913
918
  Help.js | 100 | 80 | 100 | 100 | 29
914
919
  Import.js | 92.41 | 85.38 | 100 | 92.34 | ...7,387,393,441,457-458,466-473,500
915
920
  Lcat.js | 100 | 85.71 | 100 | 100 | 54
@@ -935,18 +940,12 @@ All files | 80.07 | 67.69 | 80.91 | 79.96 |
935
940
  index.js | 87.5 | 50 | 100 | 86.95 | 15,22,31
936
941
  src/prompts | 75 | 33.33 | 50 | 75 |
937
942
  MainPromptMock.js | 75 | 33.33 | 50 | 75 | 29-35,44
938
- src/utils | 67.61 | 62.5 | 54.16 | 67.21 |
943
+ src/utils | 83.07 | 78.43 | 66.66 | 82.81 |
939
944
  AliasManager.js | 100 | 91.66 | 100 | 100 | 47
940
945
  ContactManager.js | 73.33 | 60 | 85.71 | 73.33 | 12,34-36
941
- Fido2Client.js | 9.61 | 0 | 0 | 9.61 | 8-108
942
946
  HelpProto.js | 89.07 | 82.6 | 100 | 88.88 | 49,135-137,153-154,171-176,195
943
947
  Logger.js | 63.63 | 56.25 | 36.84 | 62.79 | ...25,37-49,57,65-69,74,84,88,93,105
944
948
  --------------------|---------|----------|---------|---------|--------------------------------------
945
-
946
- > secrez@2.1.11-beta.0 posttest /Users/francescosullo/Projects/Secrez/secrez/packages/secrez
947
- > nyc check-coverage --statements 65 --branches 50 --functions 65 --lines 65
948
-
949
-
950
949
  ```
951
950
 
952
951
  ## Copyright
package/bin/secrez.js CHANGED
@@ -10,44 +10,45 @@ const pkg = require("../package");
10
10
  const MainPrompt = require("../src/prompts/MainPrompt");
11
11
  const Logger = require("../src/utils/Logger");
12
12
 
13
- // Check if the package was installed with pnpm
13
+ // Check if the package was installed with pnpm (skip check in development)
14
14
  const installPath = __dirname;
15
- if (installPath.indexOf("pnpm") === -1) {
16
- console.error(
17
- chalk.red.bold("\n⚠️ Installation Error\n")
18
- );
15
+ if (process.env.NODE_ENV !== "dev" && installPath.indexOf("pnpm") === -1) {
16
+ console.error(chalk.red.bold("\n⚠️ Installation Error\n"));
19
17
  console.error(
20
18
  chalk.yellow(
21
19
  "Secrez must be installed globally using pnpm.\n" +
22
- "It appears this package was installed with a different package manager.\n"
20
+ "It appears this package was installed with a different package manager.\n"
23
21
  )
24
22
  );
25
- console.error(
26
- chalk.white("\nPlease follow these steps:\n")
27
- );
23
+ console.error(chalk.white("\nPlease follow these steps:\n"));
28
24
  console.error(
29
25
  chalk.cyan(
30
26
  "1. Uninstall secrez using the package manager you previously used:\n" +
31
- " - If you used npm: " + chalk.bold("npm uninstall -g secrez") + "\n" +
32
- " - If you used yarn: " + chalk.bold("yarn global remove secrez") + "\n"
27
+ " - If you used npm: " +
28
+ chalk.bold("npm uninstall -g secrez") +
29
+ "\n" +
30
+ " - If you used yarn: " +
31
+ chalk.bold("yarn global remove secrez") +
32
+ "\n"
33
33
  )
34
34
  );
35
35
  console.error(
36
36
  chalk.cyan(
37
37
  "2. Install pnpm globally if you haven't already:\n" +
38
- " " + chalk.bold("npm install -g pnpm") + "\n"
38
+ " " +
39
+ chalk.bold("npm install -g pnpm") +
40
+ "\n"
39
41
  )
40
42
  );
41
43
  console.error(
42
- chalk.cyan(
43
- "3. Setup pnpm:\n" +
44
- " " + chalk.bold("pnpm setup") + "\n"
45
- )
44
+ chalk.cyan("3. Setup pnpm:\n" + " " + chalk.bold("pnpm setup") + "\n")
46
45
  );
47
46
  console.error(
48
47
  chalk.cyan(
49
48
  "4. Install secrez globally using pnpm:\n" +
50
- " " + chalk.bold("pnpm install -g secrez") + "\n"
49
+ " " +
50
+ chalk.bold("pnpm install -g secrez") +
51
+ "\n"
51
52
  )
52
53
  );
53
54
  process.exit(1);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "secrez",
3
- "version": "2.1.12",
3
+ "version": "2.1.13",
4
4
  "license": "MIT",
5
5
  "nyc": {
6
6
  "include": "src",
@@ -1,6 +1,6 @@
1
1
  if (process.env.npm_execpath.indexOf("pnpm") === -1) {
2
2
  console.error(
3
- '\x1b[31m\x1b[1m\nThis project requires pnpm as a package manager.\n\x1b[0m'
3
+ "\x1b[31m\x1b[1m\nThis project requires pnpm as a package manager.\n\x1b[0m"
4
4
  );
5
5
  process.exit(1);
6
6
  }
package/src/Welcome.js CHANGED
@@ -3,7 +3,6 @@ const inquirer = require("inquirer");
3
3
  const fs = require("fs-extra");
4
4
  const Crypto = require("@secrez/crypto");
5
5
  const Logger = require("./utils/Logger");
6
- // const Fido2Client = require("./utils/Fido2Client"); // FIDO2 support removed
7
6
 
8
7
  class Welcome {
9
8
  async start(secrez, options) {
@@ -35,10 +34,7 @@ Thanks.`);
35
34
  }
36
35
 
37
36
  if (await fs.pathExists(this.secrez.config.keysPath)) {
38
- let errorCode = await this.login();
39
- if (errorCode === 1) {
40
- await this.handleDeprecatedFido2();
41
- }
37
+ await this.login();
42
38
  } else {
43
39
  Logger.grey("Please signup to create your local account");
44
40
  await this.signup();
@@ -111,97 +107,6 @@ Thanks.`);
111
107
  }
112
108
  }
113
109
 
114
- // sharedLogin() method removed - FIDO2 support deprecated
115
- /*
116
- async sharedLogin() {
117
- let fido2Client = new Fido2Client(this.secrez);
118
- let authenticator;
119
- let list = await fido2Client.getKeys();
120
- const conf = await this.secrez.readConf();
121
- let choices = [];
122
- for (let authenticator in conf.data.keys) {
123
- choices.push(authenticator);
124
- }
125
- for (;;) {
126
- if (list.length === 1) {
127
- authenticator = list[0];
128
- } else {
129
- let p = await inquirer.prompt([
130
- {
131
- type: "list",
132
- name: "authenticator",
133
- message: "Which second factor would you like to use?",
134
- choices,
135
- },
136
- ]);
137
- authenticator = p.authenticator;
138
- }
139
- let secret;
140
- try {
141
- try {
142
- if (fido2Client.keys[authenticator]) {
143
- Logger.grey("Touch your fido2 authenticator device now...");
144
- secret = await fido2Client.verifySecret(authenticator);
145
- } else {
146
- let exitCode = Crypto.getRandomBase58String(2);
147
- let p = await inquirer.prompt([
148
- {
149
- name: "recoveryCode",
150
- type: "input",
151
- message: "Type or paste your recovery code:",
152
- validate: (value) => {
153
- if (value.length) {
154
- return true;
155
- } else {
156
- return `
157
- Please
158
- paste
159
- a
160
- valid
161
- recovery
162
- code
163
- or
164
- type ${exitCode}
165
- to
166
- choose
167
- another
168
- factor.`;
169
- }
170
- },
171
- },
172
- ]);
173
- if (p.recoveryCode === exitCode) {
174
- continue;
175
- }
176
- secret = p.recoveryCode;
177
- }
178
- let resCode = await this.secrez.sharedSignin(authenticator, secret);
179
- if (this.secrez.masterKeyHash) {
180
- await this.saveIterations();
181
- }
182
- if (resCode === 1) {
183
- Logger.bold(chalk.red("Your data has been upgraded."));
184
- Logger.red(
185
- "To avoid conflicts, any registered second factor has been removed."
186
- );
187
- Logger.grey("Please, register them again, thanks.");
188
- }
189
- return;
190
- } catch (e) {
191
- Logger.red(`${e.message}.Try
192
- again
193
- or
194
- Ctrl - C
195
- to
196
- exit.`);
197
- }
198
- } catch (e) {
199
- Logger.red("Unrecognized error. Try again or Ctrl-C to exit.");
200
- }
201
- }
202
- }
203
- */
204
-
205
110
  async signup() {
206
111
  for (;;) {
207
112
  try {
@@ -248,52 +153,6 @@ Thanks.`);
248
153
  }
249
154
  }
250
155
  }
251
-
252
- async handleDeprecatedFido2() {
253
- Logger.yellow(
254
- "FIDO2 second factor authentication is no longer supported in this version."
255
- );
256
- Logger.grey("Removing deprecated FIDO2 configuration...");
257
-
258
- try {
259
- const conf = await this.secrez.readConf();
260
- const data = conf.data;
261
-
262
- if (data.keys) {
263
- // Remove all FIDO2 keys from the configuration
264
- delete data.keys;
265
-
266
- // Save the cleaned configuration
267
- await this.secrez.saveConf(conf);
268
-
269
- Logger.green("FIDO2 configuration has been removed successfully.");
270
- Logger.grey("You can now login with your master password only.");
271
-
272
- // Try to login again with the cleaned configuration
273
- let errorCode = await this.login();
274
- if (errorCode === 1) {
275
- Logger.red(
276
- "Login still failed. Please check your password or create a new account."
277
- );
278
- // eslint-disable-next-line no-process-exit
279
- process.exit(1);
280
- }
281
- } else {
282
- Logger.red(
283
- "No FIDO2 keys found, but login still requires second factor. This may indicate a corrupted configuration."
284
- );
285
- // eslint-disable-next-line no-process-exit
286
- process.exit(1);
287
- }
288
- } catch (e) {
289
- Logger.red(`Failed to clean FIDO2 configuration: ${e.message}`);
290
- Logger.grey(
291
- "You may need to manually remove the keys.json file and create a new account."
292
- );
293
- // eslint-disable-next-line no-process-exit
294
- process.exit(1);
295
- }
296
- }
297
156
  }
298
157
 
299
158
  module.exports = new Welcome();
@@ -1,11 +1,5 @@
1
- // const Fido2Client = require('../utils/Fido2Client')
2
- // const _ = require('lodash')
3
- // const Case = require('case')
4
- const {
5
- //config,
6
- ConfigUtils,
7
- } = require("@secrez/core");
8
- // const Crypto = require('@secrez/crypto')
1
+ const { ConfigUtils } = require("@secrez/core");
2
+
9
3
  const chalk = require("chalk");
10
4
 
11
5
  class Conf extends require("../Command") {
@@ -25,33 +19,6 @@ class Conf extends require("../Command") {
25
19
  alias: "s",
26
20
  type: Boolean,
27
21
  },
28
- // {
29
- // name: 'register',
30
- // alias: 'r',
31
- // type: String
32
- // },
33
- // {
34
- // name: 'unregister',
35
- // alias: 'u',
36
- // type: String
37
- // },
38
- // {
39
- // name: 'recovery-code',
40
- // type: Boolean
41
- // },
42
- // {
43
- // name: 'fido2',
44
- // type: Boolean
45
- // },
46
- // {
47
- // name: 'list',
48
- // alias: 'l',
49
- // type: Boolean
50
- // },
51
- // {
52
- // name: 'use-this',
53
- // type: String
54
- // },
55
22
  {
56
23
  name: "new-password",
57
24
  type: Boolean,
@@ -72,28 +39,10 @@ class Conf extends require("../Command") {
72
39
  ["conf -s", "shows the general settings"],
73
40
  ["conf --new-password", "changes your password"],
74
41
  ["conf --new-iterations-number", "changes the number of iterations"],
75
- // ['conf --fido2 -r solo',
76
- // 'registers a new key saving it as "solo"; if there are registered keys, it will checks if the new one is one of them before adding it.'],
77
- // ['conf -l', 'lists second factors'],
78
- // ['conf --recovery-code -r memo',
79
- // 'registers an emergency recovery code called "memo" to be used if all the factors are lost'],
80
- // ['conf --recovery-code -r seed --use-this "salad spring peace silk snake real they thunder please final clinic close"', 'registers an emergency recovery code called "seed" using the seed passed with the parameter "--use-this"'],
81
- // ['conf -u solo',
82
- // 'unregister the fido2 key "solo"; if that is the only key, it unregister also any emergency code and restores the normal access.']
83
42
  ],
84
43
  };
85
44
  }
86
45
 
87
- // isEmergencyCodeSetUp() {
88
- // const conf = this.secrez.getConf()
89
- // let keys = conf.data.keys || {}
90
- // for (let authenticator in keys) {
91
- // if (keys[authenticator].type === this.secrez.config.sharedKeys.RECOVERY_CODE) {
92
- // return true
93
- // }
94
- // }
95
- // }
96
- //
97
46
  async getAllFactors() {
98
47
  let allFactors = {};
99
48
  const conf = this.secrez.getConf();
@@ -103,32 +52,6 @@ class Conf extends require("../Command") {
103
52
  }
104
53
  return allFactors;
105
54
  }
106
- //
107
- // async verifyIfAlreadyRegistered() {
108
- // let client = this.fido2Client
109
- // let list = await client.getKeys(true)
110
- // let now = 'now'
111
- // for (let l of list) {
112
- // this.Logger.grey(`Touch your fido2 authenticator device ${now}...`)
113
- // try {
114
- // if (await client.verifySecret(l[0])) {
115
- // return l[0]
116
- // }
117
- // } catch (e) {
118
- // }
119
- // now = 'again'
120
- // }
121
- // return false
122
- // }
123
- //
124
- // exists(list, authenticator) {
125
- // for (let l of list) {
126
- // if (l[0] === authenticator) {
127
- // return true
128
- // }
129
- // }
130
- // return false
131
- // }
132
55
 
133
56
  async showConf(options) {
134
57
  const env = await ConfigUtils.getEnv(this.secrez.config);
@@ -139,63 +62,6 @@ class Conf extends require("../Command") {
139
62
  );
140
63
  }
141
64
 
142
- // async showList(options) {
143
- // let allFactors = await this.getAllFactors()
144
- // if (!Object.keys(allFactors).length) {
145
- // return this.Logger.grey('No registered second factors')
146
- // }
147
- // this.Logger.reset('Registered second factors:')
148
- // let max = 0
149
- // let factors = []
150
- // for (let factor in allFactors) {
151
- // max = Math.max(max, factor.length)
152
- // factors.push([factor, allFactors[factor]])
153
- // }
154
- // factors.sort((a, b) => {
155
- // let A = a[1]
156
- // let B = b[1]
157
- // return A > B ? 1 : A < B ? -1 : 0
158
- // })
159
- // for (let factor of factors) {
160
- // let type = factor[1]
161
- // if ((options.fido2 && type !== config.sharedKeys.FIDO2_KEY)
162
- // || (options.recoveryCode && type !== config.sharedKeys.RECOVERY_CODE)) {
163
- // continue
164
- // }
165
- // type = chalk.grey(`(${type === config.sharedKeys.FIDO2_KEY ? 'fido2 key' : 'recoveryCode'})`)
166
- // this.Logger.reset(`${factor[0]} ${' '.repeat(max - factor[0].length)} ${type}`)
167
- // }
168
- // }
169
- //
170
- // async setRecoveryCode(options) {
171
- // let client = this.fido2Client
172
- // let list = await client.getKeys(true)
173
- // if (!Object.keys(list).length) {
174
- // throw new Error('An emergency recovery code can be set only if at least one security key has been registered.')
175
- // }
176
- // let authenticator = Case.snake(_.trim(options.register))
177
- // if (!authenticator) {
178
- // throw new Error('A valid name for the recovery code is required')
179
- // }
180
- // let conf = this.secrez.getConf()
181
- // if (conf.data.keys[authenticator]) {
182
- // throw new Error('A second factor with this name already exists')
183
- // }
184
- // let recoveryCode = options.useThis || Crypto.getMnemonic()
185
- // let type = this.secrez.config.sharedKeys.RECOVERY_CODE
186
- // let parts = this.secrez.generateSharedSecrets(recoveryCode)
187
- // let sharedData = {
188
- // parts,
189
- // type,
190
- // authenticator
191
- // }
192
- // await this.secrez.saveSharedSecrets(sharedData)
193
- // await client.updateConf()
194
- // this.Logger.reset('Your recover code is:')
195
- // this.Logger.yellow(recoveryCode)
196
- // await this.saveAndOverwrite(`main:/.RECOVERY_CODE_${authenticator}`, 'recovery code', recoveryCode, 'it')
197
- // }
198
- //
199
65
  async saveAndOverwrite(p, spec, content, message) {
200
66
  try {
201
67
  await this.prompt.commands.rm.rm({
@@ -211,135 +77,6 @@ class Conf extends require("../Command") {
211
77
  `For your convenience, ${message} has been saved in main:${node.getPath()}`
212
78
  );
213
79
  }
214
- //
215
- // async setFido2(options) {
216
- // let client = this.fido2Client
217
- // let list = await client.getKeys(true)
218
- // let authenticator = Case.snake(_.trim(options.register))
219
- // if (!authenticator) {
220
- // throw new Error('A valid name for the authenticator is required')
221
- // }
222
- // if (!options.register) {
223
- // throw new Error('The nickname of the key is invalid')
224
- // }
225
- // let conf = {}
226
- // let savedConf = await this.secrez.readConf()
227
- // if (savedConf.data.keys) {
228
- // conf = savedConf.data.keys
229
- // }
230
- // if (conf[authenticator]) {
231
- // throw new Error('A second factor with this name already exists')
232
- // }
233
- // let len = list.length
234
- // let existentName
235
- // if (len) {
236
- // this.Logger.reset(`${len} key${len > 1 ? 's' : ''} already registered. Before registering a new one, must be sure that this is a new one.`)
237
- // existentName = await this.verifyIfAlreadyRegistered()
238
- // }
239
- // if (existentName) {
240
- // throw new Error(`This key is already registered as "${existentName}"`)
241
- // } else {
242
- // this.Logger.bold('This device is not registered, yet. You can register it now.')
243
- // }
244
- //
245
- // let fido2Options = {
246
- // id: Crypto.getRandomBase58String(12),
247
- // authenticator
248
- // }
249
- //
250
- // this.Logger.grey('Touch your fido2 authenticator device now...')
251
- // let result = await client.setCredential(fido2Options)
252
- // client.checkErrorCode(result, 1)
253
- //
254
- // fido2Options.credential = result.message
255
- // fido2Options.salt = Crypto.getRandomBase58String(32)
256
- //
257
- // this.Logger.grey('Touch your fido2 authenticator device again...')
258
- // result = await client.getSecret(fido2Options)
259
- // client.checkErrorCode(result, 2)
260
- //
261
- // fido2Options.secret = result.message
262
- //
263
- // let yes = await this.useConfirm({
264
- // message: `Are you sure you want to use the key ${authenticator} as a second factor? If you lose it who could not be able to access you account anymore.`,
265
- // default: false
266
- // })
267
- // if (yes) {
268
- // let type = this.secrez.config.sharedKeys.FIDO2_KEY
269
- // let parts = this.secrez.generateSharedSecrets(fido2Options.secret)
270
- //
271
- // let sharedData = {
272
- // parts,
273
- // type,
274
- // authenticator,
275
- // id: fido2Options.id,
276
- // salt: fido2Options.salt,
277
- // credential: fido2Options.credential,
278
- // hash: Crypto.b58Hash(fido2Options.secret)
279
- // }
280
- // await this.secrez.saveSharedSecrets(sharedData)
281
- // await client.updateConf()
282
- // this.Logger.reset(`A second factor using ${authenticator} has been set.`)
283
- // if (!this.isEmergencyCodeSetUp()) {
284
- // let yes = await this.useConfirm({
285
- // message: `An emergency recovery code would allow you to recover the account if you lose ${authenticator}. Would you like to set it now?`,
286
- // default: true
287
- // })
288
- // if (yes) {
289
- // let name = await this.useInput({
290
- // message: 'Type the nickname of the recovery code'
291
- // })
292
- // if (name) {
293
- // options.recoveryCode = true
294
- // options.register = name
295
- // return await this.conf(options)
296
- // } else {
297
- // this.Logger.grey('Emergency code not set')
298
- // }
299
- // }
300
- // }
301
- // } else {
302
- // throw new Error('Operation canceled')
303
- // }
304
- // }
305
- //
306
- // async unregister(options) {
307
- // let authenticator = Case.snake(_.trim(options.unregister))
308
- // let allFactors = await this.getAllFactors()
309
- // if (!allFactors[authenticator]) {
310
- // throw new Error(`Authenticator ${authenticator} not found`)
311
- // }
312
- // let yes = await this.useConfirm({
313
- // message: `Are you sure you want to remove the ${authenticator} authenticator?`,
314
- // default: false
315
- // })
316
- // let code
317
- // if (yes) {
318
- // code = await this.secrez.removeSharedSecret(authenticator)
319
- // this.Logger.reset(code === 1 ? `${authenticator} has been removed` : 'All second factors have been removed')
320
- // } else {
321
- // this.Logger.grey('Operation canceled')
322
- // }
323
- // if (code === 2) {
324
- // for (let factor in allFactors) {
325
- // if (allFactors[factor] === this.secrez.config.sharedKeys.RECOVERY_CODE) {
326
- // try {
327
- // await this.prompt.commands.rm.rm({
328
- // path: `main:/.RECOVERY_CODE_${factor}`
329
- // })
330
- // } catch (e) {
331
- // }
332
- // }
333
- // }
334
- // } else if (allFactors[authenticator] === this.secrez.config.sharedKeys.RECOVERY_CODE) {
335
- // try {
336
- // await this.prompt.commands.rm.rm({
337
- // path: `main:/.RECOVERY_CODE_${authenticator}`
338
- // })
339
- // } catch (e) {
340
- // }
341
- // }
342
- // }
343
80
 
344
81
  async upgradeAccount(options) {
345
82
  let pw = options.newPassword;
@@ -448,28 +185,8 @@ class Conf extends require("../Command") {
448
185
  }
449
186
 
450
187
  async conf(options) {
451
- // if (!this.fido2Client) {
452
- // this.fido2Client = new Fido2Client(this.secrez)
453
- // }
454
- // if (options.list) {
455
- // await this.showList(options)
456
- // } else
457
188
  if (options.show) {
458
189
  await this.showConf(options);
459
- // } else if (options.recoveryCode) {
460
- // await this.setRecoveryCode(options)
461
- // } else if (options.fido2) {
462
- // let yes = await this.useConfirm({
463
- // message: 'Fido2 requires external libraries written in Python. It is an experimental feature, and it is not guaranteed to work. Are you sure you want to set it up?',
464
- // default: false
465
- // })
466
- // if (!yes) {
467
- // throw new Error('Operation canceled')
468
- // }
469
- // await this.fido2Client.checkIfReady()
470
- // await this.setFido2(options)
471
- // } else if (options.unregister) {
472
- // await this.unregister(options)
473
190
  } else if (options.newPassword || options.newIterationsNumber) {
474
191
  await this.upgradeAccount(options);
475
192
  } else {
@@ -482,9 +199,6 @@ class Conf extends require("../Command") {
482
199
  return this.showHelp();
483
200
  }
484
201
  try {
485
- // if (!Object.keys(options).length) {
486
- // options.list = true
487
- // }
488
202
  this.validate(options);
489
203
 
490
204
  // Check for git conflicts before changing password or iterations
@@ -495,15 +209,8 @@ class Conf extends require("../Command") {
495
209
  }
496
210
  }
497
211
 
498
- // if (options.fido2 && options.recoveryCode) {
499
- // throw new Error('Conflicting params. Launch "conf -h" for examples.')
500
- // }
501
- // if (options.register && !(options.fido2 || options.recoveryCode)) {
502
- // throw new Error('Missing parameters. Launch "conf -h" for examples.')
503
- // }
504
212
  await this.conf(options);
505
213
  } catch (e) {
506
- // console.error(e)
507
214
  this.Logger.red(e.message);
508
215
  }
509
216
  await this.prompt.run();
@@ -1,88 +0,0 @@
1
- # Copyright (c) 2018 Yubico AB
2
- # All rights reserved.
3
- #
4
- # Redistribution and use in source and binary forms, with or
5
- # without modification, are permitted provided that the following
6
- # conditions are met:
7
- #
8
- # 1. Redistributions of source code must retain the above copyright
9
- # notice, this list of conditions and the following disclaimer.
10
- # 2. Redistributions in binary form must reproduce the above
11
- # copyright notice, this list of conditions and the following
12
- # disclaimer in the documentation and/or other materials provided
13
- # with the distribution.
14
- #
15
- # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16
- # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17
- # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
18
- # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19
- # COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20
- # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21
- # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22
- # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23
- # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24
- # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
25
- # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26
- # POSSIBILITY OF SUCH DAMAGE.
27
-
28
- from __future__ import print_function, absolute_import, unicode_literals
29
-
30
- from fido2.hid import CtapHidDevice
31
- from fido2.client import Fido2Client
32
- from fido2.ctap2.extensions import HmacSecretExtension
33
- from fido2.utils import websafe_encode
34
-
35
- import sys, getopt, random, string
36
-
37
- def randomString(stringLength=8):
38
- letters = string.ascii_lowercase
39
- return ''.join(random.choice(letters) for i in range(stringLength))
40
-
41
- argv = sys.argv[1:]
42
- try:
43
- opts, args = getopt.getopt(argv,"i:n:",[])
44
- except getopt.GetoptError:
45
- print('python fido2_credential.py -i id -n name')
46
- sys.exit(2)
47
- for opt, arg in opts:
48
- if opt in ("-i"):
49
- user_id = arg
50
- elif opt in ("-n"):
51
- user_name = arg
52
-
53
- try:
54
- from fido2.pcsc import CtapPcscDevice
55
- except ImportError:
56
- CtapPcscDevice = None
57
-
58
-
59
- def enumerate_devices():
60
- for dev in CtapHidDevice.list_devices():
61
- yield dev
62
- if CtapPcscDevice:
63
- for dev in CtapPcscDevice.list_devices():
64
- yield dev
65
-
66
- for dev in enumerate_devices():
67
- client = Fido2Client(dev, "https://secrez.io")
68
- if HmacSecretExtension.NAME in client.info.extensions:
69
- break
70
- else:
71
- print("No Authenticator with the HmacSecret extension found!")
72
- sys.exit(1)
73
-
74
- rp = {"id": "secrez.io", "name": "secrez"}
75
- user = {"id": bytes(user_id, encoding='utf-8'), "name": user_name}
76
- challenge = bytes(randomString(12), encoding='utf-8')
77
- hmac_ext = HmacSecretExtension(client.ctap2)
78
- attestation_object, client_data = client.make_credential(
79
- {
80
- "rp": rp,
81
- "user": user,
82
- "challenge": challenge,
83
- "pubKeyCredParams": [{"type": "public-key", "alg": -7}],
84
- "extensions": hmac_ext.create_dict(),
85
- }
86
- )
87
- credential = attestation_object.auth_data.credential_data
88
- print(websafe_encode(credential))
@@ -1,111 +0,0 @@
1
- # Copyright (c) 2018 Yubico AB
2
- # All rights reserved.
3
- #
4
- # Redistribution and use in source and binary forms, with or
5
- # without modification, are permitted provided that the following
6
- # conditions are met:
7
- #
8
- # 1. Redistributions of source code must retain the above copyright
9
- # notice, this list of conditions and the following disclaimer.
10
- # 2. Redistributions in binary form must reproduce the above
11
- # copyright notice, this list of conditions and the following
12
- # disclaimer in the documentation and/or other materials provided
13
- # with the distribution.
14
- #
15
- # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16
- # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17
- # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
18
- # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19
- # COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20
- # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21
- # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22
- # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23
- # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24
- # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
25
- # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26
- # POSSIBILITY OF SUCH DAMAGE.
27
-
28
- from __future__ import print_function, absolute_import, unicode_literals
29
-
30
- from fido2.hid import CtapHidDevice
31
- from fido2.client import Fido2Client
32
- from fido2.ctap2.extensions import HmacSecretExtension
33
- from fido2.utils import websafe_encode, websafe_decode
34
- from fido2.ctap2 import AttestedCredentialData
35
-
36
- from binascii import b2a_hex
37
- import sys, getopt, random, string
38
-
39
- def randomString(stringLength=8):
40
- letters = string.ascii_lowercase
41
- return ''.join(random.choice(letters) for i in range(stringLength))
42
-
43
- argv = sys.argv[1:]
44
- try:
45
- opts, args = getopt.getopt(argv,"i:n:s:c:",[])
46
- except getopt.GetoptError:
47
- print('test.py -i <inputfile> -o <outputfile>')
48
- sys.exit(2)
49
- for opt, arg in opts:
50
- if opt in ("-i"):
51
- user_id = arg
52
- elif opt in ("-n"):
53
- user_name = arg
54
- elif opt in ("-s"):
55
- salt = bytes(arg, encoding='utf-8')
56
- elif opt in ("-c"):
57
- credential = AttestedCredentialData(websafe_decode(arg))
58
-
59
- try:
60
- from fido2.pcsc import CtapPcscDevice
61
- except ImportError:
62
- CtapPcscDevice = None
63
-
64
-
65
- def enumerate_devices():
66
- for dev in CtapHidDevice.list_devices():
67
- yield dev
68
- if CtapPcscDevice:
69
- for dev in CtapPcscDevice.list_devices():
70
- yield dev
71
-
72
-
73
- # Locate a device
74
- for dev in enumerate_devices():
75
- client = Fido2Client(dev, "https://secrez.io")
76
- if HmacSecretExtension.NAME in client.info.extensions:
77
- break
78
- else:
79
- print("No Authenticator with the HmacSecret extension found!")
80
- sys.exit(1)
81
-
82
- # use_nfc = CtapPcscDevice and isinstance(dev, CtapPcscDevice)
83
-
84
- # Prepare parameters for makeCredential
85
- rp = {"id": "secrez.io", "name": "secrez.io"}
86
- user = {"id": bytes(user_id, encoding='utf-8'), "name": user_name}
87
-
88
- challenge = bytes(randomString(12), encoding='utf-8')
89
-
90
- hmac_ext = HmacSecretExtension(client.ctap2)
91
-
92
- challenge = bytes(randomString(12), encoding='utf-8')
93
-
94
- allow_list = [{"type": "public-key", "id": credential.credential_id}]
95
-
96
- assertions, client_data = client.get_assertion(
97
- {
98
- "rpId": rp["id"],
99
- "challenge": challenge,
100
- "allowCredentials": allow_list,
101
- "extensions": hmac_ext.get_dict(salt),
102
- }
103
- )
104
-
105
- assertion = assertions[0]
106
- hmac_res = hmac_ext.results_for(assertion.auth_data)
107
-
108
- secret = b2a_hex(hmac_res[0]).decode("utf-8")
109
-
110
- print(secret)
111
-
@@ -1,56 +0,0 @@
1
- # Copyright (c) 2018 Yubico AB
2
- # All rights reserved.
3
- #
4
- # Redistribution and use in source and binary forms, with or
5
- # without modification, are permitted provided that the following
6
- # conditions are met:
7
- #
8
- # 1. Redistributions of source code must retain the above copyright
9
- # notice, this list of conditions and the following disclaimer.
10
- # 2. Redistributions in binary form must reproduce the above
11
- # copyright notice, this list of conditions and the following
12
- # disclaimer in the documentation and/or other materials provided
13
- # with the distribution.
14
- #
15
- # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16
- # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17
- # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
18
- # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19
- # COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20
- # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21
- # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22
- # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23
- # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24
- # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
25
- # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26
- # POSSIBILITY OF SUCH DAMAGE.
27
-
28
- from __future__ import print_function, absolute_import, unicode_literals
29
-
30
- from fido2.hid import CtapHidDevice
31
- from fido2.client import Fido2Client
32
- from fido2.ctap2.extensions import HmacSecretExtension
33
- from fido2.utils import websafe_encode, websafe_decode
34
- from fido2.ctap2 import AttestedCredentialData
35
-
36
- from binascii import b2a_hex
37
- import sys, getopt, random, string
38
-
39
- try:
40
- from fido2.pcsc import CtapPcscDevice
41
- except ImportError:
42
- CtapPcscDevice = None
43
-
44
- def enumerate_devices():
45
- for dev in CtapHidDevice.list_devices():
46
- yield dev
47
- if CtapPcscDevice:
48
- for dev in CtapPcscDevice.list_devices():
49
- yield dev
50
-
51
- for dev in enumerate_devices():
52
- client = Fido2Client(dev, "https://secrez.io")
53
- if HmacSecretExtension.NAME in client.info.extensions:
54
- break
55
-
56
- print('Ready')
@@ -1,118 +0,0 @@
1
- const path = require("path");
2
- const { Crypto } = require("@secrez/core");
3
- const { execAsync } = require("@secrez/utils");
4
- const _ = require("lodash");
5
-
6
- class Fido2Client {
7
- constructor(secrez) {
8
- this.keys = {};
9
- this.secrez = secrez;
10
- this.scriptsPath = path.resolve(__dirname, "../../scripts");
11
- }
12
-
13
- async updateConf() {
14
- const conf = await this.secrez.readConf();
15
- this.keys = {};
16
- if (conf.data.keys) {
17
- let keys = conf.data.keys;
18
- for (let authenticator in keys) {
19
- if (
20
- keys[authenticator].type === this.secrez.config.sharedKeys.FIDO2_KEY
21
- ) {
22
- let key = (this.keys[authenticator] = _.clone(keys[authenticator]));
23
- key.id = this.secrez.preDecryptData(key.id);
24
- key.salt = this.secrez.preDecryptData(key.salt);
25
- key.credential = this.secrez.preDecryptData(key.credential);
26
- }
27
- }
28
- }
29
- }
30
-
31
- async getKeys(asAList) {
32
- await this.updateConf();
33
- if (asAList) {
34
- let list = [];
35
- for (let authenticator in this.keys) {
36
- list.push([authenticator, this.keys[authenticator].type]);
37
- }
38
- return list;
39
- } else {
40
- return this.keys;
41
- }
42
- }
43
-
44
- setParams(options) {
45
- let params = [
46
- options.credential ? "hmac_secret.py" : "fido2_credential.py",
47
- "-n",
48
- options.authenticator,
49
- "-i",
50
- options.id,
51
- ];
52
- if (options.credential) {
53
- params.push("-c", options.credential);
54
- }
55
- if (options.salt) {
56
- params.push("-s", options.salt);
57
- }
58
- return params;
59
- }
60
-
61
- async checkIfReady() {
62
- let result = await execAsync("which", __dirname, ["python"]);
63
- if (result.code !== 0 || typeof result.message === "undefined") {
64
- throw new Error(
65
- "The Fido2 module requires Python. Please install it on your computer."
66
- );
67
- }
68
- result = await execAsync("python", this.scriptsPath, ["is_fido2_ready.py"]);
69
- if (result.message !== "Ready") {
70
- throw new Error(
71
- 'Python-fido2 is required. Install it with "pip install fido2"'
72
- );
73
- }
74
- }
75
-
76
- async setCredential(options) {
77
- return await execAsync("python", this.scriptsPath, this.setParams(options));
78
- }
79
-
80
- async getSecret(options) {
81
- return await execAsync("python", this.scriptsPath, this.setParams(options));
82
- }
83
-
84
- async verifySecret(authenticator) {
85
- await this.updateConf();
86
- let key = this.keys[authenticator];
87
- let fido2Options = {
88
- id: key.id,
89
- authenticator,
90
- salt: key.salt,
91
- credential: key.credential,
92
- };
93
- let result = await this.getSecret(fido2Options);
94
- this.checkErrorCode(result, 1);
95
- if (Crypto.b58Hash(result.message) === key.hash) {
96
- return result.message;
97
- } else {
98
- throw new Error(`You used a different key for ${authenticator}`);
99
- }
100
- }
101
-
102
- checkErrorCode(result, num) {
103
- if (result.code !== 0) {
104
- let err = "No Authenticator with the HmacSecret extension found!";
105
- if (result.error === err) {
106
- throw new Error(err);
107
- } else {
108
- throw new Error(
109
- num === 1
110
- ? "Fido2 authenticator device not found"
111
- : "Something went wrong"
112
- );
113
- }
114
- }
115
- }
116
- }
117
-
118
- module.exports = Fido2Client;