Projektstart
This commit is contained in:
229
backend/node_modules/@phc/format/index.js
generated
vendored
Normal file
229
backend/node_modules/@phc/format/index.js
generated
vendored
Normal file
@@ -0,0 +1,229 @@
|
||||
const idRegex = /^[a-z0-9-]{1,32}$/;
|
||||
const nameRegex = /^[a-z0-9-]{1,32}$/;
|
||||
const valueRegex = /^[a-zA-Z0-9/+.-]+$/;
|
||||
const b64Regex = /^([a-zA-Z0-9/+.-]+|)$/;
|
||||
const decimalRegex = /^((-)?[1-9]\d*|0)$/;
|
||||
const versionRegex = /^v=(\d+)$/;
|
||||
|
||||
function objToKeyVal(obj) {
|
||||
return objectKeys(obj)
|
||||
.map(k => [k, obj[k]].join('='))
|
||||
.join(',');
|
||||
}
|
||||
|
||||
function keyValtoObj(str) {
|
||||
const obj = {};
|
||||
str.split(',').forEach(ps => {
|
||||
const pss = ps.split('=');
|
||||
if (pss.length < 2) {
|
||||
throw new TypeError(`params must be in the format name=value`);
|
||||
}
|
||||
|
||||
obj[pss.shift()] = pss.join('=');
|
||||
});
|
||||
return obj;
|
||||
}
|
||||
|
||||
function objectKeys(object) {
|
||||
/* istanbul ignore next */
|
||||
return Object.keys(object);
|
||||
}
|
||||
|
||||
function objectValues(object) {
|
||||
/* istanbul ignore next */
|
||||
if (typeof Object.values === 'function') return Object.values(object);
|
||||
/* istanbul ignore next */
|
||||
return objectKeys(object).map(k => object[k]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a PHC string using the data provided.
|
||||
* @param {Object} opts Object that holds the data needed to generate the PHC
|
||||
* string.
|
||||
* @param {string} opts.id Symbolic name for the function.
|
||||
* @param {Number} [opts.version] The version of the function.
|
||||
* @param {Object} [opts.params] Parameters of the function.
|
||||
* @param {Buffer} [opts.salt] The salt as a binary buffer.
|
||||
* @param {Buffer} [opts.hash] The hash as a binary buffer.
|
||||
* @return {string} The hash string adhering to the PHC format.
|
||||
*/
|
||||
function serialize(opts) {
|
||||
const fields = [''];
|
||||
|
||||
if (typeof opts !== 'object' || opts === null) {
|
||||
throw new TypeError('opts must be an object');
|
||||
}
|
||||
|
||||
// Identifier Validation
|
||||
if (typeof opts.id !== 'string') {
|
||||
throw new TypeError('id must be a string');
|
||||
}
|
||||
|
||||
if (!idRegex.test(opts.id)) {
|
||||
throw new TypeError(`id must satisfy ${idRegex}`);
|
||||
}
|
||||
|
||||
fields.push(opts.id);
|
||||
|
||||
if (typeof opts.version !== 'undefined') {
|
||||
if (
|
||||
typeof opts.version !== 'number' ||
|
||||
opts.version < 0 ||
|
||||
!Number.isInteger(opts.version)
|
||||
) {
|
||||
throw new TypeError('version must be a positive integer number');
|
||||
}
|
||||
|
||||
fields.push(`v=${opts.version}`);
|
||||
}
|
||||
|
||||
// Parameters Validation
|
||||
if (typeof opts.params !== 'undefined') {
|
||||
if (typeof opts.params !== 'object' || opts.params === null) {
|
||||
throw new TypeError('params must be an object');
|
||||
}
|
||||
|
||||
const pk = objectKeys(opts.params);
|
||||
if (!pk.every(p => nameRegex.test(p))) {
|
||||
throw new TypeError(`params names must satisfy ${nameRegex}`);
|
||||
}
|
||||
|
||||
// Convert Numbers into Numeric Strings and Buffers into B64 encoded strings.
|
||||
pk.forEach(k => {
|
||||
if (typeof opts.params[k] === 'number') {
|
||||
opts.params[k] = opts.params[k].toString();
|
||||
} else if (Buffer.isBuffer(opts.params[k])) {
|
||||
opts.params[k] = opts.params[k].toString('base64').split('=')[0];
|
||||
}
|
||||
});
|
||||
const pv = objectValues(opts.params);
|
||||
if (!pv.every(v => typeof v === 'string')) {
|
||||
throw new TypeError('params values must be strings');
|
||||
}
|
||||
|
||||
if (!pv.every(v => valueRegex.test(v))) {
|
||||
throw new TypeError(`params values must satisfy ${valueRegex}`);
|
||||
}
|
||||
|
||||
const strpar = objToKeyVal(opts.params);
|
||||
fields.push(strpar);
|
||||
}
|
||||
|
||||
if (typeof opts.salt !== 'undefined') {
|
||||
// Salt Validation
|
||||
if (!Buffer.isBuffer(opts.salt)) {
|
||||
throw new TypeError('salt must be a Buffer');
|
||||
}
|
||||
|
||||
fields.push(opts.salt.toString('base64').split('=')[0]);
|
||||
|
||||
if (typeof opts.hash !== 'undefined') {
|
||||
// Hash Validation
|
||||
if (!Buffer.isBuffer(opts.hash)) {
|
||||
throw new TypeError('hash must be a Buffer');
|
||||
}
|
||||
|
||||
fields.push(opts.hash.toString('base64').split('=')[0]);
|
||||
}
|
||||
}
|
||||
|
||||
// Create the PHC formatted string
|
||||
const phcstr = fields.join('$');
|
||||
|
||||
return phcstr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses data from a PHC string.
|
||||
* @param {string} phcstr A PHC string to parse.
|
||||
* @return {Object} The object containing the data parsed from the PHC string.
|
||||
*/
|
||||
function deserialize(phcstr) {
|
||||
if (typeof phcstr !== 'string' || phcstr === '') {
|
||||
throw new TypeError('pchstr must be a non-empty string');
|
||||
}
|
||||
|
||||
if (phcstr[0] !== '$') {
|
||||
throw new TypeError('pchstr must contain a $ as first char');
|
||||
}
|
||||
|
||||
const fields = phcstr.split('$');
|
||||
// Remove first empty $
|
||||
fields.shift();
|
||||
|
||||
// Parse Fields
|
||||
let maxf = 5;
|
||||
if (!versionRegex.test(fields[1])) maxf--;
|
||||
if (fields.length > maxf) {
|
||||
throw new TypeError(
|
||||
`pchstr contains too many fileds: ${fields.length}/${maxf}`
|
||||
);
|
||||
}
|
||||
|
||||
// Parse Identifier
|
||||
const id = fields.shift();
|
||||
if (!idRegex.test(id)) {
|
||||
throw new TypeError(`id must satisfy ${idRegex}`);
|
||||
}
|
||||
|
||||
let version;
|
||||
// Parse Version
|
||||
if (versionRegex.test(fields[0])) {
|
||||
version = parseInt(fields.shift().match(versionRegex)[1], 10);
|
||||
}
|
||||
|
||||
let hash;
|
||||
let salt;
|
||||
if (b64Regex.test(fields[fields.length - 1])) {
|
||||
if (fields.length > 1 && b64Regex.test(fields[fields.length - 2])) {
|
||||
// Parse Hash
|
||||
hash = Buffer.from(fields.pop(), 'base64');
|
||||
// Parse Salt
|
||||
salt = Buffer.from(fields.pop(), 'base64');
|
||||
} else {
|
||||
// Parse Salt
|
||||
salt = Buffer.from(fields.pop(), 'base64');
|
||||
}
|
||||
}
|
||||
|
||||
// Parse Parameters
|
||||
let params;
|
||||
if (fields.length > 0) {
|
||||
const parstr = fields.pop();
|
||||
params = keyValtoObj(parstr);
|
||||
if (!objectKeys(params).every(p => nameRegex.test(p))) {
|
||||
throw new TypeError(`params names must satisfy ${nameRegex}`);
|
||||
}
|
||||
|
||||
const pv = objectValues(params);
|
||||
if (!pv.every(v => valueRegex.test(v))) {
|
||||
throw new TypeError(`params values must satisfy ${valueRegex}`);
|
||||
}
|
||||
|
||||
const pk = objectKeys(params);
|
||||
// Convert Decimal Strings into Numbers
|
||||
pk.forEach(k => {
|
||||
params[k] = decimalRegex.test(params[k])
|
||||
? parseInt(params[k], 10)
|
||||
: params[k];
|
||||
});
|
||||
}
|
||||
|
||||
if (fields.length > 0) {
|
||||
throw new TypeError(`pchstr contains unrecognized fileds: ${fields}`);
|
||||
}
|
||||
|
||||
// Build the output object
|
||||
const phcobj = {id};
|
||||
if (version) phcobj.version = version;
|
||||
if (params) phcobj.params = params;
|
||||
if (salt) phcobj.salt = salt;
|
||||
if (hash) phcobj.hash = hash;
|
||||
|
||||
return phcobj;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
serialize,
|
||||
deserialize
|
||||
};
|
||||
21
backend/node_modules/@phc/format/license
generated
vendored
Normal file
21
backend/node_modules/@phc/format/license
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2018-2020 Simone Primarosa
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
60
backend/node_modules/@phc/format/package.json
generated
vendored
Normal file
60
backend/node_modules/@phc/format/package.json
generated
vendored
Normal file
@@ -0,0 +1,60 @@
|
||||
{
|
||||
"name": "@phc/format",
|
||||
"version": "1.0.0",
|
||||
"description": "PHC string format serializer/deserializer",
|
||||
"license": "MIT",
|
||||
"homepage": "https://github.com/simonepri/phc-format#readme",
|
||||
"repository": "github:simonepri/phc-format",
|
||||
"bugs": {
|
||||
"url": "https://github.com/simonepri/phc-format/issues",
|
||||
"email": "simonepri@outlook.com"
|
||||
},
|
||||
"author": "Simone Primarosa <simonepri@outlook.com> (https://simoneprimarosa.com)",
|
||||
"contributors": [
|
||||
"Simone Primarosa <simonepri@outlook.com> (https://simoneprimarosa.com)"
|
||||
],
|
||||
"keywords": [
|
||||
"mcf",
|
||||
"phc",
|
||||
"modular",
|
||||
"crypt",
|
||||
"passwords",
|
||||
"hashing",
|
||||
"competition",
|
||||
"password",
|
||||
"standard",
|
||||
"crypto"
|
||||
],
|
||||
"main": "index.js",
|
||||
"files": [
|
||||
"index.js"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"scripts": {
|
||||
"lint": "xo",
|
||||
"test": "nyc ava",
|
||||
"release": "npx np",
|
||||
"update": "npx npm-check -u"
|
||||
},
|
||||
"dependencies": {},
|
||||
"devDependencies": {
|
||||
"ava": "^3.9.0",
|
||||
"nyc": "^15.1.0",
|
||||
"xo": "~0.27.2"
|
||||
},
|
||||
"ava": {
|
||||
"verbose": true
|
||||
},
|
||||
"nyc": {
|
||||
"reporter": [
|
||||
"lcovonly",
|
||||
"text"
|
||||
]
|
||||
},
|
||||
"xo": {
|
||||
"prettier": true,
|
||||
"space": true
|
||||
}
|
||||
}
|
||||
207
backend/node_modules/@phc/format/readme.md
generated
vendored
Normal file
207
backend/node_modules/@phc/format/readme.md
generated
vendored
Normal file
@@ -0,0 +1,207 @@
|
||||
<h1 align="center">
|
||||
<b>phc-format</b>
|
||||
</h1>
|
||||
<p align="center">
|
||||
<!-- Version - npm -->
|
||||
<a href="https://www.npmjs.com/package/@phc/format">
|
||||
<img src="https://img.shields.io/npm/v/@phc/format.svg" alt="Latest version on npm" />
|
||||
</a>
|
||||
<!-- Downloads - npm -->
|
||||
<a href="https://npm-stat.com/charts.html?package=@phc/format">
|
||||
<img src="https://img.shields.io/npm/dt/@phc/format.svg" alt="Downloads on npm" />
|
||||
</a>
|
||||
<!-- License - MIT -->
|
||||
<a href="https://github.com/simonepri/phc-format/tree/master/license">
|
||||
<img src="https://img.shields.io/github/license/simonepri/phc-format.svg" alt="Project license" />
|
||||
</a>
|
||||
|
||||
<br/>
|
||||
|
||||
<!-- Lint -->
|
||||
<a href="https://github.com/simonepri/phc-format/actions?query=workflow:lint+branch:master">
|
||||
<img src="https://github.com/simonepri/phc-format/workflows/lint/badge.svg?branch=master" alt="Lint status" />
|
||||
</a>
|
||||
<!-- Test - macOS -->
|
||||
<a href="https://github.com/simonepri/phc-format/actions?query=workflow:test-macos+branch:master">
|
||||
<img src="https://github.com/simonepri/phc-format/workflows/test-macos/badge.svg?branch=master" alt="Test macOS status" />
|
||||
</a>
|
||||
<!-- Test - Ubuntu -->
|
||||
<a href="https://github.com/simonepri/phc-format/actions?query=workflow:test-ubuntu+branch:master">
|
||||
<img src="https://github.com/simonepri/phc-format/workflows/test-ubuntu/badge.svg?branch=master" alt="Test Ubuntu status" />
|
||||
</a>
|
||||
<!-- Test - Windows -->
|
||||
<a href="https://github.com/simonepri/phc-format/actions?query=workflow:test-windows+branch:master">
|
||||
<img src="https://github.com/simonepri/phc-format/workflows/test-windows/badge.svg?branch=master" alt="Test Windows status" />
|
||||
</a>
|
||||
|
||||
<br/>
|
||||
|
||||
<!-- Coverage - Codecov -->
|
||||
<a href="https://codecov.io/gh/simonepri/phc-format">
|
||||
<img src="https://img.shields.io/codecov/c/github/simonepri/phc-format/master.svg" alt="Codecov Coverage report" />
|
||||
</a>
|
||||
<!-- DM - Snyk -->
|
||||
<a href="https://snyk.io/test/github/simonepri/phc-format?targetFile=package.json">
|
||||
<img src="https://snyk.io/test/github/simonepri/phc-format/badge.svg?targetFile=package.json" alt="Known Vulnerabilities" />
|
||||
</a>
|
||||
<!-- DM - David -->
|
||||
<a href="https://david-dm.org/simonepri/phc-format">
|
||||
<img src="https://david-dm.org/simonepri/phc-format/status.svg" alt="Dependency Status" />
|
||||
</a>
|
||||
|
||||
<br/>
|
||||
|
||||
<!-- Code Style - XO-Prettier -->
|
||||
<a href="https://github.com/xojs/xo">
|
||||
<img src="https://img.shields.io/badge/code_style-XO+Prettier-5ed9c7.svg" alt="XO Code Style used" />
|
||||
</a>
|
||||
<!-- Test Runner - AVA -->
|
||||
<a href="https://github.com/avajs/ava">
|
||||
<img src="https://img.shields.io/badge/test_runner-AVA-fb3170.svg" alt="AVA Test Runner used" />
|
||||
</a>
|
||||
<!-- Test Coverage - Istanbul -->
|
||||
<a href="https://github.com/istanbuljs/nyc">
|
||||
<img src="https://img.shields.io/badge/test_coverage-NYC-fec606.svg" alt="Istanbul Test Coverage used" />
|
||||
</a>
|
||||
<!-- Init - ni -->
|
||||
<a href="https://github.com/simonepri/ni">
|
||||
<img src="https://img.shields.io/badge/initialized_with-ni-e74c3c.svg" alt="NI Scaffolding System used" />
|
||||
</a>
|
||||
<!-- Release - np -->
|
||||
<a href="https://github.com/sindresorhus/np">
|
||||
<img src="https://img.shields.io/badge/released_with-np-6c8784.svg" alt="NP Release System used" />
|
||||
</a>
|
||||
</p>
|
||||
<p align="center">
|
||||
📝 PHC string format serializer/deserializer
|
||||
|
||||
<br/>
|
||||
|
||||
<sub>
|
||||
Coded with ❤️ by <a href="#authors">Simone Primarosa</a>.
|
||||
</sub>
|
||||
</p>
|
||||
|
||||
## Motivation
|
||||
The [PHC String Format][specs:phc] is an attempt to specify a common hash string format that’s a restricted & well defined subset of the Modular Crypt Format. New hashes are strongly encouraged to adhere to the PHC specification, rather than the much looser [Modular Crypt Format][specs:mcf].
|
||||
|
||||
## Install
|
||||
|
||||
```bash
|
||||
npm install --save @phc/format
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
```js
|
||||
const phc = require('@phc/format');
|
||||
|
||||
const phcobj = {
|
||||
id: 'pbkdf2-sha256',
|
||||
params: {i: 6400},
|
||||
salt: Buffer.from('0ZrzXitFSGltTQnBWOsdAw', 'base64'),
|
||||
hash: Buffer.from('Y11AchqV4b0sUisdZd0Xr97KWoymNE0LNNrnEgY4H9M', 'base64'),
|
||||
};
|
||||
|
||||
const phcstr = "$pbkdf2-sha256$i=6400$0ZrzXitFSGltTQnBWOsdAw$Y11AchqV4b0sUisdZd0Xr97KWoymNE0LNNrnEgY4H9M";
|
||||
|
||||
phc.serialize(phcobj);
|
||||
// => phcstr
|
||||
|
||||
phc.deserialize(phcstr);
|
||||
// => phcobj
|
||||
```
|
||||
|
||||
You can also pass an optional version parameter.
|
||||
|
||||
```js
|
||||
const phc = require('@phc/format');
|
||||
|
||||
const phcobj = {
|
||||
id: 'argon2i',
|
||||
version: 19,
|
||||
params: {
|
||||
m: 120,
|
||||
t: 5000,
|
||||
p: 2
|
||||
},
|
||||
salt: Buffer.from('iHSDPHzUhPzK7rCcJgOFfg', 'base64'),
|
||||
hash: Buffer.from('J4moa2MM0/6uf3HbY2Tf5Fux8JIBTwIhmhxGRbsY14qhTltQt+Vw3b7tcJNEbk8ium8AQfZeD4tabCnNqfkD1g', 'base64'),
|
||||
};
|
||||
|
||||
const phcstr = "$argon2i$v=19$m=120,t=5000,p=2$iHSDPHzUhPzK7rCcJgOFfg$J4moa2MM0/6uf3HbY2Tf5Fux8JIBTwIhmhxGRbsY14qhTltQt+Vw3b7tcJNEbk8ium8AQfZeD4tabCnNqfkD1g";
|
||||
|
||||
phc.serialize(phcobj);
|
||||
// => phcstr
|
||||
|
||||
phc.deserialize(phcstr);
|
||||
// => phcobj
|
||||
```
|
||||
|
||||
## API
|
||||
|
||||
#### TOC
|
||||
<dl>
|
||||
<dt><a href="#serialize">serialize(opts)</a> ⇒ <code>string</code></dt>
|
||||
<dd><p>Generates a PHC string using the data provided.</p>
|
||||
</dd>
|
||||
<dt><a href="#deserialize">deserialize(phcstr)</a> ⇒ <code>Object</code></dt>
|
||||
<dd><p>Parses data from a PHC string.</p>
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
<a name="serialize"></a>
|
||||
|
||||
### serialize(opts) ⇒ <code>string</code>
|
||||
Generates a PHC string using the data provided.
|
||||
|
||||
**Kind**: global function
|
||||
**Returns**: <code>string</code> - The hash string adhering to the PHC format.
|
||||
|
||||
| Param | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| opts | <code>Object</code> | Object that holds the data needed to generate the PHC string. |
|
||||
| opts.id | <code>string</code> | Symbolic name for the function. |
|
||||
| [opts.version] | <code>Number</code> | The version of the function. |
|
||||
| [opts.params] | <code>Object</code> | Parameters of the function. |
|
||||
| [opts.salt] | <code>Buffer</code> | The salt as a binary buffer. |
|
||||
| [opts.hash] | <code>Buffer</code> | The hash as a binary buffer. |
|
||||
|
||||
<a name="deserialize"></a>
|
||||
|
||||
### deserialize(phcstr) ⇒ <code>Object</code>
|
||||
Parses data from a PHC string.
|
||||
|
||||
**Kind**: global function
|
||||
**Returns**: <code>Object</code> - The object containing the data parsed from the PHC string.
|
||||
|
||||
| Param | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| phcstr | <code>string</code> | A PHC string to parse. |
|
||||
|
||||
## Contributing
|
||||
Contributions are REALLY welcome and if you find a security flaw in this code, PLEASE [report it][new issue].
|
||||
Please check the [contributing guidelines][contributing] for more details. Thanks!
|
||||
|
||||
## Authors
|
||||
- **Simone Primarosa** - *Github* ([@simonepri][github:simonepri]) • *Twitter* ([@simoneprimarosa][twitter:simoneprimarosa])
|
||||
|
||||
See also the list of [contributors][contributors] who participated in this project.
|
||||
|
||||
## License
|
||||
This project is licensed under the MIT License - see the [license][license] file for details.
|
||||
|
||||
|
||||
<!-- Links -->
|
||||
[start]: https://github.com/simonepri/phc-format#start-of-content
|
||||
[new issue]: https://github.com/simonepri/phc-format/issues/new
|
||||
[contributors]: https://github.com/simonepri/phc-format/contributors
|
||||
|
||||
[license]: https://github.com/simonepri/phc-format/tree/master/license
|
||||
[contributing]: https://github.com/simonepri/phc-format/tree/master/.github/contributing.md
|
||||
|
||||
[github:simonepri]: https://github.com/simonepri
|
||||
[twitter:simoneprimarosa]: http://twitter.com/intent/user?screen_name=simoneprimarosa
|
||||
|
||||
[specs:mcf]: https://github.com/ademarre/binary-mcf
|
||||
[specs:phc]: https://github.com/P-H-C/phc-string-format/blob/master/phc-sf-spec.md
|
||||
Reference in New Issue
Block a user