Skip to content

Commit 9ce15a4

Browse files
authored
Make SASL really fast (#554)
1 parent 44c7b05 commit 9ce15a4

File tree

2 files changed

+16
-24
lines changed

2 files changed

+16
-24
lines changed

Package.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ let package = Package(
3636
.target(name: "_ConnectionPoolModule"),
3737
.product(name: "Atomics", package: "swift-atomics"),
3838
.product(name: "Crypto", package: "swift-crypto"),
39+
.product(name: "_CryptoExtras", package: "swift-crypto"),
3940
.product(name: "Logging", package: "swift-log"),
4041
.product(name: "Metrics", package: "swift-metrics"),
4142
.product(name: "NIO", package: "swift-nio"),

Sources/PostgresNIO/Utilities/SASLAuthentication+SCRAM-SHA256.swift

Lines changed: 15 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import Crypto
2+
import _CryptoExtras
23
import Foundation
34

45
extension UInt8 {
@@ -466,8 +467,8 @@ fileprivate final class SASLMechanism_SCRAM_SHA256_Common {
466467
// TODO: Perform `Normalize(password)`, aka the SASLprep profile (RFC4013) of stringprep (RFC3454)
467468

468469
// Calculate `AuthMessage`, `ClientSignature`, and `ClientProof`
469-
let saltedPassword = Hi(string: password, salt: serverSalt, iterations: serverIterations)
470-
let clientKey = HMAC<SHA256>.authenticationCode(for: Data("Client Key".utf8), using: .init(data: saltedPassword))
470+
let saltedPassword = try Hi(string: password, salt: serverSalt, iterations: serverIterations)
471+
let clientKey = HMAC<SHA256>.authenticationCode(for: Data("Client Key".utf8), using: saltedPassword)
471472
let storedKey = SHA256.hash(data: Data(clientKey))
472473
var authMessage = firstMessageBare; authMessage.append(.comma); authMessage.append(contentsOf: message); authMessage.append(.comma); authMessage.append(contentsOf: clientFinalNoProof)
473474
let clientSignature = HMAC<SHA256>.authenticationCode(for: authMessage, using: .init(data: storedKey))
@@ -485,9 +486,11 @@ fileprivate final class SASLMechanism_SCRAM_SHA256_Common {
485486
var clientFinalMessage = clientFinalNoProof; clientFinalMessage.append(.comma)
486487
guard let proofPart = SCRAMMessageParser.serialize([.p(Array(clientProof))]) else { throw SASLAuthenticationError.genericAuthenticationFailure }
487488
clientFinalMessage.append(contentsOf: proofPart)
488-
489+
490+
let saltedPasswordBytes = saltedPassword.withUnsafeBytes { [UInt8]($0) }
491+
489492
// Save state and send
490-
self.state = .clientSentFinalMessage(saltedPassword: saltedPassword, authMessage: authMessage)
493+
self.state = .clientSentFinalMessage(saltedPassword: saltedPasswordBytes, authMessage: authMessage)
491494
return .continue(response: clientFinalMessage)
492495
}
493496

@@ -640,24 +643,12 @@ fileprivate final class SASLMechanism_SCRAM_SHA256_Common {
640643
HMAC() == output length of H().
641644
````
642645
*/
643-
private func Hi(string: [UInt8], salt: [UInt8], iterations: UInt32) -> [UInt8] {
644-
let key = SymmetricKey(data: string)
645-
var Ui = HMAC<SHA256>.authenticationCode(for: salt + [0x00, 0x00, 0x00, 0x01], using: key) // salt + 0x00000001 as big-endian
646-
var Hi = Array(Ui)
647-
var uiData = [UInt8]()
648-
uiData.reserveCapacity(32)
649-
650-
Hi.withUnsafeMutableBytes { Hibuf -> Void in
651-
for _ in 2...iterations {
652-
uiData.removeAll(keepingCapacity: true)
653-
uiData.append(contentsOf: Ui)
654-
655-
Ui = HMAC<SHA256>.authenticationCode(for: uiData, using: key)
656-
657-
Ui.withUnsafeBytes { Uibuf -> Void in
658-
for i in 0..<Uibuf.count { Hibuf[i] ^= Uibuf[i] }
659-
}
660-
}
661-
}
662-
return Hi
646+
private func Hi(string: [UInt8], salt: [UInt8], iterations: UInt32) throws -> SymmetricKey {
647+
try KDF.Insecure.PBKDF2.deriveKey(
648+
from: string,
649+
salt: salt,
650+
using: .sha256,
651+
outputByteCount: 32,
652+
unsafeUncheckedRounds: Int(iterations)
653+
)
663654
}

0 commit comments

Comments
 (0)