/// <summary> /// Verifies the user's original password by specified breach-proof password. /// </summary>/// /// <param name="originalPassword">The original user's password</param> /// <param name="breachProofPassword"></param> /// <returns>Returns true if password is valid, otherwise false.</returns> public async Task <bool> VerifyBreachProofPasswordAsync(string originalPassword, BreachProofPassword breachProofPassword, bool prove = false) { if (string.IsNullOrEmpty(originalPassword)) { throw new ArgumentNullException(nameof(originalPassword)); } if (breachProofPassword == null) { throw new ArgumentNullException(nameof(breachProofPassword)); } var blindingResult = this.pythiaCrypto.Blind(originalPassword); var transformModel = new TransformModel { BlindedPassword = blindingResult.BlindedPassword, Salt = breachProofPassword.Salt, Version = breachProofPassword.Version, IncludeProof = prove }; var tokenContext = new TokenContext("pythia", "transform"); var token = await this.tokenProvider.GetTokenAsync(tokenContext).ConfigureAwait(false); var result = await this.client.TransformPasswordAsync( transformModel, token.ToString()).ConfigureAwait(false); if (prove) { var proofKey = this.proofKeys[breachProofPassword.Version]; var proofParams = new PythiaProofParams { TransformedPassword = result.TransformedPassword, TransformationPublicKey = proofKey, BlindedPassword = blindingResult.BlindedPassword, Tweak = breachProofPassword.Salt, ProofValueC = result.Proof.ValueC, ProofValueU = result.Proof.ValueU }; if (!this.pythiaCrypto.Verify(proofParams)) { throw new PythiaProofIsNotValidException(); } } var deblindedPassword = this.pythiaCrypto.Deblind( result.TransformedPassword, blindingResult.BlindingSecret); return(deblindedPassword.SequenceEqual(breachProofPassword.DeblindedPassword)); }
/// <summary> /// Creates a new breach-proof password for specified user's password. /// </summary> /// <param name="password">The user's password.</param> public async Task <BreachProofPassword> CreateBreachProofPasswordAsync(string password) { if (string.IsNullOrEmpty(password)) { throw new ArgumentNullException(nameof(password)); } var blindingResult = this.pythiaCrypto.Blind(password); var currentVersion = this.proofKeys.Keys.Max(); var currentProofKey = this.proofKeys[currentVersion]; var salt = this.pythiaCrypto.GenerateSalt(); var transformModel = new TransformModel { BlindedPassword = blindingResult.BlindedPassword, Salt = salt, Version = currentVersion, IncludeProof = true }; var tokenContext = new TokenContext("pythia", "transform"); var token = await this.tokenProvider.GetTokenAsync(tokenContext).ConfigureAwait(false); var result = await this.client.TransformPasswordAsync( transformModel, token.ToString()).ConfigureAwait(false); var proofParams = new PythiaProofParams { TransformedPassword = result.TransformedPassword, TransformationPublicKey = currentProofKey, BlindedPassword = blindingResult.BlindedPassword, Tweak = salt, ProofValueC = result.Proof.ValueC, ProofValueU = result.Proof.ValueU }; if (!this.pythiaCrypto.Verify(proofParams)) { throw new PythiaProofIsNotValidException(); } var deblindedPassword = this.pythiaCrypto.Deblind( result.TransformedPassword, blindingResult.BlindingSecret); return(new BreachProofPassword { DeblindedPassword = deblindedPassword, Salt = salt, Version = currentVersion }); }