Skip to content

Commit 4c41bee

Browse files
committed
Add “No crypto” section
1 parent 9d16701 commit 4c41bee

File tree

2 files changed

+46
-27
lines changed

2 files changed

+46
-27
lines changed

README.md

Lines changed: 41 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ Efficiently generate cryptographically strong random strings of specified entrop
1414
- [Custom Characters](#CustomCharacters)
1515
- [Efficiency](#Efficiency)
1616
- [Custom Bytes](#CustomBytes)
17+
- [No Crypto](#NoCrypto)
1718
- [Entropy Bits](#EntropyBits)
1819
- [Why You Don't Need UUIDs](#UUID)
1920
- [Upgrading](#Upgrading)
@@ -55,13 +56,13 @@ See the [UUID](#UUID) section for a discussion of why the above is more efficien
5556

5657
```js
5758
const { Entropy } = require('entropy-string')
58-
59+
5960
const entropy = new Entropy({ total: 1e6, risk: 1e9 })
6061
const string = entropy.string()
6162
```
6263

6364
> pbbnBD4MQ3rbRN
64-
65+
6566
See [Real Need](#RealNeed) for description of what the `total` and `risk` parameters represent.
6667

6768
##### Hexidecimal strings
@@ -70,7 +71,7 @@ See [Real Need](#RealNeed) for description of what the `total` and `risk` parame
7071

7172
```js
7273
const { Entropy, charset16 } = require('entropy-string')
73-
74+
7475
const entropy = new Entropy({ total: 1e6, risk: 1e9, charset: charset16 })
7576
const string = entropy.string()
7677
```
@@ -89,31 +90,31 @@ Custom characters may also be specified. Using uppercase hexadecimal characters:
8990
```
9091

9192
> 16E26779479356B516
92-
93-
##### Convenience functions
93+
94+
##### Convenience functions
9495

9596
Convenience functions `smallID`, `mediumID`, `largeID`, `sessionID` and `token` provide random strings for various predefined bits of entropy. For example, a small id represents a potential of 30 strings with a 1 in a million chance of repeat:
9697

9798
```js
9899
const { Entropy } = require('entropy-string')
99-
100+
100101
const entropy = new Entropy()
101102
const string = entropy.smallID()
102103
```
103104

104105
> DpTQqg
105-
106+
106107
Or, to generate an OWASP session ID:
107108

108109
```js
109110
const { Entropy } = require('entropy-string')
110-
111+
111112
const entropy = new Entropy()
112113
const string = entropy.sessionID()
113114
```
114115

115116
> nqqBt2P669nmjPQRqh4NtmTPn9
116-
117+
117118
Or perhaps you need an 256-bit token using [RFC 4648](https://tools.ietf.org/html/rfc4648#section-5) file system and URL safe characters:
118119
```js
119120
const { Entropy, charset64} = require('entropy-string')
@@ -269,7 +270,7 @@ Finally, let say we're generating session IDs. Since session IDs are ephemeral,
269270
```
270271

271272
> String: Rm9gDFn6Q9DJ9rbrtrttBjR97r
272-
273+
273274
Since session ID are such an important need, `EntropyString` provides a convenience function for generating them:
274275

275276
```js
@@ -368,7 +369,7 @@ The `Entropy` constructor allows for the following cases:
368369
- One of six predefined `CharSet`s can be specified
369370
- { charset: **chars** }:
370371
- A string representing the characters to use can be specified
371-
- A combination of `charset` and either `bits` or `total`,`risk`
372+
- A combination of `charset` and either `bits` or `total`,`risk`
372373

373374
If a string of characters is used, an `EntropyStringError` will be thrown if the characters aren't appropriate for creating a valid `CharSet`.
374375
```js
@@ -392,7 +393,7 @@ If a string of characters is used, an `EntropyStringError` will be thrown if the
392393
console.log(error.message)
393394
}
394395
```
395-
396+
396397
> Characters not unique
397398
398399
[TOC](#TOC)
@@ -425,9 +426,9 @@ Compare that to the `EntropyString` scheme. For the example above, slicing off 5
425426
const entropy = new Entropy({ bits: 80 })
426427
let string = entropy.string()
427428
```
428-
429+
429430
> HFtgHQ9q9fH6B8HM
430-
431+
431432
But there is an even bigger issue with the previous code from a security perspective. `Math.random` *is not a cryptographically strong random number generator*. **_Do not_** use `Math.random` to create strings used for security purposes! This highlights an important point. Strings are only capable of carrying information (entropy); it's the random bytes that actually provide the entropy itself. `EntropyString` automatically generates the necessary bytes needed to create cryptographically strong random strings using the `crypto` library.
432433

433434
However, if you don't need cryptographically strong random strings, you can request `EntropyString` use the psuedo-random number generator (PRNG) `Math.random` rather than the `crypto` library by using passing the param `prng: true` to the `Entropy` constructor:
@@ -438,9 +439,9 @@ However, if you don't need cryptographically strong random strings, you can requ
438439
const entropy = new Entropy({ bits: 80, prng: true })
439440
string = entropy.string()
440441
```
441-
442+
442443
> fdRp9Q3rTMF7TdFN
443-
444+
444445
When using `Math.random`, the `EntropyString` scheme uses 48 of the 52(ish) bits of randomness from each call to `Math.random`. That's much more efficient than the previous code snippet but a bit less so than using bytes from `crypto`. And of course, being a PRNG, `Math.random` yields a deterministic sequence.
445446

446447
Fortunately you don't need to really understand how the bytes are efficiently sliced and diced to get the string. But you may want to provide your own [Custom Bytes](#CustomBytes) to create a string, which is the next topic.
@@ -462,7 +463,7 @@ Suppose we want a string capable of 30 bits of entropy using 32 characters. We p
462463
```
463464

464465
> Th7fjL
465-
466+
466467
The __bytes__ provided can come from any source. However, the number of bytes must be sufficient to generate the string as described in the [Efficiency](#Efficiency) section. `entropy.stringWithBytes` throws an `Error` if the string cannot be formed from the passed bytes.
467468

468469
```js
@@ -480,6 +481,21 @@ Note the number of bytes needed is dependent on the number of characters in our
480481

481482
[TOC](#TOC)
482483

484+
### <a name="NoCrypto"></a>No crypto
485+
486+
`EntropyString` uses the `crypto` library by default when generating the random bits used to systematically index into the chosen character set. In environments where the `crypto` library is not available, `EntropyString` can use the psuedo-random number generator `Math.random` by passing `prng: true` to the `Entropy` constructor:
487+
488+
```js
489+
const { Entropy } = require('entropy-string')
490+
491+
const entropy = new Entropy({ total: 1e5, risk: 1e7, prng: true })
492+
const string = entropy.string()
493+
```
494+
495+
> MJNhBg842J6
496+
497+
[TOC](#TOC)
498+
483499
### <a name="EntropyBits"></a>Entropy Bits
484500

485501
Thus far we've avoided the mathematics behind the calculation of the entropy bits required to specify a risk that some number random strings will not have a repeat. As noted in the [Overview](#Overview), the posting [Hash Collision Probabilities](http://preshing.com/20110504/hash-collision-probabilities/) derives an expression, based on the well-known [Birthday Problem](https://en.wikipedia.org/wiki/Birthday_problem#Approximations), for calculating the probability of a collision in some number of hashes (denoted by `k`) using a perfect hash with an output of `M` bits:
@@ -520,7 +536,7 @@ Per [Section 4.4 of RFC 4122](https://tools.ietf.org/html/rfc4122#section-4.4),
520536
- The 17th hex char will be one of **8**, **9**, **A** or **B**
521537
- Set all the other bits to randomly (or pseudo-randomly) chosen values
522538

523-
The algorithm designates how to create the 32 byte UUID. The string representation shown above is specified in Section 3 of the RFC.
539+
The algorithm designates how to create the 32 byte UUID. The string representation shown above is specified in Section 3 of the RFC.
524540

525541
The ramifications of the algorithm and string representation are:
526542

@@ -546,7 +562,7 @@ Let's create a 122 entropy bit string using `charset64`:
546562
const string = entropy.string()
547563
```
548564

549-
- Entropy String:
565+
- Entropy String:
550566
- Entropy bits: 126
551567
- String length: 21
552568
- String bits: 168
@@ -595,7 +611,7 @@ becomes
595611
const string = random.sessionID()
596612
```
597613

598-
or
614+
or
599615

600616
```js
601617
const { Entropy } = require('entropy-string')
@@ -615,7 +631,7 @@ For example,
615631
const string = random.sessionID()
616632
```
617633

618-
becomes
634+
becomes
619635

620636
```js
621637
const { Entropy, charset64 } = require('entropy-string')
@@ -627,7 +643,7 @@ becomes
627643

628644
- Remove `bitsWithRiskPower` and `bitsWithPowers` from `Entropy`
629645
- Move predefined `CharSet` declarations from `CharSet` to `Entropy`
630-
- `Entropy.bits` is a class method of the new `Entropy` class
646+
- `Entropy.bits` is a class method of the new `Entropy` class
631647

632648
#### <a name="Version31"></a>Version 3.1
633649

@@ -660,7 +676,7 @@ Version 4 changes:
660676
- `Entropy` constructor param `{ prng: true }` forces the `Entropy.string()` method to use `Math.random` generated bytes
661677
- Change signature of method `stringWithBytes(bitLen, bytes, <charset>)` to `stringWithBytes(bytes, <bitLen>, <charset>)` (i.e., `bitLen` defaults to the `Entropy` class setting)
662678
- This change is parallel to the version 3.1 change to `Entropy.string()` but required a semantic major version upgrade to implement
663-
679+
664680
[TOC](#TOC)
665681

666682
### <a name="TakeAway"></a>Take Away
@@ -675,12 +691,12 @@ Version 4 changes:
675691
- Specified entropy as the risk of repeat in a total number of strings
676692
- Characters used are arbitrary
677693
- You need `EntropyString`, not UUIDs
678-
694+
679695
##### 10 million strings with a 1 in a trillion chance of a repeat:
680696

681697
```js
682698
const { Entropy } = require('entropy-string')
683-
699+
684700
const entropy = new Entropy({ total: 1e7, risk: 1e12 })
685701
const string = entropy.string()
686702
```

examples/prng.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@
22

33
const { default: Entropy } = require('./entropy')
44

5-
const entropy = new Entropy({ bits: 80, prng: true })
6-
const string = entropy.string()
5+
let entropy = new Entropy({ bits: 80, prng: true })
6+
let string = entropy.string()
77
console.log(`\n PRNG 80-bit string : ${string}\n`)
88

9+
entropy = new Entropy({ total: 1e5, risk: 1e7, prng: true })
10+
string = entropy.string()
11+
console.log(`\n 10,000 potential strings with 1 in 10 million risk of repeat: ${string}\n`)

0 commit comments

Comments
 (0)