UNPKG

8.29 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* **Small.** 142 bytes (minified and gzipped). No dependencies.
9It uses [Size Limit] to control size.
10* **Safe.** It uses cryptographically strong random APIs
11and tests distribution of symbols.
12* **Fast.** It’s 16% faster than UUID.
13* **Compact.** It uses a larger alphabet than UUID (`A-Za-z0-9_~`).
14So ID size was reduced from 36 to 21 symbols.
15
16```js
17var nanoid = require('nanoid')
18model.id = nanoid() //=> "V1StGXR8_Z5jdHi6B~myT"
19```
20
21The generator supports Node.js, React Native, and [all browsers].
22
23[all browsers]: http://caniuse.com/#feat=getrandomvalues
24[Size Limit]: https://github.com/ai/size-limit
25
26<a href="https://evilmartians.com/?utm_source=nanoid">
27 <img src="https://evilmartians.com/badges/sponsored-by-evil-martians.svg"
28 alt="Sponsored by Evil Martians" width="236" height="54">
29</a>
30
31
32## Security
33
34*See a good article about random generators theory:
35[Secure random values (in Node.js)]*
36
37
38### Unpredictability
39
40Instead of using the unsafe `Math.random()`, Nano ID uses the `crypto` module
41in Node.js and the Web Crypto API in browsers. These modules use unpredictable
42hardware random generator.
43
44
45### Uniformity
46
47`random % alphabet` is a popular mistake to make when coding an ID generator.
48The spread will not be even; there will be a lower chance for some symbols
49to appear compared to others—so it will reduce the number of tries
50when brute-forcing.
51
52Nano ID uses a [better algorithm] and is tested for uniformity.
53
54<img src="img/distribution.png" alt="Nano ID uniformity"
55 width="340" height="135">
56
57[Secure random values (in Node.js)]: https://gist.github.com/joepie91/7105003c3b26e65efcea63f3db82dfba
58[better algorithm]: https://github.com/ai/nanoid/blob/master/format.js
59
60
61## Comparison with UUID
62
63Nano ID is quite comparable to UUID v4 (random-based).
64It has a similar number of random bits in the ID
65(126 in Nano ID and 122 in UUID), so it has a similar collision probability:
66
67> For there to be a one in a billion chance of duplication,
68> 103 trillion version 4 IDs must be generated.
69
70There are two main differences between Nano ID and UUID v4:
71
721. Nano ID uses a bigger alphabet, so a similar number of random bits
73 are packed in just 21 symbols instead of 36.
742. Nano ID code is 3 times less than `uuid/v4` package:
75 142 bytes instead of 435.
76
77
78## Benchmark
79
80```rust
81$ ./test/benchmark
82nanoid 413,579 ops/sec
83nanoid/generate 401,349 ops/sec
84uid.sync 354,882 ops/sec
85uuid/v4 353,836 ops/sec
86shortid 39,152 ops/sec
87
88Async:
89nanoid/async 85,168 ops/sec
90nanoid/async/generate 81,037 ops/sec
91uid 78,426 ops/sec
92
93Non-secure:
94nanoid/non-secure 2,718,186 ops/sec
95rndm 2,544,612 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 the 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
128
129To generate secure random IDs in React Native, you must use
130[a native random generator] and asynchronous API:
131
132```js
133const generateSecureRandom = require('react-native-securerandom').generateSecureRandom
134const format = require('nanoid/async/format')
135const url = require('nanoid/url')
136
137async function createUser () {
138 user.id = await format(generateSecureRandom, url, 21);
139}
140```
141
142[a native random generator]: https://github.com/rh389/react-native-securerandom
143
144
145### Web Workers
146
147Web Workers don’t have access to a secure random generator.
148
149Security is important in IDs, when IDs should be unpredictable. For instance,
150in “access by URL” link generation.
151
152If you don’t need unpredictable IDs, but you need Web Workers support,
153you can use non‑secure ID generator.
154
155```js
156const nanoid = require('nanoid/non-secure')
157model.id = nanoid() //=> "Uakgb_J5m9g~0JDMbcJqLJ"
158```
159
160
161## Async
162
163To generate hardware random bytes, CPU will collect electromagnetic noise.
164During the collection, CPU doesn’t work.
165
166If we will use asynchronous API for random generator,
167another code could be executed during the entropy collection.
168
169```js
170const nanoid = require('nanoid/async')
171
172async function createUser () {
173 user.id = await nanoid()
174}
175```
176
177Unfortunately, you will not have any benefits in a browser, since Web Crypto API
178doesn’t have asynchronous API.
179
180
181## Custom Alphabet or Length
182
183If you want to change the ID's alphabet or length
184you can use the low-level `generate` module.
185
186```js
187const generate = require('nanoid/generate')
188model.id = generate('1234567890abcdef', 10) //=> "4f90d13a42"
189```
190
191Check the safety of your custom alphabet and ID length
192in our [ID collision probability] calculator.
193You can find popular alphabets in [`nanoid-dictionary`].
194
195Alphabet must contain 256 symbols or less.
196Otherwise, the generator will not be secure.
197
198Asynchronous API is also available:
199
200```js
201const generate = require('nanoid/async/generate')
202async function createUser () {
203 user.id = await generate('1234567890abcdef', 10)
204}
205```
206
207[ID collision probability]: https://alex7kom.github.io/nano-nanoid-cc/
208[`nanoid-dictionary`]: https://github.com/CyberAP/nanoid-dictionary
209
210
211## Custom Random Bytes Generator
212
213You can replace the default safe random generator using the `format` module.
214For instance, to use a seed-based generator.
215
216```js
217const format = require('nanoid/format')
218
219function random (size) {
220 const result = []
221 for (let i = 0; i < size; i++) {
222 result.push(randomByte())
223 }
224 return result
225}
226
227format(random, "abcdef", 10) //=> "fbaefaadeb"
228```
229
230`random` callback must accept the array size and return an array
231with random numbers.
232
233If you want to use the same URL-friendly symbols with `format`,
234you can get the default alphabet from the `url` file.
235
236```js
237const url = require('nanoid/url')
238format(random, url, 10) //=> "93ce_Ltuub"
239```
240
241Asynchronous API is also available:
242
243```js
244const format = require('nanoid/async/format')
245const url = require('nanoid/url')
246
247function random (size) {
248 return new Promise(…)
249}
250
251async function createUser () {
252 user.id = await format(random, url, 10)
253}
254```
255
256
257## Tools
258
259* [ID size calculator] to choice smaller ID size depends on your case.
260* [`nanoid-dictionary`] with popular alphabets to use with `nanoid/generate`.
261* [`nanoid-cli`] to generate ID from CLI.
262* [`nanoid-good`] to be sure that your ID doesn't contain any obscene words.
263
264[`nanoid-dictionary`]: https://github.com/CyberAP/nanoid-dictionary
265[ID size calculator]: https://zelark.github.io/nano-id-cc/
266[`nanoid-cli`]: https://github.com/twhitbeck/nanoid-cli
267[`nanoid-good`]: https://github.com/y-gagar1n/nanoid-good
268
269
270## Other Programming Languages
271
272* [C#](https://github.com/codeyu/nanoid-net)
273* [Clojure and ClojureScript](https://github.com/zelark/nano-id)
274* [Crystal](https://github.com/mamantoha/nanoid.cr)
275* [Dart](https://github.com/pd4d10/nanoid)
276* [Go](https://github.com/matoous/go-nanoid)
277* [Elixir](https://github.com/railsmechanic/nanoid)
278* [Haskell](https://github.com/4e6/nanoid-hs)
279* [Java](https://github.com/aventrix/jnanoid)
280* [Nim](https://github.com/icyphox/nanoid.nim)
281* [PHP](https://github.com/hidehalo/nanoid-php)
282* [Python](https://github.com/puyuan/py-nanoid)
283* [Ruby](https://github.com/radeno/nanoid.rb)
284* [Rust](https://github.com/nikolay-govorov/nanoid)
285* [Swift](https://github.com/antiflasher/NanoID)
286
287Also, [CLI tool] is available to generate IDs from a command line.
288
289[CLI tool]: https://github.com/twhitbeck/nanoid-cli