Skip to content

Commit 2cbf79f

Browse files
committed
Add convenience functions
1 parent 59b4ae1 commit 2cbf79f

File tree

2 files changed

+174
-2
lines changed

2 files changed

+174
-2
lines changed

Sources/Random.swift

Lines changed: 89 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,8 +62,95 @@ public class Random {
6262
}
6363

6464
// MARK: - Public API
65-
//
66-
/// Generates a random string.
65+
66+
/// Generates a small ID
67+
///
68+
/// - return: A string with a one in a million chance of repeat in 30 strings.
69+
public func smallID() -> String {
70+
var secRand = true
71+
return string(bits: 29, secRand: &secRand)
72+
}
73+
74+
/// Generates a small ID
75+
///
76+
/// - parameter charSet: The `CharSet` to use
77+
///
78+
/// - return: A string with a one in a million chance of repeat in 30 strings.
79+
public func smallID(_ charSet: CharSet) -> String {
80+
var secRand = true
81+
return string(bits: 29, charSet: charSet, secRand: &secRand)
82+
}
83+
84+
/// Generates a medium ID
85+
///
86+
/// - return: A string with a one in a billion chance of repeat in a million strings.
87+
public func mediumID() -> String {
88+
return mediumID(self.charSet)
89+
}
90+
91+
/// Generates a medium ID
92+
///
93+
///
94+
/// - return: A string with a one in a billion chance of repeat in a million strings.
95+
public func mediumID(_ charSet: CharSet) -> String {
96+
var secRand = true
97+
return string(bits: 69, charSet: charSet, secRand: &secRand)
98+
}
99+
100+
/// Generates a large ID
101+
///
102+
103+
/// - return: A string with a one in a trillion chance of repeat in a billion strings.
104+
public func largeID() -> String {
105+
106+
return largeID(self.charSet)
107+
}
108+
109+
/// Generates a large ID
110+
///
111+
/// - parameter charSet: The `CharSet` to use
112+
///
113+
/// - return: A string with a one in a trillion chance of repeat in a billion strings.
114+
public func largeID(_ charSet: CharSet) -> String {
115+
var secRand = true
116+
return string(bits: 99, charSet: charSet, secRand: &secRand)
117+
}
118+
119+
/// Generates a 128 bit random session ID.
120+
///
121+
/// - return: A string suitable for a OWASP recommended session ID.
122+
public func sessionID() -> String {
123+
return sessionID(self.charSet)
124+
}
125+
126+
/// Generates a 128 bit random session ID.
127+
///
128+
/// - parameter charSet: The `CharSet` to use
129+
///
130+
/// - return: A string suitable for a OWASP recommended session ID.
131+
public func sessionID(_ charSet: CharSet) -> String {
132+
var secRand = true
133+
return string(bits: 128, charSet: charSet, secRand: &secRand)
134+
}
135+
136+
/// Generates a 256 bit random token
137+
///
138+
/// - return: A 256 bit string
139+
public func token() -> String {
140+
return token(self.charSet)
141+
}
142+
143+
/// Generates a 256 bit random token
144+
///
145+
/// - parameter charSet: The `CharSet` to use
146+
///
147+
/// - return: A 256 bit string
148+
public func token(_ charSet: CharSet) -> String {
149+
var secRand = true
150+
return string(bits: 256, charSet: charSet, secRand: &secRand)
151+
}
152+
153+
/// Generates a random session ID.
67154
///
68155
/// - parameter bits: Minimum bits of entropy.
69156
///

Tests/EntropyStringTests/RandomTests.swift

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,74 @@ class RandomTests: XCTestCase {
1717
let random = Random()
1818
XCTAssertEqual(random.charSet.chars, CharSet.charSet32.chars)
1919
}
20+
21+
func testSmallID() {
22+
random = Random()
23+
XCTAssertEqual( 6, random.smallID().count)
24+
XCTAssertEqual( 5, random.smallID(.charSet64).count)
25+
XCTAssertEqual( 6, random.smallID(.charSet32).count)
26+
XCTAssertEqual( 8, random.smallID(.charSet16).count)
27+
XCTAssertEqual(10, random.smallID(.charSet8).count)
28+
XCTAssertEqual(15, random.smallID(.charSet4).count)
29+
XCTAssertEqual(29, random.smallID(.charSet2).count)
30+
31+
for charSet in charSets {
32+
let smallIDBits = Float(29)
33+
let random = Random(charSet)
34+
let id = random.smallID()
35+
let count = Int(ceilf(smallIDBits / Float(charSet.bitsPerChar)))
36+
XCTAssertEqual(id.characters.count, count)
37+
}
38+
}
39+
40+
func testMediumID() {
41+
random = Random()
42+
XCTAssertEqual(14, random.mediumID().count)
43+
XCTAssertEqual(12, random.mediumID(.charSet64).count)
44+
XCTAssertEqual(14, random.mediumID(.charSet32).count)
45+
XCTAssertEqual(18, random.mediumID(.charSet16).count)
46+
XCTAssertEqual(23, random.mediumID(.charSet8).count)
47+
XCTAssertEqual(35, random.mediumID(.charSet4).count)
48+
XCTAssertEqual(69, random.mediumID(.charSet2).count)
49+
50+
for charSet in charSets {
51+
let mediumIDBits = Float(69)
52+
let random = Random(charSet)
53+
let id = random.mediumID()
54+
let count = Int(ceilf(mediumIDBits / Float(charSet.bitsPerChar)))
55+
XCTAssertEqual(id.characters.count, count)
56+
}
57+
}
58+
59+
func testLargeID() {
60+
random = Random()
61+
XCTAssertEqual(20, random.largeID().count)
62+
XCTAssertEqual(17, random.largeID(.charSet64).count)
63+
XCTAssertEqual(20, random.largeID(.charSet32).count)
64+
XCTAssertEqual(25, random.largeID(.charSet16).count)
65+
XCTAssertEqual(33, random.largeID(.charSet8).count)
66+
XCTAssertEqual(50, random.largeID(.charSet4).count)
67+
XCTAssertEqual(99, random.largeID(.charSet2).count)
68+
69+
for charSet in charSets {
70+
let largeIDBits = Float(99)
71+
let random = Random(charSet)
72+
let id = random.largeID()
73+
let count = Int(ceilf(largeIDBits / Float(charSet.bitsPerChar)))
74+
XCTAssertEqual(id.characters.count, count)
75+
}
76+
}
2077

2178
func testSessionID() {
79+
random = Random()
80+
XCTAssertEqual( 26, random.sessionID().count)
81+
XCTAssertEqual( 22, random.sessionID(.charSet64).count)
82+
XCTAssertEqual( 26, random.sessionID(.charSet32).count)
83+
XCTAssertEqual( 32, random.sessionID(.charSet16).count)
84+
XCTAssertEqual( 43, random.sessionID(.charSet8).count)
85+
XCTAssertEqual( 64, random.sessionID(.charSet4).count)
86+
XCTAssertEqual(128, random.sessionID(.charSet2).count)
87+
2288
for charSet in charSets {
2389
let sessionIDBits = Float(128)
2490
let random = Random(charSet)
@@ -27,6 +93,25 @@ class RandomTests: XCTestCase {
2793
XCTAssertEqual(id.characters.count, count)
2894
}
2995
}
96+
97+
func testToken() {
98+
random = Random()
99+
XCTAssertEqual( 52, random.token().count)
100+
XCTAssertEqual( 43, random.token(.charSet64).count)
101+
XCTAssertEqual( 52, random.token(.charSet32).count)
102+
XCTAssertEqual( 64, random.token(.charSet16).count)
103+
XCTAssertEqual( 86, random.token(.charSet8).count)
104+
XCTAssertEqual(128, random.token(.charSet4).count)
105+
XCTAssertEqual(256, random.token(.charSet2).count)
106+
107+
for charSet in charSets {
108+
let tokenBits = Float(256)
109+
let random = Random(charSet)
110+
let id = random.token()
111+
let count = Int(ceilf(tokenBits / Float(charSet.bitsPerChar)))
112+
XCTAssertEqual(id.characters.count, count)
113+
}
114+
}
30115

31116
func testCharSet64() {
32117
random = Random(.charSet64)

0 commit comments

Comments
 (0)