title: Problem Updating to .Net 6 - Encrypting String
body: <p>I'm using a string Encryption/Decryption class similar to the one provided <a href="https://stackoverflow.com/questions/10168240/encrypting-decrypting-a-string-in-c-sharp/10177020#10177020">here</a> as a solution.</p>
  <p>This worked well for me in .Net 5.<br />
  Now I wanted to update my project to .Net 6.</p>
  <p><strong>When using .Net 6, the decrypted string does get cut off a certain point depending on the length of the input string.</strong></p>
  <p>▶️ To make it easy to debug/reproduce my issue, I created a public repro Repository <a href="https://github.com/0ptim/EncryptionTesting" rel="noreferrer">here</a>.</p>
  <ul>
  <li>The encryption code is on purpose in a Standard 2.0 Project.</li>
  <li>Referencing this project are both a .Net 6 as well as a .Net 5 Console project.</li>
  </ul>
  <p>Both are calling the encryption methods with the exact same input of <code>&quot;12345678901234567890&quot;</code> with the path phrase of <code>&quot;nzv86ri4H2qYHqc&amp;m6rL&quot;</code>.</p>
  <p>.Net 5 output: <code>&quot;12345678901234567890&quot;</code><br />
  .Net 6 output: <code>&quot;1234567890123456&quot;</code></p>
  <p>The difference in length is <code>4</code>.</p>
  <p>I also looked at the <a href="https://docs.microsoft.com/en-us/dotnet/core/compatibility/6.0" rel="noreferrer">breaking changes for .Net 6</a>, but could not find something which guided me to a solution.</p>
  <p>I'm glad for any suggestions regarding my issue, thanks!</p>
  <p>Encryption Class</p>
  <pre><code>public static class StringCipher
  {
      // This constant is used to determine the keysize of the encryption algorithm in bits.
      // We divide this by 8 within the code below to get the equivalent number of bytes.
      private const int Keysize = 128;
  
      // This constant determines the number of iterations for the password bytes generation function.
      private const int DerivationIterations = 1000;
  
      public static string Encrypt(string plainText, string passPhrase)
      {
          // Salt and IV is randomly generated each time, but is preprended to encrypted cipher text
          // so that the same Salt and IV values can be used when decrypting.  
          var saltStringBytes = Generate128BitsOfRandomEntropy();
          var ivStringBytes = Generate128BitsOfRandomEntropy();
          var plainTextBytes = Encoding.UTF8.GetBytes(plainText);
          using (var password = new Rfc2898DeriveBytes(passPhrase, saltStringBytes, DerivationIterations))
          {
              var keyBytes = password.GetBytes(Keysize / 8);
              using (var symmetricKey = Aes.Create())
              {
                  symmetricKey.BlockSize = 128;
                  symmetricKey.Mode = CipherMode.CBC;
                  symmetricKey.Padding = PaddingMode.PKCS7;
                  using (var encryptor = symmetricKey.CreateEncryptor(keyBytes, ivStringBytes))
                  {
                      using (var memoryStream = new MemoryStream())
                      {
                          using (var cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write))
                          {
                              cryptoStream.Write(plainTextBytes, 0, plainTextBytes.Length);
                              cryptoStream.FlushFinalBlock();
                              // Create the final bytes as a concatenation of the random salt bytes, the random iv bytes and the cipher bytes.
                              var cipherTextBytes = saltStringBytes;
                              cipherTextBytes = cipherTextBytes.Concat(ivStringBytes).ToArray();
                              cipherTextBytes = cipherTextBytes.Concat(memoryStream.ToArray()).ToArray();
                              memoryStream.Close();
                              cryptoStream.Close();
                              return Convert.ToBase64String(cipherTextBytes);
                          }
                      }
                  }
              }
          }
      }
  
      public static string Decrypt(string cipherText, string passPhrase)
      {
          // Get the complete stream of bytes that represent:
          // [32 bytes of Salt] + [16 bytes of IV] + [n bytes of CipherText]
          var cipherTextBytesWithSaltAndIv = Convert.FromBase64String(cipherText);
          // Get the saltbytes by extracting the first 16 bytes from the supplied cipherText bytes.
          var saltStringBytes = cipherTextBytesWithSaltAndIv.Take(Keysize / 8).ToArray();
          // Get the IV bytes by extracting the next 16 bytes from the supplied cipherText bytes.
          var ivStringBytes = cipherTextBytesWithSaltAndIv.Skip(Keysize / 8).Take(Keysize / 8).ToArray();
          // Get the actual cipher text bytes by removing the first 64 bytes from the cipherText string.
          var cipherTextBytes = cipherTextBytesWithSaltAndIv.Skip((Keysize / 8) * 2).Take(cipherTextBytesWithSaltAndIv.Length - ((Keysize / 8) * 2)).ToArray();
  
          using (var password = new Rfc2898DeriveBytes(passPhrase, saltStringBytes, DerivationIterations))
          {
              var keyBytes = password.GetBytes(Keysize / 8);
              using (var symmetricKey = Aes.Create())
              {
                  symmetricKey.BlockSize = 128;
                  symmetricKey.Mode = CipherMode.CBC;
                  symmetricKey.Padding = PaddingMode.PKCS7;
                  using (var decryptor = symmetricKey.CreateDecryptor(keyBytes, ivStringBytes))
                  {
                      using (var memoryStream = new MemoryStream(cipherTextBytes))
                      {
                          using (var cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read))
                          {
                              var plainTextBytes = new byte[cipherTextBytes.Length];
                              var decryptedByteCount = cryptoStream.Read(plainTextBytes, 0, plainTextBytes.Length);
                              memoryStream.Close();
                              cryptoStream.Close();
                              return Encoding.UTF8.GetString(plainTextBytes, 0, decryptedByteCount);
                          }
                      }
                  }
              }
          }
      }
  
      private static byte[] Generate128BitsOfRandomEntropy()
      {
          var randomBytes = new byte[16]; // 16 Bytes will give us 128 bits.
          using (var rngCsp = RandomNumberGenerator.Create())
          {
              // Fill the array with cryptographically secure random bytes.
              rngCsp.GetBytes(randomBytes);
          }
          return randomBytes;
      }
  }
  </code></pre>
  <p>Calling code</p>
  <pre><code>var input = &quot;12345678901234567890&quot;;
  var inputLength = input.Length;
  var inputBytes = Encoding.UTF8.GetBytes(input);
  
  var encrypted = StringCipher.Encrypt(input, &quot;nzv86ri4H2qYHqc&amp;m6rL&quot;);
  
  var output = StringCipher.Decrypt(encrypted, &quot;nzv86ri4H2qYHqc&amp;m6rL&quot;);
  var outputLength = output.Length;
  var outputBytes = Encoding.UTF8.GetBytes(output);
  
  var lengthDiff = inputLength - outputLength;
  </code></pre>