jsrp
Version:
JavaScript SRP implementation
98 lines (70 loc) • 2.51 kB
text/coffeescript
transform = require './transform'
SRP = require './srp'
# This is a high-level client interface for the SRP protocol.
class Client
# Init generates the "a" value and stores it.
init: (options, callback) ->
@IBuf = Buffer.from options.username
@PBuf = Buffer.from options.password
length = options.length || 4096;
@srp = new SRP length
@srp.a (err, a) =>
@aInt = a
@ABuf = @srp.A a: @aInt
callback()
# Over-ride random "a" selection
debugInit: (options, callback) ->
@IBuf = Buffer.from options.username
@PBuf = Buffer.from options.password
length = options.length || 4096;
@srp = new SRP length
@aInt = transform.buffer.toBigInteger options.a
@ABuf = @srp.A a: @aInt
callback()
getPublicKey: () ->
return @ABuf.toString 'hex'
# Set the salt value. Salt should be provided in HEX format.
setSalt: (hexSalt) ->
@saltBuf = Buffer.from hexSalt, 'hex'
# Now that we have the salt, we can also calulate x.
@xInt = @srp.x I: @IBuf, P: @PBuf, salt: @saltBuf
# Set the server B value, B should be provided in hex as well.
# RFC 2945 states that we must abort authentication if B % N is zero.
setServerPublicKey: (hexB) ->
@BBuf = Buffer.from hexB, 'hex'
BBigInt = transform.buffer.toBigInteger @BBuf
if @srp.isZeroWhenModN BBigInt
throw Error 'Invalid B value, abort'
# We have been given B, which means we can calculate u.
@uInt = @srp.u A: @ABuf, B: @BBuf
# We can also calculate our secret.
@SBuf = @srp.clientS
B: transform.buffer.toBigInteger @BBuf
a: @aInt
u: @uInt
x: @xInt
# Once we have the secret, we can calculate K.
@KBuf = @srp.K S: @SBuf
# Get our M1 in Hex value to send to the server for verification.
getProof: () ->
@M1Buf = @srp.M1 A: @ABuf, B: @BBuf, K: @KBuf
return @M1Buf.toString 'hex'
# Allow us to verify the server's M2 response.
checkServerProof: (hexM2) ->
ServerM2Buf = Buffer.from hexM2, 'hex'
@M2Buf = @srp.M2 A: @ABuf, M: @M1Buf, K: @KBuf
result = @M2Buf.toString('hex') is ServerM2Buf.toString('hex')
return result
# Return the shared key K in hex format so that it can be used with other
# libraries.
getSharedKey: () ->
return @KBuf.toString 'hex'
createVerifier: (callback) ->
@srp.generateSalt (err, salt) =>
@saltBuf = salt
result = @srp.v I: @IBuf, P: @PBuf, salt: @saltBuf
result = result.toString 'hex'
callback null, verifier: result, salt: @getSalt()
getSalt: ->
return @saltBuf.toString 'hex'
module.exports = Client;