Skip to content

Commit

Permalink
Add distinguishable character set (#14)
Browse files Browse the repository at this point in the history
Co-authored-by: Sindre Sorhus <sindresorhus@gmail.com>
  • Loading branch information
markstos and sindresorhus committed Mar 7, 2020
1 parent 9f45399 commit c047603
Show file tree
Hide file tree
Showing 4 changed files with 27 additions and 3 deletions.
7 changes: 6 additions & 1 deletion index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ interface TypeOption {
@default 'hex'
The `distinguishable` set contains only uppercase characters that are not easily confused: `CDEHKMPRTUWXY012458`. It can be useful if you need to print out a short string that you'd like users to read and type back in with minimal errors. For example, reading a code off of a screen that needs to be typed into a phone to connect two devices.
@example
```
cryptoRandomString({length: 10});
Expand All @@ -28,9 +30,12 @@ interface TypeOption {
cryptoRandomString({length: 10, type: 'numeric'});
//=> '8314659141'
cryptoRandomString({length: 6, type: 'distinguishable'});
//=> 'CDEHKM'
```
*/
type?: 'hex' | 'base64' | 'url-safe' | 'numeric';
type?: 'hex' | 'base64' | 'url-safe' | 'numeric' | 'distinguishable';
}

interface CharactersOption {
Expand Down
8 changes: 7 additions & 1 deletion index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ const crypto = require('crypto');

const urlSafeCharacters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._~'.split('');
const numericCharacters = '0123456789'.split('');
const distinguishableCharacters = 'CDEHKMPRTUWXY012458'.split('');

const generateForCustomCharacters = (length, characters) => {
// Generating entropy is faster than complex math operations, so we use the simplest way
Expand Down Expand Up @@ -36,7 +37,8 @@ const allowedTypes = [
'hex',
'base64',
'url-safe',
'numeric'
'numeric',
'distinguishable'
];

module.exports = ({length, type, characters}) => {
Expand Down Expand Up @@ -76,6 +78,10 @@ module.exports = ({length, type, characters}) => {
return generateForCustomCharacters(length, numericCharacters);
}

if (type === 'distinguishable') {
return generateForCustomCharacters(length, distinguishableCharacters);
}

if (characters.length === 0) {
throw new TypeError('Expected `characters` string length to be greater than or equal to 1');
}
Expand Down
7 changes: 6 additions & 1 deletion readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ cryptoRandomString({length: 10, type: 'url-safe'});
cryptoRandomString({length: 10, type: 'numeric'});
//=> '8314659141'

cryptoRandomString({length: 6, type: 'distinguishable'});
//=> 'CDEHKM'

cryptoRandomString({length: 10, characters: 'abc'});
//=> 'abaaccabac'
```
Expand All @@ -52,12 +55,14 @@ Length of the returned string.

Type: `string`\
Default: `'hex'`\
Values: `'hex' | 'base64' | 'url-safe' | 'numeric'`
Values: `'hex' | 'base64' | 'url-safe' | 'numeric' | 'distinguishable'`

Use only characters from a predefined set of allowed characters.

Cannot be set at the same time as the `characters` option.

The `distinguishable` set contains only uppercase characters that are not easily confused: `CDEHKMPRTUWXY012458`. It can be useful if you need to print out a short string that you'd like users to read and type back in with minimal errors. For example, reading a code off of a screen that needs to be typed into a phone to connect two devices.

##### characters

Type: `string`\
Expand Down
8 changes: 8 additions & 0 deletions test.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,14 @@ test('numeric', t => {
t.is(generatedCharacterSetSize({type: 'numeric'}, 10), 10);
});

test('distinquishable', t => {
t.is(cryptoRandomString({length: 0, type: 'distinguishable'}).length, 0);
t.is(cryptoRandomString({length: 10, type: 'distinguishable'}).length, 10);
t.is(cryptoRandomString({length: 100, type: 'distinguishable'}).length, 100);
t.regex(cryptoRandomString({length: 100, type: 'distinguishable'}), /^[CDEHKMPRTUWXY012458]*$/); // Sanity check, probabilistic
t.is(generatedCharacterSetSize({type: 'distinguishable'}, 19), 19);
});

test('characters', t => {
t.is(cryptoRandomString({length: 0, characters: '1234'}).length, 0);
t.is(cryptoRandomString({length: 10, characters: '1234'}).length, 10);
Expand Down

0 comments on commit c047603

Please sign in to comment.