UNPKG

7.22 kBMarkdownView Raw
1# Nano ID
2
3<img src="https://ai.github.io/nanoid/logo.svg" align="right"
4 alt="Nano ID logo by Anton Lovchikov" width="180" height="94">
5
6A tiny, secure, URL-friendly, unique string ID generator for JavaScript.
7
8**Safe.** It uses cryptographically strong random APIs
9and tests distribution of symbols.
10
11**Small.** 145 bytes (minified and gzipped). No dependencies.
12It uses [Size Limit] to control size.
13
14**Compact.** It uses a larger alphabet than UUID (`A-Za-z0-9_~`).
15As result it could reduce ID size from 36 to 21 symbols.
16
17```js
18var nanoid = require('nanoid')
19model.id = nanoid() //=> "V1StGXR8_Z5jdHi6B~myT"
20```
21
22The generator supports Node.js, React Native, and [all browsers].
23
24[all browsers]: http://caniuse.com/#feat=getrandomvalues
25[Size Limit]: https://github.com/ai/size-limit
26
27<a href="https://evilmartians.com/?utm_source=nanoid">
28 <img src="https://evilmartians.com/badges/sponsored-by-evil-martians.svg"
29 alt="Sponsored by Evil Martians" width="236" height="54">
30</a>
31
32
33## Security
34
35*See a good article about random generators theory:
36[Secure random values (in Node.js)]*
37
38
39### Unpredictability
40
41Instead of using the unsafe `Math.random()`, Nano ID uses the `crypto` module
42in Node.js and the Web Crypto API in browsers. This modules use unpredictable
43hardware random generator.
44
45
46### Uniformity
47
48`random % alphabet` is a popular mistake to make when coding an ID generator.
49The spread will not be even; there will be a lower chance for some symbols
50to appear compared to others—so it will reduce the number of tries
51when brute-forcing.
52
53Nano ID uses a [better algorithm] and is tested for uniformity.
54
55<img src="img/distribution.png" alt="Nano ID uniformity"
56 width="340" height="135">
57
58[Secure random values (in Node.js)]: https://gist.github.com/joepie91/7105003c3b26e65efcea63f3db82dfba
59[better algorithm]: https://github.com/ai/nanoid/blob/master/format.js
60
61
62## Comparison with UUID
63
64Nano ID is quite comparable to UUID v4 (random-based).
65It has a similar number of random bits in the ID
66(126 in Nano ID and 122 in UUID), so it has a similar collision probability:
67
68> For there to be a one in a billion chance of duplication,
69> 103 trillion version 4 IDs must be generated.
70
71There are two main differences between Nano ID and UUID v4:
72
731. Nano ID uses a bigger alphabet, so a similar number of random bits
74 are packed in just 21 symbols instead of 36.
752. Nano ID code is 3 times less than `uuid/v4` package:
76 145 bytes instead of 435.
77
78
79## Benchmark
80
81```rust
82$ ./test/benchmark
83nanoid 354,201 ops/sec
84nanoid/generate 348,467 ops/sec
85uid.sync 325,347 ops/sec
86uuid/v4 322,328 ops/sec
87shortid 33,277 ops/sec
88
89Async:
90uid 71,998 ops/sec
91nanoid/async 72,836 ops/sec
92
93Non-secure:
94rndm 2,495,324 ops/sec
95nanoid/non-secure 2,746,033 ops/sec
96```
97
98
99## Usage
100
101### Normal
102
103The main module uses URL-friendly symbols (`A-Za-z0-9_~`) and returns an ID
104with 21 characters (to have a collision probability similar to UUID v4).
105
106```js
107const nanoid = require('nanoid')
108model.id = nanoid() //=> "Uakgb_J5m9g~0JDMbcJqLJ"
109```
110
111Symbols `-,.()` are not encoded in the URL. If used at the end of a link
112they could be identified as a punctuation symbol.
113
114If you want to reduce ID length (and increase collisions probability),
115you can pass the length as an argument.
116
117```js
118nanoid(10) //=> "IRFa~VaY2b"
119```
120
121Don’t forget to check safety of your ID length
122in our [ID collision probability] calculator.
123
124[ID collision probability]: https://zelark.github.io/nano-id-cc/
125
126
127### React Native and Web Workers
128
129React Native and Web Worker don’t have access to secure random generator.
130
131Security is important in ID, when ID should be unpredictable. For instance,
132in “access by URL” link generation.
133
134If you don’t need unpredictable IDs, but you need React Native
135or Web Workers support, you can use non‑secure ID generator.
136
137```js
138const nanoid = require('nanoid/non-secure')
139model.id = nanoid() //=> "Uakgb_J5m9g~0JDMbcJqLJ"
140```
141
142
143## Async
144
145To generate hardware random bytes, CPU will collect electromagnetic noise.
146During the collection, CPU doesn’t work. So if we will use asynchronous API
147for hardware random generator, your other code could be executed during
148the entropy collection.
149
150```js
151const nanoid = require('nanoid/async')
152nanoid.then(id => {
153 model.id = id
154})
155```
156
157Unfortunately, you will not have any benefits in browser, since Web Crypto API
158doesn’t have asynchronous API.
159
160
161### Custom Alphabet or Length
162
163If you want to change the ID's alphabet or length
164you can use the low-level `generate` module.
165
166```js
167const generate = require('nanoid/generate')
168model.id = generate('1234567890abcdef', 10) //=> "4f90d13a42"
169```
170
171Check safety of your custom alphabet and ID length
172in our [ID collision probability] calculator.
173You can find popular alphabets in [`nanoid-dictionary`].
174
175Alphabet must contain 256 symbols or less.
176Otherwise, the generator will not be secure.
177
178[ID collision probability]: https://alex7kom.github.io/nano-nanoid-cc/
179[`nanoid-dictionary`]: https://github.com/CyberAP/nanoid-dictionary
180
181
182### Custom Random Bytes Generator
183
184You can replace the default safe random generator using the `format` module.
185For instance, to use a seed-based generator.
186
187```js
188const format = require('nanoid/format')
189
190function random (size) {
191 const result = []
192 for (let i = 0; i < size; i++) {
193 result.push(randomByte())
194 }
195 return result
196}
197
198format(random, "abcdef", 10) //=> "fbaefaadeb"
199```
200
201`random` callback must accept the array size and return an array
202with random numbers.
203
204If you want to use the same URL-friendly symbols with `format`,
205you can get the default alphabet from the `url` file.
206
207```js
208const url = require('nanoid/url')
209format(random, url, 10) //=> "93ce_Ltuub"
210```
211
212
213## Tools
214
215* [ID size calculator] to choice smaller ID size depends on your case.
216* [`nanoid-dictionary`] with popular alphabets to use with `nanoid/generate`.
217* [`nanoid-cli`] to generate ID from CLI.
218* [`nanoid-good`] to be sure that your ID doesn't contain any obscene words.
219
220[`nanoid-dictionary`]: https://github.com/CyberAP/nanoid-dictionary
221[ID size calculator]: https://zelark.github.io/nano-id-cc/
222[`nanoid-cli`]: https://github.com/twhitbeck/nanoid-cli
223[`nanoid-good`]: https://github.com/y-gagar1n/nanoid-good
224
225
226## Other Programming Languages
227
228* [C#](https://github.com/codeyu/nanoid-net)
229* [Clojure and ClojureScript](https://github.com/zelark/nano-id)
230* [Crystal](https://github.com/mamantoha/nanoid.cr)
231* [Dart](https://github.com/pd4d10/nanoid)
232* [Go](https://github.com/matoous/go-nanoid)
233* [Elixir](https://github.com/railsmechanic/nanoid)
234* [Haskell](https://github.com/4e6/nanoid-hs)
235* [Java](https://github.com/aventrix/jnanoid)
236* [PHP](https://github.com/hidehalo/nanoid-php)
237* [Python](https://github.com/puyuan/py-nanoid)
238* [Ruby](https://github.com/radeno/nanoid.rb)
239* [Rust](https://github.com/nikolay-govorov/nanoid)
240* [Swift](https://github.com/antiflasher/NanoID)
241
242Also, [CLI tool] is available to generate IDs from command line.
243
244[CLI tool]: https://github.com/twhitbeck/nanoid-cli