Skip to content

Commit

Permalink
Rename Gem. Now SIRP (gem install sirp)
Browse files Browse the repository at this point in the history
  • Loading branch information
grempe committed May 13, 2016
1 parent f15580c commit 8a45757
Show file tree
Hide file tree
Showing 19 changed files with 178 additions and 171 deletions.
3 changes: 1 addition & 2 deletions .coco.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
2 changes: 1 addition & 1 deletion Gemfile
Original file line number Diff line number Diff line change
@@ -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
4 changes: 2 additions & 2 deletions LICENSE.txt
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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
Expand Down
31 changes: 20 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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.
Expand All @@ -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.
Expand All @@ -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,
Expand Down
2 changes: 1 addition & 1 deletion bin/console
Original file line number Diff line number Diff line change
@@ -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.
Expand Down
2 changes: 1 addition & 1 deletion examples/Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ source 'https://rubygems.org'
gem 'puma'
gem 'sinatra'
gem 'http'
gem 'srp-rb', path: '../'
gem 'sirp', path: '../'
2 changes: 1 addition & 1 deletion examples/README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Secure Remote Password : Example
# SiRP : Secure (interoperable) Remote Password : Example

## Install Ruby Dependencies

Expand Down
6 changes: 3 additions & 3 deletions examples/clients/ruby/client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
require 'bundler/setup'
require 'http'
require 'json'
require 'srp'
require 'sirp'
require 'logger'
logger = Logger.new $stdout

Expand All @@ -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"
Expand Down
8 changes: 4 additions & 4 deletions examples/server.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
require 'bundler/setup'
require 'sinatra'
require 'json'
require 'srp'
require 'sirp'
require 'logger'
logger = Logger.new $stdout

Expand All @@ -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 }
Expand Down Expand Up @@ -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)'
Expand All @@ -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}"

Expand Down
8 changes: 4 additions & 4 deletions lib/srp.rb → lib/sirp.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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'
20 changes: 10 additions & 10 deletions lib/srp/client.rb → lib/sirp/client.rb
Original file line number Diff line number Diff line change
@@ -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.
Expand All @@ -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
Expand Down
14 changes: 7 additions & 7 deletions lib/srp/srp.rb → lib/sirp/sirp.rb
Original file line number Diff line number Diff line change
@@ -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)
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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

Expand Down
26 changes: 13 additions & 13 deletions lib/srp/verifier.rb → lib/sirp/verifier.rb
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
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.
# Not part of the authentication process.
# Returns { <username>, <password verifier>, <salt> }
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.
Expand All @@ -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

Expand All @@ -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
Expand All @@ -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
3 changes: 3 additions & 0 deletions lib/sirp/version.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module SIRP
VERSION = '2.0.0'.freeze
end
1 change: 0 additions & 1 deletion lib/srp-rb.rb

This file was deleted.

3 changes: 0 additions & 3 deletions lib/srp/version.rb

This file was deleted.

Loading

0 comments on commit 8a45757

Please sign in to comment.