Ich habe überall nach Beispielcode gesucht, wie eine einfache Zeichenfolge mit der Verschlüsselung im Titel mit dem Bouncy Castle Framework verschlüsselt werden kann.
Dieser Code kann in einem Windows Universal-Projekt ausgeführt werden. Meine früheren Versuche, mit den Build-in-APIs zu verschlüsseln, konnten auf dem Server nicht entschlüsseln.
Ich habe folgendes versucht: was mir eine Zeichenfolge gibt:
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);
Der Server verschlüsselt/entschlüsselt mit
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.
}
}
Aber es scheitert, weil:
Das Auffüllen ist ungültig und kann nicht entfernt werden.
Deshalb möchte ich Bouncy Castle ausprobieren, finde aber keinen passenden Beispielcode.
Ich habe versucht, Bouncy Castle mit dem in der Antwort angegebenen Code zu verwenden. Nun bekomme ich den Fehler:
der Initialisierungsvektor muss die gleiche Länge wie die Blockgröße haben
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);
Die Länge auf dem Server beträgt 128. Wie kann ich erzwingen, dass er gleich und gleich lang ist?
Hier sind Ausschnitte, die ich benutze. Es verwendet den standardmäßig integrierten System.Security.Cryptography. Es muss nicht BC sein
/// <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();
}
}
}
Wenn Sie wirklich BC benötigen, ist hier ein kurzer Test, den ich basierend auf dem Testanzug von https://github.com/bcgit/bc-csharp/blob/master/crypto/test/src/crypto/test schreibe /AESFastTest.cs Sie können es an Ihre Bedürfnisse anpassen
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
}
Linkbeschreibung hier eingeben
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;