mirror of
https://github.com/esiur/esiur-dotnet.git
synced 2026-06-13 14:38:43 +00:00
661 lines
32 KiB
C#
661 lines
32 KiB
C#
using Esiur.Misc;
|
|
using Esiur.Security.Permissions;
|
|
using Org.BouncyCastle.Crypto.Digests;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Text;
|
|
using Esiur.Data;
|
|
using Esiur.Data.Types;
|
|
|
|
namespace Esiur.Security.Authority.Providers
|
|
{
|
|
public class PasswordAuthenticationHandler : IAuthenticationHandler
|
|
{
|
|
public string Protocol => "hash";
|
|
|
|
|
|
byte[] _localNonce, _remoteNonce;
|
|
byte[] _localSalt, _remoteSalt;
|
|
|
|
string _initiatorIdentity, _responderIdentity;
|
|
|
|
byte[] _initiatorPassword, _responderPassword;
|
|
|
|
string _hostName, _domain;
|
|
|
|
int _step = 0;
|
|
|
|
AuthenticationMode _mode;
|
|
AuthenticationDirection _direction;
|
|
|
|
PasswordAuthenticationProvider _provider;
|
|
|
|
public IAuthenticationProvider Provider => _provider;
|
|
|
|
|
|
public static byte[] ComputeSha3(byte[] data, int bitLength = 256)
|
|
{
|
|
// 1. Initialize the digest (supports 224, 256, 384, 512)
|
|
var digest = new Sha3Digest(bitLength);
|
|
|
|
// 3. Update the digest with data
|
|
digest.BlockUpdate(data, 0, data.Length);
|
|
|
|
// 4. Retrieve the final hash
|
|
byte[] result = new byte[digest.GetDigestSize()];
|
|
digest.DoFinal(result, 0);
|
|
|
|
return result;
|
|
}
|
|
|
|
public AuthenticationResult Process(object authData)
|
|
{
|
|
Console.WriteLine($"PasswordAuthenticationHandler: {this.GetHashCode()} Step {_step}, Mode {_mode}, Direction {_direction}");
|
|
var remoteAuthData = (object[])authData;
|
|
var localAuthData = new List<object>();
|
|
|
|
if (_direction == AuthenticationDirection.Initiator)
|
|
{
|
|
if (_mode == AuthenticationMode.None)
|
|
{
|
|
_step = -1;
|
|
return new AuthenticationResult(AuthenticationRuling.Failed, null);
|
|
}
|
|
else if (_mode == AuthenticationMode.InitializerIdentity)
|
|
{
|
|
if (_step == 0)
|
|
{
|
|
// step 0: send local nonce and initiator identity.
|
|
if (_initiatorIdentity == null)
|
|
{
|
|
var identityPassword = _provider.GetSelfIdentityAndCredential(_domain, _hostName);
|
|
_initiatorIdentity = identityPassword.Identity;
|
|
_initiatorPassword = identityPassword.Password;
|
|
}
|
|
else
|
|
_initiatorPassword = _provider.GetSelfCredential(_initiatorIdentity, _domain, _hostName);
|
|
|
|
if (_initiatorPassword == null || _initiatorIdentity == null)
|
|
return new AuthenticationResult(AuthenticationRuling.Failed, null);
|
|
|
|
// send local nonce and initiator identity
|
|
localAuthData.Add(_localNonce);
|
|
localAuthData.Add(_initiatorIdentity);
|
|
|
|
_step = 1;
|
|
return new AuthenticationResult(AuthenticationRuling.InProgress, localAuthData);
|
|
|
|
}
|
|
else if (_step == 1)
|
|
{
|
|
if (remoteAuthData == null || remoteAuthData.Length < 3)
|
|
return new AuthenticationResult(AuthenticationRuling.Failed, null);
|
|
|
|
// expect remote nonce, salt and challenge.
|
|
_remoteNonce = (byte[])remoteAuthData[0];
|
|
_remoteSalt = (byte[])remoteAuthData[1];
|
|
var remoteChallenge = (byte[])remoteAuthData[2];
|
|
|
|
// prevent reply attack by checking if remote nonce is same as local nonce.
|
|
if (_remoteNonce.SequenceEqual(_localNonce))
|
|
{
|
|
_step = -1;
|
|
return new AuthenticationResult(AuthenticationRuling.Failed, null);
|
|
}
|
|
|
|
// make salted hash of password.
|
|
var hashedPassword = ComputeSha3(_initiatorPassword.Concat(_remoteSalt).ToArray());
|
|
|
|
|
|
var expectedRemoteChallenge = ComputeSha3(_remoteNonce.Concat(hashedPassword)
|
|
.Concat(_localNonce)
|
|
.ToArray());
|
|
|
|
// compare remote challenge
|
|
if (!remoteChallenge.SequenceEqual(expectedRemoteChallenge))
|
|
{
|
|
_step = -1;
|
|
return new AuthenticationResult(AuthenticationRuling.Failed, null);
|
|
}
|
|
|
|
// make hash challenge response.
|
|
var localChallenge = ComputeSha3(_localNonce.Concat(hashedPassword)
|
|
.Concat(_remoteNonce)
|
|
.ToArray());
|
|
|
|
localAuthData.Add(localChallenge);
|
|
_step = -1;
|
|
|
|
// derive a session key from nonces and password.
|
|
// initiator identity + initiator password + initiator nonce + responder nonce
|
|
|
|
var sessionKey = ComputeSha3(_initiatorIdentity.ToBytes()
|
|
.Concat(hashedPassword)
|
|
.Concat(_localNonce)
|
|
.Concat(_remoteNonce)
|
|
.ToArray(), 512);
|
|
|
|
return new AuthenticationResult(AuthenticationRuling.Succeeded, localAuthData, _initiatorIdentity, null, sessionKey);
|
|
}
|
|
else
|
|
{
|
|
return new AuthenticationResult(AuthenticationRuling.Failed, null);
|
|
}
|
|
}
|
|
else if (_mode == AuthenticationMode.ResponderIdentity)
|
|
{
|
|
if (_step == 0)
|
|
{
|
|
// just send local nonce.
|
|
localAuthData.Add(_localNonce);
|
|
return new AuthenticationResult(AuthenticationRuling.InProgress, localAuthData);
|
|
}
|
|
else if (_step == 1)
|
|
{
|
|
if (remoteAuthData == null || remoteAuthData.Length < 2)
|
|
return new AuthenticationResult(AuthenticationRuling.Failed, null);
|
|
|
|
// expect responder identity and nonce.
|
|
_remoteNonce = (byte[])remoteAuthData[0];
|
|
_responderIdentity = (string)remoteAuthData[1];
|
|
|
|
// prevent reply attack by checking if remote nonce is same as local nonce.
|
|
if (_remoteNonce.SequenceEqual(_localNonce))
|
|
{
|
|
_step = -1;
|
|
return new AuthenticationResult(AuthenticationRuling.Failed, null);
|
|
}
|
|
|
|
// check if responder identity is valid and get password.
|
|
var hostedAccountCredential = _provider.GetHostedAccountCredential(_responderIdentity, _domain);
|
|
_localSalt = hostedAccountCredential.Salt;
|
|
_responderPassword = hostedAccountCredential.Hash;
|
|
|
|
if (_responderPassword == null)
|
|
{
|
|
_step = -1;
|
|
return new AuthenticationResult(AuthenticationRuling.Failed, null);
|
|
}
|
|
|
|
// make hash challenge response.
|
|
var localChallenge = ComputeSha3(_localNonce.Concat(_responderPassword)
|
|
.Concat(_remoteNonce)
|
|
.ToArray());
|
|
// send localSalt and challenge
|
|
localAuthData.Add(_localSalt);
|
|
localAuthData.Add(localChallenge);
|
|
_step = 2;
|
|
|
|
return new AuthenticationResult(AuthenticationRuling.InProgress, localAuthData);
|
|
|
|
}
|
|
else if (_step == 2)
|
|
{
|
|
if (remoteAuthData == null || remoteAuthData.Length < 1)
|
|
return new AuthenticationResult(AuthenticationRuling.Failed, null);
|
|
|
|
// expect remote challenge.
|
|
var remoteChallenge = (byte[])remoteAuthData[0];
|
|
|
|
// compare remote challenge
|
|
|
|
var expectedRemoteChallenge = ComputeSha3(_remoteNonce.Concat(_responderPassword)
|
|
.Concat(_localNonce)
|
|
.ToArray());
|
|
|
|
if (!remoteChallenge.SequenceEqual(expectedRemoteChallenge))
|
|
{
|
|
_step = -1;
|
|
return new AuthenticationResult(AuthenticationRuling.Failed, null);
|
|
}
|
|
|
|
// derive a session key from nonces and password.
|
|
// responder identity + responder hashed password + initiator nonce + responder nonce
|
|
|
|
var sessionKey = ComputeSha3(_responderIdentity.ToBytes()
|
|
.Concat(_responderPassword)
|
|
.Concat(_localNonce)
|
|
.Concat(_remoteNonce)
|
|
.ToArray(), 512);
|
|
|
|
_step = -1;
|
|
return new AuthenticationResult(AuthenticationRuling.Succeeded, null, _initiatorIdentity, _responderIdentity, sessionKey);
|
|
|
|
}
|
|
else
|
|
{
|
|
return new AuthenticationResult(AuthenticationRuling.Failed, null);
|
|
}
|
|
}
|
|
else if (_mode == AuthenticationMode.DualIdentity)
|
|
{
|
|
if (_step == 0)
|
|
{
|
|
// step 0: send local nonce and initiator identity.
|
|
if (_initiatorIdentity == null)
|
|
{
|
|
var identityPassword = _provider.GetSelfIdentityAndCredential(_domain, _hostName);
|
|
_initiatorIdentity = identityPassword.Identity;
|
|
_initiatorPassword = identityPassword.Password;
|
|
}
|
|
else
|
|
_initiatorPassword = _provider.GetSelfCredential(_initiatorIdentity, _domain, _hostName);
|
|
|
|
if (_initiatorPassword == null || _initiatorIdentity == null)
|
|
{
|
|
return new AuthenticationResult(AuthenticationRuling.Failed, null);
|
|
}
|
|
|
|
localAuthData.Add(_localNonce);
|
|
localAuthData.Add(_initiatorIdentity);
|
|
return new AuthenticationResult(AuthenticationRuling.InProgress, localAuthData);
|
|
|
|
}
|
|
else if (_step == 1)
|
|
{
|
|
if (remoteAuthData == null || remoteAuthData.Length < 3)
|
|
return new AuthenticationResult(AuthenticationRuling.Failed, null);
|
|
|
|
// expect responder identity, nonce and salt.
|
|
_remoteNonce = (byte[])remoteAuthData[0];
|
|
_responderIdentity = (string)remoteAuthData[1];
|
|
_remoteSalt = (byte[])remoteAuthData[2];
|
|
|
|
// prevent reply attack by checking if remote nonce is same as local nonce.
|
|
if (_remoteNonce.SequenceEqual(_localNonce))
|
|
{
|
|
_step = -1;
|
|
return new AuthenticationResult(AuthenticationRuling.Failed, null);
|
|
}
|
|
|
|
// check if responder identity is valid and get password.
|
|
var hostedAccountCredential = _provider.GetHostedAccountCredential(_responderIdentity, _domain);
|
|
_localSalt = hostedAccountCredential.Salt;
|
|
_responderPassword = hostedAccountCredential.Hash;
|
|
|
|
if (_responderPassword == null)
|
|
{
|
|
_step = -1;
|
|
return new AuthenticationResult(AuthenticationRuling.Failed, null);
|
|
}
|
|
|
|
// make salted hash of password.
|
|
var hashedPassword = ComputeSha3(_initiatorPassword.Concat(_remoteSalt).ToArray());
|
|
|
|
// make hash challenge response.
|
|
var localChallenge = ComputeSha3(_localNonce.Concat(hashedPassword)
|
|
.Concat(_responderPassword)
|
|
.Concat(_remoteNonce)
|
|
.ToArray());
|
|
|
|
// send localSalt and challenge
|
|
localAuthData.Add(_localSalt);
|
|
localAuthData.Add(localChallenge);
|
|
_step = 2;
|
|
|
|
return new AuthenticationResult(AuthenticationRuling.InProgress, localAuthData);
|
|
|
|
}
|
|
else if (_step == 2)
|
|
{
|
|
if (remoteAuthData == null || remoteAuthData.Length < 1)
|
|
return new AuthenticationResult(AuthenticationRuling.Failed, null);
|
|
|
|
// expect remote challenge.
|
|
var remoteChallenge = (byte[])remoteAuthData[0];
|
|
|
|
// make salted hash of password.
|
|
var hashedPassword = ComputeSha3(_initiatorPassword.Concat(_remoteSalt).ToArray());
|
|
|
|
// compare remote challenge
|
|
var expectedRemoteChallenge = ComputeSha3(_remoteNonce.Concat(hashedPassword)
|
|
.Concat(_responderPassword)
|
|
.Concat(_localNonce)
|
|
.ToArray());
|
|
|
|
if (!remoteChallenge.SequenceEqual(expectedRemoteChallenge))
|
|
{
|
|
_step = -1;
|
|
return new AuthenticationResult(AuthenticationRuling.Failed, null);
|
|
}
|
|
|
|
// derive a session key from nonces and password.
|
|
// responder identity + responder password + initiator nonce + responder nonce
|
|
|
|
var sessionKey = ComputeSha3(_initiatorIdentity.ToBytes()
|
|
.Concat(_responderIdentity.ToBytes())
|
|
.Concat(hashedPassword)
|
|
.Concat(_responderPassword)
|
|
.Concat(_localNonce)
|
|
.Concat(_remoteNonce)
|
|
.ToArray(), 512);
|
|
|
|
_step = -1;
|
|
return new AuthenticationResult(AuthenticationRuling.Succeeded, null, _initiatorIdentity, _responderIdentity, sessionKey);
|
|
|
|
}
|
|
else
|
|
{
|
|
return new AuthenticationResult(AuthenticationRuling.Failed, null);
|
|
}
|
|
|
|
}
|
|
}
|
|
else if (_direction == AuthenticationDirection.Responder)
|
|
{
|
|
if (_mode == AuthenticationMode.None)
|
|
{
|
|
_step = -1;
|
|
return new AuthenticationResult(AuthenticationRuling.Failed, null);
|
|
}
|
|
else if (_mode == AuthenticationMode.InitializerIdentity)
|
|
{
|
|
if (_step == 0)
|
|
{
|
|
if (remoteAuthData == null || remoteAuthData.Length < 2)
|
|
return new AuthenticationResult(AuthenticationRuling.Failed, null);
|
|
|
|
// step 0: expect remote nonce and initiator identity.
|
|
_remoteNonce = (byte[])remoteAuthData[0];
|
|
_initiatorIdentity = (string)remoteAuthData[1];
|
|
|
|
// prevent reply attack by checking if remote nonce is same as local nonce.
|
|
// @TODO: We can change our localNonce then send it
|
|
if (_remoteNonce.SequenceEqual(_localNonce))
|
|
{
|
|
_step = -1;
|
|
return new AuthenticationResult(AuthenticationRuling.Failed, null);
|
|
}
|
|
|
|
// get initiator password from provider.
|
|
var hostedAccountCredential = _provider.GetHostedAccountCredential(_initiatorIdentity, _domain);
|
|
_localSalt = hostedAccountCredential.Salt;
|
|
_initiatorPassword = hostedAccountCredential.Hash;
|
|
|
|
// account not found or no password for this account.
|
|
if (_initiatorPassword == null || _initiatorIdentity == null)
|
|
{
|
|
return new AuthenticationResult(AuthenticationRuling.Failed, null);
|
|
}
|
|
|
|
var localChallenge = ComputeSha3(_localNonce.Concat(_initiatorPassword)
|
|
.Concat(_remoteNonce)
|
|
.ToArray());
|
|
|
|
// send local nonce, salt and challenge.
|
|
localAuthData.Add(_localNonce);
|
|
localAuthData.Add(_localSalt);
|
|
localAuthData.Add(localChallenge);
|
|
|
|
_step = 1;
|
|
return new AuthenticationResult(AuthenticationRuling.InProgress,
|
|
localAuthData);
|
|
}
|
|
else if (_step == 1)
|
|
{
|
|
if (remoteAuthData == null || remoteAuthData.Length < 1)
|
|
return new AuthenticationResult(AuthenticationRuling.Failed, null);
|
|
|
|
// expect challenge response.
|
|
var remoteChallenge = (byte[])remoteAuthData[0];
|
|
|
|
var expectedRemoteChallenge = ComputeSha3(_remoteNonce.Concat(_initiatorPassword)
|
|
.Concat(_localNonce)
|
|
.ToArray());
|
|
// compare remote challenge
|
|
if (!expectedRemoteChallenge.SequenceEqual(remoteChallenge))
|
|
{
|
|
_step = -1;
|
|
return new AuthenticationResult(AuthenticationRuling.Failed, null);
|
|
}
|
|
|
|
// compute session key.
|
|
|
|
// derive a session key from nonces and password.
|
|
// initiator identity + initiator password + initiator nonce + responder nonce
|
|
|
|
var sessionKey = ComputeSha3(_initiatorIdentity.ToBytes()
|
|
.Concat(_initiatorPassword)
|
|
.Concat(_remoteNonce)
|
|
.Concat(_localNonce)
|
|
.ToArray(), 512);
|
|
|
|
_step = -1;
|
|
return new AuthenticationResult(AuthenticationRuling.Succeeded, null, _initiatorIdentity, _responderIdentity, sessionKey);
|
|
|
|
}
|
|
else
|
|
{
|
|
return new AuthenticationResult(AuthenticationRuling.Failed, null);
|
|
}
|
|
|
|
}
|
|
else if (_mode == AuthenticationMode.ResponderIdentity)
|
|
{
|
|
if (_step == 0)
|
|
{
|
|
if (remoteAuthData == null || remoteAuthData.Length < 1)
|
|
return new AuthenticationResult(AuthenticationRuling.Failed, null);
|
|
|
|
// step 0: receive remote nonce.
|
|
_remoteNonce = (byte[])remoteAuthData[0];
|
|
|
|
// prevent reply attack by checking if remote nonce is same as local nonce.
|
|
// @TODO: We can change our localNonce then send it
|
|
if (_remoteNonce.SequenceEqual(_localNonce))
|
|
{
|
|
_step = -1;
|
|
return new AuthenticationResult(AuthenticationRuling.Failed, null);
|
|
}
|
|
|
|
// get responder identity from provider.
|
|
if (_responderIdentity == null)
|
|
{
|
|
var identityPassword = _provider.GetSelfIdentityAndCredential(_domain, _hostName);
|
|
_responderIdentity = identityPassword.Identity;
|
|
_responderPassword = identityPassword.Password;
|
|
}
|
|
else
|
|
_responderPassword = _provider.GetSelfCredential(_responderIdentity, _domain, _hostName);
|
|
|
|
if (_responderPassword == null || _responderIdentity == null)
|
|
{
|
|
return new AuthenticationResult(AuthenticationRuling.Failed, null);
|
|
}
|
|
|
|
localAuthData.Add(_localNonce);
|
|
localAuthData.Add(_responderIdentity);
|
|
|
|
_step = 1;
|
|
// send local nonce and identity.
|
|
return new AuthenticationResult(AuthenticationRuling.InProgress,
|
|
localAuthData
|
|
);
|
|
}
|
|
else if (_step == 1)
|
|
{
|
|
|
|
if (remoteAuthData == null || remoteAuthData.Length < 2)
|
|
return new AuthenticationResult(AuthenticationRuling.Failed, null);
|
|
|
|
// expect remote salt and challenge.
|
|
_remoteSalt = (byte[])remoteAuthData[0];
|
|
var remoteChallenge = (byte[])remoteAuthData[1];
|
|
|
|
// compute expected challenge response.
|
|
var hashedPassword = ComputeSha3(_responderPassword.Concat(_remoteSalt).ToArray());
|
|
|
|
var expectedRemoteChallenge = ComputeSha3(_remoteNonce.Concat(hashedPassword)
|
|
.Concat(_localNonce)
|
|
.ToArray());
|
|
|
|
// compare remote challenge
|
|
if (!expectedRemoteChallenge.SequenceEqual(remoteChallenge))
|
|
{
|
|
_step = -1;
|
|
return new AuthenticationResult(AuthenticationRuling.Failed, null);
|
|
}
|
|
|
|
// compute our challenge response.
|
|
var localChallenge = ComputeSha3(_localNonce.Concat(hashedPassword)
|
|
.Concat(_remoteNonce)
|
|
.ToArray());
|
|
|
|
// derive a session key from nonces and password.
|
|
// responder identity + responder hashed password + initiator nonce + responder nonce
|
|
|
|
var sessionKey = ComputeSha3(_responderIdentity.ToBytes()
|
|
.Concat(hashedPassword)
|
|
.Concat(_remoteNonce)
|
|
.Concat(_localNonce)
|
|
.ToArray(), 512);
|
|
|
|
localAuthData.Add(localChallenge);
|
|
|
|
_step = -1;
|
|
return new AuthenticationResult(AuthenticationRuling.Succeeded, localAuthData, _responderIdentity, null, sessionKey);
|
|
}
|
|
else
|
|
{
|
|
return new AuthenticationResult(AuthenticationRuling.Failed, null);
|
|
}
|
|
|
|
}
|
|
else if (_mode == AuthenticationMode.DualIdentity)
|
|
{
|
|
if (_step == 0)
|
|
{
|
|
if (remoteAuthData == null || remoteAuthData.Length < 2)
|
|
return new AuthenticationResult(AuthenticationRuling.Failed, null);
|
|
|
|
// step 0: receive remote nonce and initiator identity.
|
|
_remoteNonce = (byte[])remoteAuthData[0];
|
|
_initiatorIdentity = (string)remoteAuthData[1];
|
|
|
|
// prevent reply attack by checking if remote nonce is same as local nonce.
|
|
// @TODO: We can change our localNonce then send it
|
|
if (_remoteNonce.SequenceEqual(_localNonce))
|
|
{
|
|
_step = -1;
|
|
return new AuthenticationResult(AuthenticationRuling.Failed, null);
|
|
}
|
|
|
|
// get responder identity from provider.
|
|
if (_responderIdentity == null)
|
|
{
|
|
var identityPassword = _provider.GetSelfIdentityAndCredential(_domain, _hostName);
|
|
_responderIdentity = identityPassword.Identity;
|
|
_responderPassword = identityPassword.Password;
|
|
}
|
|
else
|
|
_responderPassword = _provider.GetSelfCredential(_responderIdentity, _domain, _hostName);
|
|
|
|
if (_responderPassword == null || _responderIdentity == null)
|
|
{
|
|
return new AuthenticationResult(AuthenticationRuling.Failed, null);
|
|
}
|
|
|
|
// get initiator password from provider.
|
|
var hostedAccountCredential = _provider.GetHostedAccountCredential(_initiatorIdentity, _domain);
|
|
_localSalt = hostedAccountCredential.Salt;
|
|
_initiatorPassword = hostedAccountCredential.Hash;
|
|
|
|
// account not found or no password for this account.
|
|
if (_initiatorPassword == null || _initiatorIdentity == null)
|
|
{
|
|
return new AuthenticationResult(AuthenticationRuling.Failed, null);
|
|
}
|
|
|
|
// send local nonce, salt and responder identity.
|
|
localAuthData.Add(_localNonce);
|
|
localAuthData.Add(_localSalt);
|
|
localAuthData.Add(_responderIdentity);
|
|
|
|
_step = 1;
|
|
// send local nonce and identity.
|
|
return new AuthenticationResult(AuthenticationRuling.InProgress,
|
|
localAuthData
|
|
);
|
|
|
|
}
|
|
else if (_step == 1)
|
|
{
|
|
if (remoteAuthData == null || remoteAuthData.Length < 2)
|
|
return new AuthenticationResult(AuthenticationRuling.Failed, null);
|
|
|
|
// expect initiator salt and challenge.
|
|
var remoteSalt = (byte[])remoteAuthData[0];
|
|
var remoteChallenge = (byte[])remoteAuthData[1];
|
|
|
|
// compute expected challenge response.
|
|
var hashedPassword = ComputeSha3(_responderPassword.Concat(remoteSalt).ToArray());
|
|
|
|
// compare remote challenge
|
|
var expectedRemoteChallenge = ComputeSha3(_remoteNonce.Concat(_initiatorPassword)
|
|
.Concat(hashedPassword)
|
|
.Concat(_localNonce)
|
|
.ToArray());
|
|
|
|
// compare remote challenge
|
|
if (!expectedRemoteChallenge.SequenceEqual(remoteChallenge))
|
|
{
|
|
_step = -1;
|
|
return new AuthenticationResult(AuthenticationRuling.Failed, null);
|
|
}
|
|
|
|
// compute our challenge
|
|
var localChallenge = ComputeSha3(_localNonce.Concat(hashedPassword)
|
|
.Concat(_initiatorPassword)
|
|
.Concat(_remoteNonce)
|
|
.ToArray());
|
|
|
|
localAuthData.Add(localChallenge);
|
|
|
|
// derive a session key from nonces and password.
|
|
// responder identity + responder password + initiator nonce + responder nonce
|
|
|
|
var sessionKey = ComputeSha3(_initiatorIdentity.ToBytes()
|
|
.Concat(_responderIdentity.ToBytes())
|
|
.Concat(_initiatorPassword)
|
|
.Concat(hashedPassword)
|
|
.Concat(_remoteNonce)
|
|
.Concat(_localNonce)
|
|
.ToArray(), 512);
|
|
|
|
_step = -1;
|
|
return new AuthenticationResult(AuthenticationRuling.Succeeded, localAuthData, _initiatorIdentity, _responderIdentity, sessionKey);
|
|
|
|
}
|
|
else
|
|
{
|
|
return new AuthenticationResult(AuthenticationRuling.Failed, null);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
_step = -1;
|
|
return new AuthenticationResult(AuthenticationRuling.Failed, null);
|
|
}
|
|
|
|
public PasswordAuthenticationHandler(AuthenticationMode mode,
|
|
AuthenticationDirection direction,
|
|
string initiatorIdentity,
|
|
string responderIdentity,
|
|
string hostName,
|
|
string domain,
|
|
PasswordAuthenticationProvider provider)
|
|
{
|
|
_localNonce = Global.GenerateBytes(20);
|
|
|
|
this._provider = provider;
|
|
this._initiatorIdentity = initiatorIdentity;
|
|
this._responderIdentity = responderIdentity;
|
|
this._mode = mode;
|
|
this._direction = direction;
|
|
this._domain = domain;
|
|
this._hostName = hostName;
|
|
}
|
|
}
|
|
}
|