title: Manually decrypt data encrypted with MachineKey.Protect
body: <p>I am trying to manually decrypt data which was encrypted with MachineKey.Protect(). I am using AES and SHA1 algoritms.</p>
  
  <pre><code>        // unencrypted input in HEX: 010203
          // AES key in HEX: CCA0DC9874B3F9E679E0A576F77EDF9B121CAB2F9A363A4EAF99976F7B51FA89
          // want to decrypt this: A738E5F98920E37AB14C5F4332D4C7F0EC683680AAA0D34B806E75DECF04B7A3DB651E688B563F77BA107FB15990C88FB8023386
  </code></pre>
  
  <p>Here is an example. </p>
  
  <pre><code>        // Some input data
          var input = new byte[] { 1, 2, 3 };
  
          // this just works fine
          var protectedData = System.Web.Security.MachineKey.Protect(input, "ApplicationCookie", "v1");
  
          // protectedData  in hex: A738E5F98920E37AB14C5F4332D4C7F0EC683680AAA0D34B806E75DECF04B7A3DB651E688B563F77BA107FB15990C88FB8023386
  
          // works
          var unprotectedInput = System.Web.Security.MachineKey.Unprotect(protectedData, "ApplicationCookie", "v1");
  
          // now lets do it manually
          // in web.config machineKey is configured: AES and SHA1
  
          var algorithm = new AesManaged();
          algorithm.Padding = PaddingMode.PKCS7;
          algorithm.Mode = CipherMode.CBC;
          algorithm.KeySize = 256;
          algorithm.BlockSize = 128;
          var validationAlgorithm = new HMACSHA1();
  
          // this is the key from web.config
          var key = HexToBinary("CCA0DC9874B3F9E679E0A576F77EDF9B121CAB2F9A363A4EAF99976F7B51FA89");
  
          using (SymmetricAlgorithm encryptionAlgorithm = algorithm)
          {
              encryptionAlgorithm.Key = key;
              int offset = encryptionAlgorithm.BlockSize / 8; //16
              int buffer1Count = validationAlgorithm.HashSize / 8; // 20
              int count = checked(protectedData.Length - offset - buffer1Count); // 16
              byte[] numArray = new byte[offset];
              Buffer.BlockCopy((Array)protectedData, 0, (Array)numArray, 0, numArray.Length);
              encryptionAlgorithm.IV = numArray; // in HEX: A738E5F98920E37AB14C5F4332D4C7F0
              using (MemoryStream memoryStream = new MemoryStream())
              {
                  using (ICryptoTransform decryptor = encryptionAlgorithm.CreateDecryptor())
                  {
                      using (CryptoStream cryptoStream = new CryptoStream((Stream)memoryStream, decryptor, CryptoStreamMode.Write))
                      {
                          cryptoStream.Write(protectedData, offset, count);
  
                          // Padding is invalid and cannot be removed.
                          cryptoStream.FlushFinalBlock();
                          var result = memoryStream.ToArray();
                      }
                  }
              }
          }
  </code></pre>
  
  <p>I am getting an exception (padding is not right).</p>
  
  <p>I do not know what else to try...</p>
  
  <p>This is the code for MachineKey.Protect, <a href="https://msdn.microsoft.com/cs-cz/library/system.web.security.machinekey.protect(v=vs.110).aspx" rel="nofollow">https://msdn.microsoft.com/cs-cz/library/system.web.security.machinekey.protect(v=vs.110).aspx</a></p>
  
  <pre><code>    public byte[] Protect(byte[] clearData)
      {
        // this is AESManaged
        using (SymmetricAlgorithm encryptionAlgorithm = this._cryptoAlgorithmFactory.GetEncryptionAlgorithm())
        {
          // this is our key
          encryptionAlgorithm.Key = this._encryptionKey.GetKeyMaterial();
          if (this._predictableIV)
            encryptionAlgorithm.IV = CryptoUtil.CreatePredictableIV(clearData, encryptionAlgorithm.BlockSize);
          else
            encryptionAlgorithm.GenerateIV();
          byte[] iv = encryptionAlgorithm.IV;
          using (MemoryStream memoryStream = new MemoryStream())
          {
            memoryStream.Write(iv, 0, iv.Length);
            using (ICryptoTransform encryptor = encryptionAlgorithm.CreateEncryptor())
            {
              using (CryptoStream cryptoStream = new CryptoStream((Stream) memoryStream, encryptor, CryptoStreamMode.Write))
              {
                cryptoStream.Write(clearData, 0, clearData.Length);
                cryptoStream.FlushFinalBlock();
                using (KeyedHashAlgorithm validationAlgorithm = this._cryptoAlgorithmFactory.GetValidationAlgorithm())
                {
                  validationAlgorithm.Key = this._validationKey.GetKeyMaterial();
                  byte[] hash = validationAlgorithm.ComputeHash(memoryStream.GetBuffer(), 0, checked ((int) memoryStream.Length));
                  memoryStream.Write(hash, 0, hash.Length);
                  return memoryStream.ToArray();
                }
              }
            }
          }
        }
      }
  </code></pre>