Skip to content

Crystal implementation of the Secure Remote Password protocol (SRP-6a)

License

Notifications You must be signed in to change notification settings

spider-gazelle/secure-remote-password

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

5 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Secure Remote Password for Crystal Lang

CI

This is a pure Crystal implementation of the Secure Remote Password protocol (SRP-6a).

SRP is an authentication method that allows the use of user names and passwords over an insecure network connection without revealing the password. If the client side lacks the user's password or the server side lacks the proper verification key, the authentication will fail.

Unlike other common challenge-response autentication protocols, such as Kerberos and SSL, SRP does not rely on an external infrastructure of trusted key servers or certificate management.

HomeKit Accessory Protocol Specification (HAP)

HomeKit authentication is supported when using SHA-512, these changes are made to the SRP protocol:

  • SHA-512 is used as the hash function, replacing SHA-1
  • The Modulus, N, and Generator, g, are specified by the 3072-bit group of RFC 5054
  • The match, M, hash calculation is not padded

These changes improve security and are used as defaults

References

Installation

Add the dependency to your shard.yml:

  dependencies:
    secure-remote-password:
      github: spider-gazelle/secure-remote-password

Usage

require 'secure-remote-password'

username = "user"
password = "password"

# The username, verifier and salt should be stored in the server database
server_verifier = SecureRemotePassword::Verifier.new
auth = verifier.generate_user_verifier(username, password)
auth # => {username: username, verifier: ..., salt: ...}

# ~~~ Begin Authentication ~~~

client = SecureRemotePassword::Client.new(username, password)
client_a = client.start_authentication

# Send username and client_a to the server
# Client => Server: username, client_a

# Server retrieves user's verifier and salt from the database.
# auth = lookup_user(username)
salt = auth[:salt]
verifier = auth[:verifier]

# Server generates challenge for the client.
challenge, proof = server_verifier.get_challenge_and_proof(username, verifier, salt, client_a)

# Server sends the challenge containing salt and proof (B) to client.
# Server => Client: challenge.salt, challenge.proof (B)

# Client calculates match (M) as a response to the challenge.
client_m = client.process_challenge(challenge)

# Client => Server: username, client_m

# Verify challenge response M.
# The Verifier state is passed in proof (server should persist this during negotiation)
server_h_amk = verifier.verify_session(proof, client_m)
# is nil if authentication failed.


# At this point, the client and server should have a common session key
# that is secure (i.e. not known to an outside party).  To finish
# authentication, they must prove to each other that their keys are
# identical.


# server to send server_h_amk to the client
# Server => Client: server_h_amk

client.verify(server_h_amk) == true

Credit

The original SRP-6a work was done by lamikae in the srp-rb project. The HomeKit implementation by karlentwistle

About

Crystal implementation of the Secure Remote Password protocol (SRP-6a)

Resources

License

Stars

Watchers

Forks

Packages

No packages published