diff --git a/Package.swift b/Package.swift index 76b5877..5971f07 100644 --- a/Package.swift +++ b/Package.swift @@ -15,12 +15,13 @@ let package = Package( .library(name: "SRP", targets: ["SRP"]), ], dependencies: [ - .package(url: "https://github.com/apple/swift-crypto", "1.0.0"..<"5.0.0"), + .package(url: "https://github.com/apple/swift-crypto", "1.0.0" ..< "5.0.0"), .package(url: "https://github.com/adam-fowler/big-num", from: "2.0.0"), ], targets: [ .target(name: "SRP", dependencies: ["BigNum", "Crypto"]), .testTarget( - name: "SRPTests", dependencies: ["SRP"]), + name: "SRPTests", dependencies: ["SRP"] + ), ] ) diff --git a/README.md b/README.md index f19c231..300777a 100644 --- a/README.md +++ b/README.md @@ -47,7 +47,7 @@ let clientSharedSecret = try client.calculateSharedSecret( let clientProof = client.calculateClientProof( username: username, salt: salt, - clientPublicKey: clientKeys.public, + clientPublicKey: clientPublicKey, serverPublicKey: serverPublicKey, sharedSecret: clientSharedSecret ) @@ -64,7 +64,7 @@ let serverProof = try server.verifyClientProof( username: username, salt: salt, clientPublicKey: clientPublicKey, - serverPublicKey: serverKeys.public, + serverPublicKey: serverPublicKey, sharedSecret: serverSharedSecret ) ``` @@ -73,7 +73,7 @@ And finally the client can verify the server proof is valid try client.verifyServerProof( serverProof: serverProof, clientProof: clientProof, - clientKeys: clientKeys, + clientPublicKey: clientPublicKey, sharedSecret: clientSharedSecret ) ``` @@ -90,5 +90,3 @@ The library is compliant with RFC5054 and should work with any server implementi ## Proof of secret For generating the proof above I use the method detailed in [RFC2945](https://tools.ietf.org/html/rfc2945#section-3) but not all servers use this method. For this reason I have kept the sharedSecret generation separate from the proof generation, so you can insert your own version. - -I have also supplied a simple proof functions `server.verifySimpleClientProof` and `client.verifySimpleServerProof` which use the proof detailed in the Wikipedia [page](https://en.wikipedia.org/wiki/Secure_Remote_Password_protocol) on Secure Remote Password if you would prefer to use these. diff --git a/Sources/SRP/Array.swift b/Sources/SRP/Array.swift index 0061ac5..20d2da3 100644 --- a/Sources/SRP/Array.swift +++ b/Sources/SRP/Array.swift @@ -3,27 +3,27 @@ extension Array where Element: FixedWidthInteger { /// create array of random bytes static func random(count: Int) -> [Element] { var array = self.init() - for _ in 0.. String { - return self.map({ + return map { let characters = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f"] - return "\(characters[Int($0 >> 4)])\(characters[Int($0 & 0xf)])" - }).joined() + return "\(characters[Int($0 >> 4)])\(characters[Int($0 & 0xF)])" + }.joined() } } extension Array where Element == UInt8 { func pad(to size: Int) -> [UInt8] { - let padSize = size - self.count + let padSize = size - count guard padSize > 0 else { return self } // create prefix and return prefix + data - let prefix: [UInt8] = (1...padSize).reduce([]) { result,_ in return result + [0] } + let prefix: [UInt8] = (1 ... padSize).reduce([]) { result, _ in result + [0] } return prefix + self } } @@ -32,7 +32,7 @@ extension Array where Element == UInt8 { func ^ (lhs: [UInt8], rhs: [UInt8]) -> [UInt8] { precondition(lhs.count == rhs.count, "Arrays are required to be the same size") var result = lhs - for i in 0.. { /// configuration. This needs to be the same as the server configuration public let configuration: SRPConfiguration - + /// Initialise a SRPClient object /// - Parameter configuration: configuration to use public init(configuration: SRPConfiguration) { self.configuration = configuration } - + /// Initiate the authentication process /// - Returns: An authentication state. The A value from this state should be sent to the server public func generateKeys() -> SRPKeyPair { @@ -35,9 +35,9 @@ public struct SRPClient { A = configuration.g.power(a, modulus: configuration.N) } while A % configuration.N == BigNum(0) - return SRPKeyPair(public: SRPKey(A, padding: self.configuration.sizeN), private: SRPKey(a)) + return SRPKeyPair(public: SRPKey(A, padding: configuration.sizeN), private: SRPKey(a)) } - + /// return shared secret given the username, password, B value and salt from the server /// - Parameters: /// - username: user identifier @@ -48,16 +48,16 @@ public struct SRPClient { /// - Throws: `nullServerKey` /// - Returns: shared secret public func calculateSharedSecret( - username: String, - password: String, - salt: [UInt8], - clientKeys: SRPKeyPair, + username: String, + password: String, + salt: [UInt8], + clientKeys: SRPKeyPair, serverPublicKey: SRPKey ) throws -> SRPKey { let message = [UInt8]("\(username):\(password)".utf8) return try calculateSharedSecret(message: message, salt: salt, clientKeys: clientKeys, serverPublicKey: serverPublicKey) } - + /// return shared secret given a binary password, B value and salt from the server /// - Parameters: /// - password: password @@ -67,16 +67,19 @@ public struct SRPClient { /// - Throws: `nullServerKey` /// - Returns: shared secret public func calculateSharedSecret( - password: [UInt8], - salt: [UInt8], - clientKeys: SRPKeyPair, + password: [UInt8], + salt: [UInt8], + clientKeys: SRPKeyPair, serverPublicKey: SRPKey ) throws -> SRPKey { - let message = [0x3a] + password + let message = [0x3A] + password return try calculateSharedSecret(message: message, salt: salt, clientKeys: clientKeys, serverPublicKey: serverPublicKey) } - - /// calculate proof of shared secret to send to server + + /// Calculate proof of shared secret to send to server. + /// + /// This uses the method detailed in https://tools.ietf.org/html/rfc2945#section-3 + /// /// - Parameters: /// - username: Username /// - salt: The salt value associated with the user returned by the server @@ -85,29 +88,29 @@ public struct SRPClient { /// - sharedSecret: shared secret /// - Returns: The client verification code which should be passed to the server public func calculateClientProof( - username: String, - salt: [UInt8], - clientPublicKey: SRPKey, - serverPublicKey: SRPKey, + username: String, + salt: [UInt8], + clientPublicKey: SRPKey, + serverPublicKey: SRPKey, sharedSecret: SRPKey ) -> [UInt8] { - let clientPublicKey = clientPublicKey.with(padding: self.configuration.sizeN) - let serverPublicKey = serverPublicKey.with(padding: self.configuration.sizeN) - let sharedSecret = sharedSecret.with(padding: self.configuration.sizeN) + let clientPublicKey = clientPublicKey.with(padding: configuration.sizeN) + let serverPublicKey = serverPublicKey.with(padding: configuration.sizeN) + let sharedSecret = sharedSecret.with(padding: configuration.sizeN) let hashSharedSecret = [UInt8](H.hash(data: sharedSecret.bytes)) // get verification code return SRP.calculateClientProof( - configuration: configuration, - username: username, - salt: salt, - clientPublicKey: clientPublicKey, - serverPublicKey: serverPublicKey, + configuration: configuration, + username: username, + salt: salt, + clientPublicKey: clientPublicKey, + serverPublicKey: serverPublicKey, hashSharedSecret: hashSharedSecret ) } - - /// If the server returns that the client verification code was valid it will also return a server - /// verification code that the client can use to verify the server is correct. This is the calculation + + /// If the server returns that the client verification code was valid it will also return a server + /// verification code that the client can use to verify the server is correct. This is the calculation /// to verify it is correct /// /// - Parameters: @@ -115,24 +118,26 @@ public struct SRPClient { /// - clientProof: Client proof /// - sharedSecret: Shared secret public func calculateServerProof( - clientPublicKey: SRPKey, - clientProof: [UInt8], + clientPublicKey: SRPKey, + clientProof: [UInt8], sharedSecret: SRPKey ) -> [UInt8] { - let clientPublicKey = clientPublicKey.with(padding: self.configuration.sizeN) - let sharedSecret = sharedSecret.with(padding: self.configuration.sizeN) + let clientPublicKey = clientPublicKey.with(padding: configuration.sizeN) + let sharedSecret = sharedSecret.with(padding: configuration.sizeN) let hashSharedSecret = [UInt8](H.hash(data: sharedSecret.bytes)) // get out version of server proof return SRP.calculateServerVerification( - clientPublicKey: clientPublicKey, - clientProof: clientProof, + clientPublicKey: clientPublicKey, + clientProof: clientProof, hashSharedSecret: hashSharedSecret ) } - - /// If the server returns that the client verification code was valid it will also return a server + + /// If the server returns that the client verification code was valid it will also return a server /// verification code that the client can use to verify the server is correct /// + /// This uses the method detailed in https://tools.ietf.org/html/rfc2945#section-3 + /// /// - Parameters: /// - serverProof: Server proof /// - clientProof: Client proof @@ -140,9 +145,9 @@ public struct SRPClient { /// - sharedSecret: Shared secret /// - Throws: `requiresVerificationKey`, `invalidServerCode` public func verifyServerProof( - serverProof: [UInt8], - clientProof: [UInt8], - clientPublicKey: SRPKey, + serverProof: [UInt8], + clientProof: [UInt8], + clientPublicKey: SRPKey, sharedSecret: SRPKey ) throws { // get our version of server proof @@ -150,9 +155,9 @@ public struct SRPClient { // is it the same guard serverProof == HAMK else { throw SRPClientError.invalidServerCode } } - - /// Generate salt and password verifier from username and password. When creating your user instead of - /// passing your password to the server, you pass the salt and password verifier values. In this way the + + /// Generate salt and password verifier from username and password. When creating your user instead of + /// passing your password to the server, you pass the salt and password verifier values. In this way the /// server never knows your password so can never leak it. /// /// - Parameters: @@ -168,17 +173,17 @@ public struct SRPClient { /// Hash data using same hash function that SRP uses /// - Parameter data: Data to be hashed /// - Returns: Hashed data - @inlinable public func hash(data: D) -> H.Digest where D : DataProtocol { + @inlinable public func hash(data: D) -> H.Digest where D: DataProtocol { H.hash(data: data) } } -extension SRPClient { +public extension SRPClient { /// return shared secret given the message (username:password), salt from server, client keys, and B value - func calculateSharedSecret( - message: [UInt8], - salt: [UInt8], - clientKeys: SRPKeyPair, + internal func calculateSharedSecret( + message: [UInt8], + salt: [UInt8], + clientKeys: SRPKeyPair, serverPublicKey: SRPKey ) throws -> SRPKey { guard serverPublicKey.number % configuration.N != BigNum(0) else { throw SRPClientError.nullServerKey } @@ -187,23 +192,23 @@ extension SRPClient { let u = SRP.calculateU(clientPublicKey: clientKeys.public.bytes, serverPublicKey: serverPublicKey.bytes) guard u != 0 else { throw SRPClientError.nullServerKey } - + let x = BigNum(bytes: [UInt8](H.hash(data: salt + H.hash(data: message)))) - + // calculate S = (B - k*g^x)^(a+u*x) let S = (serverPublicKey.number - configuration.k * configuration.g.power(x, modulus: configuration.N)).power(clientKeys.private.number + u * x, modulus: configuration.N) - - return .init(S, padding: self.configuration.sizeN) + + return .init(S, padding: configuration.sizeN) } - + /// generate password verifier - public func generatePasswordVerifier(username: String, password: String, salt: [UInt8]) -> BigNum { + func generatePasswordVerifier(username: String, password: String, salt: [UInt8]) -> BigNum { let message = "\(username):\(password)" return generatePasswordVerifier(message: [UInt8](message.utf8), salt: salt) } - + /// generate password verifier - public func generatePasswordVerifier(message: [UInt8], salt: [UInt8]) -> BigNum { + func generatePasswordVerifier(message: [UInt8], salt: [UInt8]) -> BigNum { let x = BigNum(bytes: [UInt8](H.hash(data: salt + H.hash(data: message)))) let verifier = configuration.g.power(x, modulus: configuration.N) return verifier diff --git a/Sources/SRP/configuration.swift b/Sources/SRP/configuration.swift index 0d51b84..5d4089c 100644 --- a/Sources/SRP/configuration.swift +++ b/Sources/SRP/configuration.swift @@ -11,27 +11,27 @@ public struct SRPConfiguration { public let k: BigNum /// size in bytes of N public let sizeN: Int - + /// Initialise SRPConfiguration with known safe prime /// - Parameter prime: enum indicating size of prime public init(_ prime: Prime) { - self.N = prime.group - self.sizeN = Int(self.N.numBits() + 7) / 8 - self.g = prime.generator - self.k = BigNum(bytes: [UInt8](H.hash(data: self.N.bytes + self.g.bytes.pad(to: sizeN)))) + N = prime.group + sizeN = Int(N.numBits() + 7) / 8 + g = prime.generator + k = BigNum(bytes: [UInt8](H.hash(data: N.bytes + g.bytes.pad(to: sizeN)))) } - + /// Initialise SRPConfiguration with your own prime and multiplicative group generator /// - Parameters: /// - N: Large prime /// - g: multiplicative group generator (usually 2) public init(N: BigNum, g: BigNum) { self.N = N - self.sizeN = Int(self.N.numBits() + 7) / 8 + sizeN = Int(self.N.numBits() + 7) / 8 self.g = g - self.k = BigNum(bytes: [UInt8](H.hash(data: self.N.bytes + self.g.bytes.pad(to: sizeN)))) + k = BigNum(bytes: [UInt8](H.hash(data: self.N.bytes + self.g.bytes.pad(to: sizeN)))) } - + public enum Prime { case N1024 case N1536 @@ -40,153 +40,153 @@ public struct SRPConfiguration { case N4096 case N6144 case N8192 - + /// prime numbers and generators taken from RC 5054 https://tools.ietf.org/html/rfc5054 var group: BigNum { switch self { case .N1024: return BigNum(hex: "EEAF0AB9ADB38DD69C33F80AFA8FC5E86072618775FF3C0B9EA2314C" + - "9C256576D674DF7496EA81D3383B4813D692C6E0E0D5D8E250B98BE4" + - "8E495C1D6089DAD15DC7D7B46154D6B6CE8EF4AD69B15D4982559B29" + - "7BCF1885C529F566660E57EC68EDBC3C05726CC02FD4CBF4976EAA9A" + - "FD5138FE8376435B9FC61D2FC0EB06E3")! + "9C256576D674DF7496EA81D3383B4813D692C6E0E0D5D8E250B98BE4" + + "8E495C1D6089DAD15DC7D7B46154D6B6CE8EF4AD69B15D4982559B29" + + "7BCF1885C529F566660E57EC68EDBC3C05726CC02FD4CBF4976EAA9A" + + "FD5138FE8376435B9FC61D2FC0EB06E3")! case .N1536: return BigNum(hex: "9DEF3CAFB939277AB1F12A8617A47BBBDBA51DF499AC4C80BEEEA961" + - "4B19CC4D5F4F5F556E27CBDE51C6A94BE4607A291558903BA0D0F843" + - "80B655BB9A22E8DCDF028A7CEC67F0D08134B1C8B97989149B609E0B" + - "E3BAB63D47548381DBC5B1FC764E3F4B53DD9DA1158BFD3E2B9C8CF5" + - "6EDF019539349627DB2FD53D24B7C48665772E437D6C7F8CE442734A" + - "F7CCB7AE837C264AE3A9BEB87F8A2FE9B8B5292E5A021FFF5E91479E" + - "8CE7A28C2442C6F315180F93499A234DCF76E3FED135F9BB")! + "4B19CC4D5F4F5F556E27CBDE51C6A94BE4607A291558903BA0D0F843" + + "80B655BB9A22E8DCDF028A7CEC67F0D08134B1C8B97989149B609E0B" + + "E3BAB63D47548381DBC5B1FC764E3F4B53DD9DA1158BFD3E2B9C8CF5" + + "6EDF019539349627DB2FD53D24B7C48665772E437D6C7F8CE442734A" + + "F7CCB7AE837C264AE3A9BEB87F8A2FE9B8B5292E5A021FFF5E91479E" + + "8CE7A28C2442C6F315180F93499A234DCF76E3FED135F9BB")! case .N2048: return BigNum(hex: "AC6BDB41324A9A9BF166DE5E1389582FAF72B6651987EE07FC319294" + - "3DB56050A37329CBB4A099ED8193E0757767A13DD52312AB4B03310D" + - "CD7F48A9DA04FD50E8083969EDB767B0CF6095179A163AB3661A05FB" + - "D5FAAAE82918A9962F0B93B855F97993EC975EEAA80D740ADBF4FF74" + - "7359D041D5C33EA71D281E446B14773BCA97B43A23FB801676BD207A" + - "436C6481F1D2B9078717461A5B9D32E688F87748544523B524B0D57D" + - "5EA77A2775D2ECFA032CFBDBF52FB3786160279004E57AE6AF874E73" + - "03CE53299CCC041C7BC308D82A5698F3A8D0C38271AE35F8E9DBFBB6" + - "94B5C803D89F7AE435DE236D525F54759B65E372FCD68EF20FA7111F" + - "9E4AFF73")! + "3DB56050A37329CBB4A099ED8193E0757767A13DD52312AB4B03310D" + + "CD7F48A9DA04FD50E8083969EDB767B0CF6095179A163AB3661A05FB" + + "D5FAAAE82918A9962F0B93B855F97993EC975EEAA80D740ADBF4FF74" + + "7359D041D5C33EA71D281E446B14773BCA97B43A23FB801676BD207A" + + "436C6481F1D2B9078717461A5B9D32E688F87748544523B524B0D57D" + + "5EA77A2775D2ECFA032CFBDBF52FB3786160279004E57AE6AF874E73" + + "03CE53299CCC041C7BC308D82A5698F3A8D0C38271AE35F8E9DBFBB6" + + "94B5C803D89F7AE435DE236D525F54759B65E372FCD68EF20FA7111F" + + "9E4AFF73")! case .N3072: return BigNum(hex: "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E08" + - "8A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B" + - "302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9" + - "A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE6" + - "49286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8" + - "FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D" + - "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C" + - "180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF695581718" + - "3995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D" + - "04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7D" + - "B3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D226" + - "1AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200C" + - "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFC" + - "E0FD108E4B82D120A93AD2CAFFFFFFFFFFFFFFFF")! - + "8A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B" + + "302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9" + + "A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE6" + + "49286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8" + + "FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D" + + "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C" + + "180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF695581718" + + "3995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D" + + "04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7D" + + "B3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D226" + + "1AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200C" + + "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFC" + + "E0FD108E4B82D120A93AD2CAFFFFFFFFFFFFFFFF")! + case .N4096: return BigNum(hex: "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E08" + - "8A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B" + - "302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9" + - "A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE6" + - "49286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8" + - "FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D" + - "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C" + - "180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF695581718" + - "3995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D" + - "04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7D" + - "B3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D226" + - "1AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200C" + - "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFC" + - "E0FD108E4B82D120A92108011A723C12A787E6D788719A10BDBA5B26" + - "99C327186AF4E23C1A946834B6150BDA2583E9CA2AD44CE8DBBBC2DB" + - "04DE8EF92E8EFC141FBECAA6287C59474E6BC05D99B2964FA090C3A2" + - "233BA186515BE7ED1F612970CEE2D7AFB81BDD762170481CD0069127" + - "D5B05AA993B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934063199" + - "FFFFFFFFFFFFFFFF")! - + "8A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B" + + "302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9" + + "A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE6" + + "49286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8" + + "FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D" + + "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C" + + "180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF695581718" + + "3995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D" + + "04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7D" + + "B3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D226" + + "1AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200C" + + "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFC" + + "E0FD108E4B82D120A92108011A723C12A787E6D788719A10BDBA5B26" + + "99C327186AF4E23C1A946834B6150BDA2583E9CA2AD44CE8DBBBC2DB" + + "04DE8EF92E8EFC141FBECAA6287C59474E6BC05D99B2964FA090C3A2" + + "233BA186515BE7ED1F612970CEE2D7AFB81BDD762170481CD0069127" + + "D5B05AA993B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934063199" + + "FFFFFFFFFFFFFFFF")! + case .N6144: return BigNum(hex: "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E08" + - "8A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B" + - "302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9" + - "A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE6" + - "49286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8" + - "FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D" + - "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C" + - "180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF695581718" + - "3995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D" + - "04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7D" + - "B3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D226" + - "1AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200C" + - "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFC" + - "E0FD108E4B82D120A92108011A723C12A787E6D788719A10BDBA5B26" + - "99C327186AF4E23C1A946834B6150BDA2583E9CA2AD44CE8DBBBC2DB" + - "04DE8EF92E8EFC141FBECAA6287C59474E6BC05D99B2964FA090C3A2" + - "233BA186515BE7ED1F612970CEE2D7AFB81BDD762170481CD0069127" + - "D5B05AA993B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934028492" + - "36C3FAB4D27C7026C1D4DCB2602646DEC9751E763DBA37BDF8FF9406" + - "AD9E530EE5DB382F413001AEB06A53ED9027D831179727B0865A8918" + - "DA3EDBEBCF9B14ED44CE6CBACED4BB1BDB7F1447E6CC254B33205151" + - "2BD7AF426FB8F401378CD2BF5983CA01C64B92ECF032EA15D1721D03" + - "F482D7CE6E74FEF6D55E702F46980C82B5A84031900B1C9E59E7C97F" + - "BEC7E8F323A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AA" + - "CC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE32806A1D58B" + - "B7C5DA76F550AA3D8A1FBFF0EB19CCB1A313D55CDA56C9EC2EF29632" + - "387FE8D76E3C0468043E8F663F4860EE12BF2D5B0B7474D6E694F91E" + - "6DCC4024FFFFFFFFFFFFFFFF")! - + "8A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B" + + "302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9" + + "A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE6" + + "49286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8" + + "FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D" + + "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C" + + "180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF695581718" + + "3995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D" + + "04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7D" + + "B3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D226" + + "1AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200C" + + "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFC" + + "E0FD108E4B82D120A92108011A723C12A787E6D788719A10BDBA5B26" + + "99C327186AF4E23C1A946834B6150BDA2583E9CA2AD44CE8DBBBC2DB" + + "04DE8EF92E8EFC141FBECAA6287C59474E6BC05D99B2964FA090C3A2" + + "233BA186515BE7ED1F612970CEE2D7AFB81BDD762170481CD0069127" + + "D5B05AA993B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934028492" + + "36C3FAB4D27C7026C1D4DCB2602646DEC9751E763DBA37BDF8FF9406" + + "AD9E530EE5DB382F413001AEB06A53ED9027D831179727B0865A8918" + + "DA3EDBEBCF9B14ED44CE6CBACED4BB1BDB7F1447E6CC254B33205151" + + "2BD7AF426FB8F401378CD2BF5983CA01C64B92ECF032EA15D1721D03" + + "F482D7CE6E74FEF6D55E702F46980C82B5A84031900B1C9E59E7C97F" + + "BEC7E8F323A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AA" + + "CC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE32806A1D58B" + + "B7C5DA76F550AA3D8A1FBFF0EB19CCB1A313D55CDA56C9EC2EF29632" + + "387FE8D76E3C0468043E8F663F4860EE12BF2D5B0B7474D6E694F91E" + + "6DCC4024FFFFFFFFFFFFFFFF")! + case .N8192: return BigNum(hex: "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E08" + - "8A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B" + - "302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9" + - "A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE6" + - "49286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8" + - "FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D" + - "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C" + - "180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF695581718" + - "3995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D" + - "04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7D" + - "B3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D226" + - "1AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200C" + - "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFC" + - "E0FD108E4B82D120A92108011A723C12A787E6D788719A10BDBA5B26" + - "99C327186AF4E23C1A946834B6150BDA2583E9CA2AD44CE8DBBBC2DB" + - "04DE8EF92E8EFC141FBECAA6287C59474E6BC05D99B2964FA090C3A2" + - "233BA186515BE7ED1F612970CEE2D7AFB81BDD762170481CD0069127" + - "D5B05AA993B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934028492" + - "36C3FAB4D27C7026C1D4DCB2602646DEC9751E763DBA37BDF8FF9406" + - "AD9E530EE5DB382F413001AEB06A53ED9027D831179727B0865A8918" + - "DA3EDBEBCF9B14ED44CE6CBACED4BB1BDB7F1447E6CC254B33205151" + - "2BD7AF426FB8F401378CD2BF5983CA01C64B92ECF032EA15D1721D03" + - "F482D7CE6E74FEF6D55E702F46980C82B5A84031900B1C9E59E7C97F" + - "BEC7E8F323A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AA" + - "CC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE32806A1D58B" + - "B7C5DA76F550AA3D8A1FBFF0EB19CCB1A313D55CDA56C9EC2EF29632" + - "387FE8D76E3C0468043E8F663F4860EE12BF2D5B0B7474D6E694F91E" + - "6DBE115974A3926F12FEE5E438777CB6A932DF8CD8BEC4D073B931BA" + - "3BC832B68D9DD300741FA7BF8AFC47ED2576F6936BA424663AAB639C" + - "5AE4F5683423B4742BF1C978238F16CBE39D652DE3FDB8BEFC848AD9" + - "22222E04A4037C0713EB57A81A23F0C73473FC646CEA306B4BCBC886" + - "2F8385DDFA9D4B7FA2C087E879683303ED5BDD3A062B3CF5B3A278A6" + - "6D2A13F83F44F82DDF310EE074AB6A364597E899A0255DC164F31CC5" + - "0846851DF9AB48195DED7EA1B1D510BD7EE74D73FAF36BC31ECFA268" + - "359046F4EB879F924009438B481C6CD7889A002ED5EE382BC9190DA6" + - "FC026E479558E4475677E9AA9E3050E2765694DFC81F56E880B96E71" + - "60C980DD98EDD3DFFFFFFFFFFFFFFFFF")! + "8A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B" + + "302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9" + + "A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE6" + + "49286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8" + + "FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D" + + "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C" + + "180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF695581718" + + "3995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D" + + "04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7D" + + "B3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D226" + + "1AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200C" + + "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFC" + + "E0FD108E4B82D120A92108011A723C12A787E6D788719A10BDBA5B26" + + "99C327186AF4E23C1A946834B6150BDA2583E9CA2AD44CE8DBBBC2DB" + + "04DE8EF92E8EFC141FBECAA6287C59474E6BC05D99B2964FA090C3A2" + + "233BA186515BE7ED1F612970CEE2D7AFB81BDD762170481CD0069127" + + "D5B05AA993B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934028492" + + "36C3FAB4D27C7026C1D4DCB2602646DEC9751E763DBA37BDF8FF9406" + + "AD9E530EE5DB382F413001AEB06A53ED9027D831179727B0865A8918" + + "DA3EDBEBCF9B14ED44CE6CBACED4BB1BDB7F1447E6CC254B33205151" + + "2BD7AF426FB8F401378CD2BF5983CA01C64B92ECF032EA15D1721D03" + + "F482D7CE6E74FEF6D55E702F46980C82B5A84031900B1C9E59E7C97F" + + "BEC7E8F323A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AA" + + "CC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE32806A1D58B" + + "B7C5DA76F550AA3D8A1FBFF0EB19CCB1A313D55CDA56C9EC2EF29632" + + "387FE8D76E3C0468043E8F663F4860EE12BF2D5B0B7474D6E694F91E" + + "6DBE115974A3926F12FEE5E438777CB6A932DF8CD8BEC4D073B931BA" + + "3BC832B68D9DD300741FA7BF8AFC47ED2576F6936BA424663AAB639C" + + "5AE4F5683423B4742BF1C978238F16CBE39D652DE3FDB8BEFC848AD9" + + "22222E04A4037C0713EB57A81A23F0C73473FC646CEA306B4BCBC886" + + "2F8385DDFA9D4B7FA2C087E879683303ED5BDD3A062B3CF5B3A278A6" + + "6D2A13F83F44F82DDF310EE074AB6A364597E899A0255DC164F31CC5" + + "0846851DF9AB48195DED7EA1B1D510BD7EE74D73FAF36BC31ECFA268" + + "359046F4EB879F924009438B481C6CD7889A002ED5EE382BC9190DA6" + + "FC026E479558E4475677E9AA9E3050E2765694DFC81F56E880B96E71" + + "60C980DD98EDD3DFFFFFFFFFFFFFFFFF")! } } - + var generator: BigNum { switch self { case .N1024, .N1536, .N2048: diff --git a/Sources/SRP/error.swift b/Sources/SRP/error.swift index d082960..559ce94 100644 --- a/Sources/SRP/error.swift +++ b/Sources/SRP/error.swift @@ -11,11 +11,10 @@ public enum SRPClientError: Swift.Error { } /// Errors thrown by SRPServer -///Errors thrown by SRPServer +/// Errors thrown by SRPServer public enum SRPServerError: Swift.Error { /// the modulus of the client key and N generated a zero case nullClientKey /// client proof of the shared secret was invalid or wrong case invalidClientProof } - diff --git a/Sources/SRP/keys.swift b/Sources/SRP/keys.swift index e1bbe67..2c3009a 100644 --- a/Sources/SRP/keys.swift +++ b/Sources/SRP/keys.swift @@ -9,22 +9,22 @@ public struct SRPKey { /// padding public let padding: Int /// Representation as a byte array - public var bytes: [UInt8] { number.bytes.pad(to: self.padding) } + public var bytes: [UInt8] { number.bytes.pad(to: padding) } /// Representation as a hex string - public var hex: String { number.bytes.pad(to: self.padding).hexdigest() } + public var hex: String { number.bytes.pad(to: padding).hexdigest() } /// Initialize with an array of bytes @inlinable public init(_ bytes: C, padding: Int? = nil) { - self.number = BigNum(bytes: bytes) + number = BigNum(bytes: bytes) self.padding = padding ?? bytes.count } - + /// Initialize with a crypto digest @inlinable public init(_ digest: D, padding: Int? = nil) { - self.number = BigNum(bytes: digest) + number = BigNum(bytes: digest) self.padding = padding ?? D.byteCount } - + /// Initialize with a hex string @inlinable public init?(hex: String, padding: Int = 0) { guard let number = BigNum(hex: hex) else { return nil } @@ -40,11 +40,11 @@ public struct SRPKey { /// Return SRPKey with padding func with(padding: Int) -> SRPKey { - .init(self.number, padding: padding) + .init(number, padding: padding) } } -extension SRPKey: Equatable { } +extension SRPKey: Equatable {} /// Contains a private and a public key public struct SRPKeyPair { @@ -55,9 +55,8 @@ public struct SRPKeyPair { /// - Parameters: /// - public: The public key of the key pair /// - private: The private key of the key pair - init(`public`: SRPKey, `private`: SRPKey) { + init(public: SRPKey, private: SRPKey) { self.private = `private` self.public = `public` } } - diff --git a/Sources/SRP/server.swift b/Sources/SRP/server.swift index a059498..f658594 100644 --- a/Sources/SRP/server.swift +++ b/Sources/SRP/server.swift @@ -18,13 +18,13 @@ import Foundation public struct SRPServer { /// configuration has to be the same as the client configuration public let configuration: SRPConfiguration - + /// Initialise SRPServer /// - Parameter configuration: configuration to use public init(configuration: SRPConfiguration) { self.configuration = configuration } - + /// generate public and private keys to be used in srp authentication /// - Parameter verifier: password verifier used to generate key pair /// - Returns: return public/private key pair @@ -35,8 +35,8 @@ public struct SRPServer { b = BigNum(bytes: SymmetricKey(size: .bits256)) B = (configuration.k * verifier.number + configuration.g.power(b, modulus: configuration.N)) % configuration.N } while B % configuration.N == BigNum(0) - - return SRPKeyPair(public: SRPKey(B, padding: self.configuration.sizeN), private: SRPKey(b)) + + return SRPKeyPair(public: SRPKey(B, padding: configuration.sizeN), private: SRPKey(b)) } /// calculate the shared secret @@ -46,11 +46,11 @@ public struct SRPServer { /// - verifier: Password verifier /// - Returns: shared secret public func calculateSharedSecret( - clientPublicKey: SRPKey, - serverKeys: SRPKeyPair, + clientPublicKey: SRPKey, + serverKeys: SRPKeyPair, verifier: SRPKey ) throws -> SRPKey { - let clientPublicKey = clientPublicKey.with(padding: self.configuration.sizeN) + let clientPublicKey = clientPublicKey.with(padding: configuration.sizeN) guard clientPublicKey.number % configuration.N != BigNum(0) else { throw SRPServerError.nullClientKey } // calculate u = H(clientPublicKey | serverPublicKey) @@ -58,8 +58,8 @@ public struct SRPServer { // calculate S let S = ((clientPublicKey.number * verifier.number.power(u, modulus: configuration.N)).power(serverKeys.private.number, modulus: configuration.N)) - - return SRPKey(S, padding: self.configuration.sizeN) + + return SRPKey(S, padding: configuration.sizeN) } /// verify proof that client has shared secret and return a server verification proof. If verification fails a `invalidClientCode` error is thrown @@ -74,18 +74,18 @@ public struct SRPServer { /// - Throws: invalidClientCode /// - Returns: The server verification code public func verifyClientProof( - proof: [UInt8], - username: String, - salt: [UInt8], - clientPublicKey: SRPKey, - serverPublicKey: SRPKey, + proof: [UInt8], + username: String, + salt: [UInt8], + clientPublicKey: SRPKey, + serverPublicKey: SRPKey, sharedSecret: SRPKey ) throws -> [UInt8] { - let clientPublicKey = clientPublicKey.with(padding: self.configuration.sizeN) - let serverPublicKey = serverPublicKey.with(padding: self.configuration.sizeN) - let sharedSecret = sharedSecret.with(padding: self.configuration.sizeN) + let clientPublicKey = clientPublicKey.with(padding: configuration.sizeN) + let serverPublicKey = serverPublicKey.with(padding: configuration.sizeN) + let sharedSecret = sharedSecret.with(padding: configuration.sizeN) let hashSharedSecret = [UInt8](H.hash(data: sharedSecret.bytes)) - + let clientProof = SRP.calculateClientProof( configuration: configuration, username: username, @@ -101,7 +101,7 @@ public struct SRPServer { /// Hash data using same hash function that SRP uses /// - Parameter data: Data to be hashed /// - Returns: Hashed data - @inlinable public func hash(data: D) -> H.Digest where D : DataProtocol { + @inlinable public func hash(data: D) -> H.Digest where D: DataProtocol { H.hash(data: data) } } diff --git a/Sources/SRP/srp.swift b/Sources/SRP/srp.swift index e6d7999..454e142 100644 --- a/Sources/SRP/srp.swift +++ b/Sources/SRP/srp.swift @@ -3,12 +3,11 @@ import Crypto /// Contains common code used by both client and server SRP code public struct SRP { - /// calculate u = H(clientPublicKey | serverPublicKey) static func calculateU(clientPublicKey: [UInt8], serverPublicKey: [UInt8]) -> BigNum { - BigNum(bytes: [UInt8].init(H.hash(data: clientPublicKey + serverPublicKey))) + BigNum(bytes: [UInt8](H.hash(data: clientPublicKey + serverPublicKey))) } - + /// Calculate client verification code H(H(N)^ H(g)) | H(username) | salt | A | B | H(S)) static func calculateClientProof( configuration: SRPConfiguration, diff --git a/Tests/LinuxMain.swift b/Tests/LinuxMain.swift index f87f4e9..138759e 100644 --- a/Tests/LinuxMain.swift +++ b/Tests/LinuxMain.swift @@ -1,5 +1,5 @@ -import XCTest import SRPTests +import XCTest var tests = [XCTestCaseEntry]() tests += SRPTests.allTests() diff --git a/Tests/SRPTests/SRPTests.swift b/Tests/SRPTests/SRPTests.swift index eaca279..e41017a 100644 --- a/Tests/SRPTests/SRPTests.swift +++ b/Tests/SRPTests/SRPTests.swift @@ -1,10 +1,9 @@ -import XCTest import BigNum import Crypto @testable import SRP +import XCTest final class SRPTests: XCTestCase { - func testSRPSharedSecret() { let username = "adamfowler" let password = "testpassword" @@ -23,12 +22,14 @@ final class SRPTests: XCTestCase { password: password, salt: salt, clientKeys: clientKeys, - serverPublicKey: serverKeys.public) + serverPublicKey: serverKeys.public + ) let serverSharedSecret = try server.calculateSharedSecret( clientPublicKey: clientKeys.public, serverKeys: serverKeys, - verifier: verifier) + verifier: verifier + ) XCTAssertEqual(sharedSecret, serverSharedSecret) } catch { @@ -88,11 +89,11 @@ final class SRPTests: XCTestCase { let B = BigNum(hex: "2bfc8559a022497f1254af3c76786b95cb0dfb449af15501aa51eefe78947d7ef06df4fcc07a899bcaae0e552ca72c7a1f3016f3ec357a86a1428dad9f98cb8a69d405404e57e9aaf01e51a46a73b3fc7bc1d212569e4a882ae6d878599e098c89033838ec069fe368a49461f531e5b4662700d56d8c252d0aea9da6abe9b014")! let secret = "b6288955afd690a13686d65886b5f82018515df3".bytes(using: .hexadecimal)! let clientProof = SRP.calculateClientProof( - configuration: configuration, - username: username, - salt: salt, - clientPublicKey: SRPKey(A, padding: configuration.sizeN), - serverPublicKey: SRPKey(B, padding: configuration.sizeN), + configuration: configuration, + username: username, + salt: salt, + clientPublicKey: SRPKey(A, padding: configuration.sizeN), + serverPublicKey: SRPKey(B, padding: configuration.sizeN), hashSharedSecret: secret ) @@ -106,8 +107,8 @@ final class SRPTests: XCTestCase { let clientProof = "e1a8629a723039a61be91a173ab6260fc582192f".bytes(using: .hexadecimal)! let serverProof = SRP.calculateServerVerification( - clientPublicKey: SRPKey(A), - clientProof: clientProof, + clientPublicKey: SRPKey(A), + clientProof: clientProof, hashSharedSecret: secret ) @@ -145,10 +146,10 @@ final class SRPTests: XCTestCase { XCTAssertEqual(u.hex, "CE38B9593487DA98554ED47D70A7AE5F462EF019".lowercased()) let sharedSecret = try client.calculateSharedSecret( - username: username, - password: password, - salt: salt, - clientKeys: SRPKeyPair(public: SRPKey(A, padding: configuration.sizeN), private: SRPKey(a)), + username: username, + password: password, + salt: salt, + clientKeys: SRPKeyPair(public: SRPKey(A, padding: configuration.sizeN), private: SRPKey(a)), serverPublicKey: SRPKey(B, padding: configuration.sizeN) ) @@ -169,27 +170,27 @@ final class SRPTests: XCTestCase { let verifier = client.generatePasswordVerifier(message: message, salt: salt) XCTAssertEqual(verifier.hex, "173ffa0263e63ccfd6791b8ee2a40f048ec94cd95aa8a3125726f9805e0c8283c658dc0b607fbb25db68e68e93f2658483049c68af7e8214c49fde2712a775b63e545160d64b00189a86708c69657da7a1678eda0cd79f86b8560ebdb1ffc221db360eab901d643a75bf1205070a5791230ae56466b8c3c1eb656e19b794f1ea0d2a077b3a755350208ea0118fec8c4b2ec344a05c66ae1449b32609ca7189451c259d65bd15b34d8729afdb5faff8af1f3437bbdc0c3d0b069a8ab2a959c90c5a43d42082c77490f3afcc10ef5648625c0605cdaace6c6fdc9e9a7e6635d619f50af7734522470502cab26a52a198f5b00a279858916507b0b4e9ef9524d6") - + let b = BigNum(hex: "00f3000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f")! // copied from server.swift let B = (configuration.k * verifier + configuration.g.power(b, modulus: configuration.N)) % configuration.N - + XCTAssertEqual(SRPKey(B, padding: configuration.sizeN).hex, "0022ce5a7b9d81277172caa20b0f1efb4643b3becc53566473959b07b790d3c3f08650d5531c19ad30ebb67bdb481d1d9cf61bf272f8439848fdda58a4e6abc5abb2ac496da5098d5cbf90e29b4b110e4e2c033c70af73925fa37457ee13ea3e8fde4ab516dff1c2ae8e57a6b264fb9db637eeeae9b5e43dfaba9b329d3b8770ce89888709e026270e474eef822436e6397562f284778673a1a7bc12b6883d1c21fbc27ffb3dbeb85efda279a69a19414969113f10451603065f0a012666645651dde44a52f4d8de113e2131321df1bf4369d2585364f9e536c39a4dce33221be57d50ddccb4384e3612bbfd03a268a36e4f7e01de651401e108cc247db50392") - + let a = BigNum(hex: "00f2000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d3d7")! // copied from client.swift let A = configuration.g.power(a, modulus: configuration.N) - + XCTAssertEqual(SRPKey(A, padding: configuration.sizeN).hex, "007da76cb7e77af5ab61f334dbd5a958513afcdf0f47ab99271fc5f7860fe2132e5802ca79d2e5c064bb80a38ee08771c98a937696698d878d78571568c98a1c40cc6e7cb101988a2f9ba3d65679027d4d9068cb8aad6ebff0101bab6d52b5fdfa81d2ed48bba119d4ecdb7f3f478bd236d5749f2275e9484f2d0a9259d05e49d78a23dd26c60bfba04fd346e5146469a8c3f010a627be81c58ded1caaef2363635a45f97ca0d895cc92ace1d09a99d6beb6b0dc0829535c857a419e834db12864cd6ee8a843563b0240520ff0195735cd9d316842d5d3f8ef7209a0bb4b54ad7374d73e79be2c3975632de562c596470bb27bad79c3e2fcddf194e1666cb9fc") - + let u = SRP.calculateU(clientPublicKey: A.bytes.pad(to: configuration.sizeN), serverPublicKey: B.bytes.pad(to: configuration.sizeN)) XCTAssertEqual(u.hex, "b284aa1064e8775150da6b5e2147b47ca7df505bed94a6f4bb2ad873332ad732") let sharedSecret = try client.calculateSharedSecret( - message: message, - salt: salt, - clientKeys: SRPKeyPair(public: SRPKey(A, padding: configuration.sizeN), private: SRPKey(a)), + message: message, + salt: salt, + clientKeys: SRPKeyPair(public: SRPKey(A, padding: configuration.sizeN), private: SRPKey(a)), serverPublicKey: SRPKey(B, padding: configuration.sizeN) ) @@ -199,7 +200,7 @@ final class SRPTests: XCTestCase { XCTAssertEqual([UInt8](clientProof).hexdigest(), "27949ec1e0f1625633436865edb037e23eb6bf5cb91873f2a2729373c2039008") } - + static var allTests = [ ("testSRPSharedSecret", testSRPSharedSecret), ("testVerifySRP", testVerifySRP), @@ -216,15 +217,15 @@ extension String { case hexadecimal } - func bytes(using encoding:ExtendedEncoding) -> [UInt8]? { - guard self.count % 2 == 0 else { return nil } + func bytes(using _: ExtendedEncoding) -> [UInt8]? { + guard count % 2 == 0 else { return nil } var bytes: [UInt8] = [] var indexIsEven = true - for i in self.indices { + for i in indices { if indexIsEven { - let byteRange = i...self.index(after: i) + let byteRange = i ... index(after: i) guard let byte = UInt8(self[byteRange], radix: 16) else { return nil } bytes.append(byte) } diff --git a/Tests/SRPTests/XCTestManifests.swift b/Tests/SRPTests/XCTestManifests.swift index 97c4c9f..be87865 100644 --- a/Tests/SRPTests/XCTestManifests.swift +++ b/Tests/SRPTests/XCTestManifests.swift @@ -1,9 +1,9 @@ import XCTest #if !canImport(ObjectiveC) -public func allTests() -> [XCTestCaseEntry] { - return [ - testCase(SRPTests.allTests), - ] -} + public func allTests() -> [XCTestCaseEntry] { + return [ + testCase(SRPTests.allTests), + ] + } #endif