generate-pw 1.2.0 → 1.2.2
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 +18 -9
- package/dist/generate-pw.min.js +10 -0
- package/docs/LICENSE.md +3 -1
- package/docs/SECURITY.md +3 -1
- package/package.json +16 -5
- package/docs/zh-cn/LICENSE.md +0 -21
- package/docs/zh-cn/README.md +0 -214
- package/docs/zh-cn/SECURITY.md +0 -17
- package/docs/zh-tw/LICENSE.md +0 -21
- package/docs/zh-tw/README.md +0 -214
- package/docs/zh-tw/SECURITY.md +0 -17
- package/generate-pw.js +0 -270
package/README.md
CHANGED
|
@@ -5,8 +5,10 @@
|
|
|
5
5
|
<img height=14 src="https://raw.githubusercontent.com/adamlui/js-utils/main/docs/images/earth-icon/black/icon32.svg">
|
|
6
6
|
</picture>
|
|
7
7
|
English |
|
|
8
|
-
<a href="https://github.com/adamlui/js-utils/tree/main/
|
|
9
|
-
<a href="https://github.com/adamlui/js-utils/tree/main/
|
|
8
|
+
<a href="https://github.com/adamlui/js-utils/tree/main/generate-pw/docs/zh-cn#readme">简体中文</a> |
|
|
9
|
+
<a href="https://github.com/adamlui/js-utils/tree/main/generate-pw/docs/zh-tw#readme">繁體中文</a> |
|
|
10
|
+
<a href="https://github.com/adamlui/js-utils/tree/main/generate-pw/docs/hi#readme">हिंदी</a> |
|
|
11
|
+
<a href="https://github.com/adamlui/js-utils/tree/main/generate-pw/docs/bn#readme">বাংলা</a>
|
|
10
12
|
</h6>
|
|
11
13
|
</div>
|
|
12
14
|
|
|
@@ -15,7 +17,7 @@
|
|
|
15
17
|
### Randomly generate cryptographically-secure passwords.
|
|
16
18
|
|
|
17
19
|
<a href="#%EF%B8%8F-mit-license"><img height=31 src="https://img.shields.io/badge/License-MIT-orange.svg?logo=internetarchive&logoColor=white&labelColor=464646&style=for-the-badge"></a>
|
|
18
|
-
<a href="https://
|
|
20
|
+
<a href="https://github.com/adamlui/js-utils/releases/tag/generate-pw-1.2.2"><img height=31 src="https://img.shields.io/badge/Latest_Build-1.2.2-44cc11.svg?logo=icinga&logoColor=white&labelColor=464646&style=for-the-badge"></a>
|
|
19
21
|
<a href="https://www.npmjs.com/package/generate-pw?activeTab=code"><img height=31 src="https://img.shields.io/npm/unpacked-size/generate-pw?style=for-the-badge&logo=ebox&logoColor=white&labelColor=464646&color=blue"></a>
|
|
20
22
|
<a href="https://sonarcloud.io/component_measures?metric=new_vulnerabilities&id=adamlui_js-utils:generate-pw/generate-pw.js"><img height=31 src="https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fsonarcloud.io%2Fapi%2Fmeasures%2Fcomponent%3Fcomponent%3Dadamlui_js-utils%3Agenerate-pw%2Fgenerate-pw.js%26metricKeys%3Dvulnerabilities&query=%24.component.measures.0.value&style=for-the-badge&logo=sonarcloud&logoColor=white&labelColor=464646&label=Vulnerabilities&color=gold"></a>
|
|
21
23
|
|
|
@@ -101,14 +103,14 @@ See: [Available options](#available-options-for-generate-functions)
|
|
|
101
103
|
|
|
102
104
|
### `strictify(password[, requiredCharTypes])`
|
|
103
105
|
|
|
104
|
-
Modifies `password` given to use at least one character of each `requiredCharTypes` element passed, returning a string
|
|
106
|
+
Modifies `password` given to use at least one character of each `requiredCharTypes` element passed, returning a string:
|
|
105
107
|
|
|
106
108
|
```js
|
|
107
109
|
const password = 'abcdef',
|
|
108
110
|
strictPW = pw.strictify(password, ['numbers', 'symbols']);
|
|
109
111
|
|
|
110
112
|
console.log(strictPW);
|
|
111
|
-
// sample output: 'a!
|
|
113
|
+
// sample output: 'a!c2ef'
|
|
112
114
|
```
|
|
113
115
|
|
|
114
116
|
Available `requiredCharTypes` are: `['number', 'symbol', 'lower', 'upper']`
|
|
@@ -119,7 +121,12 @@ Available `requiredCharTypes` are: `['number', 'symbol', 'lower', 'upper']`
|
|
|
119
121
|
|
|
120
122
|
### `validateStrength(password)`
|
|
121
123
|
|
|
122
|
-
Validates the strength of a password, returning an object containing
|
|
124
|
+
Validates the strength of a password, returning an object containing:
|
|
125
|
+
- `strengthScore` (0–100)
|
|
126
|
+
- `recommendations` array
|
|
127
|
+
- `isGood` boolean (`true` if `strengthScore` >= 80)
|
|
128
|
+
|
|
129
|
+
Example:
|
|
123
130
|
|
|
124
131
|
```js
|
|
125
132
|
const password = 'AawiddsE',
|
|
@@ -128,9 +135,11 @@ const password = 'AawiddsE',
|
|
|
128
135
|
console.log(pwStrength);
|
|
129
136
|
|
|
130
137
|
/* outputs:
|
|
138
|
+
|
|
131
139
|
{
|
|
132
140
|
strengthScore: 60,
|
|
133
|
-
recommendations: [ 'Include at least one number.', 'Include at least one symbol.' ]
|
|
141
|
+
recommendations: [ 'Include at least one number.', 'Include at least one symbol.' ],
|
|
142
|
+
isGood: false
|
|
134
143
|
}
|
|
135
144
|
*/
|
|
136
145
|
```
|
|
@@ -161,13 +170,13 @@ Name | Type | Description
|
|
|
161
170
|
|
|
162
171
|
## 💻 Command line usage
|
|
163
172
|
|
|
164
|
-
When installed globally, **generate-pw** can also be used from the command line. The basic command is:
|
|
173
|
+
When installed [globally](#-installation), **generate-pw** can also be used from the command line. The basic command is:
|
|
165
174
|
|
|
166
175
|
```
|
|
167
176
|
$ generate-pw
|
|
168
177
|
```
|
|
169
178
|
|
|
170
|
-
**💡 Note:**
|
|
179
|
+
**💡 Note:** For security reasons, generated password(s) are stored in the clipboard.
|
|
171
180
|
|
|
172
181
|
#
|
|
173
182
|
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
const p=require("crypto")["randomInt"],s=require("child_process")["execSync"],u={lower:"abcdefghijklmnopqrstuvwxyz",upper:"ABCDEFGHIJKLMNOPQRSTUVWXYZ",numbers:"0123456789",symbols:"!@#$%^&*()-_=+[]{}/\\|;:'\",.<>?"};function a(o={}){var e,s={length:8,qty:1,charset:"",exclude:"",numbers:!1,symbols:!1,lowercase:!0,uppercase:!0,strict:!1};o={...s,...o};for(const r of Object.keys(o))if(!Object.prototype.hasOwnProperty.call(s,r))return console.error(`generatePassword() » ERROR: \`${r}\` is an invalid option.`+`
|
|
3
|
+
generatePassword() » Valid options:
|
|
4
|
+
[ ${Object.keys(s).join(", ")} ]`);for(const n of["length","qty"])if(isNaN(o[n])||o[n]<1)return console.error(`generatePassword() » ERROR: [${n}] option must be > 1.`);for(const a of["numbers","symbols","lowercase","uppercase","strict"])if("boolean"!=typeof o[a])return console.error(`generatePassword() » ERROR: [${a}] option can only be \`true\` or \`false\`.`);if(1<o.qty){const{qty:l,...c}=o;return i(l,c)}{let s=o.charset||(o.numbers?u.numbers:"")+(o.symbols?u.symbols:"")+(o.lowercase?u.lower:"")+(o.uppercase?u.upper:""),r=(s=(s=""===s?u.lower+u.upper:s).replace(new RegExp(`[${o.exclude}]`,"g"),""),"");for(let e=0;e<o.length;e++){var t=p(0,s.length);r+=s.charAt(t)}return o.strict&&(e=["number","symbol","lower","upper"].filter(e=>o[e+"s"]||o[e+"case"]),r=m(r,e)),r}}function i(s,r={}){var e={length:8,qty:1,charset:"",exclude:"",numbers:!1,symbols:!1,lowercase:!0,uppercase:!0,strict:!1};if(r={...e,...r},s=parseInt(s),isNaN(s))return console.error("generatePasswords() » ERROR: First argument [qty] of generatePasswords() must be an integer");for(const t of Object.keys(r))if(!Object.prototype.hasOwnProperty.call(e,t))return console.error(`generatePasswords() » ERROR: \`${t}\` is an invalid option.`+`
|
|
5
|
+
generatePassword() » Valid options:
|
|
6
|
+
[ ${Object.keys(e).join(", ")} ]`);if(isNaN(r.length)||r.length<1)return console.error("generatePasswords() » ERROR: [length] options must be > 1.");for(const n of["numbers","symbols","lowercase","uppercase","strict"])if("boolean"!=typeof r[n])return console.error(`generatePasswords() » ERROR: [${n}] option can only be \`true\` or \`false\`.`);var o=[];for(let e=0;e<s;e++)o.push(a(r));return o}function m(s,r=["number","symbol","lower","upper"]){for(const l of r)global["has"+l.charAt(0).toUpperCase()+l.slice(1)]=!1;for(let e=0;e<s.length;e++)for(const c of r)(u[c]||u[c+"s"]).includes(s.charAt(e))&&(global["has"+c.charAt(0).toUpperCase()+c.slice(1)]=!0);var e=Math.min(s.length,r.length),o=[];let t=0,n=s;for(const i of r)if(t<e&&!global["has"+i.charAt(0).toUpperCase()+i.slice(1)]){let e;for(;e=p(0,s.length),o.includes(e););o.push(e);var a=u[i]||u[i+"s"];n=n.substring(0,e)+a.charAt(p(0,a.length))+n.substring(e+1),t++}return n}function e(e){var s={minLength:8,minLower:1,minUpper:1,minNumber:1,minSymbol:1},r={lower:0,upper:0,number:0,symbol:0};for(const n of e)for(const a of Object.keys(r))(u[a]||u[a+"s"]).includes(n)&&r[a]++;var o=[];e.length<s.minLength&&o.push(`Make it at least ${s.minLength} characters long.`);for(const l of Object.keys(r))r[l]<s["min"+l.charAt(0).toUpperCase()+l.slice(1)]&&o.push("Include at least one "+l+`${["upper","lower"].includes(l)?"case letter":""}.`);let t=0;t+=e.length>=s.minLength?20:0;for(const c of Object.keys(r))t+=r[c]>=s["min"+c.charAt(0).toUpperCase()+c.slice(1)]?20:0;return{strengthScore:t,recommendations:o,isGood:80<=t}}if(require.main!==module)module.exports={generatePassword:a,generatePasswords:i,strictify:m,validateStrength:e};else{const n="[0m",l="[1;91m",c="[1;33m",h={},d={paramOptions:{length:/^--?length/,qty:/^--?qu?a?n?ti?t?y=.*$/,charset:/^--?chars/,excludeChars:/^--?exclude=/},flags:{includeNums:/^--?(?:n|(?:include-?)?num(?:ber)?s?=?(?:true|1)?)$/,includeSymbols:/^--?(?:s|(?:include-?)?symbols?=?(?:true|1)?)$/,excludeLowerChars:/^--?(?:L|(?:exclude|disable|no)-?lower-?(?:case)?|lower-?(?:case)?=(?:false|0))$/,excludeUpperChars:/^--?(?:U|(?:exclude|disable|no)-?upper-?(?:case)?|upper-?(?:case)?=(?:false|0))$/,strictMode:/^--?s(?:trict)?(?:-?mode)?$/},cmds:{help:/^--?h(?:elp)?$/,version:/^--?ve?r?s?i?o?n?$/}};if(process.argv.forEach(s=>{var e,r,o;s.startsWith("-")&&(o=Object.keys(d.flags).find(e=>d.flags[e].test(s)),e=Object.keys(d.paramOptions).find(e=>d.paramOptions[e].test(s)),r=Object.keys(d.cmds).find(e=>d.cmds[e].test(s)),o?h[o]=!0:e?(o=s.split("=")[1],h[e]=parseInt(o)||o):r||(console.error(`
|
|
7
|
+
${l}ERROR: Arg [${s}] not recognized.`+n),console.info(`
|
|
8
|
+
${c}Valid arguments are below.`+n),t(["paramOptions","booelanOptions","infoCmds"]),process.exit(1)))}),process.argv.some(e=>/^--?h(?:elp)?$/.test(e)))t();else if(process.argv.some(e=>/^--?ve?r?s?i?o?n?$/.test(e)))console.info("v"+require("./package.json").version);else{for(const g of["length","qty"])h[g]&&(isNaN(h[g])||h[g]<1)&&(console.error(`
|
|
9
|
+
${l}Error: [${g}] argument must be > 1.`+n),process.exit(1));const o={length:h.length||8,qty:h.qty||1,charset:h.charset,exclude:h.excludeChars,numbers:!!h.includeNums,symbols:!!h.includeSymbols,lowercase:!h.excludeLowerChars,uppercase:!h.excludeUpperChars,strict:!!h.strictMode},f=a(o);r(Array.isArray(f)?f.join("\n"):f)}function t(e=["cmdFormat","paramOptions","booelanOptions","infoCmds"]){const s={cmdFormat:[`
|
|
10
|
+
${c}generate-pw [options|commands]`+n],paramOptions:["\nParameter options:"," --length=n Generate password(s) of n length."," --qty=n Generate n password(s)."," --charset=chars Only include chars in password(s)."," --charset=chars Only include chars in password(s)."," --exclude=chars Exclude chars from password(s)."],booelanOptions:["\nBoolean options:"," -n, --include-numbers Allow numbers in password(s)."," -s, --include-symbols Allow symbols in password(s)."," -L, --no-lowercase Disallow lowercase letters in password(s)."," -U, --no-uppercase Disallow uppercase letters in password(s)."],infoCmds:["\nInfo commands:"," -h, --help Display help screen."," -v, --version Show version number."]};e.forEach(e=>{s[e]?.forEach(e=>{{const o=process.stdout.columns||80,t=[],s=e.match(/\S+|\s+/g);let r="";s.forEach(e=>{var s=o-(0===t.length?0:29);r.length+e.length>s&&(t.push(0===t.length?r:r.trimStart()),r=""),r+=e}),t.push(0===t.length?r:r.trimStart()),t.forEach((e,s)=>console.info(0===s?e:" ".repeat(29)+e))}})})}function r(e){e=e.replace(/\s+$/m,"").replace(/"/g,'""'),"darwin"===process.platform?s(`printf "${e}" | pbcopy`):"linux"===process.platform?s(`printf "${e}" | xclip -selection clipboard`):"win32"===process.platform&&s(`Set-Clipboard -Value "${e}"`,{shell:"powershell"})}}
|
package/docs/LICENSE.md
CHANGED
package/docs/SECURITY.md
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "generate-pw",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.2",
|
|
4
4
|
"description": "Randomly generate cryptographically-secure passwords.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Adam Lui",
|
|
@@ -9,13 +9,19 @@
|
|
|
9
9
|
},
|
|
10
10
|
"homepage": "https://github.com/adamlui/js-utils",
|
|
11
11
|
"license": "MIT",
|
|
12
|
-
"main": "generate-pw.js",
|
|
12
|
+
"main": "dist/generate-pw.min.js",
|
|
13
|
+
"files": [
|
|
14
|
+
"dist",
|
|
15
|
+
"docs/",
|
|
16
|
+
"!docs/*/"
|
|
17
|
+
],
|
|
13
18
|
"bin": {
|
|
14
|
-
"generatepw": "generate-pw.js",
|
|
15
|
-
"generate-pw": "generate-pw.js"
|
|
19
|
+
"generatepw": "dist/generate-pw.min.js",
|
|
20
|
+
"generate-pw": "dist/generate-pw.min.js"
|
|
16
21
|
},
|
|
17
22
|
"scripts": {
|
|
18
23
|
"test": "echo \"Error: no test specified\" && exit 1",
|
|
24
|
+
"build": "minify-js generate-pw.js dist",
|
|
19
25
|
"bump:patch": "bash utils/bump.sh patch",
|
|
20
26
|
"bump:minor": "bash utils/bump.sh minor",
|
|
21
27
|
"bump:major": "bash utils/bump.sh major",
|
|
@@ -31,7 +37,9 @@
|
|
|
31
37
|
"password",
|
|
32
38
|
"generator",
|
|
33
39
|
"unique",
|
|
34
|
-
"generate"
|
|
40
|
+
"generate",
|
|
41
|
+
"api",
|
|
42
|
+
"cli"
|
|
35
43
|
],
|
|
36
44
|
"bugs": {
|
|
37
45
|
"url": "https://github.com/adamlui/js-utils/issues"
|
|
@@ -39,5 +47,8 @@
|
|
|
39
47
|
"funding": {
|
|
40
48
|
"type": "github",
|
|
41
49
|
"url": "https://github.com/sponsors/adamlui"
|
|
50
|
+
},
|
|
51
|
+
"devDependencies": {
|
|
52
|
+
"@adamlui/minify.js": "^1.4.6"
|
|
42
53
|
}
|
|
43
54
|
}
|
package/docs/zh-cn/LICENSE.md
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
<div align="right">
|
|
2
|
-
<h6>
|
|
3
|
-
<picture>
|
|
4
|
-
<source type="image/svg+xml" media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/adamlui/js-utils/main/docs/images/earth-icon/white/icon32.svg">
|
|
5
|
-
<img height=14 src="https://raw.githubusercontent.com/adamlui/js-utils/main/docs/images/earth-icon/black/icon32.svg">
|
|
6
|
-
</picture>
|
|
7
|
-
简体中文 |
|
|
8
|
-
<a href="../LICENSE.md">English</a> |
|
|
9
|
-
<a href="../zh-tw/LICENSE.md">繁體中文</a>
|
|
10
|
-
</h6>
|
|
11
|
-
</div>
|
|
12
|
-
|
|
13
|
-
# 🏛️ MIT 许可证
|
|
14
|
-
|
|
15
|
-
**版权所有 © 2024 [刘展鹏 (Adam Lui)](https://github.com/adamlui)**
|
|
16
|
-
|
|
17
|
-
特此免费向任何获得副本的人授予许可本软件和相关文档文件(『软件』),处理在软件中不受限制,包括但不限于权利使用、复制、修改、合并、发布、分发、再许可和/或出售该软件的副本,并允许该软件是提供这样做,但须满足以下条件:
|
|
18
|
-
|
|
19
|
-
上述版权声明和本许可声明应包含在所有软件的副本或重要部分。
|
|
20
|
-
|
|
21
|
-
本软件『按原样』提供,不提供任何形式的明示或保证暗示的,包括但不限于适销性保证,适用于特定目的和非侵权。 在任何情况下都不得作者或版权持有人对任何索赔、损害或其他责任,无论是在合同、侵权或其他方面的行为中,由以下原因引起,出于或与软件或使用或其他交易有关软件。
|
package/docs/zh-cn/README.md
DELETED
|
@@ -1,214 +0,0 @@
|
|
|
1
|
-
<div align="right">
|
|
2
|
-
<h6>
|
|
3
|
-
<picture>
|
|
4
|
-
<source type="image/svg+xml" media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/adamlui/js-utils/main/docs/images/earth-icon/white/icon32.svg">
|
|
5
|
-
<img height=14 src="https://raw.githubusercontent.com/adamlui/js-utils/main/docs/images/earth-icon/black/icon32.svg">
|
|
6
|
-
</picture>
|
|
7
|
-
简体中文 |
|
|
8
|
-
<a href="../..#readme">English</a> |
|
|
9
|
-
<a href="../zh-tw#readme">繁體中文</a>
|
|
10
|
-
</h6>
|
|
11
|
-
</div>
|
|
12
|
-
|
|
13
|
-
# > generate-pw
|
|
14
|
-
|
|
15
|
-
### 随机生成加密安全密码。
|
|
16
|
-
|
|
17
|
-
<a href="#%EF%B8%8F-mit-%E8%AE%B8%E5%8F%AF%E8%AF%81"><img height=31 src="https://img.shields.io/badge/许可证-MIT-orange.svg?logo=internetarchive&logoColor=white&labelColor=464646&style=for-the-badge"></a>
|
|
18
|
-
<a href="https://www.npmjs.com/package/generate-pw?activeTab=versions"><img height=31 src="https://img.shields.io/badge/最新版本-1.2.0-44cc11.svg?logo=icinga&logoColor=white&labelColor=464646&style=for-the-badge"></a>
|
|
19
|
-
<a href="https://www.npmjs.com/package/generate-pw?activeTab=code"><img height=31 src="https://img.shields.io/npm/unpacked-size/generate-pw?label=%E6%8B%86%E5%B0%81%E5%B0%BA%E5%AF%B8&style=for-the-badge&logo=ebox&logoColor=white&labelColor=464646&color=blue"></a>
|
|
20
|
-
<a href="https://sonarcloud.io/component_measures?metric=new_vulnerabilities&id=adamlui_js-utils:generate-pw/generate-pw.js"><img height=31 src="https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fsonarcloud.io%2Fapi%2Fmeasures%2Fcomponent%3Fcomponent%3Dadamlui_js-utils%3Agenerate-pw%2Fgenerate-pw.js%26metricKeys%3Dvulnerabilities&query=%24.component.measures.0.value&style=for-the-badge&logo=sonarcloud&logoColor=white&labelColor=464646&label=%E6%BC%8F%E6%B4%9E&color=gold"></a>
|
|
21
|
-
|
|
22
|
-
<br>
|
|
23
|
-
|
|
24
|
-
<img height=6px width="100%" src="https://raw.githubusercontent.com/adamlui/js-utils/main/docs/images/aqua-separator.png">
|
|
25
|
-
|
|
26
|
-
## ⚡ 安装
|
|
27
|
-
|
|
28
|
-
作为**全局实用程序**:
|
|
29
|
-
|
|
30
|
-
```
|
|
31
|
-
$ npm install -g generate-pw
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
作为 **运行时依赖项**,从项目根目录:
|
|
35
|
-
|
|
36
|
-
```
|
|
37
|
-
$ npm install generate-pw
|
|
38
|
-
```
|
|
39
|
-
|
|
40
|
-
<br>
|
|
41
|
-
|
|
42
|
-
<img height=6px width="100%" src="https://raw.githubusercontent.com/adamlui/js-utils/main/docs/images/aqua-separator.png">
|
|
43
|
-
|
|
44
|
-
## 🔌 API 使用
|
|
45
|
-
|
|
46
|
-
**generate-pw** 可以作为 ECMAScript 模块或 CommonJS 模块导入到您的应用程序中。
|
|
47
|
-
|
|
48
|
-
#### ESM:
|
|
49
|
-
|
|
50
|
-
```js
|
|
51
|
-
import * as pw from 'generate-pw';
|
|
52
|
-
```
|
|
53
|
-
|
|
54
|
-
#### CJS:
|
|
55
|
-
|
|
56
|
-
```js
|
|
57
|
-
const pw = require('generate-pw');
|
|
58
|
-
```
|
|
59
|
-
|
|
60
|
-
#
|
|
61
|
-
|
|
62
|
-
### `generatePassword([options])`
|
|
63
|
-
|
|
64
|
-
如果未给出 `qty` 选项,则生成**一个**密码,并返回一个字符串:
|
|
65
|
-
|
|
66
|
-
```js
|
|
67
|
-
const password = pw.generatePassword({ length: 11, numbers: true });
|
|
68
|
-
console.log(password);
|
|
69
|
-
// 示例输出:'bAsZm3mq6Qn'
|
|
70
|
-
```
|
|
71
|
-
|
|
72
|
-
...或 **多个** 密码(如果给出了 `qty` 选项),返回一个字符串数组:
|
|
73
|
-
|
|
74
|
-
```js
|
|
75
|
-
const passwords = pw.generatePassword({ qty: 5, length: 8, symbols: true });
|
|
76
|
-
console.log(passwords);
|
|
77
|
-
// 示例输出:[ '!zSf@Q.s', '!,HT\\;m=', '?Lq&FV>^', 'gf}Y;}Ne', 'Stsx(GqE' ]
|
|
78
|
-
```
|
|
79
|
-
|
|
80
|
-
**💡 注意:**如果不传递任何选项,密码将为 8 个字符长,由大小写字母组成。
|
|
81
|
-
|
|
82
|
-
请参阅:[可用选项](#available-options-for-generate-functions)
|
|
83
|
-
|
|
84
|
-
#
|
|
85
|
-
|
|
86
|
-
### `generatePasswords(qty[, options])`
|
|
87
|
-
|
|
88
|
-
根据给定的 `qty` 生成**多个**密码,返回字符串数组:
|
|
89
|
-
|
|
90
|
-
```js
|
|
91
|
-
const passwords = pw.generatePasswords(5, { length: 3, uppercase: false });
|
|
92
|
-
console.log(passwords);
|
|
93
|
-
// 示例输出:[ 'yilppxru', 'ckvkyjfp', 'zolcpyfb' ]
|
|
94
|
-
```
|
|
95
|
-
|
|
96
|
-
**💡 注意:**如果没有传递 `qty` 参数,则只会生成一个密码,并以字符串形式返回。
|
|
97
|
-
|
|
98
|
-
请参阅:[可用选项](#available-options-for-generate-functions)
|
|
99
|
-
|
|
100
|
-
#
|
|
101
|
-
|
|
102
|
-
### `strictify(password[, requiredCharTypes])`
|
|
103
|
-
|
|
104
|
-
修改指定的 `password`,以使用传递的每个 `requiredCharTypes` 元素中的至少一个字符,返回一个字符串。
|
|
105
|
-
|
|
106
|
-
```js
|
|
107
|
-
const password = 'abcdef',
|
|
108
|
-
strictPW = pw.strictify(password, ['numbers', 'symbols']);
|
|
109
|
-
|
|
110
|
-
console.log(strictPW);
|
|
111
|
-
// 示例输出:'a!c2eR'
|
|
112
|
-
```
|
|
113
|
-
|
|
114
|
-
可用的 `requiredCharTypes` 有:`['number', 'symbol', 'lower', 'upper']`
|
|
115
|
-
|
|
116
|
-
**💡注意:**如果没有传递 `requiredCharTypes` 数组,则所有可用类型都将是必需的。
|
|
117
|
-
|
|
118
|
-
#
|
|
119
|
-
|
|
120
|
-
### `validateStrength(password)`
|
|
121
|
-
|
|
122
|
-
验证密码的强度,返回一个包含 `strengthScore`(满分 100)+ `recommendations` 数组的对象。
|
|
123
|
-
|
|
124
|
-
```js
|
|
125
|
-
const password = 'AawiddsE',
|
|
126
|
-
pwStrength = pw.validateStrength(password);
|
|
127
|
-
|
|
128
|
-
console.log(pwStrength);
|
|
129
|
-
|
|
130
|
-
/* 输出:
|
|
131
|
-
{
|
|
132
|
-
strengthScore: 60,
|
|
133
|
-
recommendations: [ 'Include at least one number.', 'Include at least one symbol.' ]
|
|
134
|
-
}
|
|
135
|
-
*/
|
|
136
|
-
```
|
|
137
|
-
|
|
138
|
-
#
|
|
139
|
-
|
|
140
|
-
### `generate*()` 函数的可用选项
|
|
141
|
-
|
|
142
|
-
其中任何一个都可以传递到每个 `generate*()` 函数的选项对象中:
|
|
143
|
-
|
|
144
|
-
姓名 | 类型 | 描述 | 默认值
|
|
145
|
-
------------|--------|-----------------------------------------|--------
|
|
146
|
-
`length` | 整数 | 密码的长度。 | `8`
|
|
147
|
-
`qty`* | 整数 | 要生成的密码数量。 | `1`
|
|
148
|
-
`charset` | 字符串 | 密码中包含的字符。 | `''`
|
|
149
|
-
`exclude` | 字符串 | 要从密码中排除的字符。 | `''`
|
|
150
|
-
`numbers` | 布尔值 | 允许密码中包含数字。 | `false`
|
|
151
|
-
`symbols` | 布尔值 | 允许密码中包含符号。 | `false`
|
|
152
|
-
`lowercase` | 布尔值 | 密码中允许使用小写字母。 | `true`
|
|
153
|
-
`uppercase` | 布尔值 | 密码中允许使用大写字母。 | `true`
|
|
154
|
-
`strict` | 布尔值 | 要求密码中每个允许的字符集中至少有一个字符。 | `false`
|
|
155
|
-
|
|
156
|
-
##### _*仅在 [`generatePassword([options])`](#generatepasswordoptions) 中可用,因为 [`generatePasswords(qty[, options])`](#generatepasswordsqty-options) 采用 `qty` 参数_
|
|
157
|
-
|
|
158
|
-
<br>
|
|
159
|
-
|
|
160
|
-
<img height=6px width="100%" src="https://raw.githubusercontent.com/adamlui/js-utils/main/docs/images/aqua-separator.png">
|
|
161
|
-
|
|
162
|
-
## 💻 命令行使用
|
|
163
|
-
|
|
164
|
-
全局安装时,**generate-pw** 也可以从命令行使用。 基本命令是:
|
|
165
|
-
|
|
166
|
-
```
|
|
167
|
-
$ generate-pw
|
|
168
|
-
```
|
|
169
|
-
|
|
170
|
-
**💡 注意:**要生成多个结果,请传递 `--qty=n`,其中 `n` 是要生成的密码数量。
|
|
171
|
-
|
|
172
|
-
#
|
|
173
|
-
|
|
174
|
-
### 命令行选项
|
|
175
|
-
|
|
176
|
-
```
|
|
177
|
-
参数选项:
|
|
178
|
-
--length=n 生成 n 长度的密码。
|
|
179
|
-
--qty=n 生成 n 个密码。
|
|
180
|
-
--charset=chars 密码中仅包含 chars。
|
|
181
|
-
--exclude=chars 从密码中排除 chars。
|
|
182
|
-
|
|
183
|
-
布尔选项:
|
|
184
|
-
-n, --include-numbers 允许密码中包含数字。
|
|
185
|
-
-s, --include-symbols 允许密码中包含符号。
|
|
186
|
-
-L, --no-lowercase 密码中不允许使用小写字母。
|
|
187
|
-
-U, --no-uppercase 密码中不允许使用大写字母。
|
|
188
|
-
|
|
189
|
-
信息命令:
|
|
190
|
-
-h, --help 显示帮助屏幕。
|
|
191
|
-
-v, --version 显示版本号。
|
|
192
|
-
```
|
|
193
|
-
|
|
194
|
-
<br>
|
|
195
|
-
|
|
196
|
-
<img height=6px width="100%" src="https://raw.githubusercontent.com/adamlui/js-utils/main/docs/images/aqua-separator.png">
|
|
197
|
-
|
|
198
|
-
## 🏛️ MIT 许可证
|
|
199
|
-
|
|
200
|
-
**版权所有 © 2024 [刘展鹏 (Adam Lui)](https://github.com/adamlui)**
|
|
201
|
-
|
|
202
|
-
特此免费向任何获得副本的人授予许可本软件和相关文档文件(『软件』),处理在软件中不受限制,包括但不限于权利使用、复制、修改、合并、发布、分发、再许可和/或出售该软件的副本,并允许该软件是提供这样做,但须满足以下条件:
|
|
203
|
-
|
|
204
|
-
上述版权声明和本许可声明应包含在所有软件的副本或重要部分。
|
|
205
|
-
|
|
206
|
-
本软件『按原样』提供,不提供任何形式的明示或保证暗示的,包括但不限于适销性保证,适用于特定目的和非侵权。 在任何情况下都不得作者或版权持有人对任何索赔、损害或其他责任,无论是在合同、侵权或其他方面的行为中,由以下原因引起,出于或与软件或使用或其他交易有关软件。
|
|
207
|
-
|
|
208
|
-
<br>
|
|
209
|
-
|
|
210
|
-
<img height=6px width="100%" src="https://raw.githubusercontent.com/adamlui/js-utils/main/docs/images/aqua-separator.png">
|
|
211
|
-
|
|
212
|
-
<a href="https://github.com/adamlui/js-utils">**家**</a> /
|
|
213
|
-
<a href="https://github.com/adamlui/js-utils/discussions">讨论</a> /
|
|
214
|
-
<a href="#-generate-pw">回到顶部 ↑</a>
|
package/docs/zh-cn/SECURITY.md
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
<div align="right">
|
|
2
|
-
<h6>
|
|
3
|
-
<picture>
|
|
4
|
-
<source type="image/svg+xml" media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/adamlui/js-utils/main/docs/images/earth-icon/white/icon32.svg">
|
|
5
|
-
<img height=14 src="https://raw.githubusercontent.com/adamlui/js-utils/main/docs/images/earth-icon/black/icon32.svg">
|
|
6
|
-
</picture>
|
|
7
|
-
简体中文 |
|
|
8
|
-
<a href="../SECURITY.md">English</a> |
|
|
9
|
-
<a href="../zh-tw/SECURITY.md">繁體中文</a>
|
|
10
|
-
</h6>
|
|
11
|
-
</div>
|
|
12
|
-
|
|
13
|
-
# 🛡️ 安全政策
|
|
14
|
-
|
|
15
|
-
如果您发现漏洞,请打开[安全公告草案](https://github.com/adamlui/js-utils/security/advisories/new)。
|
|
16
|
-
|
|
17
|
-
也欢迎拉取请求,但出于安全原因,请发送电子邮件至 <adam@kudoai.com> 并等待回复后再公开。
|
package/docs/zh-tw/LICENSE.md
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
<div align="right">
|
|
2
|
-
<h6>
|
|
3
|
-
<picture>
|
|
4
|
-
<source type="image/svg+xml" media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/adamlui/js-utils/main/docs/images/earth-icon/white/icon32.svg">
|
|
5
|
-
<img height=14 src="https://raw.githubusercontent.com/adamlui/js-utils/main/docs/images/earth-icon/black/icon32.svg">
|
|
6
|
-
</picture>
|
|
7
|
-
繁體中文 |
|
|
8
|
-
<a href="../LICENSE.md">English</a> |
|
|
9
|
-
<a href="../zh-cn/LICENSE.md">简体中文</a>
|
|
10
|
-
</h6>
|
|
11
|
-
</div>
|
|
12
|
-
|
|
13
|
-
# 🏛️ MIT 许可证
|
|
14
|
-
|
|
15
|
-
**版權所有 © 2024 [刘展鹏 (Adam Lui)](https://github.com/adamlui)**
|
|
16
|
-
|
|
17
|
-
特此免費授予任何取得副本的人許可本軟體和相關文件文件(『軟體』),處理在軟體中不受限制,包括但不限於權利使用、複製、修改、合併、發布、分發、再授權和/或出售該軟體的副本,並允許該軟體是提供這樣做,但須滿足以下條件:
|
|
18
|
-
|
|
19
|
-
上述版權聲明和本許可聲明應包含在所有軟體的副本或重要部分。
|
|
20
|
-
|
|
21
|
-
本軟體『依現況』提供,不提供任何形式的明示或保證暗示的,包括但不限於適銷性保證,適用於特定目的和非侵權。 在任何情況下都不得作者或版權持有人對任何索賠、損害或其他責任,無論是在合約、侵權或其他方面的行為中,由以下原因引起,出於或與軟體或使用或其他交易有關軟體。
|
package/docs/zh-tw/README.md
DELETED
|
@@ -1,214 +0,0 @@
|
|
|
1
|
-
<div align="right">
|
|
2
|
-
<h6>
|
|
3
|
-
<picture>
|
|
4
|
-
<source type="image/svg+xml" media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/adamlui/js-utils/main/docs/images/earth-icon/white/icon32.svg">
|
|
5
|
-
<img height=14 src="https://raw.githubusercontent.com/adamlui/js-utils/main/docs/images/earth-icon/black/icon32.svg">
|
|
6
|
-
</picture>
|
|
7
|
-
繁體中文 |
|
|
8
|
-
<a href="../..#readme">English</a> |
|
|
9
|
-
<a href="../zh-cn#readme">简体中文</a>
|
|
10
|
-
</h6>
|
|
11
|
-
</div>
|
|
12
|
-
|
|
13
|
-
# > generate-pw
|
|
14
|
-
|
|
15
|
-
### 隨機產生加密安全密碼。
|
|
16
|
-
|
|
17
|
-
<a href="#%EF%B8%8F-mit-%E8%AE%B8%E5%8F%AF%E8%AF%81"><img height=31 src="https://img.shields.io/badge/許可證-MIT-orange.svg?logo=internetarchive&logoColor=white&labelColor=464646&style=for-the-badge"></a>
|
|
18
|
-
<a href="https://www.npmjs.com/package/generate-pw?activeTab=versions"><img height=31 src="https://img.shields.io/badge/最新版本-1.2.0-44cc11.svg?logo=icinga&logoColor=white&labelColor=464646&style=for-the-badge"></a>
|
|
19
|
-
<a href="https://www.npmjs.com/package/generate-pw?activeTab=code"><img height=31 src="https://img.shields.io/npm/unpacked-size/generate-pw?label=%E6%8B%86%E5%B0%81%E5%B0%BA%E5%AF%B8&style=for-the-badge&logo=ebox&logoColor=white&labelColor=464646&color=blue"></a>
|
|
20
|
-
<a href="https://sonarcloud.io/component_measures?metric=new_vulnerabilities&id=adamlui_js-utils:generate-pw/generate-pw.js"><img height=31 src="https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fsonarcloud.io%2Fapi%2Fmeasures%2Fcomponent%3Fcomponent%3Dadamlui_js-utils%3Agenerate-pw%2Fgenerate-pw.js%26metricKeys%3Dvulnerabilities&query=%24.component.measures.0.value&style=for-the-badge&logo=sonarcloud&logoColor=white&labelColor=464646&label=%E6%BC%8F%E6%B4%9E&color=gold"></a>
|
|
21
|
-
|
|
22
|
-
<br>
|
|
23
|
-
|
|
24
|
-
<img height=6px width="100%" src="https://raw.githubusercontent.com/adamlui/js-utils/main/docs/images/aqua-separator.png">
|
|
25
|
-
|
|
26
|
-
## ⚡ 安裝
|
|
27
|
-
|
|
28
|
-
作為**全域實用程式**:
|
|
29
|
-
|
|
30
|
-
```
|
|
31
|
-
$ npm install -g generate-pw
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
作為 **運行時依賴項**,從專案根目錄:
|
|
35
|
-
|
|
36
|
-
```
|
|
37
|
-
$ npm install generate-pw
|
|
38
|
-
```
|
|
39
|
-
|
|
40
|
-
<br>
|
|
41
|
-
|
|
42
|
-
<img height=6px width="100%" src="https://raw.githubusercontent.com/adamlui/js-utils/main/docs/images/aqua-separator.png">
|
|
43
|
-
|
|
44
|
-
## 🔌 API 使用
|
|
45
|
-
|
|
46
|
-
**generate-pw** 可以作為 ECMAScript 模組或 CommonJS 模組匯入到您的應用程式中。
|
|
47
|
-
|
|
48
|
-
#### ESM:
|
|
49
|
-
|
|
50
|
-
```js
|
|
51
|
-
import * as pw from 'generate-pw';
|
|
52
|
-
```
|
|
53
|
-
|
|
54
|
-
#### CJS:
|
|
55
|
-
|
|
56
|
-
```js
|
|
57
|
-
const pw = require('generate-pw');
|
|
58
|
-
```
|
|
59
|
-
|
|
60
|
-
#
|
|
61
|
-
|
|
62
|
-
### `generatePassword([options])`
|
|
63
|
-
|
|
64
|
-
如果未給予 `qty` 選項,則產生**一個**密碼,並傳回字串:
|
|
65
|
-
|
|
66
|
-
```js
|
|
67
|
-
const password = pw.generatePassword({ length: 11, numbers: true });
|
|
68
|
-
console.log(password);
|
|
69
|
-
// 範例輸出:'bAsZm3mq6Qn'
|
|
70
|
-
```
|
|
71
|
-
|
|
72
|
-
...或 **多個** 密碼(如果給了 `qty` 選項),傳回一個字串陣列:
|
|
73
|
-
|
|
74
|
-
```js
|
|
75
|
-
const passwords = pw.generatePassword({ qty: 5, length: 8, symbols: true });
|
|
76
|
-
console.log(passwords);
|
|
77
|
-
// 範例輸出:[ '!zSf@Q.s', '!,HT\\;m=', '?Lq&FV>^', 'gf}Y;}Ne', 'Stsx(GqE' ]
|
|
78
|
-
```
|
|
79
|
-
|
|
80
|
-
**💡注意:**如果不傳遞任何選項,密碼將為 8 個字元長,由大小寫字母組成。
|
|
81
|
-
|
|
82
|
-
請參閱:[可用選項](#available-options-for-generate-functions)
|
|
83
|
-
|
|
84
|
-
#
|
|
85
|
-
|
|
86
|
-
### `generatePasswords(qty[, options])`
|
|
87
|
-
|
|
88
|
-
根據給定的 `qty` 產生**多個**密碼,傳回字串陣列:
|
|
89
|
-
|
|
90
|
-
```js
|
|
91
|
-
const passwords = pw.generatePasswords(5, { length: 3, uppercase: false });
|
|
92
|
-
console.log(passwords);
|
|
93
|
-
// 範例輸出:[ 'yilppxru', 'ckvkyjfp', 'zolcpyfb' ]
|
|
94
|
-
```
|
|
95
|
-
|
|
96
|
-
**💡 注意:** 如果沒有傳遞 `qty` 參數,則只會產生一個密碼,並以字串形式傳回。
|
|
97
|
-
|
|
98
|
-
請參閱:[可用選項](#available-options-for-generate-functions)
|
|
99
|
-
|
|
100
|
-
#
|
|
101
|
-
|
|
102
|
-
### `strictify(password[, requiredCharTypes])`
|
|
103
|
-
|
|
104
|
-
修改指定的 `password`,以使用傳遞的每個 `requiredCharTypes` 元素中的至少一個字符,傳回一個字串。
|
|
105
|
-
|
|
106
|
-
```js
|
|
107
|
-
const password = 'abcdef',
|
|
108
|
-
strictPW = pw.strictify(password, ['numbers', 'symbols']);
|
|
109
|
-
|
|
110
|
-
console.log(strictPW);
|
|
111
|
-
// 範例輸出:'a!c2eR'
|
|
112
|
-
```
|
|
113
|
-
|
|
114
|
-
可用的 `requiredCharTypes` 有:`['number', 'symbol', 'lower', 'upper']`
|
|
115
|
-
|
|
116
|
-
**💡注意:**如果沒有傳遞 `requiredCharTypes` 數組,則所有可用類型都將是必需的。
|
|
117
|
-
|
|
118
|
-
#
|
|
119
|
-
|
|
120
|
-
### `validateStrength(password)`
|
|
121
|
-
|
|
122
|
-
驗證密碼的強度,傳回一個包含 `strengthScore`(滿分 100)+ `recommendations` 陣列的物件。
|
|
123
|
-
|
|
124
|
-
```js
|
|
125
|
-
const password = 'AawiddsE',
|
|
126
|
-
pwStrength = pw.validateStrength(password);
|
|
127
|
-
|
|
128
|
-
console.log(pwStrength);
|
|
129
|
-
|
|
130
|
-
/* 輸出:
|
|
131
|
-
{
|
|
132
|
-
strengthScore: 60,
|
|
133
|
-
recommendations: [ 'Include at least one number.', 'Include at least one symbol.' ]
|
|
134
|
-
}
|
|
135
|
-
*/
|
|
136
|
-
```
|
|
137
|
-
|
|
138
|
-
#
|
|
139
|
-
|
|
140
|
-
### `generate*()` 函數的可用選項
|
|
141
|
-
|
|
142
|
-
其中任何一個都可以傳遞到每個 `generate*()` 函數的選項物件中:
|
|
143
|
-
|
|
144
|
-
姓名 | 類型 | 描述 | 預設值
|
|
145
|
-
------------|--------|-----------------------------------------|---------
|
|
146
|
-
`length` | 整數 | 密碼的長度。 | `8`
|
|
147
|
-
`qty`* | 整數 | 要產生的密碼數量。 | `1`
|
|
148
|
-
`charset` | 字串 | 密碼中包含的字元。 | `''`
|
|
149
|
-
`exclude` | 字串 | 要從密碼中排除的字元。 | `''`
|
|
150
|
-
`numbers` | 布林值 | 允許密碼中包含數字。 | `false`
|
|
151
|
-
`symbols` | 布林值 | 允許密碼中包含符號。 | `false`
|
|
152
|
-
`lowercase` | 布林值 | 密碼中允許使用小寫字母。 | `true`
|
|
153
|
-
`uppercase` | 布林值 | 密碼中允許使用大寫字母。 | `true`
|
|
154
|
-
`strict` | 布林值 | 要求密碼中每個允許的字元集中至少有一個字元。 | `false`
|
|
155
|
-
|
|
156
|
-
##### _*只在 [`generatePassword([options])`](#generatepasswordoptions) 中可用,因為 [`generatePasswords(qty[, options])`](#generatepasswordsqty-options) 採用 `qty` 參數_
|
|
157
|
-
|
|
158
|
-
<br>
|
|
159
|
-
|
|
160
|
-
<img height=6px width="100%" src="https://raw.githubusercontent.com/adamlui/js-utils/main/docs/images/aqua-separator.png">
|
|
161
|
-
|
|
162
|
-
## 💻 命令列使用
|
|
163
|
-
|
|
164
|
-
全域安裝時,**generate-pw** 也可以從命令列使用。 基本指令是:
|
|
165
|
-
|
|
166
|
-
```
|
|
167
|
-
$ generate-pw
|
|
168
|
-
```
|
|
169
|
-
|
|
170
|
-
**💡 注意:** 若要產生多個結果,請傳遞 `--qty=n`,其中 `n` 是要產生的密碼數量。
|
|
171
|
-
|
|
172
|
-
#
|
|
173
|
-
|
|
174
|
-
### 命令列選項
|
|
175
|
-
|
|
176
|
-
```
|
|
177
|
-
參數選項:
|
|
178
|
-
--length=n 產生 n 長度的密碼。
|
|
179
|
-
--qty=n 產生 n 個密碼。
|
|
180
|
-
--charset=chars 密碼中僅包含 chars。
|
|
181
|
-
--exclude=chars 從密碼中排除 chars。
|
|
182
|
-
|
|
183
|
-
布林選項:
|
|
184
|
-
-n, --include-numbers 允許密碼中包含數字。
|
|
185
|
-
-s, --include-symbols 允許密碼中包含符號。
|
|
186
|
-
-L, --no-lowercase 密碼中不允許使用小寫字母。
|
|
187
|
-
-U, --no-uppercase 密碼中不允許使用大寫字母。
|
|
188
|
-
|
|
189
|
-
訊息命令:
|
|
190
|
-
-h, --help 顯示幫助畫面。
|
|
191
|
-
-v, --version 顯示版本號。
|
|
192
|
-
```
|
|
193
|
-
|
|
194
|
-
<br>
|
|
195
|
-
|
|
196
|
-
<img height=6px width="100%" src="https://raw.githubusercontent.com/adamlui/js-utils/main/docs/images/aqua-separator.png">
|
|
197
|
-
|
|
198
|
-
## 🏛️ MIT 许可证
|
|
199
|
-
|
|
200
|
-
**版權所有 © 2024 [刘展鹏 (Adam Lui)](https://github.com/adamlui)**
|
|
201
|
-
|
|
202
|
-
特此免費授予任何取得副本的人許可本軟體和相關文件文件(『軟體』),處理在軟體中不受限制,包括但不限於權利使用、複製、修改、合併、發布、分發、再授權和/或出售該軟體的副本,並允許該軟體是提供這樣做,但須滿足以下條件:
|
|
203
|
-
|
|
204
|
-
上述版權聲明和本許可聲明應包含在所有軟體的副本或重要部分。
|
|
205
|
-
|
|
206
|
-
本軟體『依現況』提供,不提供任何形式的明示或保證暗示的,包括但不限於適銷性保證,適用於特定目的和非侵權。 在任何情況下都不得作者或版權持有人對任何索賠、損害或其他責任,無論是在合約、侵權或其他方面的行為中,由以下原因引起,出於或與軟體或使用或其他交易有關軟體。
|
|
207
|
-
|
|
208
|
-
<br>
|
|
209
|
-
|
|
210
|
-
<img height=6px width="100%" src="https://raw.githubusercontent.com/adamlui/js-utils/main/docs/images/aqua-separator.png">
|
|
211
|
-
|
|
212
|
-
<a href="https://github.com/adamlui/js-utils">**家**</a> /
|
|
213
|
-
<a href="https://github.com/adamlui/js-utils/discussions">討論</a> /
|
|
214
|
-
<a href="#-generate-pw">回到頂部 ↑</a>
|
package/docs/zh-tw/SECURITY.md
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
<div align="right">
|
|
2
|
-
<h6>
|
|
3
|
-
<picture>
|
|
4
|
-
<source type="image/svg+xml" media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/adamlui/js-utils/main/docs/images/earth-icon/white/icon32.svg">
|
|
5
|
-
<img height=14 src="https://raw.githubusercontent.com/adamlui/js-utils/main/docs/images/earth-icon/black/icon32.svg">
|
|
6
|
-
</picture>
|
|
7
|
-
繁體中文 |
|
|
8
|
-
<a href="../SECURITY.md">English</a> |
|
|
9
|
-
<a href="../zh-cn/SECURITY.md">简体中文</a>
|
|
10
|
-
</h6>
|
|
11
|
-
</div>
|
|
12
|
-
|
|
13
|
-
# 🛡️ 安全策略
|
|
14
|
-
|
|
15
|
-
如果您發現漏洞,請打開[安全公告草案](https://github.com/adamlui/js-utils/security/advisories/new)。
|
|
16
|
-
|
|
17
|
-
也歡迎拉取請求,但出於安全原因,請發送電子郵件至 <adam@kudoai.com> 並等待回復後再公開。
|
package/generate-pw.js
DELETED
|
@@ -1,270 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
// Import crypto.randomInt() for secure RNG
|
|
4
|
-
const { randomInt } = require('crypto');
|
|
5
|
-
|
|
6
|
-
// Init CHARACTER SETS
|
|
7
|
-
const charsets = {
|
|
8
|
-
lower: 'abcdefghijklmnopqrstuvwxyz',
|
|
9
|
-
upper: 'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
|
|
10
|
-
numbers: '0123456789',
|
|
11
|
-
symbols: '!@#$%^&*()-_=+[]{}/\\|;:\'",.<>?'
|
|
12
|
-
};
|
|
13
|
-
|
|
14
|
-
// Define MAIN functions
|
|
15
|
-
|
|
16
|
-
function generatePassword(options = {}) {
|
|
17
|
-
|
|
18
|
-
// Init options
|
|
19
|
-
const defaultOptions = {
|
|
20
|
-
length: 8, // length of password
|
|
21
|
-
qty: 1, // number of passwords to generate
|
|
22
|
-
charset: '', // characters to include
|
|
23
|
-
exclude: '', // characters to exclude
|
|
24
|
-
numbers: false, // include numberChars
|
|
25
|
-
symbols: false, // include symbolChars
|
|
26
|
-
lowercase: true, // include lowercase letters
|
|
27
|
-
uppercase: true, // include uppercase letters
|
|
28
|
-
strict: false // require at least one char from each enabled set
|
|
29
|
-
};
|
|
30
|
-
options = { ...defaultOptions, ...options };
|
|
31
|
-
|
|
32
|
-
// Validate integer args
|
|
33
|
-
for (const numArgType of ['length', 'qty'])
|
|
34
|
-
if (isNaN(options[numArgType]) || options[numArgType] < 1)
|
|
35
|
-
return console.error(
|
|
36
|
-
`ERROR: [${ numArgType }] argument must be 1 or greater.`);
|
|
37
|
-
|
|
38
|
-
if (options.qty > 1) { // return array of [qty] password strings
|
|
39
|
-
const { qty, ...otherOptions } = options;
|
|
40
|
-
return generatePasswords(qty, otherOptions);
|
|
41
|
-
|
|
42
|
-
} else { // return single password string
|
|
43
|
-
|
|
44
|
-
// Init password's char set
|
|
45
|
-
let pwCharset = options.charset || ( // use passed [charset], or construct from options
|
|
46
|
-
(options.numbers ? charsets.numbers : '')
|
|
47
|
-
+ (options.symbols ? charsets.symbols : '')
|
|
48
|
-
+ (options.lowercase ? charsets.lower : '')
|
|
49
|
-
+ (options.uppercase ? charsets.upper : '')
|
|
50
|
-
);
|
|
51
|
-
if (pwCharset === '') // all flags false + no charset passed
|
|
52
|
-
pwCharset = charsets.lower + charsets.upper; // default to upper + lower
|
|
53
|
-
|
|
54
|
-
// Exclude passed `exclude` chars
|
|
55
|
-
pwCharset = pwCharset.replace(new RegExp(`[${ options.exclude }]`, 'g'), '');
|
|
56
|
-
|
|
57
|
-
// Generate unstrict password
|
|
58
|
-
let password = '';
|
|
59
|
-
for (let i = 0; i < options.length; i++) {
|
|
60
|
-
const randomIndex = randomInt(0, pwCharset.length);
|
|
61
|
-
password += pwCharset.charAt(randomIndex);
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
// Enforce strict mode if enabled
|
|
65
|
-
if (options.strict) {
|
|
66
|
-
const charTypes = ['number', 'symbol', 'lower', 'upper'],
|
|
67
|
-
requiredCharTypes = charTypes.filter(charType => options[charType + 's'] || options[charType + 'case']);
|
|
68
|
-
password = strictify(password, requiredCharTypes);
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
return password;
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
function generatePasswords(qty, options) {
|
|
76
|
-
qty = parseInt(qty);
|
|
77
|
-
if (isNaN(qty)) return console.error(
|
|
78
|
-
'ERROR: First argument [qty] of generatePasswords() must be an integer');
|
|
79
|
-
const passwords = [];
|
|
80
|
-
for (let i = 0; i < qty; i++) passwords.push(generatePassword(options));
|
|
81
|
-
return passwords;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
function strictify(password, requiredCharTypes = ['number', 'symbol', 'lower', 'upper']) {
|
|
85
|
-
|
|
86
|
-
// Init flags
|
|
87
|
-
for (const charType of requiredCharTypes)
|
|
88
|
-
global['has' + charType.charAt(0).toUpperCase() + charType.slice(1)] = false;
|
|
89
|
-
for (let i = 0; i < password.length; i++)
|
|
90
|
-
for (const charType of requiredCharTypes)
|
|
91
|
-
if ((charsets[charType] || charsets[charType + 's']).includes(password.charAt(i)))
|
|
92
|
-
global['has' + charType.charAt(0).toUpperCase() + charType.slice(1)] = true;
|
|
93
|
-
|
|
94
|
-
// Modify password if necessary
|
|
95
|
-
const maxReplacements = Math.min(password.length, requiredCharTypes.length),
|
|
96
|
-
replacedPositions = []; let replacementCnt = 0;
|
|
97
|
-
for (const charType of requiredCharTypes) {
|
|
98
|
-
if (replacementCnt < maxReplacements) {
|
|
99
|
-
if (!global['has' + charType.charAt(0).toUpperCase() + charType.slice(1)]) {
|
|
100
|
-
let replacementPos;
|
|
101
|
-
do replacementPos = randomInt(0, password.length); // pick random pos
|
|
102
|
-
while (replacedPositions.includes(replacementPos)); // check if pos already replaced
|
|
103
|
-
replacedPositions.push(replacementPos); // track new replacement pos
|
|
104
|
-
const replacementCharSet = charsets[charType] || charsets[charType + 's'];
|
|
105
|
-
password = password.substring(0, replacementPos) // perform actual replacement
|
|
106
|
-
+ replacementCharSet.charAt(randomInt(0, replacementCharSet.length))
|
|
107
|
-
+ password.substring(replacementPos + 1);
|
|
108
|
-
replacementCnt++;
|
|
109
|
-
}}}
|
|
110
|
-
|
|
111
|
-
return password;
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
function validateStrength(password) {
|
|
115
|
-
const strengthCriteria = { minLength: 8, minLower: 1, minUpper: 1, minNumber: 1, minSymbol: 1 };
|
|
116
|
-
|
|
117
|
-
// Count occurrences of each char type
|
|
118
|
-
const charCnts = { 'lower': 0, 'upper': 0, 'number': 0, 'symbol': 0 };
|
|
119
|
-
for (let i = 0; i < password.length; i++) {
|
|
120
|
-
const char = password[i];
|
|
121
|
-
for (const charType of Object.keys(charCnts))
|
|
122
|
-
if ((charsets[charType] || charsets[charType + 's']).includes(char))
|
|
123
|
-
charCnts[charType]++;
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
// Check criteria + add recommendations
|
|
127
|
-
const recommendations = [];
|
|
128
|
-
if (password.length < strengthCriteria.minLength)
|
|
129
|
-
recommendations.push(`Make it at least ${ strengthCriteria.minLength } characters long.`);
|
|
130
|
-
for (const charType of Object.keys(charCnts))
|
|
131
|
-
if (charCnts[charType] < strengthCriteria['min' + charType.charAt(0).toUpperCase() + charType.slice(1)])
|
|
132
|
-
recommendations.push('Include at least one ' + charType
|
|
133
|
-
+ `${ ['upper', 'lower'].includes(charType) ? 'case letter' : '' }.`);
|
|
134
|
-
|
|
135
|
-
// Calculate strength score based on counts and criteria
|
|
136
|
-
let strengthScore = 0;
|
|
137
|
-
strengthScore += ( // +20 for satisfying min length
|
|
138
|
-
password.length >= strengthCriteria.minLength) ? 20 : 0;
|
|
139
|
-
for (const charType of Object.keys(charCnts))
|
|
140
|
-
strengthScore += ( // +20 per char type included
|
|
141
|
-
charCnts[charType] >= strengthCriteria['min' + charType.charAt(0).toUpperCase() + charType.slice(1)]) ? 20 : 0;
|
|
142
|
-
|
|
143
|
-
return { strengthScore, recommendations };
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
// EXPORT functions if script was required
|
|
147
|
-
if (require.main !== module) module.exports = { generatePassword, generatePasswords, strictify, validateStrength };
|
|
148
|
-
|
|
149
|
-
else { // run as CLI tool
|
|
150
|
-
|
|
151
|
-
// Init UI colors
|
|
152
|
-
const nc = '\x1b[0m', // no color
|
|
153
|
-
br = '\x1b[1;91m', // bright red
|
|
154
|
-
by = '\x1b[1;33m', // bright yellow
|
|
155
|
-
bw = '\x1b[1;97m'; // bright white
|
|
156
|
-
|
|
157
|
-
// Load settings from ARGS
|
|
158
|
-
const config = {};
|
|
159
|
-
const argRegex = {
|
|
160
|
-
paramOptions: {
|
|
161
|
-
'length': /^--?length/,
|
|
162
|
-
'qty': /^--?qu?a?n?ti?t?y=\d+$/,
|
|
163
|
-
'charset': /^--?chars/,
|
|
164
|
-
'excludeChars': /^--?exclude=/
|
|
165
|
-
},
|
|
166
|
-
flags: {
|
|
167
|
-
'includeNums': /^--?(?:n|(?:include-?)?num(?:ber)?s?=?(?:true|1)?)$/,
|
|
168
|
-
'includeSymbols': /^--?(?:s|(?:include-?)?symbols?=?(?:true|1)?)$/,
|
|
169
|
-
'excludeLowerChars': /^--?(?:L|(?:exclude|disable|no)-?lower-?(?:case)?|lower-?(?:case)?=(?:false|0))$/,
|
|
170
|
-
'excludeUpperChars': /^--?(?:U|(?:exclude|disable|no)-?upper-?(?:case)?|upper-?(?:case)?=(?:false|0))$/,
|
|
171
|
-
'strictMode': /^--?s(?:trict)?(?:-?mode)?$/
|
|
172
|
-
},
|
|
173
|
-
cmds: {
|
|
174
|
-
'help': /^--?h(?:elp)?$/,
|
|
175
|
-
'version': /^--?ve?r?s?i?o?n?$/
|
|
176
|
-
}
|
|
177
|
-
};
|
|
178
|
-
process.argv.forEach(arg => {
|
|
179
|
-
if (!arg.startsWith('-')) return;
|
|
180
|
-
const matchedFlag = Object.keys(argRegex.flags).find(flag => argRegex.flags[flag].test(arg)),
|
|
181
|
-
matchedArgOption = Object.keys(argRegex.paramOptions).find(option => argRegex.paramOptions[option].test(arg)),
|
|
182
|
-
matchedCmd = Object.keys(argRegex.cmds).find(cmd => argRegex.cmds[cmd].test(arg));
|
|
183
|
-
if (matchedFlag) config[matchedFlag] = true;
|
|
184
|
-
else if (matchedArgOption) {
|
|
185
|
-
const value = arg.split('=')[1];
|
|
186
|
-
config[matchedArgOption] = parseInt(value) || value;
|
|
187
|
-
} else if (!matchedCmd) {
|
|
188
|
-
console.error(`\n${br}ERROR: Arg [${ arg }] not recognized.${nc}`);
|
|
189
|
-
console.info(`\n${by}Valid arguments are below.${nc}`);
|
|
190
|
-
printHelpScreen(['paramOptions', 'booelanOptions', 'infoCmds']);
|
|
191
|
-
process.exit(1);
|
|
192
|
-
}});
|
|
193
|
-
|
|
194
|
-
// Show HELP screen if -h or --help passed
|
|
195
|
-
if (process.argv.some(arg => /^--?h(?:elp)?$/.test(arg))) printHelpScreen();
|
|
196
|
-
|
|
197
|
-
// Show VERSION number if -v or --version passed
|
|
198
|
-
else if (process.argv.some(arg => /^--?ve?r?s?i?o?n?$/.test(arg)))
|
|
199
|
-
console.info('v' + require('./package.json').version);
|
|
200
|
-
|
|
201
|
-
else { // run MAIN routine
|
|
202
|
-
for (const numArgType of ['length', 'qty'])
|
|
203
|
-
if (config[numArgType] && (isNaN(config[numArgType]) || config[numArgType] < 1))
|
|
204
|
-
return console.error(`\n${br}Error: [${ numArgType }] argument must be 1 or greater.${nc}`);
|
|
205
|
-
const funcOptions = {
|
|
206
|
-
length: config.length || 8, qty: config.qty || 1,
|
|
207
|
-
charset: config.charset, exclude: config.excludeChars,
|
|
208
|
-
numbers: config.includeNums, symbols: config.includeSymbols,
|
|
209
|
-
lowercase: !config.excludeLowerChars, uppercase: !config.excludeUpperChars,
|
|
210
|
-
strict: config.strictMode
|
|
211
|
-
};
|
|
212
|
-
const pwResult = generatePassword(funcOptions);
|
|
213
|
-
console.log('\n' + bw + ( Array.isArray(pwResult) ? pwResult.join('\n') : pwResult ) + nc);
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
// Define LOGGING functions
|
|
217
|
-
|
|
218
|
-
function printHelpMsg(msg) { // wrap msg + indent 2nd+ lines (for --help screen)
|
|
219
|
-
const terminalWidth = process.stdout.columns || 80,
|
|
220
|
-
indentation = 29, lines = [], words = msg.match(/\S+|\s+/g);
|
|
221
|
-
|
|
222
|
-
// Split msg into lines of appropriate lengths
|
|
223
|
-
let currentLine = '';
|
|
224
|
-
words.forEach(word => {
|
|
225
|
-
const lineLength = terminalWidth - ( lines.length === 0 ? 0 : indentation );
|
|
226
|
-
if (currentLine.length + word.length > lineLength) { // cap/store it
|
|
227
|
-
lines.push(lines.length === 0 ? currentLine : currentLine.trimStart());
|
|
228
|
-
currentLine = '';
|
|
229
|
-
}
|
|
230
|
-
currentLine += word;
|
|
231
|
-
});
|
|
232
|
-
lines.push(lines.length === 0 ? currentLine : currentLine.trimStart());
|
|
233
|
-
|
|
234
|
-
// Print formatted msg
|
|
235
|
-
lines.forEach((line, index) => console.info(
|
|
236
|
-
index === 0 ? line // print 1st line unindented
|
|
237
|
-
: ' '.repeat(indentation) + line // print subsequent lines indented
|
|
238
|
-
));
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
function printHelpScreen(includeSections = ['cmdFormat', 'paramOptions', 'booelanOptions', 'infoCmds']) {
|
|
242
|
-
const sections = {
|
|
243
|
-
'cmdFormat': [
|
|
244
|
-
`\n${by}generate-pw [options|commands]${nc}`
|
|
245
|
-
],
|
|
246
|
-
'paramOptions': [
|
|
247
|
-
'\nParameter options:',
|
|
248
|
-
' --length=n Generate password(s) of n length.',
|
|
249
|
-
' --qty=n Generate n password(s).',
|
|
250
|
-
' --charset=chars Only include chars in password(s).',
|
|
251
|
-
' --charset=chars Only include chars in password(s).',
|
|
252
|
-
' --exclude=chars Exclude chars from password(s).'
|
|
253
|
-
],
|
|
254
|
-
'booelanOptions': [
|
|
255
|
-
'\nBoolean options:',
|
|
256
|
-
' -n, --include-numbers Allow numbers in password(s).',
|
|
257
|
-
' -s, --include-symbols Allow symbols in password(s).',
|
|
258
|
-
' -L, --no-lowercase Disallow lowercase letters in password(s).',
|
|
259
|
-
' -U, --no-uppercase Disallow uppercase letters in password(s).'
|
|
260
|
-
],
|
|
261
|
-
'infoCmds': [
|
|
262
|
-
'\nInfo commands:',
|
|
263
|
-
' -h, --help Display help screen.',
|
|
264
|
-
' -v, --version Show version number.'
|
|
265
|
-
]
|
|
266
|
-
};
|
|
267
|
-
includeSections.forEach(section => { // print valid arg elems
|
|
268
|
-
if (sections[section]) sections[section].forEach(line => printHelpMsg(line)); });
|
|
269
|
-
}
|
|
270
|
-
}
|