Skip to content

Commit b46343a

Browse files
committed
Rework README and playground
1 parent 2c78688 commit b46343a

File tree

7 files changed

+111
-135
lines changed

7 files changed

+111
-135
lines changed

EntropyString.playground/Pages/More Examples.xcplaygroundpage/Contents.swift

Lines changed: 28 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -4,54 +4,51 @@
44
//: In [Real Need](Real%20Need) our developer used hexadecimal characters for the strings.
55
//: Let's look at using other characters instead.
66
//:
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
99

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)
1313

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")
1616
//: * callout(string): pPp2F6RhHJ
1717
//:
1818
//: 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).
1919
//:
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()
2422

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
2826
//:
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)
3229

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
3635
//:
3736
//: Okay, we probably wouldn't use 4 characters (and what's up with those characters?), but you get the idea.
3837
//:
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)
4442

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")
4745
//: * callout(string): frN7L8b9bHrpnBHPmR9RnM
4846
//:
4947
//: 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)
5249

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")
5552
//: * callout(string): p-own2zCpNx1Y4TdfyuDsI
5653
//:
5754
//: Using 64 characters, our string length is 22 characters. That's actually `22*6 = 132` bits, so we've got our OWASP requirement covered! 😌

EntropyString.playground/Pages/Overview.xcplaygroundpage/Contents.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,6 @@
1010
//:
1111
//: Understanding probabilistic uniqueness requires some understanding of [*entropy*](https://en.wikipedia.org/wiki/Entropy_(information_theory)) and of estimating the probability of a [*collision*](https://en.wikipedia.org/wiki/Birthday_problem#Cast_as_a_collision_problem) (i.e., the probability that two strings in a set of randomly generated strings might be the same). Happily, you can use `entropy-string` without a deep understanding of these topics.
1212
//:
13-
//: We'll begin investigating `EntropyString` by considering our [Real Need](Read%20Need) when generating random strings.
13+
//: We'll begin investigating `EntropyString` by considering our [Real Need](Real%20Need) when generating random strings.
1414
//:
1515
//: [TOC](Table%20of%20Contents) | [Next](@next)

EntropyString.playground/Pages/Real Need.xcplaygroundpage/Contents.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@
4545
import EntropyString
4646

4747
let random = Random(.charSet16)
48-
let bits = Entropy.bits(for: 10000, risk: .ten06)
48+
let bits = Entropy.bits(for: 10000, risk: 1.0e6)
4949
var strings = [String]()
5050
for i in 0 ..< 5 {
5151
let string = random.string(bits: bits)
@@ -58,7 +58,7 @@
5858
//: To generate the IDs, we first use
5959
//:
6060
//: ```swift
61-
//: let bits = Entropy.bits(total: 10000, risk: .ten06)
61+
//: let bits = Entropy.bits(total: 10000, risk: 1.0e6)
6262
//: ```
6363
//:
6464
//: to determine the bits of entropy needed to satisfy our probabilistic uniqueness of **10,000** strings with a **1 in a million** (ten to the sixth power) risk of repeat. We didn't print the result, but if you did you'd see it's about **45.51**. Then inside a loop we used
Lines changed: 31 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,56 +1,47 @@
11
//: [Previous](@previous)
22
//:## TL;DR
3-
import EntropyString
3+
import EntropyString
44

5-
//: ###### OWASP session ID using base 32 characters:
6-
var random = Random()
7-
var string = random.sessionID()
5+
//: ##### One million random strings with one in a billion risk of repeat
6+
var random = Random()
7+
var bits = Entropy.bits(for: 1.0e6, risk: 1.0e9)
8+
var string = random.string(bits: bits)
89

9-
var descr = "OWASP session ID using base 32 characters"
10-
print("\n \(descr): \(string)")
11-
//: * callout(string): NPgHpr37TNPL7DpgDh3q6T4h2B
12-
//:
10+
descr = "A million random strings with one in a billion risk of repeat:"
11+
print("\n \(descr): \(string)")
12+
//: * callout(string): 2tF6bMNPqQ82Qj
1313
//:
14-
//: ##### OWASP session ID using [RFC 4648](https://tools.ietf.org/html/rfc4648#section-5) file system and URL safe characters:
15-
random.use(CharSet.charSet64)
16-
string = random.sessionID()
14+
//: ##### One million hex random strings with one in a billion risk of repeat
15+
//: `EntropyString` uses predefined `charset32` characters by default (reference [Character Sets](Character%20Sets)). To get a random hexadecimal string with the same entropy bits as above (see [Real Need](Real%20Need) for description of what entropy bits represents):
16+
random.use(.charSet16)
17+
string = random.string(bits: bits)
1718

18-
descr = "OWASP session ID using RFC 4648 file system and URL safe characters"
19-
print("\n \(descr): \(string)")
20-
//: * callout(string): 9gTtKf_LGD19GCt26LEo1d
19+
descr = "A million hex random strings with one in a billion risk of repeat:"
20+
print("\n \(descr): \(string)")
21+
//: * callout(string): a946ff97a1c4e64e79
2122
//:
22-
//: ##### 48-bit string using hex characters:
23-
random.use(CharSet.charSet16)
24-
string = random.string(bits: 48)
23+
//: ##### Custom characters
24+
//: Custom characters may be specified. Using uppercase hexadecimal characters:
25+
try! random.use("0123456789ABCDEF")
26+
string = random.string(bits: bits)
2527

26-
descr = "48-bit string using hex characters"
27-
print("\n \(descr): \(string)")
28-
//: * callout(string): b16851e3ac98
28+
descr = "A million uppercase hex random strings with one in a billion risk of repeat:"
29+
print("\n \(descr): \(string)")
30+
//: * callout(string): 78E3ACABE544EBA7DF
2931
//:
30-
//: ##### 96-bit string using uppercase hex characters:
31-
try! random.use("0123456789ABCDEF")
32-
string = random.string(bits: 96)
33-
34-
descr = "96-bit string using uppercase hex characters"
35-
print("\n \(descr): \(string)")
36-
//: * callout(string): 134BBC6465B0DF101BFBC44B
37-
//:
38-
//: ##### Base 32 character string with a 1 in a million chance of a repeat in 30 strings:
39-
var bits = Entropy.bits(for: 30, risk: 1000000)
40-
random.use(.charSet32)
41-
string = random.string(bits: bits)
32+
//: ##### Convenience functions
33+
//: Convenience functions exists for a variety of random string needs. For example, to create OWASP session ID:
34+
string = random.sessionID()
4235

43-
descr = "Base 32 character string with a 1 in a million chance of a repeat in 30 strings"
36+
var descr = "OWASP session ID using base custom hex characters"
4437
print("\n \(descr): \(string)")
45-
//: * callout(string): QmtGhb
38+
//: * callout(string): CC287C99158BF152DF98AF36D5E92AE3
4639
//:
47-
//: ##### Base 64 character string with a 1 in a trillion chance of a repeat in 100 million strings:
48-
bits = Entropy.bits(for: .ten07, risk: .ten12)
49-
random = Random(.charSet64)
50-
string = random.string(bits: bits)
40+
//: Or a 256 bit token using [RFC 4648](https://tools.ietf.org/html/rfc4648#section-5) file system and URL safe characters:
41+
string = random.token(.charSet64)
5142

52-
descr = "Base 64 character string with a 1 in a trillion chance of a repeat in 100 million strings"
43+
descr = "256 bit token using RFC 4648 file system and URL safe characters"
5344
print("\n \(descr): \(string)")
54-
//: * callout(string): Datt9RQXWXm5Etj
45+
//: * callout(string): X2AZRHuNN3mFUhsYzHSE_r2SeZJ_9uqdw-j9zvPqU2O
5546
//:
5647
//: [TOC](Table%20of%20Contents) | [Next](@next)

EntropyString.playground/Pages/TLDR2.xcplaygroundpage/Contents.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
import EntropyString
1616

1717
let random = Random()
18-
let bits = Entropy.bits(for: .ten06, risk: .ten09)
18+
let bits = Entropy.bits(for: 1.0e6, risk: 1.0e9)
1919
let string = random.string(bits: bits)
2020

2121
print("String: \(string)\n")

EntropyString.playground/contents.xcplayground

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
2-
<playground version='6.0' target-platform='ios' display-mode='rendered'>
2+
<playground version='6.0' target-platform='ios' display-mode='rendered' executeOnSourceChanges='false'>
33
<pages>
44
<page name='Table of Contents'/>
55
<page name='TLDR'/>

0 commit comments

Comments
 (0)