'm trying to encrypt a string on a server and have the string decrypted on another machine, I'm using the technique for encrypting the string found on another thread linked below - .NET Built-in Encrypt(AES)-Then-MAC(HMAC) Encrypt and decrypt a string
I get a "Padding is invalid and cannot be removed" error message if the string is encrypted on one server and I try to decrypt it on another.
I can not use any nuget packages for this code.
I I'm then sending the IV and Keyfile to a base64 string to store it, passing the base64 String into an application and trying to decrypt the string. This will work if I do the process on one machine.
- Encrypt the string and generate an IV + Key (or two key pair) 
- Convert all of the encrypted password information as a base64 string. 
- Convert the information back into byte[] and decrypt the password. - [TestMethod] public void EncryptAString() { byte[] ba_TestIV = AESThenHMAC.NewKey(); byte[] ba_TestKey = AESThenHMAC.NewKey(); string s_EncryptedPassword = AESThenHMAC.SimpleEncrypt("PassOrFailMessage", ba_TestIV, ba_TestKey); string s_TestIV = Convert.ToBase64String(ba_TestIV); string s_TestKey = Convert.ToBase64String(ba_TestKey); /*Everything Below This Point Is Run From A Different Application Which Is Passed The Three Base64 Strings */ string s_DecryptedString = AESThenHMAC.SimpleDecrypt(s_EncryptedPassword, Convert.FromBase64String(s_TestIV), Convert.FromBase64String(s_TestKey)); Assert.IsTrue(s_DecryptedString == "PassOrFailMessage"); }
This Test method should help clarify the steps I'm trying to achieve.
using the class provided in the other thread does anyone know if I can encrypt the string and decrypt it elsewhere without having a padding issue error?
Apologies for not including the referenced code. Please find below found in thread Encrypt and decrypt a string
https://gist.github.com/jbtule/4336842#file-aesgcm-cs
    /*
      * This work (Modern Encryption of a String C#, by James Tuley), 
     * identified by James Tuley, is free of known copyright restrictions.
      * https://gist.github.com/4336842
     * http://creativecommons.org/publicdomain/mark/1.0/ 
     */
    using System;
    using System.IO;
    using System.Security.Cryptography;
    using System.Text;
    namespace Encryption
    {
        public static class AESThenHMAC
        {
            private static readonly RandomNumberGenerator Random =
            RandomNumberGenerator.Create();
            //Preconfigured Encryption Parameters
            public static readonly int BlockBitSize = 128;
            public static readonly int KeyBitSize = 256;
            //Preconfigured Password Key Derivation Parameters
            public static readonly int SaltBitSize = 64;
            public static readonly int Iterations = 10000;
            public static readonly int MinPasswordLength = 12;
            /// <summary>
            /// Helper that generates a random key on each call.
            /// </summary>
            /// <returns></returns>
            public static byte[] NewKey()
            {
                var key = new byte[KeyBitSize / 8];
                Random.GetBytes(key);
                return key;
            }
            /// <summary>
            /// Simple Encryption (AES) then Authentication (HMAC) for a UTF8 Message.
            /// </summary>
            /// <param name="secretMessage">The secret message.</param>
            /// <param name="cryptKey">The crypt key.</param>
            /// <param name="authKey">The auth key.</param>
            /// <param name="nonSecretPayload">(Optional) Non-Secret Payload.</param>
            /// <returns>
            /// Encrypted Message
            /// </returns>
            /// <exception cref="System.ArgumentException">Secret Message Required!;secretMessage</exception>
            /// <remarks>
            /// Adds overhead of (Optional-Payload + BlockSize(16) + Message-Padded-To-Blocksize +  HMac-Tag(32)) * 1.33 Base64
            /// </remarks>
            public static string SimpleEncrypt(string secretMessage, byte[] cryptKey, byte[] authKey,
                               byte[] nonSecretPayload = null)
            {
                if (string.IsNullOrEmpty(secretMessage))
                    throw new ArgumentException("Secret Message Required!", "secretMessage");
                var plainText = Encoding.UTF8.GetBytes(secretMessage);
                var cipherText = SimpleEncrypt(plainText, cryptKey, authKey, nonSecretPayload);
                return Convert.ToBase64String(cipherText);
            }
            /// <summary>
            /// Simple Authentication (HMAC) then Decryption (AES) for a secrets UTF8 Message.
            /// </summary>
            /// <param name="encryptedMessage">The encrypted message.</param>
            /// <param name="cryptKey">The crypt key.</param>
            /// <param name="authKey">The auth key.</param>
            /// <param name="nonSecretPayloadLength">Length of the non secret payload.</param>
            /// <returns>
            /// Decrypted Message
            /// </returns>
            /// <exception cref="System.ArgumentException">Encrypted Message Required!;encryptedMessage</exception>
            public static string SimpleDecrypt(string encryptedMessage, byte[] cryptKey, byte[] authKey,
                               int nonSecretPayloadLength = 0)
            {
                if (string.IsNullOrWhiteSpace(encryptedMessage))
                    throw new ArgumentException("Encrypted Message Required!", "encryptedMessage");
                var cipherText = Convert.FromBase64String(encryptedMessage);
                var plainText = SimpleDecrypt(cipherText, cryptKey, authKey, nonSecretPayloadLength);
                return plainText == null ? null : Encoding.UTF8.GetString(plainText);
            }
            /// <summary>
            /// Simple Encryption (AES) then Authentication (HMAC) of a UTF8 message
            /// using Keys derived from a Password (PBKDF2).
            /// </summary>
            /// <param name="secretMessage">The secret message.</param>
            /// <param name="password">The password.</param>
            /// <param name="nonSecretPayload">The non secret payload.</param>
            /// <returns>
            /// Encrypted Message
            /// </returns>
            /// <exception cref="System.ArgumentException">password</exception>
            /// <remarks>
            /// Significantly less secure than using random binary keys.
            /// Adds additional non secret payload for key generation parameters.
            /// </remarks>
            public static byte[] SimpleEncrypt(byte[] secretMessage, byte[] cryptKey, byte[] authKey, byte[] nonSecretPayload = null)
            {
                //User Error Checks
                if (cryptKey == null || cryptKey.Length != KeyBitSize / 8)
                    throw new ArgumentException(String.Format("Key needs to be {0} bit!", KeyBitSize), "cryptKey");
                if (authKey == null || authKey.Length != KeyBitSize / 8)
                    throw new ArgumentException(String.Format("Key needs to be {0} bit!", KeyBitSize), "authKey");
                if (secretMessage == null || secretMessage.Length < 1)
                    throw new ArgumentException("Secret Message Required!", "secretMessage");
                //non-secret payload optional
                nonSecretPayload = nonSecretPayload ?? new byte[] { };
                byte[] cipherText;
                byte[] iv;
                using (var aes = new AesManaged
                {
                    KeySize = KeyBitSize,
                    BlockSize = BlockBitSize,
                    Mode = CipherMode.CBC,
                    Padding = PaddingMode.PKCS7
                })
                {
                    //Use random IV
                    aes.GenerateIV();
                    iv = aes.IV;
                    using (var encrypter = aes.CreateEncryptor(cryptKey, iv))
                    using (var cipherStream = new MemoryStream())
                    {
                        using (var cryptoStream = new CryptoStream(cipherStream, encrypter, CryptoStreamMode.Write))
                        using (var binaryWriter = new BinaryWriter(cryptoStream))
                        {
                            //Encrypt Data
                            binaryWriter.Write(secretMessage);
                        }
                        cipherText = cipherStream.ToArray();
                    }
                }
                //Assemble encrypted message and add authentication
                using (var hmac = new HMACSHA256(authKey))
                using (var encryptedStream = new MemoryStream())
                {
                    using (var binaryWriter = new BinaryWriter(encryptedStream))
                    {
                        //Prepend non-secret payload if any
                        binaryWriter.Write(nonSecretPayload);
                        //Prepend IV
                        binaryWriter.Write(iv);
                        //Write Ciphertext
                        binaryWriter.Write(cipherText);
                        binaryWriter.Flush();
                        //Authenticate all data
                        var tag = hmac.ComputeHash(encryptedStream.ToArray());
                        //Postpend tag
                        binaryWriter.Write(tag);
                    }
                    return encryptedStream.ToArray();
                }
            }
            public static byte[] SimpleDecrypt(byte[] encryptedMessage, byte[] cryptKey, byte[] authKey, int nonSecretPayloadLength = 0)
            {
                //Basic Usage Error Checks
                if (cryptKey == null || cryptKey.Length != KeyBitSize / 8)
                    throw new ArgumentException(String.Format("CryptKey needs to be {0} bit!", KeyBitSize), "cryptKey");
                if (authKey == null || authKey.Length != KeyBitSize / 8)
                    throw new ArgumentException(String.Format("AuthKey needs to be {0} bit!", KeyBitSize), "authKey");
                if (encryptedMessage == null || encryptedMessage.Length == 0)
                    throw new ArgumentException("Encrypted Message Required!", "encryptedMessage");
                using (var hmac = new HMACSHA256(authKey))
                {
                    var sentTag = new byte[hmac.HashSize / 8];
                    //Calculate Tag
                    var calcTag = hmac.ComputeHash(encryptedMessage, 0, encryptedMessage.Length - sentTag.Length);
                    var ivLength = (BlockBitSize / 8);
                    //if message length is to small just return null
                    if (encryptedMessage.Length < sentTag.Length + nonSecretPayloadLength + ivLength)
                        return null;
                    //Grab Sent Tag
                    Array.Copy(encryptedMessage, encryptedMessage.Length - sentTag.Length, sentTag, 0, sentTag.Length);
                    //Compare Tag with constant time comparison
                    var compare = 0;
                    for (var i = 0; i < sentTag.Length; i++)
                        compare |= sentTag[i] ^ calcTag[i];
                    //if message doesn't authenticate return null
                    if (compare != 0)
                        return null;
                    using (var aes = new AesManaged
                    {
                        KeySize = KeyBitSize,
                        BlockSize = BlockBitSize,
                        Mode = CipherMode.CBC,
                        Padding = PaddingMode.PKCS7
                    })
                    {
                        //Grab IV from message
                        var iv = new byte[ivLength];
                        Array.Copy(encryptedMessage, nonSecretPayloadLength, iv, 0, iv.Length);
                        using (var decrypter = aes.CreateDecryptor(cryptKey, iv))
                        using (var plainTextStream = new MemoryStream())
                        {
                            using (var decrypterStream = new CryptoStream(plainTextStream, decrypter, CryptoStreamMode.Write))
                            using (var binaryWriter = new BinaryWriter(decrypterStream))
                            {
                                //Decrypt Cipher Text from Message
                                binaryWriter.Write(
                                  encryptedMessage,
                                  nonSecretPayloadLength + iv.Length,
                                  encryptedMessage.Length - nonSecretPayloadLength - iv.Length - sentTag.Length
                                );
                            }
                            //Return Plain Text
                            return plainTextStream.ToArray();
                        }
                    }
                }
            }
        }
    }
