Class: SIRP::Verifier
Constant Summary
Constants included from SIRP
Instance Attribute Summary collapse
-
#A ⇒ Object
readonly
Returns the value of attribute A.
-
#b ⇒ Object
readonly
Returns the value of attribute b.
-
#B ⇒ Object
readonly
Returns the value of attribute B.
-
#g ⇒ Object
readonly
Returns the value of attribute g.
-
#H_AMK ⇒ Object
readonly
Returns the value of attribute H_AMK.
-
#hash ⇒ Object
readonly
Returns the value of attribute hash.
-
#k ⇒ Object
readonly
Returns the value of attribute k.
-
#K ⇒ Object
readonly
Returns the value of attribute K.
-
#M ⇒ Object
readonly
Returns the value of attribute M.
-
#N ⇒ Object
readonly
Returns the value of attribute N.
-
#S ⇒ Object
readonly
Returns the value of attribute S.
Instance Method Summary collapse
-
#generate_userauth(username, password) ⇒ Hash
Phase 0 ; Generate a verifier and salt client-side.
-
#get_challenge_and_proof(username, xverifier, xsalt, xaa) ⇒ Hash
Phase 1 : Step 2 : Create a challenge for the client, and a proof to be stored on the server for later use when verifying the client response.
-
#initialize(group = 2048) ⇒ Verifier
constructor
Select modulus (N), generator (g), and one-way hash function (SHA1 or SHA256).
-
#verify_session(proof, client_M) ⇒ String, false
Phase 2 : Step 2 : Use the server stored proof and the client provided ‘M’ value.
Methods included from SIRP
#H, #Ng, #calc_A, #calc_B, #calc_H_AMK, #calc_M, #calc_client_S, #calc_k, #calc_server_S, #calc_u, #calc_v, #calc_x, #hex_to_bytes, #mod_exp, #num_to_hex, #secure_compare, #sha_hex, #sha_str
Constructor Details
#initialize(group = 2048) ⇒ Verifier
Select modulus (N), generator (g), and one-way hash function (SHA1 or SHA256)
9 10 11 12 13 14 15 |
# File 'lib/sirp/verifier.rb', line 9 def initialize(group = 2048) raise ArgumentError, 'must be an Integer' unless group.is_a?(Integer) raise ArgumentError, 'must be a known group size' unless [1024, 1536, 2048, 3072, 4096, 6144, 8192].include?(group) @N, @g, @hash = Ng(group) @k = calc_k(@N, @g, hash) end |
Instance Attribute Details
#A ⇒ Object (readonly)
Returns the value of attribute A.
4 5 6 |
# File 'lib/sirp/verifier.rb', line 4 def A @A end |
#b ⇒ Object (readonly)
Returns the value of attribute b.
4 5 6 |
# File 'lib/sirp/verifier.rb', line 4 def b @b end |
#B ⇒ Object (readonly)
Returns the value of attribute B.
4 5 6 |
# File 'lib/sirp/verifier.rb', line 4 def B @B end |
#g ⇒ Object (readonly)
Returns the value of attribute g.
4 5 6 |
# File 'lib/sirp/verifier.rb', line 4 def g @g end |
#H_AMK ⇒ Object (readonly)
Returns the value of attribute H_AMK.
4 5 6 |
# File 'lib/sirp/verifier.rb', line 4 def H_AMK @H_AMK end |
#hash ⇒ Object (readonly)
Returns the value of attribute hash.
4 5 6 |
# File 'lib/sirp/verifier.rb', line 4 def hash @hash end |
#k ⇒ Object (readonly)
Returns the value of attribute k.
4 5 6 |
# File 'lib/sirp/verifier.rb', line 4 def k @k end |
#K ⇒ Object (readonly)
Returns the value of attribute K.
4 5 6 |
# File 'lib/sirp/verifier.rb', line 4 def K @K end |
#M ⇒ Object (readonly)
Returns the value of attribute M.
4 5 6 |
# File 'lib/sirp/verifier.rb', line 4 def M @M end |
#N ⇒ Object (readonly)
Returns the value of attribute N.
4 5 6 |
# File 'lib/sirp/verifier.rb', line 4 def N @N end |
#S ⇒ Object (readonly)
Returns the value of attribute S.
4 5 6 |
# File 'lib/sirp/verifier.rb', line 4 def S @S end |
Instance Method Details
#generate_userauth(username, password) ⇒ Hash
Phase 0 ; Generate a verifier and salt client-side. This should only be used during the initial user registration process. All three values should be provided as attributes in the user registration process. The verifier and salt should be persisted server-side. The verifier should be protected and never made public or given to any user. The salt should be returned to any user requesting it to start Phase 1 of the authentication process.
28 29 30 31 32 33 34 35 36 |
# File 'lib/sirp/verifier.rb', line 28 def generate_userauth(username, password) raise ArgumentError, 'username must be a string' unless username.is_a?(String) && !username.empty? raise ArgumentError, 'password must be a string' unless password.is_a?(String) && !password.empty? @salt ||= SecureRandom.hex(10) x = calc_x(username, password, @salt, hash) v = calc_v(x, @N, @g) { username: username, verifier: num_to_hex(v), salt: @salt } end |
#get_challenge_and_proof(username, xverifier, xsalt, xaa) ⇒ Hash
Phase 1 : Step 2 : Create a challenge for the client, and a proof to be stored on the server for later use when verifying the client response.
46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 |
# File 'lib/sirp/verifier.rb', line 46 def get_challenge_and_proof(username, xverifier, xsalt, xaa) raise ArgumentError, 'username must be a string' unless username.is_a?(String) && !username.empty? raise ArgumentError, 'xverifier must be a string' unless xverifier.is_a?(String) raise ArgumentError, 'xverifier must be a hex string' unless xverifier =~ /^[a-fA-F0-9]+$/ raise ArgumentError, 'xsalt must be a string' unless xsalt.is_a?(String) raise ArgumentError, 'xsalt must be a hex string' unless xsalt =~ /^[a-fA-F0-9]+$/ raise ArgumentError, 'xaa must be a string' unless xaa.is_a?(String) raise ArgumentError, 'xaa must be a hex string' unless xaa =~ /^[a-fA-F0-9]+$/ # SRP-6a safety check return false if (xaa.to_i(16) % @N).zero? # Generate b and B v = xverifier.to_i(16) @b ||= SecureRandom.hex(32).hex @B = num_to_hex(calc_B(@b, k, v, @N, @g)) { challenge: { B: @B, salt: xsalt }, proof: { A: xaa, B: @B, b: num_to_hex(@b), I: username, s: xsalt, v: xverifier } } end |
#verify_session(proof, client_M) ⇒ String, false
Phase 2 : Step 2 : Use the server stored proof and the client provided ‘M’ value. Calculates a server ‘M’ value and compares it to the client provided one, and if they match the client and server have negotiated equal secrets. Returns a H(A, M, K) value on success and false on failure.
Sets the @K value, which is the client and server negotiated secret key if verification succeeds. This can be used to derive strong encryption keys for later use. The client independently calculates the same @K value as well.
If authentication fails the H_AMK value must not be provided to the client.
87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 |
# File 'lib/sirp/verifier.rb', line 87 def verify_session(proof, client_M) raise ArgumentError, 'proof must be a hash' unless proof.is_a?(Hash) # gracefully handle string or symbol keys Hashie.symbolize_keys!(proof) raise ArgumentError, 'proof must have required hash keys' unless proof.keys == [:A, :B, :b, :I, :s, :v] raise ArgumentError, 'client_M must be a string' unless client_M.is_a?(String) raise ArgumentError, 'client_M must be a hex string' unless client_M =~ /^[a-fA-F0-9]+$/ @A = proof[:A] @B = proof[:B] @b = proof[:b].to_i(16) v = proof[:v].to_i(16) u = calc_u(@A, @B, @N, hash) # SRP-6a safety check return false if u.zero? # Calculate session key 'S' and secret key 'K' @S = num_to_hex(calc_server_S(@A.to_i(16), @b, v, u, @N)) @K = sha_hex(@S, hash) # Calculate the 'M' matcher @M = calc_M(@A, @B, @K, hash) # Secure constant time comparison, hash the params to ensure # that both strings being compared are equal length 32 Byte strings. if secure_compare(Digest::SHA256.hexdigest(@M), Digest::SHA256.hexdigest(client_M)) # Authentication succeeded, Calculate the H(A,M,K) verifier @H_AMK = num_to_hex(calc_H_AMK(@A, @M, @K, hash)) else # Authentication failed false end end |