SRP-6a Secure Remote Password protocol for OCaml
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

srp: Extract n_len, pad_z, and hash_xor_ng helpers

+47 -55
+47 -55
lib/srp.ml
··· 30 30 (** Group prime N *) 31 31 let n = Z.of_string_base 16 n_hex 32 32 33 + (** Length of N in bytes *) 34 + let n_len = (Z.numbits n + 7) / 8 35 + 33 36 (** {1 Utility Functions} *) 34 37 35 38 (** Hash data using SHA-512 *) ··· 62 65 if pad > 0 && String.length s < pad then 63 66 String.make (pad - String.length s) '\x00' ^ s 64 67 else s 68 + 69 + (** Pad a Z value to n_len bytes *) 70 + let pad_z z = bytes_of_z ~pad:n_len z 71 + 72 + (** XOR of H(N) and H(g), used in proof computation *) 73 + let hash_xor_ng = 74 + let h_n = hash (bytes_of_z n) in 75 + let h_g = hash (bytes_of_z g) in 76 + String.init (String.length h_n) (fun i -> 77 + Char.chr (Char.code h_n.[i] lxor Char.code h_g.[i])) 65 78 66 79 (** Compute k = H(N | PAD(g)) *) 67 80 let compute_k () = ··· 98 111 let public_key t = t.big_a 99 112 100 113 let compute_session_key t ~salt ~big_b = 101 - if Z.(equal (big_b mod n) zero) then Error (`Msg "Invalid B value") 102 - else 103 - let k = compute_k () in 104 - let n_len = (Z.numbits n + 7) / 8 in 105 - let a_pad = bytes_of_z ~pad:n_len t.big_a in 106 - let b_pad = bytes_of_z ~pad:n_len big_b in 107 - let u = z_of_bytes (hash (a_pad ^ b_pad)) in 108 - if Z.(equal u zero) then Error (`Msg "Invalid u value") 109 - else 110 - let x = compute_x ~salt ~username:t.username ~password:t.password in 111 - (* S = (B - k * g^x)^(a + u * x) mod N *) 112 - let base = Z.((big_b - (k * powm g x n)) mod n) in 113 - let base = if Z.(lt base zero) then Z.(base + n) else base in 114 - let exp = Z.((t.a + (u * x)) mod (n - one)) in 115 - let s = Z.powm base exp n in 116 - let session_key = hash (bytes_of_z s) in 117 - Ok session_key 114 + let ( let* ) = Result.bind in 115 + let* () = 116 + if Z.(equal (big_b mod n) zero) then Error (`Msg "Invalid B value") 117 + else Ok () 118 + in 119 + let k = compute_k () in 120 + let u = z_of_bytes (hash (pad_z t.big_a ^ pad_z big_b)) in 121 + let* () = 122 + if Z.(equal u zero) then Error (`Msg "Invalid u value") else Ok () 123 + in 124 + let x = compute_x ~salt ~username:t.username ~password:t.password in 125 + (* S = (B - k * g^x)^(a + u * x) mod N *) 126 + let base = Z.((big_b - (k * powm g x n)) mod n) in 127 + let base = if Z.(lt base zero) then Z.(base + n) else base in 128 + let exp = Z.((t.a + (u * x)) mod (n - one)) in 129 + let s = Z.powm base exp n in 130 + Ok (hash (bytes_of_z s)) 118 131 119 132 let compute_proof t ~salt ~big_b ~session_key = 120 - let h_n = hash (bytes_of_z n) in 121 - let h_g = hash (bytes_of_z g) in 122 - let h_xor = 123 - String.init (String.length h_n) (fun i -> 124 - Char.chr (Char.code h_n.[i] lxor Char.code h_g.[i])) 125 - in 126 133 let h_user = hash t.username in 127 - let n_len = (Z.numbits n + 7) / 8 in 128 134 hash 129 - (h_xor ^ h_user ^ salt 130 - ^ bytes_of_z ~pad:n_len t.big_a 131 - ^ bytes_of_z ~pad:n_len big_b 132 - ^ session_key) 135 + (hash_xor_ng ^ h_user ^ salt ^ pad_z t.big_a ^ pad_z big_b ^ session_key) 133 136 134 137 let verify_proof t ~m1 ~m2 ~session_key = 135 - let n_len = (Z.numbits n + 7) / 8 in 136 - let expected = hash (bytes_of_z ~pad:n_len t.big_a ^ m1 ^ session_key) in 138 + let expected = hash (pad_z t.big_a ^ m1 ^ session_key) in 137 139 String.equal expected m2 138 140 end 139 141 ··· 159 161 let salt t = t.salt 160 162 161 163 let compute_session_key t ~big_a = 162 - if Z.(equal (big_a mod n) zero) then Error (`Msg "Invalid A value") 163 - else 164 - let n_len = (Z.numbits n + 7) / 8 in 165 - let a_pad = bytes_of_z ~pad:n_len big_a in 166 - let b_pad = bytes_of_z ~pad:n_len t.big_b in 167 - let u = z_of_bytes (hash (a_pad ^ b_pad)) in 168 - if Z.(equal u zero) then Error (`Msg "Invalid u value") 169 - else 170 - (* S = (A * v^u)^b mod N *) 171 - let s = Z.(powm (big_a * powm t.verifier u n) t.b n) in 172 - let session_key = hash (bytes_of_z s) in 173 - Ok session_key 164 + let ( let* ) = Result.bind in 165 + let* () = 166 + if Z.(equal (big_a mod n) zero) then Error (`Msg "Invalid A value") 167 + else Ok () 168 + in 169 + let u = z_of_bytes (hash (pad_z big_a ^ pad_z t.big_b)) in 170 + let* () = 171 + if Z.(equal u zero) then Error (`Msg "Invalid u value") else Ok () 172 + in 173 + (* S = (A * v^u)^b mod N *) 174 + let s = Z.(powm (big_a * powm t.verifier u n) t.b n) in 175 + Ok (hash (bytes_of_z s)) 174 176 175 177 let verify_proof t ~big_a ~m1 ~session_key = 176 - let h_n = hash (bytes_of_z n) in 177 - let h_g = hash (bytes_of_z g) in 178 - let h_xor = 179 - String.init (String.length h_n) (fun i -> 180 - Char.chr (Char.code h_n.[i] lxor Char.code h_g.[i])) 181 - in 182 178 let h_user = hash t.username in 183 - let n_len = (Z.numbits n + 7) / 8 in 184 179 let expected = 185 180 hash 186 - (h_xor ^ h_user ^ t.salt 187 - ^ bytes_of_z ~pad:n_len big_a 188 - ^ bytes_of_z ~pad:n_len t.big_b 189 - ^ session_key) 181 + (hash_xor_ng ^ h_user ^ t.salt ^ pad_z big_a ^ pad_z t.big_b 182 + ^ session_key) 190 183 in 191 184 String.equal expected m1 192 185 193 186 let compute_proof _t ~big_a ~m1 ~session_key = 194 - let n_len = (Z.numbits n + 7) / 8 in 195 - hash (bytes_of_z ~pad:n_len big_a ^ m1 ^ session_key) 187 + hash (pad_z big_a ^ m1 ^ session_key) 196 188 end