it-swarm.com.ru

Зашифруйте строку с помощью Bouncy Castle AES/CBC/PKCS7

Я искал повсюду пример кода о том, как зашифровать простую строку с шифрованием в заголовке, используя Bouncy Castle Framework.

Этот код будет выполняться в проекте Windows Universal . Мои предыдущие попытки шифрования с использованием встроенного API не удалось расшифровать на сервере.

Я попробовал это: что дает мне строку вроде: 

4pQUfomwVVsl68oQqWoWYNRmRM + CP + vNFXBNdkN6dZPQ34VZ35vsKn9Q7QGTDVOj + w5mqVYHnGuAOFOgdgl8kA ==

s = String.Format("{0}_{1}", s, DateTime.Now.ToString("ddMMyyyyHmmss"));
SymmetricKeyAlgorithmProvider algorithm = SymmetricKeyAlgorithmProvider.OpenAlgorithm(SymmetricAlgorithmNames.AesCbcPkcs7);
IBuffer keymaterial = CryptographicBuffer.ConvertStringToBinary("[Key]", BinaryStringEncoding.Utf8);
CryptographicKey KEY = algorithm.CreateSymmetricKey(keymaterial);
IBuffer IV = CryptographicBuffer.ConvertStringToBinary("[IV]", BinaryStringEncoding.Utf8);
IBuffer data = CryptographicBuffer.ConvertStringToBinary(s, BinaryStringEncoding.Utf8);
IBuffer output = CryptographicEngine.Encrypt(KEY, data, IV);
return CryptographicBuffer.EncodeToBase64String(output);

Сервер выполняет шифрование/дешифрование с

public static string Encrypt(string text, byte[] key, byte[] iv, int keysize = 128, int blocksize = 128, CipherMode cipher = CipherMode.CBC, PaddingMode padding = PaddingMode.PKCS7)
{
    AesCryptoServiceProvider aes = new AesCryptoServiceProvider();
    aes.BlockSize = blocksize;
    aes.KeySize = keysize;
    aes.Mode = cipher;
    aes.Padding = padding;

    byte[] src = Encoding.UTF8.GetBytes(text);
    using (ICryptoTransform encrypt = aes.CreateEncryptor(key, iv))
    {
        byte[] dest = encrypt.TransformFinalBlock(src, 0, src.Length);
        encrypt.Dispose();
        return Convert.ToBase64String(dest);
    }
}

public static string Decrypt(string text, byte[] key, byte[] iv, int keysize = 128, int blocksize = 128, CipherMode cipher = CipherMode.CBC, PaddingMode padding = PaddingMode.PKCS7)
{
    AesCryptoServiceProvider aes = new AesCryptoServiceProvider();
    aes.BlockSize = blocksize;
    aes.KeySize = keysize;
    aes.Mode = cipher;
    aes.Padding = padding;

    byte[] src = Convert.FromBase64String(text);
    using (ICryptoTransform decrypt = aes.CreateDecryptor(key, iv))
    {
        byte[] dest = decrypt.TransformFinalBlock(src, 0, src.Length);
        decrypt.Dispose();
        return Encoding.UTF8.GetString(dest); //Padding is invalid and cannot be removed. 
    }
}

Но это не удается, потому что:

Заполнение недействительно и не может быть удалено. 

Вот почему я хочу попробовать Bouncy Castle, но я не могу найти подходящий пример кода.

Правка

Я попытался использовать Bouncy Castle с кодом, указанным в ответе. Теперь я получаю сообщение об ошибке:

вектор инициализации должен иметь ту же длину, что и размер блока

byte[] inputBytes = Encoding.UTF8.GetBytes(s);
byte[] IV = Encoding.UTF8.GetBytes("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX");
byte[] key = Encoding.UTF8.GetBytes("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX");

//Set up
AesEngine engine = new AesEngine();
CbcBlockCipher blockCipher = new CbcBlockCipher(engine);
PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(blockCipher, new Pkcs7Padding());
Debug.WriteLine(IV.Length); //32
Debug.WriteLine(cipher.GetBlockSize()); //16
KeyParameter keyParam = new KeyParameter(key);
ParametersWithIV keyParamWithIv = new ParametersWithIV(keyParam, IV);


cipher.Init(true, keyParamWithIv); //Error Message thrown
byte[] outputBytes = new byte[cipher.GetOutputSize(inputBytes.Length)]; //cip
int length = cipher.ProcessBytes(inputBytes, outputBytes, 0);
cipher.DoFinal(outputBytes, length); //Do the final block
string encryptedInput = Convert.ToBase64String(outputBytes);

Длина на сервере составляет 128. Как я могу заставить его быть равным и одинаковой длины?

24
tim

Вот фрагменты, которые я использую. Он использует встроенную по умолчанию System.Security.Cryptography. Это не должно быть до нашей эры

    /// <summary>
    /// Encrypt a byte array using AES 128
    /// </summary>
    /// <param name="key">128 bit key</param>
    /// <param name="secret">byte array that need to be encrypted</param>
    /// <returns>Encrypted array</returns>
    public static byte[] EncryptByteArray(byte[] key, byte[] secret)
    {
        using (MemoryStream ms = new MemoryStream())
        {
            using (AesManaged cryptor = new AesManaged())
            {
                cryptor.Mode = CipherMode.CBC;
                cryptor.Padding = PaddingMode.PKCS7;
                cryptor.KeySize = 128;
                cryptor.BlockSize = 128;

                //We use the random generated iv created by AesManaged
                byte[] iv = cryptor.IV;

                using (CryptoStream cs = new CryptoStream(ms, cryptor.CreateEncryptor(key, iv), CryptoStreamMode.Write))
                {
                    cs.Write(secret, 0, secret.Length);
                }
                byte[] encryptedContent = ms.ToArray();

                //Create new byte array that should contain both unencrypted iv and encrypted data
                byte[] result = new byte[iv.Length + encryptedContent.Length];

                //copy our 2 array into one
                System.Buffer.BlockCopy(iv, 0, result, 0, iv.Length);
                System.Buffer.BlockCopy(encryptedContent, 0, result, iv.Length, encryptedContent.Length);

                return result;
            }
        }
    }

    /// <summary>
    /// Decrypt a byte array using AES 128
    /// </summary>
    /// <param name="key">key in bytes</param>
    /// <param name="secret">the encrypted bytes</param>
    /// <returns>decrypted bytes</returns>
    public static byte[] DecryptByteArray(byte[] key, byte[] secret)
    {
        byte[] iv = new byte[16]; //initial vector is 16 bytes
        byte[] encryptedContent = new byte[secret.Length - 16]; //the rest should be encryptedcontent

        //Copy data to byte array
        System.Buffer.BlockCopy(secret, 0, iv, 0, iv.Length);
        System.Buffer.BlockCopy(secret, iv.Length, encryptedContent, 0, encryptedContent.Length);

        using (MemoryStream ms = new MemoryStream())
        {
            using (AesManaged cryptor = new AesManaged())
            {
                cryptor.Mode = CipherMode.CBC;
                cryptor.Padding = PaddingMode.PKCS7;
                cryptor.KeySize = 128;
                cryptor.BlockSize = 128;

                using (CryptoStream cs = new CryptoStream(ms, cryptor.CreateDecryptor(key, iv), CryptoStreamMode.Write))
                {
                    cs.Write(encryptedContent, 0, encryptedContent.Length);

                }
                return ms.ToArray();
            }
        }
    }

Если вам действительно нужен BC, вот быстрый тест, который мне удастся написать на основе тестового набора от https://github.com/bcgit/bc-csharp/blob/master/crypto/test/src/crypto/test /AESFastTest.cs Вы можете настроить его для своих нужд

    private static void TestBC()
    {
        //Demo params
        string keyString = "jDxESdRrcYKmSZi7IOW4lw==";   

        string input = "abc";
        byte[] inputBytes = Encoding.UTF8.GetBytes(input);            
        byte[] iv = new byte[16]; //for the sake of demo

        //Set up
        AesEngine engine = new AesEngine();
        CbcBlockCipher blockCipher = new CbcBlockCipher(engine); //CBC
        PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(blockCipher); //Default scheme is PKCS5/PKCS7
        KeyParameter keyParam = new KeyParameter(Convert.FromBase64String(keyString));
        ParametersWithIV keyParamWithIV = new ParametersWithIV(keyParam, iv, 0, 16);

        // Encrypt
        cipher.Init(true, keyParamWithIV);
        byte[] outputBytes = new byte[cipher.GetOutputSize(inputBytes.Length)];
        int length = cipher.ProcessBytes(inputBytes, outputBytes, 0);
        cipher.DoFinal(outputBytes, length); //Do the final block
        string encryptedInput = Convert.ToBase64String(outputBytes);

        Console.WriteLine("Encrypted string: {0}", encryptedInput);

        //Decrypt            
        cipher.Init(false, keyParamWithIV);
        byte[] comparisonBytes = new byte[cipher.GetOutputSize(outputBytes.Length)];
        length = cipher.ProcessBytes(outputBytes, comparisonBytes, 0);
        cipher.DoFinal(comparisonBytes, length); //Do the final block

        Console.WriteLine("Decrypted string: {0}",Encoding.UTF8.GetString(comparisonBytes)); //Should be abc
    }
17
Eledra Nguyen

введите описание ссылки здесь

        byte[] k; //32 byte
        string para; // plaintext
        string msgRefNo; // 16byte

        byte[] inputBytes = Encoding.UTF8.GetBytes(para);
        byte[] IV = Encoding.UTF8.GetBytes(msgRefNo);
        byte[] key = k;


        AesEngine engine = new AesEngine();
        CbcBlockCipher blockCipher = new CbcBlockCipher(engine);
        PaddedBufferedBlockCipher cipher1 = new PaddedBufferedBlockCipher(blockCipher, new Pkcs7Padding());

        KeyParameter keyParam = new KeyParameter(key);
        ParametersWithIV keyParamWithIv = new ParametersWithIV(keyParam, IV);


        cipher1.Init(true, keyParamWithIv); //Error Message thrown
        byte[] outputBytes = new byte[cipher1.GetOutputSize(inputBytes.Length)]; //cip
        int length = cipher1.ProcessBytes(inputBytes, outputBytes, 0);
        cipher1.DoFinal(outputBytes, length); //Do the final block
        string encryptedInput = Convert.ToBase64String(outputBytes);
        return encryptedInput;
0
Arun Singh