@phc/format
Advanced tools
Comparing version 0.1.1 to 0.2.0
69
index.js
@@ -1,2 +0,2 @@ | ||
/* eslint-disable max-params,capitalized-comments */ | ||
/* eslint-disable max-params,capitalized-comments,complexity */ | ||
'use strict'; | ||
@@ -40,4 +40,4 @@ | ||
* @param {string} opts.id Symbolic name for the function. | ||
* @param {string} [opts.raw] Additinal raw data added between id and params. | ||
* It's here only to support argon2 v parameter. | ||
* @param {string} [opts.raw] Additional raw data added after the identifier. | ||
* It's here to support argon2 v parameter and to generate MCF formatted strings. | ||
* @param {Object} [opts.params] Parameters of the function. | ||
@@ -113,5 +113,12 @@ * @param {Buffer} [opts.salt] The salt as a binary buffer. | ||
* @param {string} phcstr A PHC string to parse. | ||
* @param {boolean} strict If false does not throw an error if there is | ||
* one filed not unrecognized. The content of the unrecognized filed will be | ||
* stored in the raw property of the output object. This is useful to parse | ||
* out of specs parameters like the 'v' present in the argon2 hash format or | ||
* to parse MCF formatted strings. | ||
* @return {Object} The object containing the data parsed from the PHC string. | ||
*/ | ||
function deserialize(phcstr) { | ||
function deserialize(phcstr, strict) { | ||
strict = strict !== false; | ||
if (typeof phcstr !== 'string') { | ||
@@ -121,2 +128,4 @@ throw new TypeError('pchstr must be a string'); | ||
const fields = phcstr.split('$'); | ||
// Parse Fields | ||
if (fields.length === 1) { | ||
@@ -127,2 +136,9 @@ throw new TypeError('pchstr must contain at least one $ char'); | ||
fields.shift(); | ||
let maxf = 5; | ||
if (strict) maxf--; | ||
if (fields.length > maxf) { | ||
throw new TypeError( | ||
`pchstr contains too many fileds: ${fields.length}/${maxf}` | ||
); | ||
} | ||
@@ -150,14 +166,42 @@ // Parse Identifier | ||
// Parse Parameters | ||
let params = {}; | ||
let params; | ||
if (fields.length > 0) { | ||
params = keyValtoObj(fields.pop()); | ||
if (!objectKeys(params).every(p => nameRegex.test(p))) { | ||
throw new TypeError(`params names must satisfy ${nameRegex}`); | ||
const parstr = fields.pop(); | ||
let isKeyVal = false; | ||
try { | ||
params = keyValtoObj(parstr); | ||
isKeyVal = true; | ||
} catch (err) { | ||
if (strict) { | ||
throw err; | ||
} | ||
fields.push(parstr); | ||
} | ||
const vs = objectValues(params); | ||
if (!vs.every(v => valueRegex.test(v))) { | ||
throw new TypeError(`params values must satisfy ${valueRegex}`); | ||
if (isKeyVal) { | ||
if (!objectKeys(params).every(p => nameRegex.test(p))) { | ||
throw new TypeError(`params names must satisfy ${nameRegex}`); | ||
} | ||
const vs = objectValues(params); | ||
if (!vs.every(v => valueRegex.test(v))) { | ||
throw new TypeError(`params values must satisfy ${valueRegex}`); | ||
} | ||
} | ||
} | ||
// Parse Raw Data if not in strict mode | ||
let raw; | ||
if (fields.length > 0) { | ||
if (strict) { | ||
throw new TypeError( | ||
`pchstr contains unrecognized fileds: ${fields.length}/0` | ||
); | ||
} | ||
if (fields.length !== 1) { | ||
throw new TypeError( | ||
`pchstr contains too many unrecognized fileds: ${fields.length}/1` | ||
); | ||
} | ||
raw = fields.pop(); | ||
} | ||
// Build the output object | ||
@@ -168,4 +212,3 @@ const phcobj = {id}; | ||
if (hash) phcobj.hash = hash; | ||
if (hash) phcobj.hash = hash; | ||
if (fields.length > 0) phcobj.raw = fields.join('$'); | ||
if (raw) phcobj.raw = raw; | ||
@@ -172,0 +215,0 @@ return phcobj; |
{ | ||
"name": "@phc/format", | ||
"version": "0.1.1", | ||
"version": "0.2.0", | ||
"description": "PHC string format serializer/deserializer", | ||
@@ -5,0 +5,0 @@ "license": "MIT", |
@@ -86,16 +86,38 @@ <h1 align="center"> | ||
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 | ||
``` | ||
Using the `raw` and `strict` parameters you can even serialize/deserialize | ||
PHC strings that does not strictly adhere to the 'standard', like the one | ||
used by [argon2](https://github.com/P-H-C/phc-winner-argon2/issues/157) | ||
```js | ||
const phc = require('@phc/format'); | ||
const phcobj = { | ||
id: 'argon2i', | ||
raw: 'v=19', | ||
raw: 'v=19', <- Note the v parameter | ||
params: { | ||
m: '120', | ||
t: '5000', | ||
p: '2', | ||
keyid: 'Hj5+dsK0', | ||
data: 'sRlHhRmKUGzdOmXn01XmXygd5Kc', | ||
p: '2' | ||
}, | ||
salt: Buffer.from('dsK0,data=sRlHhRmKUGzdOmXn01XmXygd5Kc', 'base64'), | ||
salt: Buffer.from('iHSDPHzUhPzK7rCcJgOFfg', 'base64'), | ||
hash: Buffer.from('J4moa2MM0/6uf3HbY2Tf5Fux8JIBTwIhmhxGRbsY14qhTltQt+Vw3b7tcJNEbk8ium8AQfZeD4tabCnNqfkD1g', 'base64'), | ||
}; | ||
const phcstr = "$argon2i$v=19$m=120,t=5000,p=2,keyid=Hj5+dsK0,data=sRlHhRmKUGzdOmXn01XmXygd5Kc$iHSDPHzUhPzK7rCcJgOFfg$J4moa2MM0/6uf3HbY2Tf5Fux8JIBTwIhmhxGRbsY14qhTltQt+Vw3b7tcJNEbk8ium8AQfZeD4tabCnNqfkD1g"; | ||
const phcstr = "$argon2i$v=19$m=120,t=5000,p=2$iHSDPHzUhPzK7rCcJgOFfg$J4moa2MM0/6uf3HbY2Tf5Fux8JIBTwIhmhxGRbsY14qhTltQt+Vw3b7tcJNEbk8ium8AQfZeD4tabCnNqfkD1g"; <- Note the v parameter | ||
@@ -106,5 +128,33 @@ phc.serialize(phcobj); | ||
phc.deserialize(phcstr); | ||
// => throws an error since there are more than 4 fields (a field is one $) | ||
phc.deserialize(phcstr, false); | ||
// => phcobj | ||
``` | ||
With the same philosophy you can even serialize/deserialize MCF formatted strings. | ||
```js | ||
const phc = require('@phc/format'); | ||
const phcobj = { | ||
id: 'pbkdf2-sha256', | ||
raw: '6400', | ||
salt: Buffer.from('0ZrzXitFSGltTQnBWOsdAw', 'base64'), | ||
hash: Buffer.from('Y11AchqV4b0sUisdZd0Xr97KWoymNE0LNNrnEgY4H9M', 'base64'), | ||
}; | ||
const phcstr = "$pbkdf2-sha256$6400$0ZrzXitFSGltTQnBWOsdAw$Y11AchqV4b0sUisdZd0Xr97KWoymNE0LNNrnEgY4H9M"; | ||
phc.serialize(phcobj); | ||
// => phcstr | ||
phc.deserialize(phcstr); | ||
// => throws an error since the second field (a field is one $) is not a valid | ||
// params string | ||
phc.deserialize(phcstr, false); | ||
// => phcobj | ||
``` | ||
## API | ||
@@ -116,3 +166,3 @@ | ||
</dd> | ||
<dt><a href="#deserialize">deserialize(phcstr)</a> ⇒ <code>Object</code></dt> | ||
<dt><a href="#deserialize">deserialize(phcstr, strict)</a> ⇒ <code>Object</code></dt> | ||
<dd><p>Parses data from a PHC string.</p> | ||
@@ -134,3 +184,3 @@ </dd> | ||
| opts.id | <code>string</code> | Symbolic name for the function. | | ||
| [opts.raw] | <code>string</code> | Additinal raw data added between id and params. It's here only to support argon2 v parameter. | | ||
| [opts.raw] | <code>string</code> | Additional raw data added after the identifier. It's here to support argon2 v parameter and to generate MCF formatted strings. | | ||
| [opts.params] | <code>Object</code> | Parameters of the function. | | ||
@@ -142,3 +192,3 @@ | [opts.salt] | <code>Buffer</code> | The salt as a binary buffer. | | ||
## deserialize(phcstr) ⇒ <code>Object</code> | ||
## deserialize(phcstr, strict) ⇒ <code>Object</code> | ||
Parses data from a PHC string. | ||
@@ -149,5 +199,6 @@ | ||
| Param | Type | Description | | ||
| --- | --- | --- | | ||
| phcstr | <code>string</code> | A PHC string to parse. | | ||
| Param | Type | Default | Description | | ||
| --- | --- | --- | --- | | ||
| phcstr | <code>string</code> | | A PHC string to parse. | | ||
| strict | <code>boolean</code> | <code>true</code> | If false does not throw an error if there is one filed not unrecognized. The content of the unrecognized filed will be stored in the raw property of the output object. This is useful to parse out of specs parameters like the 'v' present in the argon2 hash format or to parse MCF formatted strings. | | ||
@@ -154,0 +205,0 @@ ## Contributing |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
16522
193
225