From 44e430076e4ad1c9bde7345d700f44a4038b2c64 Mon Sep 17 00:00:00 2001 From: Glenn Rempe Date: Sun, 15 May 2016 10:05:01 -0700 Subject: [PATCH] Factor away Verifier#generate_B method which is not needed for the public API. --- lib/sirp/client.rb | 2 +- lib/sirp/verifier.rb | 13 +++------ ...thentication.rb => authentication_spec.rb} | 15 +++++----- spec/verifier_spec.rb | 28 ++++++++----------- 4 files changed, 23 insertions(+), 35 deletions(-) rename spec/{authentication.rb => authentication_spec.rb} (91%) diff --git a/lib/sirp/client.rb b/lib/sirp/client.rb index 6237882..ff15e2c 100644 --- a/lib/sirp/client.rb +++ b/lib/sirp/client.rb @@ -61,7 +61,7 @@ def process_challenge(username, password, xsalt, xbb) # @return [true,false] returns true if the server and client agree on the # H_AMK value, false if not def verify(server_HAMK) - return false unless @H_AMK + return false unless @H_AMK && server_HAMK # Secure constant time comparison, hash the params to ensure # that both strings being compared are equal length 32 Byte strings. secure_compare(Digest::SHA256.hexdigest(@H_AMK), Digest::SHA256.hexdigest(server_HAMK)) diff --git a/lib/sirp/verifier.rb b/lib/sirp/verifier.rb index 7ac56e3..134223e 100644 --- a/lib/sirp/verifier.rb +++ b/lib/sirp/verifier.rb @@ -39,7 +39,10 @@ def get_challenge_and_proof(username, xverifier, xsalt, xaa) # SRP-6a safety check return false if (xaa.to_i(16) % @N).zero? - generate_B(xverifier) + # 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 }, @@ -88,13 +91,5 @@ def verify_session(proof, client_M) false end end - - # @param xverifier [String] the server stored verifier for the username in hex - # @return [String] the B value in hex - def generate_B(xverifier) - v = xverifier.to_i(16) - @b ||= SecureRandom.hex(32).hex - @B = num_to_hex(calc_B(@b, k, v, @N, @g)) - end end end diff --git a/spec/authentication.rb b/spec/authentication_spec.rb similarity index 91% rename from spec/authentication.rb rename to spec/authentication_spec.rb index f89d89e..97b580e 100644 --- a/spec/authentication.rb +++ b/spec/authentication_spec.rb @@ -31,14 +31,14 @@ # phaase 1 (server) v = @auth[:verifier] salt = @auth[:salt] - bb = verifier.generate_B(v) - b = format('%x' % verifier.b) + + cp = verifier.get_challenge_and_proof(@username, v, salt, aa) # phase 2 (client) - client_M = client.process_challenge(@username, 'icnivad', salt, bb) + client_M = client.process_challenge(@username, 'icnivad', salt, cp[:proof][:B]) # phase 2 (server) - proof = { A: aa, B: bb, b: b, I: @username, s: salt, v: v } + proof = { A: aa, B: cp[:proof][:B], b: cp[:proof][:b], I: @username, s: salt, v: v } server_H_AMK = verifier.verify_session(proof, client_M) expect(server_H_AMK).to be_truthy @@ -56,14 +56,13 @@ # phaase 1 (server) v = @auth[:verifier] salt = @auth[:salt] - bb = verifier.generate_B(v) - b = format('%x' % verifier.b) + cp = verifier.get_challenge_and_proof(@username, v, salt, aa) # phase 2 (client) - client_M = client.process_challenge(@username, 'BAD PASSWORD', salt, bb) + client_M = client.process_challenge(@username, 'BAD PASSWORD', salt, cp[:proof][:B]) # phase 2 (server) - proof = { A: aa, B: bb, b: b, I: @username, s: salt, v: v } + proof = { A: aa, B: cp[:proof][:B], b: cp[:proof][:b], I: @username, s: salt, v: v } server_H_AMK = verifier.verify_session(proof, client_M) expect(server_H_AMK).to be false diff --git a/spec/verifier_spec.rb b/spec/verifier_spec.rb index 77abb81..08faba6 100644 --- a/spec/verifier_spec.rb +++ b/spec/verifier_spec.rb @@ -71,6 +71,17 @@ expect(cp[:proof].key?(:s)).to be true expect(cp[:proof].key?(:v)).to be true end + + it 'should generate expected B with predefined b' do + v = '321307d87ca3462f5b0cb5df295bea04498563794e5401899b2f32dd5cab5b7de9da78e7d62ea235e6d7f43a4ea09fea7c0dafdee6e79a1d12e2e374048deeaf5ba7c68e2ad952a3f5dc084400a7f1599a31d6d9d50269a9208db88f84090e8aa3c7b019f39529dcc19baa985a8d7ffb2d7628071d2313c9eaabc504d3333688' + verifier = SIRP::Verifier.new(1024) + @auth = verifier.generate_userauth('foo', 'bar') + verifier.set_b(@b.to_i(16)) + cp = verifier.get_challenge_and_proof(@username, v, @auth[:salt], @auth[:verifier]) + expect(('%b' % cp[:proof][:b].to_i(16)).length).to be > 200 + expect(('%b' % cp[:challenge][:B].to_i(16)).length).to be >= 1000 + expect(cp[:challenge][:B]).to eq '56777d24af1121bd6af6aeb84238ff8d250122fe75ed251db0f47c289642ae7adb9ef319ce3ab23b6ecc97e5904749fc42f12bb016ecf39691db541f066667b8399bfa685c82b03ad8f92f75975ed086dbe0d470d4dd907ce11b19ee41b74aee72bd8445cde6b58c01f678e39ed9cd6b93c79382637df90777a96c10a768c510' + end end context 'verify_session' do @@ -108,21 +119,4 @@ expect(verifier.H_AMK).to eq 'a93d906ef5c0a15a8e525da6a271692d2e553c72' end end - - context 'generate_B' do - it 'should generate B with predefined b' do - v = '321307d87ca3462f5b0cb5df295bea04498563794e5401899b2f32dd5cab5b7de9da78e7d62ea235e6d7f43a4ea09fea7c0dafdee6e79a1d12e2e374048deeaf5ba7c68e2ad952a3f5dc084400a7f1599a31d6d9d50269a9208db88f84090e8aa3c7b019f39529dcc19baa985a8d7ffb2d7628071d2313c9eaabc504d3333688' - verifier = SIRP::Verifier.new(1024) - verifier.set_b(@b.to_i(16)) - bb = verifier.generate_B(v) - expect(bb).to eq '56777d24af1121bd6af6aeb84238ff8d250122fe75ed251db0f47c289642ae7adb9ef319ce3ab23b6ecc97e5904749fc42f12bb016ecf39691db541f066667b8399bfa685c82b03ad8f92f75975ed086dbe0d470d4dd907ce11b19ee41b74aee72bd8445cde6b58c01f678e39ed9cd6b93c79382637df90777a96c10a768c510' - end - - it 'should generate B' do - verifier = SIRP::Verifier.new(1024) - bb = verifier.generate_B('0') - expect(('%b' % bb.to_i(16)).length).to be >= 1000 - expect(('%b' % verifier.b).length).to be > 200 - end - end end