/// <summary> /// Decrypt string data with a supported cipher, authenticate the cipher using a supported digest type, deviate the cipher password with a supported divination type, and, finally pad a cipher using a supported padding type. /// </summary> /// <param name="data">String data.</param> /// <param name="password">Cipher password. Will be deviated using the supplied divination type.</param> /// <param name="salt">Cipher salt to be used, should be proper format for the cipher type. (Note: Normally 8, or, 14 bytes)</param> /// <param name="secondaryVerifier">Secondary data you wish to use to validate the cipher. This is a secondary validation check. The cipher binary is already validated. (Note: This will increase the size of the cipher)</param> /// <returns>Byte data</returns> public static string FromEncryptionAtRest(this string data, string password, byte[] salt, string secondaryVerifier = null) { var iv = new UTF8Encoding().GetBytes(data.Substring(0, 16)); var key = password.ToHash(salt); var suspectedInputVerifier = data.Substring(data.Length - 32, data.Length); var input = new UTF8Encoding().GetBytes(data.Substring(16, data.Length - 32)); var expectedInputVerifier = input.ToHmac(key.Data, salt); if (!suspectedInputVerifier.Equals(expectedInputVerifier.Data)) { return string.Empty; } var cipher = CipherUtilities.GetCipher("AES/CBC/PKCS7"); cipher.Init(false, new ParametersWithIV(new KeyParameter(key.Data), iv)); var outputData = cipher.DoFinal(input); cipher.Reset(); var output = new UTF8Encoding().GetString(outputData); if (!string.IsNullOrEmpty(secondaryVerifier)) { var expectedVerifier = secondaryVerifier.ToHmac(key.Data, salt).Data.ToHex(); var suspectedVerifier = output.Substring(output.Length - 64, 64); if (!expectedVerifier.SequenceEqual(suspectedVerifier)) { return string.Empty; } output = output.Substring(0, output.Length - 64); } return output; }