@@ -39,11 +39,11 @@ public struct SRPClient<H: HashFunction> {
39
39
40
40
/// return shared secret given the username, password, B value and salt from the server
41
41
/// - Parameters:
42
- /// - username: user identifier
43
- /// - password: password
44
- /// - salt: salt
45
- /// - clientKeys: client public/private keys
46
- /// - serverPublicKey: server public key
42
+ /// - username: user identifier (I)
43
+ /// - password: password (p)
44
+ /// - salt: salt (s)
45
+ /// - clientKeys: client public/private keys (A,a)
46
+ /// - serverPublicKey: server public key (B)
47
47
/// - Throws: `nullServerKey`
48
48
/// - Returns: shared secret
49
49
public func calculateSharedSecret( username: String , password: String , salt: [ UInt8 ] , clientKeys: SRPKeyPair , serverPublicKey: SRPKey ) throws -> SRPKey {
@@ -54,10 +54,10 @@ public struct SRPClient<H: HashFunction> {
54
54
55
55
/// return shared secret given a binary password, B value and salt from the server
56
56
/// - Parameters:
57
- /// - password: password
58
- /// - salt: salt
59
- /// - clientKeys: client public/private keys
60
- /// - serverPublicKey: server public key
57
+ /// - password: password (p)
58
+ /// - salt: salt (s)
59
+ /// - clientKeys: client public/private keys (A,a)
60
+ /// - serverPublicKey: server public key (B)
61
61
/// - Throws: `nullServerKey`
62
62
/// - Returns: shared secret
63
63
public func calculateSharedSecret( password: [ UInt8 ] , salt: [ UInt8 ] , clientKeys: SRPKeyPair , serverPublicKey: SRPKey ) throws -> SRPKey {
@@ -66,40 +66,56 @@ public struct SRPClient<H: HashFunction> {
66
66
return SRPKey ( sharedSecret)
67
67
}
68
68
69
- /// calculate proof of shared secret to send to server
69
+ /// calculate proof of shared secret to send to server.
70
+ ///
71
+ /// There doesn't seem to be any agreement on the simple version of the client/server proof.
72
+ /// Some versions use K (H(S)) instead of S, some pad all values regardless of whether their
73
+ /// source is a hash or a big num. This is a simple version of the client proof as used by
74
+ /// the mozilla srp library https://github.com/mozilla/node-srp
75
+ ///
70
76
/// - Parameters:
71
- /// - clientPublicKey: client public key
72
- /// - serverPublicKey: server public key
73
- /// - sharedSecret: shared secret
77
+ /// - clientPublicKey: client public key (A)
78
+ /// - serverPublicKey: server public key (B)
79
+ /// - sharedSecret: shared secret (S)
74
80
/// - Returns: The client verification code which should be passed to the server
75
- public func calculateSimpleClientProof ( clientPublicKey: SRPKey , serverPublicKey: SRPKey , sharedSecret: SRPKey ) -> [ UInt8 ] {
81
+ public func calculateMozillaClientProof ( clientPublicKey: SRPKey , serverPublicKey: SRPKey , sharedSecret: SRPKey ) -> [ UInt8 ] {
76
82
// get verification code
77
- return SRP< H> . calculateSimpleClientProof ( clientPublicKey: clientPublicKey, serverPublicKey: serverPublicKey, sharedSecret: sharedSecret, padding: configuration. sizeN)
83
+ return SRP< H> . calculateMozillaClientProof ( clientPublicKey: clientPublicKey, serverPublicKey: serverPublicKey, sharedSecret: sharedSecret, padding: configuration. sizeN)
78
84
}
79
85
80
- /// If the server returns that the client verification code was valiid it will also return a server verification code that the client can use to verify the server is correct
81
- ///
86
+ /// If the server returns that the client verification code was valid it will also return
87
+ /// a server verification code that the client can use to verify the server is correct
88
+ ///
89
+ /// There doesn't seem to be any agreement on the simple version of the client/server proof.
90
+ /// Some versions use K (H(S)) instead of S, some pad all values regardless of whether their
91
+ /// source is a hash or a big num. This is a simple version of the server proof as used by
92
+ /// the mozilla srp library https://github.com/mozilla/node-srp
93
+ ///
82
94
/// - Parameters:
83
- /// - code: Verification code returned by server
84
- /// - state: Authentication state
95
+ /// - serverProof: Proof returned by server (M2)
96
+ /// - clientProof: Proof created by client (M1)
97
+ /// - clientKeys: client public key (A,a)
98
+ /// - sharedSecret: shared secret (S)
85
99
/// - Throws: `requiresVerificationKey`, `invalidServerCode`
86
- public func verifySimpleServerProof ( serverProof: [ UInt8 ] , clientProof: [ UInt8 ] , clientKeys: SRPKeyPair , sharedSecret: SRPKey ) throws {
100
+ public func verifyMozillaServerProof ( serverProof: [ UInt8 ] , clientProof: [ UInt8 ] , clientKeys: SRPKeyPair , sharedSecret: SRPKey ) throws {
87
101
// get out version of server proof
88
- let HAMS = SRP< H> . calculateSimpleServerVerification( clientPublicKey: clientKeys. public, clientProof: clientProof, sharedSecret: sharedSecret, padding: configuration. sizeN)
102
+ let hashSharedSecret = [ UInt8] ( H . hash ( data: sharedSecret. bytes ( padding: configuration. sizeN) ) )
103
+ let HAMK = SRP< H> . calculateMozillaServerVerification( clientPublicKey: clientKeys. public, clientProof: clientProof, hashSharedSecret: hashSharedSecret, padding: configuration. sizeN)
89
104
// is it the same
90
- guard serverProof == HAMS else { throw SRPClientError . invalidServerCode }
105
+ guard serverProof == HAMK else { throw SRPClientError . invalidServerCode }
91
106
}
92
107
93
108
/// calculate proof of shared secret to send to server
109
+ ///
110
+ /// This is the client proof detailed in https://www.rfc-editor.org/rfc/rfc2945
94
111
/// - Parameters:
95
- /// - username: username
96
- /// - salt: The salt value associated with the user returned by the server
97
- /// - clientPublicKey: client public key
98
- /// - serverPublicKey: server public key
99
- /// - sharedSecret: shared secret
112
+ /// - username: username (I)
113
+ /// - salt: The salt value associated with the user returned by the server (s)
114
+ /// - clientPublicKey: client public key (A)
115
+ /// - serverPublicKey: server public key (B)
116
+ /// - sharedSecret: shared secret (S)
100
117
/// - Returns: The client verification code which should be passed to the server
101
118
public func calculateClientProof( username: String , salt: [ UInt8 ] , clientPublicKey: SRPKey , serverPublicKey: SRPKey , sharedSecret: SRPKey ) -> [ UInt8 ] {
102
-
103
119
let hashSharedSecret = [ UInt8] ( H . hash ( data: sharedSecret. bytes ( padding: configuration. sizeN) ) )
104
120
105
121
// get verification code
@@ -110,24 +126,26 @@ public struct SRPClient<H: HashFunction> {
110
126
/// verification code that the client can use to verify the server is correct. This is the calculation
111
127
/// to verify it is correct
112
128
///
129
+ /// This is the server proof detailed in https://www.rfc-editor.org/rfc/rfc2945
113
130
/// - Parameters:
114
- /// - clientPublicKey: Client public key
115
- /// - clientProof: Client proof
116
- /// - sharedSecret: Shared secret
131
+ /// - clientPublicKey: Client public key (A)
132
+ /// - clientProof: Client proof (M1)
133
+ /// - sharedSecret: Shared secret (M2)
117
134
public func calculateServerProof( clientPublicKey: SRPKey , clientProof: [ UInt8 ] , sharedSecret: SRPKey ) -> [ UInt8 ] {
118
135
let hashSharedSecret = [ UInt8] ( H . hash ( data: sharedSecret. bytes ( padding: configuration. sizeN) ) )
119
- // get out version of server proof
136
+ // get our version of server proof
120
137
return SRP< H> . calculateServerVerification( clientPublicKey: clientPublicKey, clientProof: clientProof, hashSharedSecret: hashSharedSecret, padding: configuration. sizeN)
121
138
}
122
139
123
140
/// If the server returns that the client verification code was valid it will also return a server
124
141
/// verification code that the client can use to verify the server is correct
125
142
///
143
+ /// This is the client/server proof detailed in https://www.rfc-editor.org/rfc/rfc2945
126
144
/// - Parameters:
127
- /// - clientProof: Server proof
128
- /// - clientProof: Client proof
129
- /// - clientKeys: Client keys
130
- /// - sharedSecret: Shared secret
145
+ /// - clientProof: Server proof (M2)
146
+ /// - clientProof: Client proof (M1)
147
+ /// - clientKeys: Client keys (A,a)
148
+ /// - sharedSecret: Shared secret (S)
131
149
/// - Throws: `requiresVerificationKey`, `invalidServerCode`
132
150
public func verifyServerProof( serverProof: [ UInt8 ] , clientProof: [ UInt8 ] , clientKeys: SRPKeyPair , sharedSecret: SRPKey ) throws {
133
151
// get our version of server proof
@@ -141,8 +159,8 @@ public struct SRPClient<H: HashFunction> {
141
159
/// server never knows your password so can never leak it.
142
160
///
143
161
/// - Parameters:
144
- /// - username: username
145
- /// - password: user password
162
+ /// - username: username (I)
163
+ /// - password: user password (p)
146
164
/// - Returns: tuple containing salt and password verifier
147
165
public func generateSaltAndVerifier( username: String , password: String ) -> ( salt: [ UInt8 ] , verifier: SRPKey ) {
148
166
let salt = [ UInt8 ] . random ( count: 16 )
0 commit comments