Skip to content

Commit 9b8a460

Browse files
committed
Finish up hashing
1 parent d204b03 commit 9b8a460

File tree

3 files changed

+42
-50
lines changed

3 files changed

+42
-50
lines changed

Sources/Bcrypt/Base64.swift

Lines changed: 36 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ struct Base64 {
1212
0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
1313
0x59, 0x5A, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b,
1414
0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
15-
0x79, 0x80, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
15+
0x79, 0x7a, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
1616
]
1717

1818
@usableFromInline
@@ -50,50 +50,44 @@ struct Base64 {
5050

5151
while offset < len {
5252
c1 = bytes[offset] & 0xff
53-
offset += 1
54-
result.append(encodingTable[Int((c1 >> 2) & 0x3f)])
55-
c1 = (c1 & 0x03) << 4
53+
offset &+= 1
54+
result.append(encodingTable[Int(truncatingIfNeeded: (c1 >> 2) & 0x3f)])
55+
c1 = (c1 & 0x03) &<< 4
5656
if offset >= len {
57-
result.append(encodingTable[Int(c1 & 0x3f)])
57+
result.append(encodingTable[Int(truncatingIfNeeded: c1 & 0x3f)])
5858
break
5959
}
6060

6161
c2 = bytes[offset] & 0xff
62-
offset += 1
63-
c1 |= (c2 >> 4) & 0x0f
64-
result.append(encodingTable[Int(c1 & 0x3f)])
65-
c1 = (c2 & 0x0f) << 2
62+
offset &+= 1
63+
c1 |= (c2 &>> 4) & 0x0f
64+
result.append(encodingTable[Int(truncatingIfNeeded: c1 & 0x3f)])
65+
c1 = (c2 & 0x0f) &<< 2
6666
if offset >= len {
67-
result.append(encodingTable[Int(c1 & 0x3f)])
67+
result.append(encodingTable[Int(truncatingIfNeeded: c1 & 0x3f)])
6868
break
6969
}
7070

7171
c2 = bytes[offset] & 0xff
72-
offset += 1
73-
c1 |= (c2 >> 6) & 0x03
74-
result.append(encodingTable[Int(c1 & 0x3f)])
75-
result.append(encodingTable[Int(c2 & 0x3f)])
72+
offset &+= 1
73+
c1 |= (c2 &>> 6) & 0x03
74+
result.append(encodingTable[Int(truncatingIfNeeded: c1 & 0x3f)])
75+
result.append(encodingTable[Int(truncatingIfNeeded: c2 & 0x3f)])
7676
}
7777

7878
return result
7979
}
8080

81-
private static func char64of(x: UInt8) -> UInt8 {
82-
guard x >= 0, x <= 128 - 1 else {
83-
// The character would go out of bounds of the pre-calculated array so return -1.
84-
return UInt8.max
85-
}
86-
87-
// Return the matching Base64 encoded character.
88-
return decodingTable[Int(x)]
81+
private static func char64(of x: UInt8) -> UInt8 {
82+
x > 127 ? 255 : decodingTable[Int(x)]
8983
}
9084

9185
@usableFromInline
92-
static func decode(_ s: [UInt8], count maxolen: UInt) -> [UInt8] {
93-
let maxolen = Int(maxolen)
86+
static func decode(_ s: [UInt8], count maxolen: Int) -> [UInt8] {
87+
let maxolen = maxolen
9488

95-
var off: Int = 0
96-
var olen: Int = 0
89+
var off = 0
90+
var olen = 0
9791
var result = [UInt8](repeating: 0, count: maxolen)
9892

9993
var c1: UInt8
@@ -103,43 +97,43 @@ struct Base64 {
10397
var o: UInt8
10498

10599
while off < s.count - 1 && olen < maxolen {
106-
c1 = char64of(x: s[off])
107-
off += 1
108-
c2 = char64of(x: s[off])
109-
off += 1
100+
c1 = char64(of: s[off])
101+
off &+= 1
102+
c2 = char64(of: s[off])
103+
off &+= 1
110104
if c1 == UInt8.max || c2 == UInt8.max {
111105
break
112106
}
113107

114-
o = c1 << 2
115-
o |= (c2 & 0x30) >> 4
108+
o = c1 &<< 2
109+
o |= (c2 & 0x30) &>> 4
116110
result[olen] = o
117-
olen += 1
111+
olen &+= 1
118112
if olen >= maxolen || off >= s.count {
119113
break
120114
}
121115

122-
c3 = char64of(x: s[Int(off)])
123-
off += 1
116+
c3 = char64(of: s[off])
117+
off &+= 1
124118

125119
if c3 == UInt8.max {
126120
break
127121
}
128122

129-
o = (c2 & 0x0f) << 4
130-
o |= (c3 & 0x3c) >> 2
123+
o = (c2 & 0x0f) &<< 4
124+
o |= (c3 & 0x3c) &>> 2
131125
result[olen] = o
132-
olen += 1
126+
olen &+= 1
133127
if olen >= maxolen || off >= s.count {
134128
break
135129
}
136130

137-
c4 = char64of(x: s[off])
138-
off += 1
139-
o = (c3 & 0x03) << 6
131+
c4 = char64(of: s[off])
132+
off &+= 1
133+
o = (c3 & 0x03) &<< 6
140134
o |= c4
141135
result[olen] = o
142-
olen += 1
136+
olen &+= 1
143137
}
144138

145139
return Array(result[0..<olen])

Sources/Bcrypt/Hasher.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ public struct Hasher {
3434
throw BcryptError.invalidSaltLength
3535
}
3636

37-
let cSalt = Base64.decode(salt, count: UInt(Self.maxSalt))
37+
let cSalt = Base64.decode(salt, count: Self.maxSalt)
3838

3939
guard password.count > 0 else {
4040
throw BcryptError.emptyPassword

Tests/BcryptTests/BcryptTests.swift

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ import Testing
55

66
@Suite("Bcrypt Tests")
77
struct BcryptTests {
8-
@Test("Raw test vectors")
9-
func testVectors() throws {
8+
@Test("Test Vectors Hashing")
9+
func testVectorsHashin() throws {
1010
let testVectors: [(password: String, cost: Int, salt: String, expectedHash: String)] =
1111
[
1212
("ππππππππ", 10, ".TtQJ4Jr6isd4Hp.mVfZeu", "$2a$10$.TtQJ4Jr6isd4Hp.mVfZeuh6Gws4rOQ/vdBczhDx.19NFK0Y84Dle"),
@@ -18,12 +18,8 @@ struct BcryptTests {
1818
("U*U", 5, "CCCCCCCCCCCCCCCCCCCCC.", "$2a$05$CCCCCCCCCCCCCCCCCCCCC.E5YPO9kmyuRGyh0XouQYb4YMJKvyOeW"),
1919
("U*U*", 5, "CCCCCCCCCCCCCCCCCCCCC.", "$2a$05$CCCCCCCCCCCCCCCCCCCCC.VGOzA784oUp/Z0DY336zx7pLYAy0lwK"),
2020
("U*U*U", 5, "XXXXXXXXXXXXXXXXXXXXXO", "$2a$05$XXXXXXXXXXXXXXXXXXXXXOAcXxm9kjPGEMsLznoKqmqw7tc8WCx4a"),
21-
("", 6, "DCq7YPn5Rq63x1Lad4cll.", "$2a$06$DCq7YPn5Rq63x1Lad4cll.TV4S6ytwfsfvkgY8jIucDrjc8deX1s."),
2221

2322
// see: https://github.com/BcryptNet/bcrypt.net/blob/main/src/BCrypt.Net.UnitTests/BCryptTests.cs
24-
("", 8, "HqWuK6/Ng6sg9gQzbLrgb.", "$2a$08$HqWuK6/Ng6sg9gQzbLrgb.Tl.ZHfXLhvt/SgVyWhQqgqcZ7ZuUtye"),
25-
("", 10, "k1wbIrmNyFAPwPVPSVa/ze", "$2a$10$k1wbIrmNyFAPwPVPSVa/zecw2BCEnBwVS2GbrmgzxFUOqW9dk4TCW"),
26-
("", 12, "k42ZFHFWqBp3vWli.nIn8u", "$2a$12$k42ZFHFWqBp3vWli.nIn8uYyIkbvYRvodzbfbK18SSsY.CsIQPlxO"),
2723
("a", 6, "m0CrhHm10qJ3lXRY.5zDGO", "$2a$06$m0CrhHm10qJ3lXRY.5zDGO3rS2KdeeWLuGmsfGlMfOxih58VYVfxe"),
2824
("a", 8, "cfcvVd2aQ8CMvoMpP2EBfe", "$2a$08$cfcvVd2aQ8CMvoMpP2EBfeodLEkkFJ9umNEfPD18.hUF62qqlC/V."),
2925
("a", 10, "k87L/MF28Q673VKh8/cPi.", "$2a$10$k87L/MF28Q673VKh8/cPi.SUl7MU/rWuSiIDDFayrKk/1tBsSQu4u"),
@@ -64,7 +60,9 @@ struct BcryptTests {
6460
let hash = try Hasher(version: .v2a)
6561
.hash(password: Array(testVector.password.utf8), cost: testVector.cost, salt: Array(testVector.salt.utf8))
6662

67-
#expect(hash == Array(testVector.expectedHash.utf8))
63+
#expect(
64+
hash == Array(testVector.expectedHash.utf8),
65+
"Expected: \(testVector.expectedHash), got: \(String(decoding: hash, as: UTF8.self))")
6866
}
6967
}
7068

0 commit comments

Comments
 (0)