Error on encrypt a message using Elliptic curve - c#

when I encrypt a message using Elliptic curve by clicking on button1 several times (more than 10 times), I get the following error
index was outside the bounds of the array.
Code is given below:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using DiffieHellmanMerkle;
using System.Security.Cryptography;
using System.IO;
namespace TestEllipticCurveDiffieHellman
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
byte[] SecretA = null;
byte[] SecretB = null;
try
{
ECDiffieHellmanMerkle A = new ECDiffieHellmanMerkle(ECDHAlgorithm.ECDH_384);
ECDiffieHellmanMerkle B = new ECDiffieHellmanMerkle(ECDHAlgorithm.ECDH_384);
A.KeyDerivationFunction = ECDHKeyDerivationFunction.HASH;
B.KeyDerivationFunction = ECDHKeyDerivationFunction.HASH;
A.HashAlgorithm = DerivedKeyHashAlgorithm.SHA256_ALGORITHM;
B.HashAlgorithm = DerivedKeyHashAlgorithm.SHA256_ALGORITHM;
SecretA = A.RetrieveSecretKey(B.PublicKey);
SecretB = B.RetrieveSecretKey(A.PublicKey);
}
catch(Exception ex)
{
MessageBox.Show(ex.Message,"Win32 Error Message");
}
//Alice encrypts the message with her secret key
string SecretMessage = plain.Text;// "The owl of Minerva only flies at dusk.";
byte[] SecretMessageByteArray = Encoding.Unicode.GetBytes(SecretMessage);
string IVString = "initialV";
byte[] IVByteArray = Encoding.Unicode.GetBytes(IVString);
RijndaelManaged rijndael = new RijndaelManaged();
ICryptoTransform encryptor = rijndael.CreateEncryptor(SecretA, IVByteArray);
MemoryStream memoryStream = new MemoryStream();
CryptoStream cryptoStream = new CryptoStream(memoryStream, Encryptor,CryptoStreamMode.Write);
cryptoStream.Write(SecretMessageByteArray, 0, SecretMessageByteArray.Length);
cryptoStream.FlushFinalBlock();
byte[] cipherText = memoryStream.ToArray();
memoryStream.Close();
cryptoStream.Close();
Encrypted.Text = Encoding.Unicode.GetString(cipherText);
/* string strcipherTextUni = Encoding.Unicode.GetString(cipherText);
MessageBox.Show("Encrypted Unicode = " + strcipherTextUni.ToString());*/
//Bob decrypts the message with his secret key
ICryptoTransform decryptor = rijndael.CreateDecryptor(SecretB, IVByteArray);
memoryStream = new MemoryStream(cipherText);
cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read);
byte[] clearText = new byte[cipherText.Length];
int clearTextByteSize = cryptoStream.Read(clearText, 0, clearText.Length);
memoryStream.Close();
cryptoStream.Close();
this.Decrypted.Text = Encoding.Unicode.GetString(clearText, 0, clearTextByteSize);
}
}
}

Encrypted.Text = Encoding.Unicode.GetString(cipherText); is likely the culprit.
Random bytes are not character encoding. It might be that an unknown encoding is translated into a substitution or no character at all here. This will happen now and then (as encrypted text is indistinguishable from random).
Use base 64 encoding of the ciphertext instead, there are oodles of examples of how to do this on stackoverflow. Luckily for you the base 64 encoding/decoding is build into the .net API (are you receiving that, Oracle?).

Related

encrypt and decrypt string given key

I inherited the code below. Unfortunately, the decrypted value of hello_world is not:
hello world
but (in my case):
&�|ktR���ڼ��S����%��< ���8�
Any ideas? It also appears that the result is different every time, which is kind of obvious given the code. Could I change this so that I can send the data encryted once and then decrypt in the future again? Thanks!
Code:
using System;
using System.IO;
using System.Security.Cryptography;
namespace crypt
{
class Program
{
static void Main(string[] args)
{
var key = #"abcdefghijklmnopqrstuvw==";
using (var aesAlg = Aes.Create())
{
aesAlg.Mode = CipherMode.CBC;
aesAlg.Padding = PaddingMode.PKCS7;
aesAlg.Key = Convert.FromBase64String(key);
aesAlg.GenerateIV();
var encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);
var enc_hello_world = EncryptProperty(encryptor, "hello world");
var hello_world = DecryptProperty(encryptor, enc_hello_world);
}
}
private static string EncryptProperty(ICryptoTransform encryptor, string valueToEncrypt)
{
byte[] encrypted;
using (var msEncrypt = new MemoryStream())
{
using (var csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
{
using (var swEncrypt = new StreamWriter(csEncrypt))
{
swEncrypt.Write(valueToEncrypt);
}
encrypted = msEncrypt.ToArray();
}
}
return Convert.ToBase64String(encrypted);
}
private static string DecryptProperty(ICryptoTransform decryptor, string valueToDecrypt)
{
string decrypted;
using (var msDecrypt = new MemoryStream(Convert.FromBase64String(valueToDecrypt)))
{
using (var csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
{
using (var srDecrypt = new StreamReader(csDecrypt))
{
decrypted = srDecrypt.ReadToEnd();
}
}
}
return decrypted;
}
}
}
AES-CBC requires two variables to encode and decode data: key and IV (initialization vector). Initialization vector can be sent in plaintext and it doesn't result in worse security of your encryption.
aesAlg.GenerateIV();
This is where your IV gets created, you need to store this (I do this by prepending that to the resulting data) and then access it and set the IV when decrypting.
You could also use an empty IV but this will make it easier for attackers to expose your key, so this is not recommended.
Here is a good example of AES in C#: https://gist.github.com/mark-adams/87aa34da3a5ed48ed0c7 (it seems to be using the method I've mentioned).

C# - Problem with AES Decryption - always get null

I am trying to implement image steganography with LSB and everything works except decrypting.
There is my class responsible for encryption and decryption of strings below. Encrypting works fine but Decrypt method always returns null:
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
namespace WindowsFormsApp1
{
class Encryptor {
//text to encrypt or already decrypted
private String decryptedText = "";
//text to decrypt or already encrypted
private String encryptedText = "";
private String key = "";
public Encryptor setDecryptedText(String text)
{
decryptedText = text;
return this;
}
public Encryptor setEncryptedText(String text)
{
encryptedText = text;
return this;
}
public Encryptor setKey(String text)
{
key = text;
return this;
}
Byte[] getHash(Byte[] hash)
{
Byte[] newHash = new Byte[32];
for (int i = 0; i < 32; i++)
{
newHash[i] = hash[i];
}
return newHash;
}
Byte[] getIV(Byte[] hash)
{
Byte[] newHash = new Byte[16];
int j = 0;
for (int i = 32; i < 48; i++)
{
newHash[j++] = hash[i];
}
return newHash;
}
String EncryptAesManaged()
{
SHA512 shaM = new SHA512Managed();
Byte[] data = Encoding.UTF8.GetBytes(key);
Byte[] hash = shaM.ComputeHash(data);
try
{
return Encrypt(decryptedText, getHash(hash), getIV(hash));
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
return null;
}
String DecryptAesManaged()
{
SHA512 shaM = new SHA512Managed();
var data = Encoding.UTF8.GetBytes(key);
Byte[] hash = shaM.ComputeHash(data);
try
{
return Decrypt(Convert.FromBase64String(encryptedText), getHash(hash), getIV(hash));
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
return "";
}
String Encrypt(string plainText, byte[] Key, byte[] IV)
{
Byte[] encrypted;
using (RijndaelManaged aes = new RijndaelManaged())
{
aes.Mode = CipherMode.CBC;
aes.BlockSize = 128;
aes.KeySize = 256;
ICryptoTransform encryptor = aes.CreateEncryptor(Key, IV);
using (MemoryStream ms = new MemoryStream())
{
using (CryptoStream cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write))
{
using (StreamWriter sw = new StreamWriter(cs)) {
sw.Write(Encoding.UTF8.GetBytes(plainText));
cs.FlushFinalBlock();
encrypted = ms.ToArray();
}
}
}
aes.Clear();
}
return Convert.ToBase64String(encrypted);
}
string Decrypt(byte[] cipherText, byte[] Key, byte[] IV)
{
string plaintext = null;
using (RijndaelManaged aes = new RijndaelManaged())
{
aes.Mode = CipherMode.CBC;
aes.BlockSize = 128;
aes.KeySize = 256;
ICryptoTransform decryptor = aes.CreateDecryptor(Key, IV);
try
{
using (MemoryStream ms = new MemoryStream(cipherText))
using (CryptoStream cs = new CryptoStream(ms, decryptor, CryptoStreamMode.Read))
using (StreamReader reader = new StreamReader(cs))
{
plaintext = reader.ReadToEnd(); //Here get null
}
aes.Clear();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
return plaintext;
}
public String getEncrypted()
{
return EncryptAesManaged();
}
public String getDecrypted()
{
return DecryptAesManaged();
}
}
}
Why is Decrypt() returning null rather than the originally encrypted string?
You don't show how you use your Encryptor class, so your question doesn't quite include a Minimal, Complete, and Verifiable example. I was able to reproduce the problem with the following test harness:
public static void Test()
{
var key = "my key";
var plainText = "hello";
var encryptor = new Encryptor();
encryptor.setDecryptedText(plainText);
encryptor.setKey(key);
var encrypted = encryptor.getEncrypted();
Console.WriteLine(encrypted);
var deecryptor = new Encryptor();
deecryptor.setEncryptedText(encrypted);
deecryptor.setKey(key);
var decrypted = deecryptor.getDecrypted();
Console.WriteLine(decrypted);
Assert.IsTrue(plainText == decrypted);
}
Demo fiddle #1 here.
Given that, your code has 2 problems, both of which are actually in encryption rather than decryption.
Firstly, in Encrypt(string plainText, byte[] Key, byte[] IV), you are writing to the StreamWriter sw, then flushing the CryptoStream and returning the MemoryStream contents -- but you never flush or dispose sw, so its buffered contents are never forwarded to the underlying stream(s).
To fix this, your code should looks something like:
using (MemoryStream ms = new MemoryStream())
{
using (CryptoStream cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write))
{
using (StreamWriter sw = new StreamWriter(cs))
{
sw.Write(Encoding.UTF8.GetBytes(plainText));
}
}
encrypted = ms.ToArray();
}
Now getDecrypted() no longer returns a null result -- but instead returns a wrong result of "System.Byte[]", as shown in demo fiddle #2 here.
Secondly, again in Encrypt(...), you are effectively encoding your plainText twice at this line:
sw.Write(Encoding.UTF8.GetBytes(plainText));
Encoding.UTF8.GetBytes(plainText) converts the plain text to a byte array, but the StreamWriter is also intended to do this job, converting strings to bytes and passing them to the underlying stream. So, since you are not passing a string to Write(), the overload that gets called is StreamWriter.Write(Object):
Writes the text representation of an object to the text string or stream by calling the ToString() method on that object.
Thus what actually gets encrypted is the ToString() value of a byte array, which is "System.Byte[]".
To fix this, simply remove the call to Encoding.UTF8.GetBytes(plainText) and write the string directly. Thus your Encrypt() method should now look like:
static String Encrypt(string plainText, byte[] Key, byte[] IV)
{
string encrypted;
using (var aes = new RijndaelManaged())
{
aes.Mode = CipherMode.CBC;
aes.BlockSize = 128;
aes.KeySize = 256;
ICryptoTransform encryptor = aes.CreateEncryptor(Key, IV);
using (var ms = new MemoryStream())
{
using (var cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write, true))
{
using (var sw = new StreamWriter(cs))
{
sw.Write(plainText);
}
}
// Calling GetBuffer() avoids the extra allocation of ToArray().
encrypted = Convert.ToBase64String(ms.GetBuffer(), 0, checked((int)ms.Length));
}
aes.Clear();
}
return encrypted;
}
Demo fiddle #3 here that now passes successfully.
Disclaimer: this answer does not attempt to to review your code for security best practices such as secure setup of salt and IV.

Encrypting and Decrypting a file with AES generates a broken file

I'm trying to encrypt and decrypt a file using AES. The problem that I have is that when the file gets decrypted, it is broken and you can't open it. The original file has a length of 81.970 bytes and the decrypted file has a length of 81.984 bytes...so there are 14 bytes added for some reason. The problem could be in the way the file gets encrypted but I don't know what I'm doing wrong.
What am I missing here? Could it be the way I'm processing the password, the iv and the padding?
Thanks for your time!
This is the code I use to encrypt:
private AesManaged aesManaged;
private string filePathToEncrypt;
public Encrypt(AesManaged aesManaged, string filePathToEncrypt)
{
this.aesManaged = aesManaged;
this.filePathToEncrypt = filePathToEncrypt;
}
public void DoEncryption()
{
byte[] cipherTextBytes;
byte[] textBytes = File.ReadAllBytes(this.filePathToEncrypt);
using(ICryptoTransform encryptor = aesManaged.CreateEncryptor(aesManaged.Key, aesManaged.IV))
using (MemoryStream ms = new MemoryStream())
using (CryptoStream cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write))
{
cs.Write(textBytes, 0, textBytes.Length);
cs.FlushFinalBlock();
cipherTextBytes = ms.ToArray();
}
File.WriteAllBytes("EncryptedFile.aes", cipherTextBytes);
}
This is the code I use to decrypt:
private AesManaged aesManaged;
private string filePathToDecrypt;
public Decrypt(AesManaged aesManaged, string filePathToDecrypt)
{
this.aesManaged = aesManaged;
this.filePathToDecrypt = filePathToDecrypt;
}
public void DoDecrypt()
{
byte[] cypherBytes = File.ReadAllBytes(this.filePathToDecrypt);
byte[] clearBytes = new byte[cypherBytes.Length];
ICryptoTransform encryptor = aesManaged.CreateDecryptor(aesManaged.Key, aesManaged.IV);
using (MemoryStream ms = new MemoryStream(cypherBytes))
using (CryptoStream cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Read))
{
cs.Read(clearBytes, 0, clearBytes.Length);
clearBytes = ms.ToArray();
}
File.WriteAllBytes("DecryptedFile.gif", clearBytes);
}
And here is how I call the functions:
string filePathToEncrypt = "dilbert.gif";
string filePathToDecrypt = "EncryptedFile.aes";
string password = "Password";
string passwordSalt = "PasswordSalt";
Rfc2898DeriveBytes deriveBytes = new Rfc2898DeriveBytes(password, Encoding.ASCII.GetBytes(passwordSalt));
var aesManaged = new AesManaged
{
Key = deriveBytes.GetBytes(128 / 8),
IV = deriveBytes.GetBytes(16),
Padding = PaddingMode.PKCS7
};
Console.WriteLine("Encrypting File...");
var encryptor = new Encrypt(aesManaged, filePathToEncrypt);
encryptor.DoEncryption();
Thread.Sleep(300);
Console.WriteLine("Decrypting File...");
var decryptor = new Decrypt(aesManaged, filePathToDecrypt);
decryptor.DoDecrypt();
Thread.Sleep(300);
Try with:
public void DoEncryption()
{
byte[] cipherBytes;
byte[] textBytes = File.ReadAllBytes(this.filePathToEncrypt);
using (ICryptoTransform encryptor = aesManaged.CreateEncryptor(aesManaged.Key, aesManaged.IV))
using (MemoryStream input = new MemoryStream(textBytes))
using (MemoryStream output = new MemoryStream())
using (CryptoStream cs = new CryptoStream(output, encryptor, CryptoStreamMode.Write))
{
input.CopyTo(cs);
cs.FlushFinalBlock();
cipherBytes = output.ToArray();
}
File.WriteAllBytes("EncryptedFile.aes", cipherBytes);
}
and
public void DoDecrypt()
{
byte[] cypherBytes = File.ReadAllBytes(this.filePathToDecrypt);
byte[] textBytes;
using (ICryptoTransform decryptor = aesManaged.CreateDecryptor(aesManaged.Key, aesManaged.IV))
using (MemoryStream input = new MemoryStream(cypherBytes))
using (MemoryStream output = new MemoryStream())
using (CryptoStream cs = new CryptoStream(input, decryptor, CryptoStreamMode.Read))
{
cs.CopyTo(output);
textBytes = output.ToArray();
}
File.WriteAllBytes("DecryptedFile.gif", textBytes);
}
Note that the code could be modified to not use temporary byte[] and read/write directly to input/output streams.
In general you can't desume the length of the plaintext from the length of the cyphertext, so this line:
new byte[cypherBytes.Length]
was totally wrong.
And please, don't use Encoding.ASCII in 2016. It is so like previous century. Use Encoding.UTF8 to support non-english characters.
The answer may be very simple. I don't see where do u try to choose a cipher mode, so by default it probably takes CBC, as IV was inited. Then, 81.970 are padded by 14 bytes, to be divisible by 32. So when it happens, the memory you allocated was just 81.970, so the padding bytes doesn't write correctly, cause of some sort of memory leak, and when decrypt is started, unpadding doesn't work correctly.

Unable to call com registered dll function in php

I have completed the com registration of a dll file and it is showing in the registry(which I got after entering regedit in command prompt)
If I use $obj1 = new COM("Encryptiondll.ClsEncryption"); I am getting no error
But when I am trying to access a method(which is declared as public string in .net) I am getting the following error from my php code
Fatal error: Call to undefined method com::Encrypt12() in C:\xampp\htdocs\test1\index.php on line 12
Please help
Below is the c# code I used to constract the dll:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
namespace Encryptiondll
{
public class ClsEncryption
{
public static void Main(string[] args)
{
}
public static string Encrypt12(string plaintext)
{
ASCIIEncoding textConverter = new ASCIIEncoding();
byte[] key = textConverter.GetBytes("2a1c907916add59edffb3a4b");
byte[] IV = textConverter.GetBytes("00000000");
byte[] clearData = Encoding.ASCII.GetBytes(plaintext);
byte[] cipherData = Encrypt1(clearData, key, IV);
return Convert.ToBase64String(cipherData);
}
public static byte[] Encrypt1(byte[] clearData, byte[] Key, byte[] IV)
{
MemoryStream ms = new MemoryStream();
TripleDESCryptoServiceProvider tdes = new TripleDESCryptoServiceProvider();
tdes.Mode = CipherMode.ECB;
tdes.Padding = PaddingMode.PKCS7;
ICryptoTransform alg = tdes.CreateEncryptor(Key, IV);
CryptoStream cs = new CryptoStream(ms, alg, CryptoStreamMode.Write);
cs.Write(clearData, 0, clearData.Length);
cs.FlushFinalBlock();
cs.Close();
byte[] encryptedData = ms.ToArray();
return encryptedData;
}
}
}

DES-ECB encryption and decryption

I'm using DES-ECB + base64 encryption in my application. That's the code of the class I called "Crypto"
public class Crypto
{
public static string Decrypt(string encryptedString)
{
DESCryptoServiceProvider desProvider = new DESCryptoServiceProvider();
desProvider.Mode = CipherMode.ECB;
desProvider.Padding = PaddingMode.PKCS7;
desProvider.Key = Encoding.ASCII.GetBytes("e5d66cf8");
using (MemoryStream stream = new MemoryStream(Convert.FromBase64String(encryptedString)))
{
using (CryptoStream cs = new CryptoStream(stream, desProvider.CreateDecryptor(), CryptoStreamMode.Read))
{
using (StreamReader sr = new StreamReader(cs, Encoding.ASCII))
{
return sr.ReadToEnd();
}
}
}
}
public static string Encrypt(string decryptedString)
{
DESCryptoServiceProvider desProvider = new DESCryptoServiceProvider();
desProvider.Mode = CipherMode.ECB;
desProvider.Padding = PaddingMode.PKCS7;
desProvider.Key = Encoding.ASCII.GetBytes("e5d66cf8");
using (MemoryStream stream = new MemoryStream())
{
using (CryptoStream cs = new CryptoStream(stream, desProvider.CreateEncryptor(), CryptoStreamMode.Write))
{
byte[] data = Encoding.Default.GetBytes(decryptedString);
cs.Write(data, 0, data.Length);
return Convert.ToBase64String(stream.ToArray());
}
}
}
}
but when I encrypt a string, then decrypt it again and encrypt one more time, the encrypted string is not the same as previous encrypted was. So that's the first encrypted string:
kEN0HUp/dqz8kXA7nYivJG6Jl3haLJjhBq1UfEtQTwaPwizW//03M0UxF8dBuYZo2BoZ5vsVcXRJF1LpFZLWxDsdeKAC43L2K2OoYRxTn/dA6KmM13YS9xOezGiROQfVj5qrkdokJRCvj0gYfFoH2oeDGyN+EAw5Dgzsp697kj4=
and here comes the second encrypted string:
kEN0HUp/dqz8kXA7nYivJG6Jl3haLJjhBq1UfEtQTwaPwizW//03M0UxF8dBuYZo2BoZ5vsVcXRJF1LpFZLWxDsdeKAC43L2K2OoYRxTn/dA6KmM13YS9xOezGiROQfVj5qrkdokJRCvj0gYfFoH2oeDGyN+EAw5
They are almost same, except this "Dgzsp697kj4=" in the first string.
What's wrong?
Thanks in advance.
You are losing data. In your Encrypt() method you need to call EncryptFinalBlock() to let the padding algorithm know that you are done so that it can add the padding:
using (CryptoStream cs = new CryptoStream(stream, desProvider.CreateEncryptor(), CryptoStreamMode.Write))
{
byte[] data = Encoding.Default.GetBytes(decryptedString);
cs.Write(data, 0, data.Length);
cs.FlushFinalBlock(); // <-- Add this
return Convert.ToBase64String(stream.ToArray());
}
I had a similar problem. You should check that white space is not getting appended to the end of the decrypted string. You might need to trim the white space off.

Categories

Resources