|
4 | 4 | //: In [Real Need](Real%20Need) our developer used hexadecimal characters for the strings. |
5 | 5 | //: Let's look at using other characters instead. |
6 | 6 | //: |
7 | | -//: We'll start with using 32 characters. What 32 characters, you ask? The [Character Sets](Character%20Sets) section discusses the default characters available in `EntropyString` and the [Custom Characters](Custom%20Characters) section describes how you can use whatever characters you want. By default, `EntropyString` uses `charSet32` characters, so we don't need to pass that parameter into `Random()`. We also pass the `risk` as a power of 10 into the `bits` function. |
8 | | - import EntropyString |
| 7 | +//: We'll start with using 32 characters. What 32 characters, you ask? The [Character Sets](Character%20Sets) section discusses the default characters available in `EntropyString` and the [Custom Characters](Custom%20Characters) section describes how you can use whatever characters you want. By default, `EntropyString` uses `charSet32` characters, so we don't need to pass that parameter into `Random()`. |
| 8 | +import EntropyString |
9 | 9 |
|
10 | | - var random = Random() |
11 | | - var bits = Entropy.bits(for: 10000, risk: .ten06) |
12 | | - var string = random.string(bits: bits) |
| 10 | +var random = Random() |
| 11 | +var bits = Entropy.bits(for: 1.0e5, risk: 1.0e6) |
| 12 | +var string = random.string(bits: bits) |
13 | 13 |
|
14 | | - var descr = "Base 32 string with 1 in a million chance of repeat in ten thousands strings" |
15 | | - print("\n \(descr): \(string)\n") |
| 14 | +var descr = "Ten thousand base 32 strings with 1 in a million risk of repeat" |
| 15 | +print("\n \(descr): \(string)\n") |
16 | 16 | //: * callout(string): pPp2F6RhHJ |
17 | 17 | //: |
18 | 18 | //: We're using the same __bits__ calculation since we haven't changed the number of IDs or the accepted risk of probabilistic uniqueness. But this time we use 32 characters and our resulting ID only requires 10 characters (and can carry 50 bits of entropy). |
19 | 19 | //: |
20 | | -//: As another example, let's assume we need to ensure the names of a handful of items are unique. Let's say 30 items. And suppose we decide we can live with a 1 in 100,000 probability of collision (we're just futzing with some coding ideas). Using the default provided hex characters: |
21 | | - random = Random(.charSet16) |
22 | | - bits = Entropy.bits(for: 30, risk: .ten05) |
23 | | - string = random.string(bits: bits) |
| 20 | +//: As another example, let's assume we need to ensure the names of a handful of items are unique. `EntropyString.smallID` yields strings that have a 1 in a million chance of repeat in 30 strings. |
| 21 | +string = random.smallID() |
24 | 22 |
|
25 | | - descr = "Hex string with 1 in a hundred thousand chance of repeat in 30 strings" |
26 | | - print("\n \(descr): \(string)\n") |
27 | | -//: * callout(string): f9b8f77 |
| 23 | +descr = "Small ID with a 1 in a million chance of repeat in 30 strings:" |
| 24 | +print("\n \(descr): \(string)\n") |
| 25 | +//: * callout(string): ThfLbm |
28 | 26 | //: |
29 | | -//: Using the CharSet 4 characters: |
30 | | - random.use(.charSet4) |
31 | | - string = random.string(bits: bits) |
| 27 | +//: Using the same `Random` instance, we can switch to the predefined `charSet4` characters: |
| 28 | +string = random.smallID(.charSet4) |
32 | 29 |
|
33 | | - descr = "Base 4 string with 1 in a hundred thousand chance of repeat in 30 strings" |
34 | | - print("\n \(descr): \(string)\n") |
35 | | -//: * callout(string): CGCAACAGTTCAT |
| 30 | +random.smallID(.charSet4) |
| 31 | + |
| 32 | +descr = "Base 4 small ID" |
| 33 | +print("\n \(descr): \(string)\n") |
| 34 | +//: * callout(string): CCCCTCAGGCATAGG |
36 | 35 | //: |
37 | 36 | //: Okay, we probably wouldn't use 4 characters (and what's up with those characters?), but you get the idea. |
38 | 37 | //: |
39 | | -//: Suppose we have a more extreme need. We want less than a 1 in a trillion chance that 10 billion strings of 64 characters repeat. Let's see, our risk (trillion) is 10 to the 12th and our total (10 billion) is 10 to the 10th, so: |
40 | | -//: |
41 | | - random.use(.charSet32) |
42 | | - bits = Entropy.bits(for: .ten10, risk: .ten12) |
43 | | - string = random.string(bits: bits) |
| 38 | +//: Suppose we have a more extreme need. We want less than a 1 in a trillion chance that 10 billion strings repeat. Let's see, our risk (trillion) is 10 to the 12th and our total (10 billion) is 10 to the 10th, so: |
| 39 | +random.use(.charSet32) |
| 40 | +bits = Entropy.bits(for: 1.0e10, risk: 1.0e12) |
| 41 | +string = random.string(bits: bits) |
44 | 42 |
|
45 | | - descr = "Base 32 string with 1 in a trillion chance of repeat in 10 billion strings" |
46 | | - print("\n \(descr): \(string)\n") |
| 43 | +descr = "String with 1 in a trillion chance of repeat in 10 billion strings" |
| 44 | +print("\n \(descr): \(string)\n") |
47 | 45 | //: * callout(string): frN7L8b9bHrpnBHPmR9RnM |
48 | 46 | //: |
49 | 47 | //: Finally, let say we're generating session IDs. Since session IDs are ephemeral, we aren't interested in uniqueness per se, but in ensuring our IDs aren't predictable since we can't have the bad guys guessing a valid session ID. In this case, we're using entropy as a measure of unpredictability of the IDs. Rather than calculate our entropy, we declare it as 128 bits (since we read on the OWASP web site that session IDs should be 128 bits). |
50 | | - random.use(.charSet64) |
51 | | - string = random.sessionID() |
| 48 | +string = random.sessionID(.charSet64) |
52 | 49 |
|
53 | | - descr = "OWASP base 64 session ID" |
54 | | - print("\n \(descr): \(string)\n") |
| 50 | +descr = "OWASP URL and file system safe session ID" |
| 51 | +print("\n \(descr): \(string)\n") |
55 | 52 | //: * callout(string): p-own2zCpNx1Y4TdfyuDsI |
56 | 53 | //: |
57 | 54 | //: Using 64 characters, our string length is 22 characters. That's actually `22*6 = 132` bits, so we've got our OWASP requirement covered! 😌 |
|
0 commit comments