/// <summary> /// Updates the user's breach-proof password by specified update token. /// </summary> /// <returns>The breach-proof password.</returns> /// <param name="breachProofPassword">Breach proof password.</param> /// <param name="updateToken">Update token.</param> public BreachProofPassword UpdateBreachProofPassword( string updateToken, BreachProofPassword breachProofPassword) { if (string.IsNullOrEmpty(updateToken)) { throw new ArgumentNullException(nameof(updateToken)); } if (breachProofPassword == null) { throw new ArgumentNullException(nameof(breachProofPassword)); } var parsedUpdateToken = this.TryParseUpdateToken(updateToken); if (breachProofPassword.Version == parsedUpdateToken.Item2) { throw new PythiaUpdatingException("This breach-proof password has already been updated"); } if (breachProofPassword.Version != parsedUpdateToken.Item1) { throw new PythiaUpdatingException("This breach-proof password version does not match this update token"); } var newDeblindedPassword = this.pythiaCrypto.UpdateDeblindedPassword( breachProofPassword.DeblindedPassword, parsedUpdateToken.Item3); return(new BreachProofPassword { DeblindedPassword = newDeblindedPassword, Version = parsedUpdateToken.Item2, Salt = breachProofPassword.Salt }); }
/// <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)); }