Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 896d38d

Browse files
committed
README work
1 parent f258e8b commit 896d38d

File tree

13 files changed

+147
-129
lines changed

13 files changed

+147
-129
lines changed

‎EntropyString.playground/Pages/Character Sets.xcplaygroundpage/Contents.swift

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,14 @@
22
//: ## Character Sets
33
//:
44
//: As we\'ve seen in the previous sections, `EntropyString` provides default characters for each of the supported character sets. Let\'s see what\'s under the hood. The available `CharSet`s are *.charSet64*, *.charSet32*, *.charSet16*, *.charSet8*, *.charSet4* and *.charSet2*. The default characters for each were chosen as follows:
5-
import EntropyString
5+
import EntropyString
66

7-
print("Base 64 chars: \(CharSet.charSet64.chars)\n")
8-
print("Base 32 chars: \(CharSet.charSet32.chars)\n")
9-
print("Base 16 chars: \(CharSet.charSet16.chars)\n")
10-
print("Base 8 chars: \(CharSet.charSet8.chars)\n")
11-
print("Base 4 chars: \(CharSet.charSet4.chars)\n")
12-
print("Base 2 chars: \(CharSet.charSet2.chars)\n")
7+
print("Base 64 chars: \(CharSet.charSet64.chars)\n")
8+
print("Base 32 chars: \(CharSet.charSet32.chars)\n")
9+
print("Base 16 chars: \(CharSet.charSet16.chars)\n")
10+
print("Base 8 chars: \(CharSet.charSet8.chars)\n")
11+
print("Base 4 chars: \(CharSet.charSet4.chars)\n")
12+
print("Base 2 chars: \(CharSet.charSet2.chars)\n")
1313
//: The default character sets were chosen as follows:
1414
//: - Base 64: **ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_**
1515
//: - The file system and URL safe char set from
Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,33 @@
11
//: [Previous](@previous)
22
//: ## Custom Bytes
33
//:
4-
//: As described in [Secure Bytes](Secure%20Bytes), `EntropyString` automatically generates random bytes using either `SecRandomCopyBuf` or `arc4random_buf`. These functions are fine, but you may have a need to provide your own btyes for deterministic testing or to use a specialized byte genterator. The function `random.string(bits:using)` allows specifying your own bytes to create a string.
4+
//: As described in [Secure Bytes](Secure%20Bytes), `EntropyString` automatically generates random bytes using either `SecRandomCopyBuf` or `arc4random_buf`. These functions are fine, but you may have a need to provide your own bytes for deterministic testing or to use a specialized byte genterator. The function `random.string(bits:using)` allows specifying your own bytes to create a string.
55
//:
66
//: Suppose we want a string capable of 30 bits of entropy using 32 characters. We pass in 4 bytes (to cover the 30 bits):
7-
import EntropyString
7+
import EntropyString
88

9-
let random = Random()
10-
let bytes: [UInt8] = [250, 200, 150, 100]
11-
let string = try! random.string(bits: 30, using: bytes)
9+
let random = Random()
10+
let bytes: [UInt8] = [250, 200, 150, 100]
11+
let string = try! random.string(bits: 30, using: bytes)
1212

13-
print("String: \(string)\n")
13+
print("String: \(string)\n")
1414
//: * callout(string): Th7fjL
1515
//:
1616
//: The __bytes__ provided can come from any source. However, if the number of bytes is insufficient to generate the string as described in the [Efficiency](Efficiency) section, an `EntropyStringError.tooFewBytes` is thrown.
17-
do {
18-
try random.string(bits: 32, using: bytes)
19-
}
20-
catch {
21-
print(error)
22-
}
17+
do {
18+
try random.string(bits: 32, using: bytes)
19+
}
20+
catch {
21+
print(error)
22+
}
2323
//: * callout(error): tooFewBytes
2424
//:
25-
//: Note the number of bytes needed is dependent on the number of characters in our set. In using a string to represent entropy, we can only have multiples of the bits of entropy per character used. So in the example above, to get at least 32 bits of entropy using a character set of 32 characters (5 bits per char), we'll need enough bytes to cover 35 bits, not 32, so a `tooFewBytes` error is thrown.
25+
//: Note the number of bytes needed is dependent on the number of characters in the character set. For a string representation of entropy, we can only have multiples of the entropy bits per character. In the example above, each character represents 5 bits of entropy. So we can't get exactly 32 bits and we round up by the bits per character to a total 35 bits. We need 5 bytes (40 bits), not 4 (32 bits).
26+
//:
27+
//: `CharSet.bytes_needed(bits)` can be used to determine the number of bytes needed to cover a specified amount of entropy for a given character set.
28+
let bytesNeeded = random.charSet.bytesNeeded(bits: 32)
29+
30+
print("\nBytes needed: \(bytesNeeded)\n")
31+
//: * callout(bytesNeeded): 5
2632
//:
2733
//: [TOC](Table%20of%20Contents) | [Next](@next)

‎EntropyString.playground/Pages/Custom Characters.xcplaygroundpage/Contents.swift

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2,26 +2,26 @@
22
//: ## Custom Characters
33
//:
44
//: Being able to easily generate random strings is great, but what if you want to specify your own characters? For example, suppose you want to visualize flipping a coin to produce 10 bits of entropy.
5-
import EntropyString
5+
import EntropyString
66

7-
let random = Random(.charSet2)
8-
var flips = random.string(bits: 10)
7+
let random = Random(.charSet2)
8+
var flips = random.string(bits: 10)
99

10-
print("flips: \(flips)\n")
10+
print("flips: \(flips)\n")
1111
//: * callout(flips): 0101001110
1212
//:
1313
//: The resulting string of __0__'s and __1__'s doesn't look quite right. Perhaps you want to use the characters __H__ and __T__ instead.
14-
try! random.use("HT")
15-
flips = random.string(bits: 10)
14+
try! random.use("HT")
15+
flips = random.string(bits: 10)
1616

17-
print("flips: \(flips)\n")
17+
print("flips: \(flips)\n")
1818
//: * callout(flips): HTTTHHTTHH
1919
//:
2020
//: As another example, we saw in [Character Sets](Character%20Sets) the default characters for `charSet16` are **0123456789abcdef**. Suppose you like uppercase hexadecimal letters instead.
21-
try! random.use("0123456789ABCDEF")
22-
let hex = random.string(bits: 48)
21+
try! random.use("0123456789ABCDEF")
22+
let hex = random.string(bits: 48)
2323

24-
print("hex: \(hex)\n")
24+
print("hex: \(hex)\n")
2525
//: * callout(hex): 4D20D9AA862C
2626
//:
2727
//: The `Random` constructor allows for three separate cases:
@@ -30,20 +30,20 @@
3030
//: - A string representing the characters to use can be specified.
3131
//:
3232
//: The 3rd option above will throw an `EntropyStringError` if the characters string isn't appropriate for creating a `CharSet`.
33-
do {
34-
try random.use("abcdefg")
35-
}
36-
catch {
37-
print(error)
38-
}
33+
do {
34+
try random.use("abcdefg")
35+
}
36+
catch {
37+
print(error)
38+
}
3939
//: * callout(error): invalidCharCount
4040
//:
41-
do {
42-
try random.use("01233210")
43-
}
44-
catch {
45-
print(error)
46-
}
41+
do {
42+
try random.use("01233210")
43+
}
44+
catch {
45+
print(error)
46+
}
4747
//: * callout(error): charsNotUnique
4848
//:
4949
//: [TOC](Table%20of%20Contents) | [Next](@next)

‎EntropyString.playground/Pages/Efficiency.xcplaygroundpage/Contents.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
//: string += String(char)
1515
//: }
1616
//:
17-
//: In the code above, `arc4random_uniform` generates 32 bits of randomness, returned as an `UInt32`. The returned value is used to create **index**. Suppose we're creating strings with **len=16** and **charCount=32**. Each **char** consumes 32 bits of randomness (`UInt32`) while only injecting 5 bits (`log2(32)`) of entropy into **string**. The resulting string has an information carrying capacity of 80 bits. So creating each string requires a *total* of 512 bits of randomness while only actually *carrying* 80 bits of that entropy forward in the string itself. That means 432 bits (84% of the total!) of the generated randomness is simply wasted.
17+
//: In the code above, `arc4random_uniform` generates 32 bits of randomness, returned as an `UInt32`. The returned value is used to create **index**. Suppose we're creating strings with **len = 16** and **charCount = 32**. Each **char** consumes 32 bits of randomness (`UInt32`) while only injecting 5 bits (`log2(32)`) of entropy into **string**. The resulting string has an information carrying capacity of 80 bits. So creating each string requires a *total* of 512 bits of randomness while only actually *carrying* 80 bits of that entropy forward in the string itself. That means 432 bits (84% of the total!) of the generated randomness is simply wasted.
1818
//:
1919
//: Compare that to the `EntropyString` scheme. For the example above, slicing off 5 bits at a time requires a total of 80 bits (10 bytes). Creating the same strings as above, `EntropyString` uses 80 bits of randomness per string with no wasted bits. In general, the `EntropyString` scheme can waste up to 7 bits per string, but that's the worst case scenario and that's *per string*, not *per character*!
2020
//:

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ descr = "String with 1 in a trillion chance of repeat in 10 billion strings"
4444
print("\n\(descr): \(string)\n")
4545
//: * callout(string): frN7L8b9bHrpnBHPmR9RnM
4646
//:
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).
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 predict0able 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).
4848
string = random.sessionID(.charSet64)
4949

5050
descr = "OWASP URL and file system safe session ID"

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@
44
//:
55
//: `EntropyString` provides easy creation of randomly generated strings of specific entropy using various character sets. Such strings are needed when generating, for example, random IDs and you don't want the overkill of a GUID, or for ensuring that some number of items have unique identifiers.
66
//:
7-
//: A key concern when generating such strings is that they be unique. To truly guarantee uniqueness requires either deterministic generation (e.g., a counter) that is not random, or that each newly created random string be compared against all existing strings. When ramdoness is required, the overhead of storing and comparing strings is often too onerous and a different tack is needed.
7+
//: A key concern when generating such strings is that they be unique. To truly guarantee uniqueness requires either deterministic generation (e.g., a counter) that is not random, or that each newly created random string be compared against all existing strings. When randomnress is required, the overhead of storing and comparing strings is often too onerous and a different tack is needed.
88
//:
9-
//: A common strategy is to replace the *guarantee of uniqueness* with a weaker but often sufficient *probabilistic uniqueness*. Specifically, rather than being absolutely sure of uniqueness, we settle for a statement such as *"there is less than a 1 in a billion chance that two of my strings are the same"*. This strategy requires much less overhead, but does require we have some manner of qualifying what we mean by, for example, *"there is less than a 1 in a billion chance that 1 million strings of this form will have a repeat"*.
9+
//: A common strategy is to replace the *guaranteed uniqueness* with a weaker but often sufficient *probabilistic uniqueness*. Specifically, rather than being absolutely sure of uniqueness, we settle for a statement such as *"there is less than a 1 in a billion chance that two of my strings are the same"*. This strategy requires much less overhead, but does require we have some manner of qualifying what we mean by *"there is less than a 1 in a billion chance that 1 million strings of this form will have a repeat"*.
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
//:

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

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
//:
2424
//: *I need to generate 10,000 random, unique IDs*.
2525
//:
26-
//: And the cat's out of the bag. We're getting at the real need, and it's not the same as the original statement. The developer needs *uniqueness* across a total of some number of strings. The length of the string is a by-product of the uniqueness, not the goal.
26+
//: And the cat's out of the bag. We're getting at the real need, and it's not the same as the original statement. The developer needs *uniqueness* across some potential number of strings. The length of the string is a by-product of the uniqueness, not the goal.
2727
//:
2828
//: As noted in the [Overview](Overview), guaranteeing uniqueness is difficult, so we'll replace that declaration with one of *probabilistic uniqueness* by asking:
2929
//:
@@ -42,17 +42,17 @@
4242
//: How do you address this need using a library designed to generate strings of specified length? Well, you don't directly, because that library was designed to answer the originally stated need, not the real need we've uncovered. We need a library that deals with probabilistic uniqueness of a total number of some strings. And that's exactly what `EntropyString` does.
4343
//:
4444
//: Let's use `EntropyString` to help this developer:
45-
import EntropyString
45+
import EntropyString
4646

47-
let random = Random(.charSet16)
48-
let bits = Entropy.bits(for: 10000, risk: 1.0e6)
49-
var strings = [String]()
50-
for i in 0 ..< 5 {
51-
let string = random.string(bits: bits)
52-
strings.append(string)
53-
}
47+
let random = Random(.charSet16)
48+
let bits = Entropy.bits(for: 10000, risk: 1.0e6)
49+
var strings = [String]()
50+
for i in 0 ..< 5 {
51+
let string = random.string(bits: bits)
52+
strings.append(string)
53+
}
5454

55-
print("Strings: \(strings)")
55+
print("Strings: \(strings)")
5656
//: * callout(strings): ["85e442fa0e83", "a74dc126af1e", "368cd13b1f6e", "81bf94e1278d", "fe7dec099ac9"]
5757
//:
5858
//: To generate the IDs, we first use

‎EntropyString.playground/Pages/Secure Bytes.xcplaygroundpage/Contents.swift

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,20 +9,20 @@
99
//:
1010
//: On Linux, `EntropyString` always uses `arc4random_buf`. The `secRand` parameter is ignored.
1111
//:
12-
import EntropyString
12+
import EntropyString
1313

14-
let random = Random()
15-
var secRand = true
16-
random.string(bits: 20, secRand: &secRand)
14+
let random = Random()
15+
var secRand = true
16+
random.string(bits: 20, secRand: &secRand)
1717

18-
print("secRand: \(secRand)")
18+
print("secRand: \(secRand)")
1919
//: * callout(secRand): true
2020
//:
2121
//: If `SecRandomCopyBytes` is used, the __secRand__ parameter will remain `true`; otherwise it will be set to `false`.
2222
//:
2323
//: You can also pass in __secRand__ as `false`, in which case the `entropy` call will not attempt to use `SecRandomCopyBytes` and will use `arc4random_buf`.
24-
secRand = false
25-
random.string(bits: 20, secRand: &secRand)
24+
secRand = false
25+
random.string(bits: 20, secRand: &secRand)
2626
//:
2727
//: Rather than have `EntropyString` generate bytes automatically, you can provide your own [Custom Bytes](Custom%20Bytes) to create a string, which is the next topic.
2828
//:

‎EntropyString.playground/Pages/TLDR.xcplaygroundpage/Contents.swift

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
//: [Previous](@previous)
22
//:## TL;DR
3+
//: ##### One million random strings with one in a billion risk of repeat
4+
//: Generate up to a _1 million_ random strings with _1 in a billion_ chance of repeat:
35
import EntropyString
46

5-
//: ##### One million random strings with one in a billion risk of repeat
67
var random = Random()
78
var bits = Entropy.bits(for: 1.0e6, risk: 1.0e9)
89
var string = random.string(bits: bits)
@@ -30,18 +31,18 @@ print("\n \(descr): \(string)")
3031
//: * callout(string): 78E3ACABE544EBA7DF
3132
//:
3233
//: ##### Convenience functions
33-
//: Convenience functions exists for a variety of random string needs. For example, to create OWASP session ID:
34-
string = random.sessionID()
34+
//: Convenience functions exists for a variety of scenarios. For example, to create OWASP session ID:
35+
string = random.sessionID()
3536

36-
var descr = "OWASP session ID using base custom hex characters"
37-
print("\n\(descr): \(string)")
37+
var descr = "OWASP session ID using custom hex characters"
38+
print("\n\(descr): \(string)")
3839
//: * callout(string): CC287C99158BF152DF98AF36D5E92AE3
3940
//:
4041
//: 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)
42+
string = random.token(.charSet64)
4243

43-
descr = "256 bit token using RFC 4648 file system and URL safe characters"
44-
print("\n\(descr): \(string)")
44+
descr = "256 bit token using RFC 4648 file system and URL safe characters"
45+
print("\n\(descr): \(string)")
4546
//: * callout(string): X2AZRHuNN3mFUhsYzHSE_r2SeZJ_9uqdw-j9zvPqU2O
4647
//:
4748
//: [TOC](Table%20of%20Contents) | [Next](@next)

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

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,14 @@
1111
//: - You need to a total of **_N_** strings with a risk **_1/n_** of repeat.
1212
//: - The characters are arbitrary.
1313
//: - You need `EntropyString`.
14-
//: ##### Base 32 character string with a 1 in a million chance of a repeat a billion strings:
15-
import EntropyString
14+
//: ##### A million potential strings with a 1 billion chance of a repeat:
15+
import EntropyString
1616

17-
let random = Random()
18-
let bits = Entropy.bits(for: 1.0e6, risk: 1.0e9)
19-
let string = random.string(bits: bits)
17+
let random = Random()
18+
let bits = Entropy.bits(for: 1.0e6, risk: 1.0e9)
19+
let string = random.string(bits: bits)
2020

21-
print("String: \(string)\n")
21+
print("String: \(string)\n")
2222
//: * callout(string): DdHrT2NdrHf8tM
2323
//:
2424
//: [TOC](Table%20of%20Contents)
25-

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /