diff --git a/.coco.yml b/.coco.yml index c088931..61a7d7d 100644 --- a/.coco.yml +++ b/.coco.yml @@ -2,7 +2,6 @@ - lib :exclude: - spec - - lib/srp/version.rb - - lib/srp-rb.rb + - lib/sirp/version.rb :theme: dark :show_link_in_terminal: true diff --git a/Gemfile b/Gemfile index c1d4293..a3741ff 100644 --- a/Gemfile +++ b/Gemfile @@ -1,4 +1,4 @@ source 'https://rubygems.org' -# Specify your gem's dependencies in srp.gemspec +# Specify your gem's dependencies in sirp.gemspec gemspec diff --git a/LICENSE.txt b/LICENSE.txt index eb40892..39fd603 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,4 +1,4 @@ -Copyright (c) 2012, Mikael Lammentausta +Copyright (c) 2016, Glenn Rempe, Mikael Lammentausta All rights reserved. Redistribution and use in source and binary forms, with or without @@ -15,7 +15,7 @@ modification, are permitted provided that the following conditions are met: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL Mikael Lammentausta BE LIABLE FOR ANY +DISCLAIMED. IN NO EVENT SHALL Glenn Rempe or Mikael Lammentausta BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND diff --git a/README.md b/README.md index 7e18adc..3de4ece 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,10 @@ -# Secure Remote Password +# SiRP : Secure (interoperable) Remote Password Authentication This is a pure Ruby implementation of the [Secure Remote Password](http://srp.stanford.edu/) protocol (SRP-6a), -a 'zero-knowledge' authentication system. +which is a 'zero-knowledge' mutual authentication system. -SRP is an authentication method that allows the use of user names and passwords +SiRP is an authentication method that allows the use of user names and passwords over an insecure network connection without revealing the password. If either the client lacks the user's password or the server lacks the proper verification key, the authentication will fail. This approach is much more secure than the @@ -15,7 +15,7 @@ attack would be of similar difficulty as deriving a private encryption key from its public key. Unlike other common challenge-response authentication protocols, such as -Kerberos and SSL, SRP does not rely on an external infrastructure of trusted +Kerberos and SSL, SiRP does not rely on an external infrastructure of trusted key servers or complex certificate management. ## Compatibility @@ -32,19 +32,19 @@ purposes. See the `examples` dir for simple working client and server implementations. ``` ruby -require 'srp' +require 'sirp' -username = "user" -password = "password" +username = 'user' +password = 'password' prime_length = 2048 # The salt and verifier should be stored on the server database. -@auth = SRP::Verifier.new(prime_length).generate_userauth(username, password) +@auth = SIRP::Verifier.new(prime_length).generate_userauth(username, password) # @auth is a hash containing :username, :verifier and :salt # ~~~ Begin Authentication ~~~ -client = SRP::Client.new(prime_length) +client = SIRP::Client.new(prime_length) A = client.start_authentication # Client => Server: username, A @@ -54,7 +54,7 @@ v = @auth[:verifier] salt = @auth[:salt] # Server generates challenge for the client. -verifier = SRP::Verifier.new(prime_length) +verifier = SIRP::Verifier.new(prime_length) session = verifier.get_challenge_and_proof(username, v, salt, A) # Server has to persist proof to authenticate the client response later. @@ -71,7 +71,7 @@ client_M = client.process_challenge(username, password, salt, B) # Client => Server: username, M # Instantiate a new verifier on the server. -verifier = SRP::Verifier.new(prime_length) +verifier = SIRP::Verifier.new(prime_length) # Verify challenge response M. # The Verifier state is passed in @proof. @@ -89,6 +89,15 @@ client.verify(server_H_AMK) == true ``` +## History + +This gem is a fork of the [lamikae/srp-rb](https://github.com/lamikae/srp-rb) +repository created by Mikael Lammentausta [@lamikae](https://github.com/lamikae). +Significant changes were needed for my use-case which demanded breaking changes +for the sake of greater interoperability. With these factors in mind, a hard +fork seemed the most appropriate path to take. Much credit is due to Mikael for +his original implementation. + ## Development After checking out the repo, run `bin/setup` to install dependencies. Then, diff --git a/bin/console b/bin/console index 6804439..d760260 100755 --- a/bin/console +++ b/bin/console @@ -1,7 +1,7 @@ #!/usr/bin/env ruby require 'bundler/setup' -require 'srp' +require 'sirp' # You can add fixtures and/or initialization code here to make experimenting # with your gem easier. You can also use a different console, if you like. diff --git a/examples/Gemfile b/examples/Gemfile index ca2fd77..2603afc 100644 --- a/examples/Gemfile +++ b/examples/Gemfile @@ -3,4 +3,4 @@ source 'https://rubygems.org' gem 'puma' gem 'sinatra' gem 'http' -gem 'srp-rb', path: '../' +gem 'sirp', path: '../' diff --git a/examples/README.md b/examples/README.md index eda2526..82452f1 100644 --- a/examples/README.md +++ b/examples/README.md @@ -1,4 +1,4 @@ -# Secure Remote Password : Example +# SiRP : Secure (interoperable) Remote Password : Example ## Install Ruby Dependencies diff --git a/examples/clients/ruby/client.rb b/examples/clients/ruby/client.rb index 56ebc2e..0fdef67 100755 --- a/examples/clients/ruby/client.rb +++ b/examples/clients/ruby/client.rb @@ -5,7 +5,7 @@ require 'bundler/setup' require 'http' require 'json' -require 'srp' +require 'sirp' require 'logger' logger = Logger.new $stdout @@ -16,12 +16,12 @@ # The salt and verifier should be stored on the server database. # In this example code these values are hard-coded in server.rb -# @auth = SRP::Verifier.new(prime_length).generate_userauth(username, password) +# @auth = SIRP::Verifier.new(prime_length).generate_userauth(username, password) # @auth is a hash containing :username, :verifier and :salt logger.info 'Start authentication' -client = SRP::Client.new(prime_length) +client = SIRP::Client.new(prime_length) A = client.start_authentication logger.info "Sending username: '#{username}' and A: '#{A}' to server" diff --git a/examples/server.rb b/examples/server.rb index eac44e9..fd4d18c 100755 --- a/examples/server.rb +++ b/examples/server.rb @@ -5,7 +5,7 @@ require 'bundler/setup' require 'sinatra' require 'json' -require 'srp' +require 'sirp' require 'logger' logger = Logger.new $stdout @@ -24,7 +24,7 @@ } user_verifiers = users.map do |username, password| - { username => SRP::Verifier.new(prime_length).generate_userauth(username, password) } + { username => SIRP::Verifier.new(prime_length).generate_userauth(username, password) } end user_verifiers.each { |h| users.update h } @@ -52,7 +52,7 @@ salt = user[:salt] # Server generates B, saves A and B to database - verifier = SRP::Verifier.new(prime_length) + verifier = SIRP::Verifier.new(prime_length) session = verifier.get_challenge_and_proof(username, v, salt, aa) logger.info 'P1 : Server persisting user verifier (proof)' @@ -72,7 +72,7 @@ proof = user[:session_proof] logger.info 'P2 : Verifying client/server M match, generating H_AMK' - verifier = SRP::Verifier.new(prime_length) + verifier = SIRP::Verifier.new(prime_length) server_H_AMK = verifier.verify_session(proof, client_M) logger.info "P2 : server M: #{verifier.M}" diff --git a/lib/srp.rb b/lib/sirp.rb similarity index 50% rename from lib/srp.rb rename to lib/sirp.rb index 48c1d92..5dc8c67 100644 --- a/lib/srp.rb +++ b/lib/sirp.rb @@ -2,7 +2,7 @@ require 'digest' require 'rbnacl/libsodium' require 'securer_randomer' -require 'srp/srp' -require 'srp/client' -require 'srp/verifier' -require 'srp/version' +require 'sirp/sirp' +require 'sirp/client' +require 'sirp/verifier' +require 'sirp/version' diff --git a/lib/srp/client.rb b/lib/sirp/client.rb similarity index 65% rename from lib/srp/client.rb rename to lib/sirp/client.rb index 844d929..25095fa 100644 --- a/lib/srp/client.rb +++ b/lib/sirp/client.rb @@ -1,17 +1,17 @@ -module SRP +module SIRP class Client attr_reader :N, :g, :k, :a, :A, :S, :K, :M, :H_AMK, :hash def initialize(group = 2048) # select modulus (N) and generator (g) - @N, @g, @hash = SRP.Ng(group) - @k = SRP.calc_k(@N, @g, hash) + @N, @g, @hash = SIRP.Ng(group) + @k = SIRP.calc_k(@N, @g, hash) end def start_authentication # Generate a/A private and public components @a ||= SecureRandom.hex(32).hex - @A = SRP.num_to_hex(SRP.calc_A(@a, @N, @g)) + @A = SIRP.num_to_hex(SIRP.calc_A(@a, @N, @g)) end # Process initiated authentication challenge. @@ -23,21 +23,21 @@ def process_challenge(username, password, xsalt, xbb) # SRP-6a safety check return false if (bb % @N) == 0 - x = SRP.calc_x(username, password, xsalt, hash) - u = SRP.calc_u(@A, xbb, @N, hash) + x = SIRP.calc_x(username, password, xsalt, hash) + u = SIRP.calc_u(@A, xbb, @N, hash) # SRP-6a safety check return false if u == 0 # calculate session key - @S = SRP.num_to_hex(SRP.calc_client_S(bb, @a, @k, x, u, @N, @g)) - @K = SRP.sha_hex(@S, hash) + @S = SIRP.num_to_hex(SIRP.calc_client_S(bb, @a, @k, x, u, @N, @g)) + @K = SIRP.sha_hex(@S, hash) # calculate match - @M = SRP.calc_M(@A, xbb, @K, hash) + @M = SIRP.calc_M(@A, xbb, @K, hash) # calculate verifier - @H_AMK = SRP.num_to_hex(SRP.calc_H_AMK(@A, @M, @K, hash)) + @H_AMK = SIRP.num_to_hex(SIRP.calc_H_AMK(@A, @M, @K, hash)) @M end diff --git a/lib/srp/srp.rb b/lib/sirp/sirp.rb similarity index 97% rename from lib/srp/srp.rb rename to lib/sirp/sirp.rb index 20d8558..88a1d64 100644 --- a/lib/srp/srp.rb +++ b/lib/sirp/sirp.rb @@ -1,4 +1,4 @@ -module SRP +module SIRP class << self # http://stackoverflow.com/questions/3772410/convert-a-string-of-0-f-into-a-byte-array-in-ruby def hex_to_bytes(str) @@ -30,7 +30,7 @@ def H(hash_klass, n, *a) hashin = a.map do |s| next unless s - shex = (s.class == String) ? s : SRP.num_to_hex(s) + shex = (s.class == String) ? s : num_to_hex(s) if shex.length > nlen raise 'Bit width does not match - client uses different prime' end @@ -41,7 +41,7 @@ def H(hash_klass, n, *a) end # Multiplier parameter - # k = H(N, g) (in SRP-6a) + # k = H(N, g) (in SIRP-6a) def calc_k(n, g, hash_klass) H(hash_klass, n, n, g) end @@ -90,15 +90,15 @@ def calc_server_S(aa, b, v, u, n) # M = H(A, B, K) def calc_M(xaa, xbb, xkk, hash_klass) digester = hash_klass.new - digester << SRP.hex_to_bytes(xaa).pack('C*') - digester << SRP.hex_to_bytes(xbb).pack('C*') - digester << SRP.hex_to_bytes(xkk).pack('C*') + digester << hex_to_bytes(xaa).pack('C*') + digester << hex_to_bytes(xbb).pack('C*') + digester << hex_to_bytes(xkk).pack('C*') digester.hexdigest end # H(A, M, K) def calc_H_AMK(xaa, xmm, xkk, hash_klass) - byte_string = SRP.hex_to_bytes([xaa, xmm, xkk].join('')).pack('C*') + byte_string = hex_to_bytes([xaa, xmm, xkk].join('')).pack('C*') sha_str(byte_string, hash_klass).hex end diff --git a/lib/srp/verifier.rb b/lib/sirp/verifier.rb similarity index 69% rename from lib/srp/verifier.rb rename to lib/sirp/verifier.rb index 80f3f1c..0da3a44 100644 --- a/lib/srp/verifier.rb +++ b/lib/sirp/verifier.rb @@ -1,11 +1,11 @@ -module SRP +module SIRP class Verifier attr_reader :N, :g, :k, :A, :B, :b, :S, :K, :M, :H_AMK, :hash def initialize(group = 2048) # select modulus (N) and generator (g) - @N, @g, @hash = SRP.Ng(group) - @k = SRP.calc_k(@N, @g, hash) + @N, @g, @hash = SIRP.Ng(group) + @k = SIRP.calc_k(@N, @g, hash) end # Initial user creation for the persistance layer. @@ -13,9 +13,9 @@ def initialize(group = 2048) # Returns { , , } def generate_userauth(username, password) @salt ||= SecureRandom.hex(10) - x = SRP.calc_x(username, password, @salt, hash) - v = SRP.calc_v(x, @N, @g) - { username: username, verifier: SRP.num_to_hex(v), salt: @salt } + x = SIRP.calc_x(username, password, @salt, hash) + v = SIRP.calc_v(x, @N, @g) + { username: username, verifier: SIRP.num_to_hex(v), salt: @salt } end # Authentication phase 1 - create challenge. @@ -28,7 +28,7 @@ def get_challenge_and_proof(username, xverifier, xsalt, xaa) { challenge: { B: @B, salt: xsalt }, - proof: { A: xaa, B: @B, b: SRP.num_to_hex(@b), I: username, s: xsalt, v: xverifier } + proof: { A: xaa, B: @B, b: SIRP.num_to_hex(@b), I: username, s: xsalt, v: xverifier } } end @@ -41,21 +41,21 @@ def verify_session(proof, client_M) @b = proof[:b].to_i(16) v = proof[:v].to_i(16) - u = SRP.calc_u(@A, @B, @N, hash) + u = SIRP.calc_u(@A, @B, @N, hash) # SRP-6a safety check return false if u == 0 # calculate session key - @S = SRP.num_to_hex(SRP.calc_server_S(@A.to_i(16), @b, v, u, @N)) - @K = SRP.sha_hex(@S, hash) + @S = SIRP.num_to_hex(SIRP.calc_server_S(@A.to_i(16), @b, v, u, @N)) + @K = SIRP.sha_hex(@S, hash) # calculate match - @M = SRP.calc_M(@A, @B, @K, hash) + @M = SIRP.calc_M(@A, @B, @K, hash) if @M == client_M # authentication succeeded - @H_AMK = SRP.num_to_hex(SRP.calc_H_AMK(@A, @M, @K, hash)) + @H_AMK = SIRP.num_to_hex(SIRP.calc_H_AMK(@A, @M, @K, hash)) else false end @@ -66,7 +66,7 @@ def verify_session(proof, client_M) def generate_B(xverifier) v = xverifier.to_i(16) @b ||= SecureRandom.hex(32).hex - @B = SRP.num_to_hex(SRP.calc_B(@b, k, v, @N, @g)) + @B = SIRP.num_to_hex(SIRP.calc_B(@b, k, v, @N, @g)) end end end diff --git a/lib/sirp/version.rb b/lib/sirp/version.rb new file mode 100644 index 0000000..03f0b42 --- /dev/null +++ b/lib/sirp/version.rb @@ -0,0 +1,3 @@ +module SIRP + VERSION = '2.0.0'.freeze +end diff --git a/lib/srp-rb.rb b/lib/srp-rb.rb deleted file mode 100644 index 5825536..0000000 --- a/lib/srp-rb.rb +++ /dev/null @@ -1 +0,0 @@ -require 'srp' diff --git a/lib/srp/version.rb b/lib/srp/version.rb deleted file mode 100644 index 100e720..0000000 --- a/lib/srp/version.rb +++ /dev/null @@ -1,3 +0,0 @@ -module SRP - VERSION = '1.0.2'.freeze -end diff --git a/srp.gemspec b/sirp.gemspec similarity index 64% rename from srp.gemspec rename to sirp.gemspec index f2b7fff..bb708a9 100644 --- a/srp.gemspec +++ b/sirp.gemspec @@ -1,24 +1,24 @@ # coding: utf-8 lib = File.expand_path('../lib', __FILE__) $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) -require 'srp/version' +require 'sirp/version' Gem::Specification.new do |spec| - spec.name = 'srp-rb' - spec.version = SRP::VERSION - spec.authors = ['lamikae'] - spec.email = [''] + spec.name = 'sirp' + spec.version = SIRP::VERSION + spec.authors = ['Glenn Rempe', 'lamikae'] + spec.email = ['glenn@rempe.us'] spec.required_ruby_version = '>= 2.1.0' - spec.summary = 'Secure Remote Password protocol SRP-6a' + spec.summary = 'Secure (interoperable) Remote Password Auth (SRP-6a)' spec.description = <<-EOF - Ruby implementation of the Secure Remote Password protocol (SRP-6a). - SRP is a cryptographically strong authentication protocol for + A Ruby implementation of the Secure Remote Password protocol (SRP-6a). + SiRP is a cryptographically strong authentication protocol for password-based, mutual authentication over an insecure network connection. EOF - spec.homepage = 'https://github.com/lamikae/srp-rb' + spec.homepage = 'https://github.com/grempe/sirp' # http://spdx.org/licenses/BSD-3-Clause.html spec.license = 'BSD-3-Clause' @@ -29,8 +29,8 @@ Gem::Specification.new do |spec| spec.require_paths = ['lib'] # See : https://bugs.ruby-lang.org/issues/9569 - spec.add_dependency 'rbnacl-libsodium', '~> 1.0' - spec.add_dependency 'securer_randomer', '~> 0.1.0' + spec.add_runtime_dependency 'rbnacl-libsodium', '~> 1.0' + spec.add_runtime_dependency 'securer_randomer', '~> 0.1.0' spec.add_development_dependency 'bundler', '~> 1.12' spec.add_development_dependency 'rake', '~> 11.0' diff --git a/spec/srp_spec.rb b/spec/sirp_spec.rb similarity index 78% rename from spec/srp_spec.rb rename to spec/sirp_spec.rb index d6f9642..abf9b02 100644 --- a/spec/srp_spec.rb +++ b/spec/sirp_spec.rb @@ -1,7 +1,7 @@ # encoding: utf-8 require 'spec_helper' -describe SRP do +describe SIRP do ### Test SRP functions. ### Values are from http://srp.stanford.edu/demo/demo.html ### using 256 bit values. @@ -21,36 +21,36 @@ a = 2988348162058574136915891421498819466320163312926952423791023078876139 b = 2351399303373464486466122544523690094744975233415544072992656881240319 m = 10 ** 40 - c = SRP.mod_exp(a, b, m) + c = SIRP.mod_exp(a, b, m) c.should == 1527229998585248450016808958343740453059 end it 'should hash correctly with H()' do a = 2988348162058574136915891421498819466320163312926952423791023078876139 b = 2351399303373464486466122544523690094744975233415544072992656881240319 - c = SRP.H(Digest::SHA1, a, b) + c = SIRP.H(Digest::SHA1, a, b) c.should == 870206349645559849154987479939336526106829135959 end it 'should raise an error when h() is given invalid args' do - expect { SRP.H(Digest::SHA1, 1, '123456789abcdef') }.to raise_error(RuntimeError, 'Bit width does not match - client uses different prime') + expect { SIRP.H(Digest::SHA1, 1, '123456789abcdef') }.to raise_error(RuntimeError, 'Bit width does not match - client uses different prime') end it 'should calculate k' do - k = SRP.calc_k(@N, @g, Digest::SHA1) + k = SIRP.calc_k(@N, @g, Digest::SHA1) ('%x' % k).should == 'dbe5dfe0704fee4c85ff106ecd38117d33bcfe50' ('%b' % k).length.should == 160 end it 'should calculate x' do - x = SRP.calc_x(@username, @password, @salt, Digest::SHA1) + x = SIRP.calc_x(@username, @password, @salt, Digest::SHA1) ('%x' % x).should == 'bdd0a4e1c9df4082684d8d358b8016301b025375' ('%b' % x).length.should == 160 end it 'should calculate verifier' do x = 'bdd0a4e1c9df4082684d8d358b8016301b025375'.to_i(16) - v = SRP.calc_v(x, @N, @g) + v = SIRP.calc_v(x, @N, @g) ('%x' % v).should == 'ce36e101ed8c37ed98ba4e441274dabd1062f3440763eb98bd6058e5400b6309' ('%b' % v).length.should == 256 end @@ -58,13 +58,13 @@ it 'should calculate u' do aa = 'b1c4827b0ce416953789db123051ed990023f43b396236b86e12a2c69638fb8e' bb = 'fbc56086bb51e26ee1a8287c0a7f3fd4e067e55beb8530b869b10b961957ff68' - u = SRP.calc_u(aa, bb, @N, Digest::SHA1) + u = SIRP.calc_u(aa, bb, @N, Digest::SHA1) ('%x' % u).should == 'c60b17ddf568dd5743d0e3ba5621646b742432c5' ('%b' % u).length.should == 160 end it 'should calculate public client value A' do - aa = SRP.calc_A(@a, @N, @g) + aa = SIRP.calc_A(@a, @N, @g) ('%x' % aa).should == 'b1c4827b0ce416953789db123051ed990023f43b396236b86e12a2c69638fb8e' ('%b' % aa).length.should == 256 end @@ -72,7 +72,7 @@ it 'should calculate public server value B' do k = 'dbe5dfe0704fee4c85ff106ecd38117d33bcfe50'.to_i(16) v = 'ce36e101ed8c37ed98ba4e441274dabd1062f3440763eb98bd6058e5400b6309'.to_i(16) - bb = SRP.calc_B(@b, k, v, @N, @g) + bb = SIRP.calc_B(@b, k, v, @N, @g) ('%x' % bb).should == 'fbc56086bb51e26ee1a8287c0a7f3fd4e067e55beb8530b869b10b961957ff68' ('%b' % bb).length.should == 256 end @@ -83,7 +83,7 @@ x = 'bdd0a4e1c9df4082684d8d358b8016301b025375'.to_i(16) u = 'c60b17ddf568dd5743d0e3ba5621646b742432c5'.to_i(16) a = @a - ss = SRP.calc_client_S(bb, a, k, x, u, @N, @g) + ss = SIRP.calc_client_S(bb, a, k, x, u, @N, @g) ('%x' % ss).should == 'a606c182e364d2c15f9cdbeeeb63bb00c831d1da65eedc1414f21157d0312a5a' ('%b' % ss).length.should == 256 end @@ -93,7 +93,7 @@ v = 'ce36e101ed8c37ed98ba4e441274dabd1062f3440763eb98bd6058e5400b6309'.to_i(16) u = 'c60b17ddf568dd5743d0e3ba5621646b742432c5'.to_i(16) b = @b - ss = SRP.calc_server_S(aa, b, v, u, @N) + ss = SIRP.calc_server_S(aa, b, v, u, @N) ('%x' % ss).should == 'a606c182e364d2c15f9cdbeeeb63bb00c831d1da65eedc1414f21157d0312a5a' ('%b' % ss).length.should == 256 end @@ -102,9 +102,9 @@ xaa = 'b1c4827b0ce416953789db123051ed990023f43b396236b86e12a2c69638fb8e' xbb = 'fbc56086bb51e26ee1a8287c0a7f3fd4e067e55beb8530b869b10b961957ff68' xss = 'a606c182e364d2c15f9cdbeeeb63bb00c831d1da65eedc1414f21157d0312a5a' - xkk = SRP.sha_hex(xss, Digest::SHA1) + xkk = SIRP.sha_hex(xss, Digest::SHA1) xkk.should == '5844898ea6e5f5d9b737bc0ba2fb9d5edd3f8e67' - mm = SRP.calc_M(xaa, xbb, xkk, Digest::SHA1) + mm = SIRP.calc_M(xaa, xbb, xkk, Digest::SHA1) mm.should == '0c6de5c7892a71bf971d733a511c44940e227941' end @@ -112,7 +112,7 @@ xaa = 'b1c4827b0ce416953789db123051ed990023f43b396236b86e12a2c69638fb8e' xmm = 'd597503056af882d5b27b419302ac7b2ea9d7468' xkk = '5844898ea6e5f5d9b737bc0ba2fb9d5edd3f8e67' - h_amk = SRP.calc_H_AMK(xaa, xmm, xkk, Digest::SHA1) + h_amk = SIRP.calc_H_AMK(xaa, xmm, xkk, Digest::SHA1) ('%x' % h_amk).should == '530fccc1c4aa82ae5c5cdfa8bdec987c6032451d' end end @@ -122,64 +122,64 @@ ### context '@predefined-Ng' do it 'should raise an error on unknown verifier group size' do - expect { SRP::Verifier.new(1234) }.to raise_error(NotImplementedError, 'unknown group size') + expect { SIRP::Verifier.new(1234) }.to raise_error(NotImplementedError, 'unknown group size') end it 'should be 1024 bits' do - srp = SRP::Verifier.new(1024) - nn = srp.N + verifier = SIRP::Verifier.new(1024) + nn = verifier.N ('%x' % nn).should == 'eeaf0ab9adb38dd69c33f80afa8fc5e86072618775ff3c0b9ea2314c9c256576d674df7496ea81d3383b4813d692c6e0e0d5d8e250b98be48e495c1d6089dad15dc7d7b46154d6b6ce8ef4ad69b15d4982559b297bcf1885c529f566660e57ec68edbc3c05726cc02fd4cbf4976eaa9afd5138fe8376435b9fc61d2fc0eb06e3' ('%b' % nn).length.should == 1024 - srp.g.should == 2 - srp.hash.should == Digest::SHA1 + verifier.g.should == 2 + verifier.hash.should == Digest::SHA1 end it 'should be 1536 bits' do - srp = SRP::Verifier.new(1536) - nn = srp.N + verifier = SIRP::Verifier.new(1536) + nn = verifier.N ('%b' % nn).length.should == 1536 - srp.g.should == 2 - srp.hash.should == Digest::SHA1 + verifier.g.should == 2 + verifier.hash.should == Digest::SHA1 end it 'should be 2048 bits' do - srp = SRP::Verifier.new(2048) - nn = srp.N + verifier = SIRP::Verifier.new(2048) + nn = verifier.N ('%b' % nn).length.should == 2048 - srp.g.should == 2 - srp.hash.should == Digest::SHA256 + verifier.g.should == 2 + verifier.hash.should == Digest::SHA256 end it 'should be 3072 bits' do - srp = SRP::Verifier.new(3072) - nn = srp.N + verifier = SIRP::Verifier.new(3072) + nn = verifier.N ('%b' % nn).length.should == 3072 - srp.g.should == 5 - srp.hash.should == Digest::SHA256 + verifier.g.should == 5 + verifier.hash.should == Digest::SHA256 end it 'should be 4096 bits' do - srp = SRP::Verifier.new(4096) - nn = srp.N + verifier = SIRP::Verifier.new(4096) + nn = verifier.N ('%b' % nn).length.should == 4096 - srp.g.should == 5 - srp.hash.should == Digest::SHA256 + verifier.g.should == 5 + verifier.hash.should == Digest::SHA256 end it 'should be 6144 bits' do - srp = SRP::Verifier.new(6144) - nn = srp.N + verifier = SIRP::Verifier.new(6144) + nn = verifier.N ('%b' % nn).length.should == 6144 - srp.g.should == 5 - srp.hash.should == Digest::SHA256 + verifier.g.should == 5 + verifier.hash.should == Digest::SHA256 end it 'should be 8192 bits' do - srp = SRP::Verifier.new(8192) - nn = srp.N + verifier = SIRP::Verifier.new(8192) + nn = verifier.N ('%b' % nn).length.should == 8192 - srp.g.should == 19 # decimal, is 13 (hex) in jsrp lib which is 19 decimal - srp.hash.should == Digest::SHA256 + verifier.g.should == 19 # decimal, is 13 (hex) in jsrp lib which is 19 decimal + verifier.hash.should == Digest::SHA256 end end @@ -197,21 +197,21 @@ end it 'should calculate k' do - k = SRP::Verifier.new(1024).k + k = SIRP::Verifier.new(1024).k k.should == '7556aa045aef2cdd07abaf0f665c3e818913186f'.to_i(16) end it 'should generate salt and verifier' do - auth = SRP::Verifier.new(1024).generate_userauth(@username, @password) + auth = SIRP::Verifier.new(1024).generate_userauth(@username, @password) auth[:username].should == @username auth[:verifier].should be auth[:salt].should be end it 'should calculate verifier with given salt' do - srp = SRP::Verifier.new(1024) - srp.set_salt @salt - auth = srp.generate_userauth(@username, @password) + verifier = SIRP::Verifier.new(1024) + verifier.set_salt @salt + auth = verifier.generate_userauth(@username, @password) v = auth[:verifier] salt = auth[:salt] salt.should == @salt @@ -219,8 +219,8 @@ end it 'should generate salt and calculate verifier' do - srp = SRP::Verifier.new(1024) - auth = srp.generate_userauth(@username, @password) + verifier = SIRP::Verifier.new(1024) + auth = verifier.generate_userauth(@username, @password) v = auth[:verifier] salt = auth[:salt] ('%b' % v.to_i(16)).length.should >= 1000 @@ -229,17 +229,17 @@ it 'should generate B with predefined b' do v = '321307d87ca3462f5b0cb5df295bea04498563794e5401899b2f32dd5cab5b7de9da78e7d62ea235e6d7f43a4ea09fea7c0dafdee6e79a1d12e2e374048deeaf5ba7c68e2ad952a3f5dc084400a7f1599a31d6d9d50269a9208db88f84090e8aa3c7b019f39529dcc19baa985a8d7ffb2d7628071d2313c9eaabc504d3333688' - srp = SRP::Verifier.new(1024) - srp.set_b @b.to_i(16) - bb = srp.generate_B(v) + verifier = SIRP::Verifier.new(1024) + verifier.set_b @b.to_i(16) + bb = verifier.generate_B(v) bb.should == '56777d24af1121bd6af6aeb84238ff8d250122fe75ed251db0f47c289642ae7adb9ef319ce3ab23b6ecc97e5904749fc42f12bb016ecf39691db541f066667b8399bfa685c82b03ad8f92f75975ed086dbe0d470d4dd907ce11b19ee41b74aee72bd8445cde6b58c01f678e39ed9cd6b93c79382637df90777a96c10a768c510' end it 'should generate B' do - srp = SRP::Verifier.new(1024) - bb = srp.generate_B('0') + verifier = SIRP::Verifier.new(1024) + bb = verifier.generate_B('0') ('%b' % bb.to_i(16)).length.should >= 1000 - ('%b' % srp.b).length.should > 200 + ('%b' % verifier.b).length.should > 200 end it 'should calculate server session and key' do @@ -250,11 +250,11 @@ # v is from db v = '321307d87ca3462f5b0cb5df295bea04498563794e5401899b2f32dd5cab5b7de9da78e7d62ea235e6d7f43a4ea09fea7c0dafdee6e79a1d12e2e374048deeaf5ba7c68e2ad952a3f5dc084400a7f1599a31d6d9d50269a9208db88f84090e8aa3c7b019f39529dcc19baa985a8d7ffb2d7628071d2313c9eaabc504d3333688' _proof = { A: aa, B: bb, b: @b, I: @username, s: @salt, v: v } - srp = SRP::Verifier.new(1024) - srp.verify_session(_proof, 'match insignificant') - ss = srp.S + verifier = SIRP::Verifier.new(1024) + verifier.verify_session(_proof, 'match insignificant') + ss = verifier.S ss.should == '7f44592cc616e0d761b2d3309d513b69b386c35f3ed9b11e6d43f15799b673d6dcfa4117b4456af978458d62ad61e1a37be625f46d2a5bd9a50aae359e4541275f0f4bd4b4caed9d2da224b491231f905d47abd9953179aa608854b84a0e0c6195e73715932b41ab8d0d4a2977e7642163be6802c5907fb9e233b8c96e457314' - kk = srp.K + kk = verifier.K kk.should == '404bf923682abeeb3c8c9164d2cdb6b6ba21b64d' end @@ -268,13 +268,13 @@ # S is validated ss = '7f44592cc616e0d761b2d3309d513b69b386c35f3ed9b11e6d43f15799b673d6dcfa4117b4456af978458d62ad61e1a37be625f46d2a5bd9a50aae359e4541275f0f4bd4b4caed9d2da224b491231f905d47abd9953179aa608854b84a0e0c6195e73715932b41ab8d0d4a2977e7642163be6802c5907fb9e233b8c96e457314' # K = H(S) - kk = SRP.sha_hex(ss, Digest::SHA1) + kk = SIRP.sha_hex(ss, Digest::SHA1) client_M = 'b2c4a9a9cf40fb2db67bbab4ebe36a50223e51e9' _proof = { A: aa, B: bb, b: @b, I: @username, s: @salt, v: v } - srp = SRP::Verifier.new(1024) - srp.verify_session(_proof, client_M) - srp.M.should == client_M - srp.H_AMK.should == 'a93d906ef5c0a15a8e525da6a271692d2e553c72' + verifier = SIRP::Verifier.new(1024) + verifier.verify_session(_proof, client_M) + verifier.M.should == client_M + verifier.H_AMK.should == 'a93d906ef5c0a15a8e525da6a271692d2e553c72' end end @@ -293,33 +293,33 @@ end it 'should generate A from random a' do - srp = SRP::Client.new(1024) - aa1 = srp.start_authentication + client = SIRP::Client.new(1024) + aa1 = client.start_authentication ('%b' % aa1.to_i(16)).length.should >= 1000 - ('%b' % srp.start_authentication.to_i(16)).length.should >= 200 - srp = SRP::Client.new(1024) - aa2 = srp.start_authentication + ('%b' % client.start_authentication.to_i(16)).length.should >= 200 + client = SIRP::Client.new(1024) + aa2 = client.start_authentication ('%b' % aa2.to_i(16)).length.should >= 1000 - ('%b' % srp.start_authentication.to_i(16)).length.should >= 200 + ('%b' % client.start_authentication.to_i(16)).length.should >= 200 aa1.should_not == aa2 end it 'should calculate A' do - srp = SRP::Client.new(1024) - srp.set_a @a.to_i(16) - aa = srp.start_authentication + client = SIRP::Client.new(1024) + client.set_a @a.to_i(16) + aa = client.start_authentication aa.should == '165366e23a10006a62fb8a0793757a299e2985103ad2e8cdee0cc37cac109f3f338ee12e2440eda97bfa7c75697709a5dc66faadca7806d43ea5839757d134ae7b28dd3333049198cc8d328998b8cd8352ff4e64b3bd5f08e40148d69b0843bce18cbbb30c7e4760296da5c92717fcac8bddc7875f55302e55d90a34226868d2' end it 'should calculate client session and key' do - srp = SRP::Client.new(1024) - srp.set_a @a.to_i(16) - aa = srp.start_authentication # created in phase 1 + client = SIRP::Client.new(1024) + client.set_a @a.to_i(16) + aa = client.start_authentication # created in phase 1 bb = '56777d24af1121bd6af6aeb84238ff8d250122fe75ed251db0f47c289642ae7adb9ef319ce3ab23b6ecc97e5904749fc42f12bb016ecf39691db541f066667b8399bfa685c82b03ad8f92f75975ed086dbe0d470d4dd907ce11b19ee41b74aee72bd8445cde6b58c01f678e39ed9cd6b93c79382637df90777a96c10a768c510' - mm = srp.process_challenge(@username, @password, @salt, bb) - ss = srp.S + mm = client.process_challenge(@username, @password, @salt, bb) + ss = client.S ss.should == '7f44592cc616e0d761b2d3309d513b69b386c35f3ed9b11e6d43f15799b673d6dcfa4117b4456af978458d62ad61e1a37be625f46d2a5bd9a50aae359e4541275f0f4bd4b4caed9d2da224b491231f905d47abd9953179aa608854b84a0e0c6195e73715932b41ab8d0d4a2977e7642163be6802c5907fb9e233b8c96e457314' - kk = srp.K + kk = client.K kk.should == '404bf923682abeeb3c8c9164d2cdb6b6ba21b64d' end end @@ -332,7 +332,7 @@ before :all do @username = 'leonardo' password = 'icnivad' - @auth = SRP::Verifier.new(1024).generate_userauth(@username, password) + @auth = SIRP::Verifier.new(1024).generate_userauth(@username, password) # imitate database persistance layer @db = { @@ -344,8 +344,8 @@ end it 'should authenticate' do - client = SRP::Client.new(1024) - verifier = SRP::Verifier.new(1024) + client = SIRP::Client.new(1024) + verifier = SIRP::Verifier.new(1024) # phase 1 # (client) aa = client.start_authentication @@ -366,8 +366,8 @@ end it 'should not authenticate' do - client = SRP::Client.new(1024) - verifier = SRP::Verifier.new(1024) + client = SIRP::Client.new(1024) + verifier = SIRP::Verifier.new(1024) # phase 1 # (client) aa = client.start_authentication @@ -389,7 +389,7 @@ username = @username # client generates A and begins authentication process - client = SRP::Client.new(1024) + client = SIRP::Client.new(1024) aa = client.start_authentication # @@ -403,14 +403,14 @@ salt = _user[:salt] # server generates B, saves A and B to database - srp = SRP::Verifier.new(1024) - _session = srp.get_challenge_and_proof username, v, salt, aa - _session[:challenge][:B].should == srp.B + verifier = SIRP::Verifier.new(1024) + _session = verifier.get_challenge_and_proof username, v, salt, aa + _session[:challenge][:B].should == verifier.B _session[:challenge][:salt].should == salt # store proof to memory _user[:session_proof] = _session[:proof] # clear variables to simulate end of phase 1 - srp = username = v = bb = salt = nil + verifier = username = v = bb = salt = nil # server sends salt and B client_response = _session[:challenge] @@ -435,8 +435,8 @@ _user = @db[username] # retrive session from database proof = _user[:session_proof] - srp = SRP::Verifier.new(1024) - verification = srp.verify_session(proof, client_M) + verifier = SIRP::Verifier.new(1024) + verification = verifier.verify_session(proof, client_M) verification.should_not == false # Now the two parties have a shared, strong session key K. diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index c701f48..eadf6d0 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -10,7 +10,7 @@ require 'coco' end -require 'srp' +require 'sirp' RSpec.configure do |config| config.expect_with :rspec do |c| @@ -21,7 +21,7 @@ end # Monkey-patch API to define a, b and salt presetters -module SRP +module SIRP class Verifier def set_b(val) @b = val @@ -33,7 +33,7 @@ def set_salt(val) end end -module SRP +module SIRP class Client def set_a(val) @a = val