From fcff1d09602d660c15b5050ea8f0359cd22563ff Mon Sep 17 00:00:00 2001 From: Bouke Haarsma Date: Sat, 26 Aug 2017 10:21:05 +0200 Subject: [PATCH 01/11] Update manifest for Swift 4 --- Package.swift | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/Package.swift b/Package.swift index bb6d447..3a543be 100644 --- a/Package.swift +++ b/Package.swift @@ -1,9 +1,16 @@ +// swift-tools-version:4.0 + import PackageDescription let package = Package( name: "SRP", dependencies: [ - .Package(url: "https://github.com/IBM-Swift/BlueCryptor.git", majorVersion: 0, minor: 8), - .Package(url: "https://github.com/lorentey/BigInt.git", majorVersion: 2, minor: 1), - ] + .package(url: "https://github.com/IBM-Swift/BlueCryptor.git", from: "0.8.16"), + .package(url: "https://github.com/lorentey/BigInt.git", .branch("swift4")), + ], + targets: [ + .target(name: "SRP", dependencies: ["Cryptor", "BigInt"], path: "Sources"), + .testTarget(name: "SRPTests", dependencies: ["Cryptor", "SRP"]), + ], + swiftLanguageVersions: [4] ) From 7d105356a0d9ce1424cfb13b97bb160a83fdb64f Mon Sep 17 00:00:00 2001 From: Bouke Haarsma Date: Sat, 26 Aug 2017 10:27:59 +0200 Subject: [PATCH 02/11] Test against Swift 4 --- .swift-version | 2 +- .travis.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.swift-version b/.swift-version index 94ff29c..b7d9796 100644 --- a/.swift-version +++ b/.swift-version @@ -1 +1 @@ -3.1.1 +4.0-DEVELOPMENT-SNAPSHOT-2017-08-21-a diff --git a/.travis.yml b/.travis.yml index dc0f389..6ec42f5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,7 +4,7 @@ os: language: generic sudo: required dist: trusty -osx_image: xcode8.2 +osx_image: xcode9 install: - pip install srptools - eval "$(curl -sL https://gist.githubusercontent.com/kylef/5c0475ff02b7c7671d2a/raw/9f442512a46d7a2af7b850d65a7e9bd31edfb09b/swiftenv-install.sh)" From 3a141b0522543e4f11ecde9cdc6e35cb616bbadc Mon Sep 17 00:00:00 2001 From: Bouke Haarsma Date: Sat, 26 Aug 2017 10:53:34 +0200 Subject: [PATCH 03/11] Resolve issue with Data slicing offsets --- Tests/SRPTests/TestUtils.swift | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Tests/SRPTests/TestUtils.swift b/Tests/SRPTests/TestUtils.swift index 2ac5653..d6033e6 100644 --- a/Tests/SRPTests/TestUtils.swift +++ b/Tests/SRPTests/TestUtils.swift @@ -109,9 +109,10 @@ class Remote { while true { if let eol = pipe.buffer.index(of: 10) { defer { - pipe.buffer.removeFirst(eol + 1) + let lineLength = eol - pipe.buffer.startIndex + 1 + pipe.buffer.removeFirst(lineLength) } - guard let line = String(data: Data(pipe.buffer[0.. Date: Sun, 27 Aug 2017 17:38:19 +0200 Subject: [PATCH 04/11] fileHandleForWriting is not used on readonly streams --- Tests/SRPTests/TestUtils.swift | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Tests/SRPTests/TestUtils.swift b/Tests/SRPTests/TestUtils.swift index d6033e6..5dd0fe8 100644 --- a/Tests/SRPTests/TestUtils.swift +++ b/Tests/SRPTests/TestUtils.swift @@ -53,10 +53,6 @@ class Remote { var fileHandleForReading: FileHandle { return pipe.fileHandleForReading } - - var fileHandleForWriting: FileHandle { - return pipe.fileHandleForWriting - } } fileprivate init(process: Process) { From 3fcdf6e76b7d360cdb98d704917d952c6d643d20 Mon Sep 17 00:00:00 2001 From: Bouke Haarsma Date: Fri, 15 Sep 2017 19:22:27 +0200 Subject: [PATCH 05/11] Only use stderr for errors in tests Previously we used stderr for secret messages, however it is difficult to easily distinguish between error messages and secret messages. So now all output on stderr is simply a error message. --- Tests/SRPTests/TestUtils.swift | 24 ++++++++++++------------ remote.py | 12 ++++++------ 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/Tests/SRPTests/TestUtils.swift b/Tests/SRPTests/TestUtils.swift index 5dd0fe8..1df3b89 100644 --- a/Tests/SRPTests/TestUtils.swift +++ b/Tests/SRPTests/TestUtils.swift @@ -28,15 +28,15 @@ let remotepy = URL(fileURLWithPath: #file) .deletingLastPathComponent() .appendingPathComponent("remote.py") -enum RemoteError: Error { +indirect enum RemoteError: Error { case noPython case unexpectedPrompt(String) case commandFailure case commandFailureWithMessage(String) - case valueExpected + case valueExpected(RemoteError) case unexpectedValueLabel(String) case decodingError - case unexpectedExit + case unexpectedExit(RemoteError) } class Remote { @@ -80,7 +80,7 @@ class Remote { private func readprompt(from pipe: BufferedPipe) throws -> String { if !process.isRunning { - throw RemoteError.unexpectedExit + throw RemoteError.unexpectedExit(readError()) } if pipe.buffer.count > 0 { defer { pipe.buffer = Data() } @@ -93,7 +93,7 @@ class Remote { fileprivate func read(label: String, from pipe: BufferedPipe) throws -> (String) { let splitted = try readline(from: pipe).components(separatedBy: ": ") guard splitted.count == 2 else { - throw RemoteError.valueExpected + throw RemoteError.valueExpected(readError()) } guard label == splitted[0] else { throw RemoteError.unexpectedValueLabel(splitted[0]) @@ -118,7 +118,7 @@ class Remote { if availableData.count == 0 && !process.isRunning { // No more data coming and buffer doesn't contain a newline - throw RemoteError.unexpectedExit + throw RemoteError.unexpectedExit(readError()) } } } @@ -185,7 +185,7 @@ class RemoteServer: Remote { } super.init(process: process) - verificationKey = try Data(hex: read(label: "v", from: error)) + verificationKey = try Data(hex: read(label: "v", from: output)) } /// Get server's challenge @@ -196,7 +196,7 @@ class RemoteServer: Remote { func getChallenge(publicKey A: Data) throws -> (salt: Data, publicKey: Data) { do { try write(prompt: "A", line: A.hex) - privateKey = try Data(hex: try read(label: "b", from: error)) + privateKey = try Data(hex: try read(label: "b", from: output)) salt = try Data(hex: try read(label: "s", from: output)) publicKey = try Data(hex: try read(label: "B", from: output)) return (salt!, publicKey!) @@ -213,7 +213,7 @@ class RemoteServer: Remote { func verifySession(keyProof M: Data) throws -> Data { do { try write(prompt: "M", line: M.hex) - expectedM = try Data(hex: try read(label: "expected M", from: error)) + expectedM = try Data(hex: try read(label: "expected M", from: output)) return try Data(hex: try read(label: "HAMK", from: output)) } catch RemoteError.unexpectedExit { throw readError() @@ -225,7 +225,7 @@ class RemoteServer: Remote { /// - Returns: session key /// - Throws: on I/O Error func getSessionKey() throws -> Data { - return try Data(hex: try read(label: "K", from: error)) + return try Data(hex: try read(label: "K", from: output)) } } @@ -270,7 +270,7 @@ class RemoteClient: Remote { } super.init(process: process) - self.privateKey = try Data(hex: try read(label: "a", from: error)) + self.privateKey = try Data(hex: try read(label: "a", from: output)) } /// Read public key from stdout. @@ -311,6 +311,6 @@ class RemoteClient: Remote { /// - Returns: session key (K) /// - Throws: on I/O Error func getSessionKey() throws -> Data { - return try Data(hex: try read(label: "K", from: error)) + return try Data(hex: try read(label: "K", from: output)) } } diff --git a/remote.py b/remote.py index 84f4ec1..fe5db7b 100755 --- a/remote.py +++ b/remote.py @@ -109,7 +109,7 @@ def hex_encoded_utf8(value): else: _, password_verifier, salt = context.get_user_data_triplet() - print("v:", password_verifier, file=sys.stderr) + print("v:", password_verifier) # Client => Server: username, A sys.stdout.write("A: ") @@ -119,7 +119,7 @@ def hex_encoded_utf8(value): # Receive username from client and generate server public. server_session = SRPServerSession(context, password_verifier, private=args.private) - print("b:", server_session.private, file=sys.stderr) + print("b:", server_session.private) # Server => Client: s, B print("s:", salt) @@ -132,7 +132,7 @@ def hex_encoded_utf8(value): # Process client public and verify session key proof. server_session.process(A, salt) - print("expected M:", server_session.key_proof, file=sys.stderr) + print("expected M:", server_session.key_proof) assert server_session.verify_proof(M) @@ -140,11 +140,11 @@ def hex_encoded_utf8(value): print("HAMK:", ensure_hash_size(server_session.key_proof_hash)) # Always keep the key secret! It is printed to validate the implementation. - print("K:", ensure_hash_size(server_session.key), file=sys.stderr) + print("K:", ensure_hash_size(server_session.key)) if args.command == "client": client_session = SRPClientSession(context, private=args.private) - print("a:", client_session.private, file=sys.stderr) + print("a:", client_session.private) # Client => Server: username, A print("A:", client_session.public) @@ -169,4 +169,4 @@ def hex_encoded_utf8(value): print("OK") # Always keep the key secret! It is printed to validate the implementation. - print("K:", ensure_hash_size(client_session.key), file=sys.stderr) + print("K:", ensure_hash_size(client_session.key)) From 3a3471aef7540ec369c77e3dd117ca4c3d992b27 Mon Sep 17 00:00:00 2001 From: Bouke Haarsma Date: Sat, 16 Sep 2017 10:59:45 +0200 Subject: [PATCH 06/11] Record Python/pip version for debugging travis failures --- .travis.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.travis.yml b/.travis.yml index 6ec42f5..27b724c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,6 +5,9 @@ language: generic sudo: required dist: trusty osx_image: xcode9 +before_install: + - python -V + - pip -V install: - pip install srptools - eval "$(curl -sL https://gist.githubusercontent.com/kylef/5c0475ff02b7c7671d2a/raw/9f442512a46d7a2af7b850d65a7e9bd31edfb09b/swiftenv-install.sh)" From b1cdc618626ecdfde0fd293313a17116660b50e4 Mon Sep 17 00:00:00 2001 From: Bouke Haarsma Date: Sat, 16 Sep 2017 10:59:55 +0200 Subject: [PATCH 07/11] Upgrade to latest Swift snapshot --- .swift-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.swift-version b/.swift-version index b7d9796..2a4c127 100644 --- a/.swift-version +++ b/.swift-version @@ -1 +1 @@ -4.0-DEVELOPMENT-SNAPSHOT-2017-08-21-a +4.0-DEVELOPMENT-SNAPSHOT-2017-09-13-a From 5f03c9395288a1a745c4396719f6dc06cc66326b Mon Sep 17 00:00:00 2001 From: Bouke Haarsma Date: Sat, 16 Sep 2017 11:04:10 +0200 Subject: [PATCH 08/11] Maybe do without sudo build on Travis --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 27b724c..b063689 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,7 +2,6 @@ os: - osx - linux language: generic -sudo: required dist: trusty osx_image: xcode9 before_install: From 2733759a7c821104c6d6410f76f9800e986f8066 Mon Sep 17 00:00:00 2001 From: Bouke Haarsma Date: Sat, 16 Sep 2017 11:20:33 +0200 Subject: [PATCH 09/11] =?UTF-8?q?Don=E2=80=99t=20fail=20Python=20on=20trav?= =?UTF-8?q?is?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Travis regressed to a previous version of Python that is no longer supported: 2.7.6. --- .travis.yml | 12 ++++++++++-- Makefile | 2 ++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index b063689..b051337 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,9 @@ os: - osx - linux +env: + - INTEGRATION_TESTS=false + - INTEGRATION_TESTS=true language: generic dist: trusty osx_image: xcode9 @@ -8,6 +11,11 @@ before_install: - python -V - pip -V install: - - pip install srptools + - if [ $INTEGRATION_TESTS == 'true' ]; then pip install srptools; fi - eval "$(curl -sL https://gist.githubusercontent.com/kylef/5c0475ff02b7c7671d2a/raw/9f442512a46d7a2af7b850d65a7e9bd31edfb09b/swiftenv-install.sh)" -script: make test +script: + - if [ $INTEGRATION_TESTS == 'true' ]; then make test-with-python; fi + - if [ $INTEGRATION_TESTS == 'false' ]; then make test; fi +matrix: + allow_failures: + - env: INTEGRATION_TESTS=true diff --git a/Makefile b/Makefile index d71af7f..13411f4 100755 --- a/Makefile +++ b/Makefile @@ -1,2 +1,4 @@ test: + swift test -c release -Xswiftc -enable-testing +test-with-python: PYTHON=`which python` swift test -c release -Xswiftc -enable-testing From 6db8df3c60b5677f92da877185fe9458f9472216 Mon Sep 17 00:00:00 2001 From: Bouke Haarsma Date: Sat, 16 Sep 2017 11:33:29 +0200 Subject: [PATCH 10/11] Upgrade to BigInt 3 (Swift 4) --- Package.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Package.swift b/Package.swift index 3a543be..22c75e0 100644 --- a/Package.swift +++ b/Package.swift @@ -6,7 +6,7 @@ let package = Package( name: "SRP", dependencies: [ .package(url: "https://github.com/IBM-Swift/BlueCryptor.git", from: "0.8.16"), - .package(url: "https://github.com/lorentey/BigInt.git", .branch("swift4")), + .package(url: "https://github.com/lorentey/BigInt.git", from: "3.0.0"), ], targets: [ .target(name: "SRP", dependencies: ["Cryptor", "BigInt"], path: "Sources"), From b6c11243758bd0fd667c881102d77b04b2f3feb1 Mon Sep 17 00:00:00 2001 From: Bouke Haarsma Date: Sat, 16 Sep 2017 11:36:10 +0200 Subject: [PATCH 11/11] Release version 3 --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index 631bf3f..7208d84 100644 --- a/README.md +++ b/README.md @@ -49,6 +49,11 @@ assert(server.sessionKey == client.sessionKey) More information can be found in the [documentation](http://boukehaarsma.nl/SRP). +## Swift Compatibility + +Swift 4 is required with version 3 of this package. Use version 2 if you need +Swift 3 compatibility. + ## Compatibility with other implementations I like to believe this implementation does correctly implements the RFC.