pax_global_header00006660000000000000000000000064137241665550014530gustar00rootroot0000000000000052 comment=98e54d259454598b753b88b3096321c308de66fb
crypto-random-string-3.3.0/000077500000000000000000000000001372416655500156355ustar00rootroot00000000000000crypto-random-string-3.3.0/.editorconfig000066400000000000000000000002571372416655500203160ustar00rootroot00000000000000root = true
[*]
indent_style = tab
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[*.yml]
indent_style = space
indent_size = 2
crypto-random-string-3.3.0/.gitattributes000066400000000000000000000000231372416655500205230ustar00rootroot00000000000000* text=auto eol=lf
crypto-random-string-3.3.0/.github/000077500000000000000000000000001372416655500171755ustar00rootroot00000000000000crypto-random-string-3.3.0/.github/funding.yml000066400000000000000000000000701372416655500213470ustar00rootroot00000000000000github: sindresorhus
tidelift: npm/crypto-random-string
crypto-random-string-3.3.0/.github/security.md000066400000000000000000000002631372416655500213670ustar00rootroot00000000000000# Security Policy
To report a security vulnerability, please use the [Tidelift security contact](https://tidelift.com/security). Tidelift will coordinate the fix and disclosure.
crypto-random-string-3.3.0/.gitignore000066400000000000000000000000271372416655500176240ustar00rootroot00000000000000node_modules
yarn.lock
crypto-random-string-3.3.0/.npmrc000066400000000000000000000000231372416655500167500ustar00rootroot00000000000000package-lock=false
crypto-random-string-3.3.0/.travis.yml000066400000000000000000000000651372416655500177470ustar00rootroot00000000000000language: node_js
node_js:
- '12'
- '10'
- '8'
crypto-random-string-3.3.0/index.d.ts000066400000000000000000000060571372416655500175460ustar00rootroot00000000000000import {MergeExclusive} from 'type-fest';
interface BaseOptions {
/**
Length of the returned string.
*/
length: number;
}
interface TypeOption {
/**
Use only characters from a predefined set of allowed characters.
Cannot be set at the same time as the `characters` option.
@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.
The `ascii-printable` set contains all [printable ASCII characters](https://en.wikipedia.org/wiki/ASCII#ASCII_printable_characters): ``!"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~`` Useful for generating passwords where all possible ASCII characters should be used.
The `alphanumeric` set contains uppercase letters, lowercase letters, and digits: `ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789`. Useful for generating [nonce](https://developer.mozilla.org/en-US/docs/Web/API/HTMLOrForeignElement/nonce) values.
@example
```
cryptoRandomString({length: 10});
//=> '87fc70e2b9'
cryptoRandomString({length: 10, type: 'base64'});
//=> 'mhsX7xmIv/'
cryptoRandomString({length: 10, type: 'url-safe'});
//=> 'VEjfNW3Yej'
cryptoRandomString({length: 10, type: 'numeric'});
//=> '8314659141'
cryptoRandomString({length: 6, type: 'distinguishable'});
//=> 'CDEHKM'
cryptoRandomString({length: 10, type: 'ascii-printable'});
//=> '`#Rt8$IK>B'
cryptoRandomString({length: 10, type: 'alphanumeric'});
//=> 'DMuKL8YtE7'
```
*/
type?: 'hex' | 'base64' | 'url-safe' | 'numeric' | 'distinguishable' | 'ascii-printable' | 'alphanumeric';
}
interface CharactersOption {
/**
Use only characters from a custom set of allowed characters.
Cannot be set at the same time as the `type` option.
Minimum length: `1`
Maximum length: `65536`
@example
```
cryptoRandomString({length: 10, characters: '0123456789'});
//=> '8796225811'
```
*/
characters?: string;
}
declare namespace cryptoRandomString {
type Options = BaseOptions & MergeExclusive;
}
declare const cryptoRandomString: {
/**
Generate a [cryptographically strong](https://en.wikipedia.org/wiki/Strong_cryptography) random string.
@returns A randomized string.
@example
```
import cryptoRandomString = require('crypto-random-string');
cryptoRandomString({length: 10});
//=> '2cf05d94db'
```
*/
(options?: cryptoRandomString.Options): string;
/**
Asynchronously generate a [cryptographically strong](https://en.wikipedia.org/wiki/Strong_cryptography) random string.
@returns A promise which resolves to a randomized string.
@example
```
import cryptoRandomString = require('crypto-random-string');
await cryptoRandomString.async({length: 10});
//=> '2cf05d94db'
```
*/
async(options?: cryptoRandomString.Options): Promise;
}
export = cryptoRandomString;
crypto-random-string-3.3.0/index.js000066400000000000000000000125521372416655500173070ustar00rootroot00000000000000'use strict';
const {promisify} = require('util');
const crypto = require('crypto');
const randomBytesAsync = promisify(crypto.randomBytes);
const urlSafeCharacters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._~'.split('');
const numericCharacters = '0123456789'.split('');
const distinguishableCharacters = 'CDEHKMPRTUWXY012458'.split('');
const asciiPrintableCharacters = '!"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~'.split('');
const alphanumericCharacters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'.split('');
const generateForCustomCharacters = (length, characters) => {
// Generating entropy is faster than complex math operations, so we use the simplest way
const characterCount = characters.length;
const maxValidSelector = (Math.floor(0x10000 / characterCount) * characterCount) - 1; // Using values above this will ruin distribution when using modular division
const entropyLength = 2 * Math.ceil(1.1 * length); // Generating a bit more than required so chances we need more than one pass will be really low
let string = '';
let stringLength = 0;
while (stringLength < length) { // In case we had many bad values, which may happen for character sets of size above 0x8000 but close to it
const entropy = crypto.randomBytes(entropyLength);
let entropyPosition = 0;
while (entropyPosition < entropyLength && stringLength < length) {
const entropyValue = entropy.readUInt16LE(entropyPosition);
entropyPosition += 2;
if (entropyValue > maxValidSelector) { // Skip values which will ruin distribution when using modular division
continue;
}
string += characters[entropyValue % characterCount];
stringLength++;
}
}
return string;
};
const generateForCustomCharactersAsync = async (length, characters) => {
// Generating entropy is faster than complex math operations, so we use the simplest way
const characterCount = characters.length;
const maxValidSelector = (Math.floor(0x10000 / characterCount) * characterCount) - 1; // Using values above this will ruin distribution when using modular division
const entropyLength = 2 * Math.ceil(1.1 * length); // Generating a bit more than required so chances we need more than one pass will be really low
let string = '';
let stringLength = 0;
while (stringLength < length) { // In case we had many bad values, which may happen for character sets of size above 0x8000 but close to it
const entropy = await randomBytesAsync(entropyLength); // eslint-disable-line no-await-in-loop
let entropyPosition = 0;
while (entropyPosition < entropyLength && stringLength < length) {
const entropyValue = entropy.readUInt16LE(entropyPosition);
entropyPosition += 2;
if (entropyValue > maxValidSelector) { // Skip values which will ruin distribution when using modular division
continue;
}
string += characters[entropyValue % characterCount];
stringLength++;
}
}
return string;
};
const generateRandomBytes = (byteLength, type, length) => crypto.randomBytes(byteLength).toString(type).slice(0, length);
const generateRandomBytesAsync = async (byteLength, type, length) => {
const buffer = await randomBytesAsync(byteLength);
return buffer.toString(type).slice(0, length);
};
const allowedTypes = [
undefined,
'hex',
'base64',
'url-safe',
'numeric',
'distinguishable',
'ascii-printable',
'alphanumeric'
];
const createGenerator = (generateForCustomCharacters, generateRandomBytes) => ({length, type, characters}) => {
if (!(length >= 0 && Number.isFinite(length))) {
throw new TypeError('Expected a `length` to be a non-negative finite number');
}
if (type !== undefined && characters !== undefined) {
throw new TypeError('Expected either `type` or `characters`');
}
if (characters !== undefined && typeof characters !== 'string') {
throw new TypeError('Expected `characters` to be string');
}
if (!allowedTypes.includes(type)) {
throw new TypeError(`Unknown type: ${type}`);
}
if (type === undefined && characters === undefined) {
type = 'hex';
}
if (type === 'hex' || (type === undefined && characters === undefined)) {
return generateRandomBytes(Math.ceil(length * 0.5), 'hex', length); // Need 0.5 byte entropy per character
}
if (type === 'base64') {
return generateRandomBytes(Math.ceil(length * 0.75), 'base64', length); // Need 0.75 byte of entropy per character
}
if (type === 'url-safe') {
return generateForCustomCharacters(length, urlSafeCharacters);
}
if (type === 'numeric') {
return generateForCustomCharacters(length, numericCharacters);
}
if (type === 'distinguishable') {
return generateForCustomCharacters(length, distinguishableCharacters);
}
if (type === 'ascii-printable') {
return generateForCustomCharacters(length, asciiPrintableCharacters);
}
if (type === 'alphanumeric') {
return generateForCustomCharacters(length, alphanumericCharacters);
}
if (characters.length === 0) {
throw new TypeError('Expected `characters` string length to be greater than or equal to 1');
}
if (characters.length > 0x10000) {
throw new TypeError('Expected `characters` string length to be less or equal to 65536');
}
return generateForCustomCharacters(length, characters.split(''));
};
module.exports = createGenerator(generateForCustomCharacters, generateRandomBytes);
module.exports.async = createGenerator(generateForCustomCharactersAsync, generateRandomBytesAsync);
crypto-random-string-3.3.0/index.test-d.ts000066400000000000000000000012771372416655500205220ustar00rootroot00000000000000import {expectType, expectError} from 'tsd';
import cryptoRandomString = require('.');
expectType(cryptoRandomString({length: 10}));
expectType(cryptoRandomString({length: 10, type: 'url-safe'}));
expectType(cryptoRandomString({length: 10, type: 'numeric'}));
expectType(cryptoRandomString({length: 10, characters: '1234'}));
expectType>(cryptoRandomString.async({length: 10}));
expectError(cryptoRandomString({type: 'url-safe'}));
expectError(cryptoRandomString({length: 10, type: 'url-safe', characters: '1234'}));
expectError(cryptoRandomString({type: 'numeric'}));
expectError(cryptoRandomString({length: 10, type: 'numeric', characters: '1234'}));
crypto-random-string-3.3.0/license000066400000000000000000000021251372416655500172020ustar00rootroot00000000000000MIT License
Copyright (c) Sindre Sorhus (sindresorhus.com)
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.
crypto-random-string-3.3.0/package.json000066400000000000000000000013411372416655500201220ustar00rootroot00000000000000{
"name": "crypto-random-string",
"version": "3.3.0",
"description": "Generate a cryptographically strong random string",
"license": "MIT",
"repository": "sindresorhus/crypto-random-string",
"author": {
"name": "Sindre Sorhus",
"email": "sindresorhus@gmail.com",
"url": "sindresorhus.com"
},
"engines": {
"node": ">=8"
},
"scripts": {
"test": "xo && ava && tsd"
},
"files": [
"index.js",
"index.d.ts"
],
"keywords": [
"random",
"string",
"text",
"id",
"identifier",
"slug",
"salt",
"pin",
"crypto",
"strong",
"secure",
"hex",
"secret",
"protect"
],
"dependencies": {
"type-fest": "^0.8.1"
},
"devDependencies": {
"ava": "^2.1.0",
"tsd": "^0.11.0",
"xo": "^0.25.3"
}
}
crypto-random-string-3.3.0/readme.md000066400000000000000000000076551372416655500174310ustar00rootroot00000000000000# crypto-random-string [](https://travis-ci.org/sindresorhus/crypto-random-string)
> Generate a [cryptographically strong](https://en.wikipedia.org/wiki/Strong_cryptography) random string
Can be useful for creating an identifier, slug, salt, PIN code, fixture, etc.
## Install
```
$ npm install crypto-random-string
```
## Usage
```js
const cryptoRandomString = require('crypto-random-string');
cryptoRandomString({length: 10});
//=> '2cf05d94db'
cryptoRandomString({length: 10, type: 'base64'});
//=> 'YMiMbaQl6I'
cryptoRandomString({length: 10, type: 'url-safe'});
//=> 'YN-tqc8pOw'
cryptoRandomString({length: 10, type: 'numeric'});
//=> '8314659141'
cryptoRandomString({length: 6, type: 'distinguishable'});
//=> 'CDEHKM'
cryptoRandomString({length: 10, type: 'ascii-printable'});
//=> '`#Rt8$IK>B'
cryptoRandomString({length: 10, type: 'alphanumeric'});
//=> 'DMuKL8YtE7'
cryptoRandomString({length: 10, characters: 'abc'});
//=> 'abaaccabac'
```
## API
### cryptoRandomString(options)
Returns a randomized string. [Hex](https://en.wikipedia.org/wiki/Hexadecimal) by default.
### cryptoRandomString.async(options)
Returns a promise which resolves to a randomized string. [Hex](https://en.wikipedia.org/wiki/Hexadecimal) by default.
#### options
Type: `object`
##### length
*Required*\
Type: `number`
Length of the returned string.
##### type
Type: `string`\
Default: `'hex'`\
Values: `'hex' | 'base64' | 'url-safe' | 'numeric' | 'distinguishable' | 'ascii-printable' | 'alphanumeric'`
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.
The `ascii-printable` set contains all [printable ASCII characters](https://en.wikipedia.org/wiki/ASCII#ASCII_printable_characters): ``!"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~`` Useful for generating passwords where all possible ASCII characters should be used.
The `alphanumeric` set contains uppercase letters, lowercase letters, and digits: `ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789`. Useful for generating [nonce](https://developer.mozilla.org/en-US/docs/Web/API/HTMLOrForeignElement/nonce) values.
##### characters
Type: `string`\
Minimum length: `1`\
Maximum length: `65536`
Use only characters from a custom set of allowed characters.
Cannot be set at the same time as the `type` option.
## Related
- [random-int](https://github.com/sindresorhus/random-int) - Generate a random integer
- [random-float](https://github.com/sindresorhus/random-float) - Generate a random float
- [random-item](https://github.com/sindresorhus/random-item) - Get a random item from an array
- [random-boolean](https://github.com/arthurvr/random-boolean) - Get a random boolean
- [random-obj-key](https://github.com/sindresorhus/random-obj-key) - Get a random key from an object
- [random-obj-prop](https://github.com/sindresorhus/random-obj-prop) - Get a random property from an object
- [unique-random](https://github.com/sindresorhus/unique-random) - Generate random numbers that are consecutively unique
---
crypto-random-string-3.3.0/test.js000066400000000000000000000115431372416655500171560ustar00rootroot00000000000000import test from 'ava';
import cryptoRandomString from '.';
// Probabilistic, result is always less than or equal to actual set size, chance it is less is below 1e-256 for sizes up to 32656
const generatedCharacterSetSize = (options, targetSize) => {
const set = new Set();
const length = targetSize * 640;
const string = cryptoRandomString({...options, length});
for (let i = 0; i < length; i++) {
set.add(string[i]);
}
return set.size;
};
test('main', t => {
t.is(cryptoRandomString({length: 0}).length, 0);
t.is(cryptoRandomString({length: 10}).length, 10);
t.is(cryptoRandomString({length: 100}).length, 100);
t.regex(cryptoRandomString({length: 100}), /^[a-f\d]*$/); // Sanity check, probabilistic
t.is(generatedCharacterSetSize({}, 16), 16);
});
test('async', async t => {
t.is((await cryptoRandomString.async({length: 0})).length, 0);
t.is((await cryptoRandomString.async({length: 10})).length, 10);
t.is((await cryptoRandomString.async({length: 100})).length, 100);
t.regex(await cryptoRandomString.async({length: 100}), /^[a-f\d]*$/); // Sanity check, probabilistic
});
test('hex', t => {
t.is(cryptoRandomString({length: 0, type: 'hex'}).length, 0);
t.is(cryptoRandomString({length: 10, type: 'hex'}).length, 10);
t.is(cryptoRandomString({length: 100, type: 'hex'}).length, 100);
t.regex(cryptoRandomString({length: 100, type: 'hex'}), /^[a-f\d]*$/); // Sanity check, probabilistic
t.is(generatedCharacterSetSize({type: 'hex'}, 16), 16);
});
test('base64', t => {
t.is(cryptoRandomString({length: 0, type: 'base64'}).length, 0);
t.is(cryptoRandomString({length: 10, type: 'base64'}).length, 10);
t.is(cryptoRandomString({length: 100, type: 'base64'}).length, 100);
t.regex(cryptoRandomString({length: 100, type: 'base64'}), /^[a-zA-Z\d/+]*$/); // Sanity check, probabilistic
t.is(generatedCharacterSetSize({type: 'base64'}, 64), 64);
});
test('url-safe', t => {
t.is(cryptoRandomString({length: 0, type: 'url-safe'}).length, 0);
t.is(cryptoRandomString({length: 10, type: 'url-safe'}).length, 10);
t.is(cryptoRandomString({length: 100, type: 'url-safe'}).length, 100);
t.regex(cryptoRandomString({length: 100, type: 'url-safe'}), /^[a-zA-Z\d._~-]*$/); // Sanity check, probabilistic
t.is(generatedCharacterSetSize({type: 'url-safe'}, 66), 66);
});
test('numeric', t => {
t.is(cryptoRandomString({length: 0, type: 'numeric'}).length, 0);
t.is(cryptoRandomString({length: 10, type: 'numeric'}).length, 10);
t.is(cryptoRandomString({length: 100, type: 'numeric'}).length, 100);
t.regex(cryptoRandomString({length: 100, type: 'numeric'}), /^[\d]*$/); // Sanity check, probabilistic
t.is(generatedCharacterSetSize({type: 'numeric'}, 10), 10);
});
test('distinguishable', 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('ascii-printable', t => {
t.is(cryptoRandomString({length: 0, type: 'ascii-printable'}).length, 0);
t.is(cryptoRandomString({length: 10, type: 'ascii-printable'}).length, 10);
t.is(cryptoRandomString({length: 100, type: 'ascii-printable'}).length, 100);
t.regex(cryptoRandomString({length: 100, type: 'ascii-printable'}), /^[!"#$%&'()*+,-./\d:;<=>?@A-Z[\\\]^_`a-z{|}~]*$/); // Sanity check, probabilistic
});
test('alphanumeric', t => {
t.is(cryptoRandomString({length: 0, type: 'alphanumeric'}).length, 0);
t.is(cryptoRandomString({length: 10, type: 'alphanumeric'}).length, 10);
t.is(cryptoRandomString({length: 100, type: 'alphanumeric'}).length, 100);
t.regex(cryptoRandomString({length: 100, type: 'alphanumeric'}), /^[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789]*$/); // Sanity check, probabilistic
t.is(generatedCharacterSetSize({type: 'alphanumeric'}, 19), 62);
});
test('characters', t => {
t.is(cryptoRandomString({length: 0, characters: '1234'}).length, 0);
t.is(cryptoRandomString({length: 10, characters: '1234'}).length, 10);
t.is(cryptoRandomString({length: 100, characters: '1234'}).length, 100);
t.regex(cryptoRandomString({length: 100, characters: '1234'}), /^[1-4]*$/); // Sanity check, probabilistic
t.is(generatedCharacterSetSize({characters: '1234'}, 4), 4);
t.is(generatedCharacterSetSize({characters: '0123456789'}, 10), 10);
});
test('argument errors', t => {
t.throws(() => {
cryptoRandomString({length: Infinity});
});
t.throws(() => {
cryptoRandomString({length: -1});
});
t.throws(() => {
cryptoRandomString({length: 0, type: 'hex', characters: '1234'});
});
t.throws(() => {
cryptoRandomString({length: 0, characters: 42});
});
t.throws(() => {
cryptoRandomString({length: 0, type: 'unknown'});
});
});