serverinfoview
This commit is contained in:
1 parent
d4b4c92759
commit
1650145d4d
12 files changed
+551
-23
No files matched your search
@@ -0,0 +1,91 @@
|
||||
import XCTest
|
||||
@testable import Luma
|
||||
|
||||
final class SCRAMDowngradeProtectionTests: XCTestCase {
|
||||
/// Reference vector from XEP-0474 §6.3: the server's `h` attribute is
|
||||
/// base64(SHA-1('SCRAM-SHA-1\u{1E}SCRAM-SHA-1-PLUS\u{1F}tls-exporter\u{1E}tls-server-end-point')).
|
||||
func testHashMatchesXEP0474Example() {
|
||||
let hash = SCRAMDowngradeProtection.hash(
|
||||
mechanisms: ["SCRAM-SHA-1", "SCRAM-SHA-1-PLUS"],
|
||||
channelBindingTypes: ["tls-exporter", "tls-server-end-point"],
|
||||
using: .sha1
|
||||
)
|
||||
XCTAssertEqual(hash.base64EncodedString(), "G6k/rBLDqgOhRRaCuuatSDFkJ08=")
|
||||
}
|
||||
|
||||
func testHashSortsListsPerIOctetCollation() {
|
||||
// XEP-0474 §5.1 requires i;octet-sorted lists, so advertisement order
|
||||
// must not affect the hash.
|
||||
let advertisedOrder = SCRAMDowngradeProtection.hash(
|
||||
mechanisms: ["SCRAM-SHA-1", "SCRAM-SHA-1-PLUS"],
|
||||
channelBindingTypes: ["tls-exporter", "tls-server-end-point"],
|
||||
using: .sha1
|
||||
)
|
||||
let reordered = SCRAMDowngradeProtection.hash(
|
||||
mechanisms: ["SCRAM-SHA-1-PLUS", "SCRAM-SHA-1"],
|
||||
channelBindingTypes: ["tls-server-end-point", "tls-exporter"],
|
||||
using: .sha1
|
||||
)
|
||||
XCTAssertEqual(advertisedOrder, reordered)
|
||||
}
|
||||
|
||||
func testHashOmitsBindingSectionWhenNoTypesAdvertised() {
|
||||
let withBindings = SCRAMDowngradeProtection.hash(
|
||||
mechanisms: ["SCRAM-SHA-1"],
|
||||
channelBindingTypes: ["tls-exporter"],
|
||||
using: .sha1
|
||||
)
|
||||
let withoutBindings = SCRAMDowngradeProtection.hash(
|
||||
mechanisms: ["SCRAM-SHA-1"],
|
||||
channelBindingTypes: [],
|
||||
using: .sha1
|
||||
)
|
||||
XCTAssertNotEqual(withBindings, withoutBindings)
|
||||
// Without bindings the input is exactly the sorted mechanisms with no
|
||||
// trailing 0x1F delimiter.
|
||||
let expected = SCRAMHash.sha1.hash(data: Data("SCRAM-SHA-1".utf8))
|
||||
XCTAssertEqual(withoutBindings, expected)
|
||||
}
|
||||
|
||||
func testServerFirstParsesDowngradeProtectionHash() throws {
|
||||
let message = "r=12C4CD5C-E38E-4A98-8F6D-15C38F51CCC6a09117a6-ac50-4f2f-93f1-93799c2bddf6,s=QSXCR+Q6sek8bf92,i=4096,h=G6k/rBLDqgOhRRaCuuatSDFkJ08="
|
||||
let parsed = try SCRAMSHA512.parseServerFirst(
|
||||
message,
|
||||
expectedNoncePrefix: "12C4CD5C-E38E-4A98-8F6D-15C38F51CCC6"
|
||||
)
|
||||
XCTAssertEqual(parsed.downgradeProtectionHash, "G6k/rBLDqgOhRRaCuuatSDFkJ08=")
|
||||
}
|
||||
|
||||
func testServerFirstWithoutHashParsesCleanly() throws {
|
||||
let message = "r=fyko+d2lbbFgONRv9qkxdawL3rfcNHYJY1ZVvWVs7j,s=W22ZaJ0SNY7soEsUEjb6gQ==,i=4096"
|
||||
let parsed = try SCRAMSHA512.parseServerFirst(
|
||||
message,
|
||||
expectedNoncePrefix: "fyko+d2lbbFgONRv9qkxdawL"
|
||||
)
|
||||
XCTAssertNil(parsed.downgradeProtectionHash)
|
||||
}
|
||||
|
||||
func testClientFinalIncludesXAttributeWhenHashPresent() throws {
|
||||
let exchange = SCRAMPlusExchange(
|
||||
hash: .sha1,
|
||||
username: "user",
|
||||
password: "pencil",
|
||||
channelBindingType: "tls-server-end-point",
|
||||
channelBindingData: Data(0..<32),
|
||||
clientNonce: "fyko+d2lbbFgONRv9qkxdawL"
|
||||
)
|
||||
let serverFirst = "r=fyko+d2lbbFgONRv9qkxdawL3rfcNHYJY1ZVvWVs7j,s=W22ZaJ0SNY7soEsUEjb6gQ==,i=4096,h=G6k/rBLDqgOhRRaCuuatSDFkJ08="
|
||||
let final = try exchange.clientFinalMessage(
|
||||
serverFirst: serverFirst,
|
||||
downgradeProtectionHashBase64: "G6k/rBLDqgOhRRaCuuatSDFkJ08="
|
||||
)
|
||||
XCTAssertTrue(final.contains(",x=G6k/rBLDqgOhRRaCuuatSDFkJ08=,"))
|
||||
// The same x-attribute must be part of the expected signature's
|
||||
// auth message (server reconstructs client-final-without-proof).
|
||||
let expected = try exchange.expectedServerSignature(
|
||||
serverFirst: serverFirst,
|
||||
downgradeProtectionHashBase64: "G6k/rBLDqgOhRRaCuuatSDFkJ08="
|
||||
)
|
||||
XCTAssertFalse(expected.isEmpty)
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user