Tool : Visual Studio 2012. Windows 7 64bit.
Keywords : C#,registry,Triple DES Encryption Decryption.
I have created one demo program to read and write (Encrypted string) to registry.
Concept behind this program is : I want to Encrypt and Decrypt Data using Triple DES(I have Used TripleDESCryptoServiceProvider Class.).After Encryption, encrypted byte array is stored in Registry as a string. Upto this, it work perfectly. But when I get this string from registry and convert it in byte array for decryption, the size of array is different and during encryption it display error :
Length of the data to decrypt is invalid.
Below is my code :
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Win32;
namespace TripleDES_in_Memory
{
class Program
{
static void Main(string[] args)
{
try
{
using (RegistryKey key = Registry.CurrentUser.OpenSubKey("MyCompanyName\\"))
{
if (key != null)
{
object o = key.GetValue("TrialPeriod");
if (o != null)
{
string result = Convert.ToString(o);
byte[] Data = Encoding.UTF8.GetBytes(result);
BinaryFormatter bf = new BinaryFormatter();
using (var ms = new MemoryStream())
{
bf.Serialize(ms, o);
byte[] narray = ms.ToArray();
}
TripleDESCryptoServiceProvider tDESalg = new TripleDESCryptoServiceProvider();
string keybyjaimesh = "MyEncryptKey";
tDESalg.Key = Encoding.UTF8.GetBytes(keybyjaimesh.PadRight(24, ' '));
string ipmanual = "ivmanual";
tDESalg.IV = Encoding.UTF8.GetBytes(ipmanual.PadRight(8, ' '));
byte[] iv = tDESalg.IV;
tDESalg.IV = iv;
string Final = DecryptTextFromMemory(Data, tDESalg.Key, tDESalg.IV); //decrypt
Console.WriteLine(Final);
}
}
else
{
TripleDESCryptoServiceProvider tDESalg = new TripleDESCryptoServiceProvider();
string sData = "aaaaaaaaaaaaaaaaaaaaaaaa";
DateTime today = DateTime.Today;
DateTime answer = today.AddDays(1);
string keybyjaimesh = "MyEncryptKey";
tDESalg.Key = Encoding.UTF8.GetBytes(keybyjaimesh.PadRight(24, ' '));
string ipmanual = "ivmanual";
tDESalg.IV = Encoding.UTF8.GetBytes(ipmanual.PadRight(8, ' '));
byte[] iv = tDESalg.IV;
byte[] Data = EncryptTextToMemory(sData, tDESalg.Key, tDESalg.IV);
Console.WriteLine("Encrypted data main function : " + System.Text.Encoding.UTF8.GetString(Data));
Microsoft.Win32.RegistryKey key1;
key1 = Microsoft.Win32.Registry.CurrentUser.CreateSubKey("MyCompanyName");
key1.SetValue("TrialPeriod", System.Text.Encoding.UTF8.GetString(Data));
key1.SetValue("IV", System.Text.Encoding.UTF8.GetString(iv));
key1.Close();
}
}
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
public static byte[] EncryptTextToMemory(string Data, byte[] Key, byte[] IV)
{
try
{
MemoryStream mStream = new MemoryStream();
CryptoStream cStream = new CryptoStream(mStream,
new TripleDESCryptoServiceProvider().CreateEncryptor(Key, IV),
CryptoStreamMode.Write);
byte[] toEncrypt = new ASCIIEncoding().GetBytes(Data);
string result = System.Text.Encoding.UTF8.GetString(toEncrypt);
Console.WriteLine("byte to array : " + result);
cStream.Write(toEncrypt, 0, toEncrypt.Length);
cStream.FlushFinalBlock();
byte[] ret = mStream.ToArray();
Console.WriteLine("Encrypted data : " + System.Text.Encoding.UTF8.GetString(ret));
cStream.Close();
mStream.Close();
return ret;
}
catch (CryptographicException e)
{
Console.WriteLine("A Cryptographic error occurred: {0}", e.Message);
return null;
}
}
public static string DecryptTextFromMemory(byte[] Data, byte[] Key, byte[] IV)
{
try
{
MemoryStream msDecrypt = new MemoryStream(Data);
CryptoStream csDecrypt = new CryptoStream(msDecrypt,
new TripleDESCryptoServiceProvider().CreateDecryptor(Key, IV),
CryptoStreamMode.Read);
byte[] fromEncrypt = new byte[Data.Length];
csDecrypt.Read(fromEncrypt, 0, fromEncrypt.Length);
return new ASCIIEncoding().GetString(fromEncrypt);
}
catch (CryptographicException e)
{
Console.WriteLine("A Cryptographic error occurred: {0}", e.Message);
return null;
}
}
}
}
Encrypted String in registry :
Please suggest your opinion on this.
How can I solve this?
I have Solved it.
I have store Encrypted string in registry after convert it in TOBase64String.
string base64 = Convert.ToBase64String(encrypted string);
For Decrypt, Get string using :
string encrypteddatafromregistry = (string)key.GetValue("TrialPeriod",typeof(String));
And then convert to 64 base string :
byte[] encoded = Convert.FromBase64String(encrypteddatafromregistry );
And apply this array to Decryption.
Related
Trying to implement Encryption/Decryption.. the way is to serialize the data into a JSON and then encrypting that JSON to save it. sometimes, it works without any issue while sometimes I get this bad padding error. is there anything that I am missing? tried switching to Rijndael but getting a similar exception.
Save/Load Mechanics
public static void SaveGameJson()
{
Debug.Log("TRYING TO SAVE THE GMAE THROUGH Json File");
SaveManager data = new SaveManager();
string jsonData = JsonUtility.ToJson(data); // encrypting the json data..
// string jsonData = JsonConvert.SerializeObject(data); // encrypting the json data..
string encryptedJsonData = EncryptionRijndael.Encrypt(jsonData);
WriteToFile(JsonfileName, encryptedJsonData);
Debug.LogError("Json data Saved: " + jsonData);
Debug.LogError("Json Encrypted data: " + encryptedJsonData);
}
public static SaveManager LoadGameJson()
{
string path = GetFilePath(JsonfileName);
Debug.Log("TRYING TO LOAD THE GMAE THROUGH FILE");
if (File.Exists(path))
{
string encryptedJsonData = ReadFromFile(JsonfileName); // reading encrypted data from json Encrypted file
string jsonData = EncryptionRijndael.Decrypt(encryptedJsonData); // decrypting json data from encrypted string
Debug.LogError("Json data Load: " + jsonData);
Debug.LogError("Encrypted Data: " + encryptedJsonData);
SaveManager data = JsonUtility.FromJson<SaveManager>(jsonData);
//SaveManager data = JsonConvert.DeserializeObject<SaveManager>(jsonData);
return data;
}
else
{
Debug.LogError("save file not found on:" + path);
return null;
}
}
Additional Function
static void WriteToFile(string fileName, string json) {
string path = GetFilePath(fileName);
FileStream fileStream = new FileStream(path, FileMode.OpenOrCreate);
using (StreamWriter writer = new StreamWriter(fileStream)) {
writer.Write(json);
}
}
Encryption
public static string Encrypt(string strPlain)
{
string password = strPassword;
if (!useSecure)
return strPlain;
try
{
DESCryptoServiceProvider des = new DESCryptoServiceProvider();
Rfc2898DeriveBytes rfc2898DeriveBytes = new Rfc2898DeriveBytes(password, GetIV(), Iterations);
byte[] key = rfc2898DeriveBytes.GetBytes(8);
using (var memoryStream = new MemoryStream())
using (var cryptoStream = new CryptoStream(memoryStream, des.CreateEncryptor(key, GetIV()), CryptoStreamMode.Write))
{
memoryStream.Write(GetIV(), 0, GetIV().Length);
byte[] plainTextBytes = Encoding.UTF8.GetBytes(strPlain);
cryptoStream.Write(plainTextBytes, 0, plainTextBytes.Length);
cryptoStream.FlushFinalBlock();
return Convert.ToBase64String(memoryStream.ToArray());
}
}
catch (Exception e)
{
Debug.LogWarning("Encrypt Exception: " + e);
return strPlain;
}
}
Decryption
public static string Decrypt(string strEncript)
{
string password = strPassword;
if (!useSecure)
return strEncript;
try
{
byte[] cipherBytes = Convert.FromBase64String(strEncript);
using (var memoryStream = new MemoryStream(cipherBytes))
{
DESCryptoServiceProvider des = new DESCryptoServiceProvider();
byte[] iv = GetIV();
memoryStream.Read(iv, 0, iv.Length);
// use derive bytes to generate key from password and IV
var rfc2898DeriveBytes = new Rfc2898DeriveBytes(password, iv, Iterations);
byte[] key = rfc2898DeriveBytes.GetBytes(8);
using (var cryptoStream = new CryptoStream(memoryStream, des.CreateDecryptor(key, iv), CryptoStreamMode.Read))
using (var streamReader = new StreamReader(cryptoStream))
{
string strPlain = streamReader.ReadToEnd();
return strPlain;
}
}
}
catch (Exception e)
{
Debug.LogWarning("Decrypt Exception: " + e);
return strEncript;
}
}
JSON getting saved
Loading JSON from encrypted string
PS: it seems like the encryption is working fine in the logs but when it tries to decrypt the string, it throughs this exception. Is there any better option for this?
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.
I got a textbox and a 'decrypt' button in my Windows Form Application where I put an encrypted string in there and try to decrypt it but the problem is this. First, I got this class code called DataEncryptor from a guy on this website:
public class DataEncryptor
{
TripleDESCryptoServiceProvider symm;
#region Factory
public DataEncryptor()
{
this.symm = new TripleDESCryptoServiceProvider();
this.symm.Padding = PaddingMode.PKCS7;
}
public DataEncryptor(TripleDESCryptoServiceProvider keys)
{
this.symm = keys;
}
public DataEncryptor(byte[] key, byte[] iv)
{
this.symm = new TripleDESCryptoServiceProvider();
this.symm.Padding = PaddingMode.PKCS7;
this.symm.Key = key;
this.symm.IV = iv;
}
#endregion
#region Properties
public TripleDESCryptoServiceProvider Algorithm
{
get { return symm; }
set { symm = value; }
}
public byte[] Key
{
get { return symm.Key; }
set { symm.Key = value; }
}
public byte[] IV
{
get { return symm.IV; }
set { symm.IV = value; }
}
#endregion
#region Crypto
public byte[] Encrypt(byte[] data) { return Encrypt(data, data.Length); }
public byte[] Encrypt(byte[] data, int length)
{
try
{
// Create a MemoryStream.
var ms = new MemoryStream();
// Create a CryptoStream using the MemoryStream
// and the passed key and initialization vector (IV).
var cs = new CryptoStream(ms,
symm.CreateEncryptor(symm.Key, symm.IV),
CryptoStreamMode.Write);
// Write the byte array to the crypto stream and flush it.
cs.Write(data, 0, length);
cs.FlushFinalBlock();
// Get an array of bytes from the
// MemoryStream that holds the
// encrypted data.
byte[] ret = ms.ToArray();
// Close the streams.
cs.Close();
ms.Close();
// Return the encrypted buffer.
return ret;
}
catch (CryptographicException ex)
{
Console.WriteLine("A cryptographic error occured: {0}", ex.Message);
}
return null;
}
public string EncryptString(string text)
{
return Convert.ToBase64String(Encrypt(Encoding.UTF8.GetBytes(text)));
}
public byte[] Decrypt(byte[] data) { return Decrypt(data, data.Length); }
public byte[] Decrypt(byte[] data, int length)
{
try
{
// Create a new MemoryStream using the passed
// array of encrypted data.
MemoryStream ms = new MemoryStream(data);
// Create a CryptoStream using the MemoryStream
// and the passed key and initialization vector (IV).
CryptoStream cs = new CryptoStream(ms,
symm.CreateDecryptor(symm.Key, symm.IV),
CryptoStreamMode.Read);
// Create buffer to hold the decrypted data.
byte[] result = new byte[length];
// Read the decrypted data out of the crypto stream
// and place it into the temporary buffer.
cs.Read(result, 0, result.Length);
return result;
}
catch (CryptographicException ex)
{
Console.WriteLine("A cryptographic error occured: {0}", ex.Message);
}
return null;
}
public string DecryptString(string data)
{
return Encoding.UTF8.GetString(Decrypt(Convert.FromBase64String(data))).TrimEnd('\0');
}
#endregion
}
And he gave the usage of it:
string message="A very secret message here.";
DataEncryptor keys=new DataEncryptor();
string encr=keys.EncryptString(message);
// later
string actual=keys.DecryptString(encr);
I copied his code and works at encrypting and decrypting:
//my code
private void proceedED(string data)
{
DataEncryptor key = new DataEncryptor();
string encr = key.EncryptString(data);
string actual = key.DecryptString(encr);
encryptedLabel.Text = encr;
decryptedLabel.Text = actual;
}
Then I created a method like this:
private void proceedDecrypt(string data)
{
DataEncryptor key = new DataEncryptor();
string decr = key.DecryptString(data);
decryptedData.Text = decr;
}
The problem is that it crashes when I submit and I don't know why.
I think it should be a true encrypted string because it's just a normal string.
How do I fix this?
Each instance of DataEncryptor generates new keys. You need to use the same keys which encrypted the string to decrypt. If this is done in the same process then keep a reference to DataEncryptor key. Otherwise you need to initialize using the DataEncryptor(byte[] key, byte[] iv) constructor.
Try code like this:
class Program
{
static void Main(string[] args)
{
string key, iv;
var plain="A very secret message.";
var cipher=EncryptString(plain, out key, out iv);
// Later ...
var message=DecryptString(cipher, key, iv);
}
public static string EncryptString(string plain, out string key, out string iv)
{
var crypto=new DataEncryptor();
iv=Convert.ToBase64String(crypto.IV);
key=Convert.ToBase64String(crypto.Key);
return crypto.EncryptString(plain);
}
public static string DecryptString(string cipher, string key, string iv)
{
var crypto=new DataEncryptor(
Convert.FromBase64String(key),
Convert.FromBase64String(iv));
return crypto.DecryptString(cipher);
}
}
You can use encryption and decription with System.Security.Cryptography
1) Set encryption decription key
2) Encrypt data with encryption key
3) Decrypt data with same encryption key
Please refer below link with Encryption and Decription example.
Encryption/Decryption Function in .NET using the TripleDESCryptoServiceProvider Class
you are creating new object in both function;
DataEncryptor key = new DataEncryptor();
That is the reason, for your error.
Just declare;
DataEncryptor key = new DataEncryptor();
Out side of your proceedED() and proceedDecrypt(), I mean make it public.
OR you can pass pass key as parameter to proceedDecrypt() and use it in that function.
Like;
DataEncryptor key = new DataEncryptor();
private void proceedED(string data)
{
string encr = key.EncryptString(data);
string actual = key.DecryptString(encr);
encryptedLabel.Text = encr;
decryptedLabel.Text = actual;
proceedDecrypt(encr);
}
private void proceedDecrypt(string data)
{
string decr = key.DecryptString(data);
decryptedData.Text = decr;
}
Hope it helps..!!!
Well I finally solved it...
I copied this code from https://social.msdn.microsoft.com/Forums/vstudio/en-US/d6a2836a-d587-4068-8630-94f4fb2a2aeb/encrypt-and-decrypt-a-string-in-c?forum=csharpgeneral
static readonly string PasswordHash = "P##Sw0rd";
static readonly string SaltKey = "S#LT&KEY";
static readonly string VIKey = "#1B2c3D4e5F6g7H8";
public static string Encrypt(string plainText)
{
byte[] plainTextBytes = Encoding.UTF8.GetBytes(plainText);
byte[] keyBytes = new Rfc2898DeriveBytes(PasswordHash, Encoding.ASCII.GetBytes(SaltKey)).GetBytes(256 / 8);
var symmetricKey = new RijndaelManaged() { Mode = CipherMode.CBC, Padding = PaddingMode.Zeros };
var encryptor = symmetricKey.CreateEncryptor(keyBytes, Encoding.ASCII.GetBytes(VIKey));
byte[] cipherTextBytes;
using (var memoryStream = new MemoryStream())
{
using (var cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write))
{
cryptoStream.Write(plainTextBytes, 0, plainTextBytes.Length);
cryptoStream.FlushFinalBlock();
cipherTextBytes = memoryStream.ToArray();
cryptoStream.Close();
}
memoryStream.Close();
}
return Convert.ToBase64String(cipherTextBytes);
}
public static string Decrypt(string encryptedText)
{
byte[] cipherTextBytes = Convert.FromBase64String(encryptedText);
byte[] keyBytes = new Rfc2898DeriveBytes(PasswordHash, Encoding.ASCII.GetBytes(SaltKey)).GetBytes(256 / 8);
var symmetricKey = new RijndaelManaged() { Mode = CipherMode.CBC, Padding = PaddingMode.None };
var decryptor = symmetricKey.CreateDecryptor(keyBytes, Encoding.ASCII.GetBytes(VIKey));
var memoryStream = new MemoryStream(cipherTextBytes);
var cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read);
byte[] plainTextBytes = new byte[cipherTextBytes.Length];
int decryptedByteCount = cryptoStream.Read(plainTextBytes, 0, plainTextBytes.Length);
memoryStream.Close();
cryptoStream.Close();
return Encoding.UTF8.GetString(plainTextBytes, 0, decryptedByteCount).TrimEnd("\0".ToCharArray());
}
and removed the DataEncryptor class
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions must demonstrate a minimal understanding of the problem being solved. Tell us what you've tried to do, why it didn't work, and how it should work. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Threading;
using System.Net;
using System.Net.Sockets;
using System.Security.Cryptography;
namespace GUISimpleTCPClient
{
public partial class GUISimpleTCPClient : Form
{
TcpClient client=null;
NetworkStream stream;
StreamReader reader;
StreamWriter writer;
public GUISimpleTCPClient()
{
InitializeComponent();
}
private void Connect_Click(object sender, EventArgs e)
{
try
{
client=new TcpClient(ipAddress.Text,Convert.ToInt32(port.Text));
listBox1.Items.Add("Connected to Server");
stream = client.GetStream();
reader = new StreamReader(stream);
writer = new StreamWriter(stream);
string msg = reader.ReadLine();
listBox1.Items.Add("Recieved form server:");
listBox1.Items.Add(msg);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
private void send_Click(object sender, EventArgs e)
{
string msg = M.Text;
SymmetricAlgorithm symmetricAlgorithm = SymmetricAlgorithm.Create();
byte[] data = Encoding.UTF8.GetBytes("password");
symmetricAlgorithm.Key = GetLegalKey("PASSWORD");
symmetricAlgorithm.IV = GetLegalIV();
byte[] cipher = Encrypt(symmetricAlgorithm, data);
System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding();
msg = enc.GetString(cipher);
// System.Text.Encoding encoding=new System.Text.Encoding() ;
System.Text.ASCIIEncoding denc = new System.Text.ASCIIEncoding();
Byte[] dec_data = denc.GetBytes(msg);
string decode = Decrypt(symmetricAlgorithm, dec_data);
try
{
writer.WriteLine(msg);
writer.Flush();
msg = reader.ReadLine();
if (msg.Length!=0)
listBox1.Items.Add(decode);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
private static byte[] Encrypt(SymmetricAlgorithm symmetricAlgorithm,
byte[] data)
{
// FileStream outStream = File.OpenWrite(outPath);
ICryptoTransform transform = symmetricAlgorithm.CreateEncryptor();
MemoryStream t = new MemoryStream();
CryptoStream cryptoStream =
new CryptoStream(t, transform, CryptoStreamMode.Write);
Byte[] inFile = data;
// File.ReadAllBytes(inPath);
cryptoStream.Write(data, 0, data.Length);
cryptoStream.FlushFinalBlock();
cryptoStream.Close();
return t.ToArray();
}
private static string Decrypt(SymmetricAlgorithm symmetricAlgorithm,
byte[] cipher)
{
ICryptoTransform transform = symmetricAlgorithm.CreateDecryptor();
// Stream inStream = File.OpenRead(inPath);
MemoryStream inStream = new MemoryStream();
CryptoStream cryptoStream =
new CryptoStream(inStream, transform, CryptoStreamMode.Write);
Byte[] buffer = new Byte[100];
cryptoStream.Write(cipher, 0, cipher.Length);
cryptoStream.FlushFinalBlock();
//Console.WriteLine();
return Encoding.UTF8.GetString(inStream.ToArray());
// int length = cryptoStream.Read(buffer, 0, buffer.Length);
// Stream outStream = File.OpenWrite(outPath);
/* while (length > 0)
{
outStream.Write(buffer, 0, length);
length = cryptoStream.Read(buffer, 0, buffer.Length);
}*/
//inStream.Close();
// outStream.Close();
}
private byte[] GetLegalKey(string Key)
{
SymmetricAlgorithm symmetricAlgorithm = SymmetricAlgorithm.Create();
string sTemp = Key;
symmetricAlgorithm.GenerateKey();
byte[] bytTemp = symmetricAlgorithm.Key;
int KeyLength = bytTemp.Length;
if (sTemp.Length > KeyLength)
sTemp = sTemp.Substring(0, KeyLength);
else if (sTemp.Length < KeyLength)
sTemp = sTemp.PadRight(KeyLength, ' ');
return ASCIIEncoding.ASCII.GetBytes(sTemp);
}
private byte[] GetLegalIV()
{
string initialIV = "12345678";
SymmetricAlgorithm symmetricAlgorithm = SymmetricAlgorithm.Create();
// The initial string of IV may be modified with any data you like
string sTemp = initialIV;
symmetricAlgorithm.GenerateIV();
byte[] bytTemp = symmetricAlgorithm.IV;
int IVLength = bytTemp.Length;
if (sTemp.Length > IVLength)
sTemp = sTemp.Substring(0, IVLength);
else if (sTemp.Length < IVLength)
sTemp = sTemp.PadRight(IVLength, ' ');
return ASCIIEncoding.ASCII.GetBytes(sTemp);
}
}
}
This is the problem:
byte[] cipher = Encrypt(symmetricAlgorithm, data);
System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding();
msg = enc.GetString(cipher);
Never, ever do this.
The encrypted data is not an ASCII-encoded string, so don't treat it that way. Use base64 instead. So this snippet should be:
byte[] cipher = Encrypt(symmetricAlgorithm, data);
msg = Convert.ToBase64String(cipher);
and the reverse should be:
byte[] dec_data = Convert.FromBase64String(msg);
You should never treat opaque binary data as if it were really encoded text. It's like trying to load an MP3 file as if it were a JPG. It's not - you'll lose data.
public class TrippleENCRSPDESCSP
{
public TrippleENCRSPDESCSP()
{
}
public void EncryptIt(string sData,ref byte[] sEncData,ref byte[] Key1,ref byte[] Key2)
{
try
{
// Create a new TripleDESCryptoServiceProvider object
// to generate a key and initialization vector (IV).
TripleDESCryptoServiceProvider tDESalg = new TripleDESCryptoServiceProvider();
// Create a string to encrypt.
// Encrypt the string to an in-memory buffer.
byte[] Data = EncryptTextToMemory(sData,tDESalg.Key,tDESalg.IV);
sEncData = Data;
Key1 = tDESalg.Key;
Key2 = tDESalg.IV;
}
catch (Exception)
{
throw;
}
}
public string DecryptIt(byte[] sEncData)
{
//byte[] toEncrypt = new ASCIIEncoding().GetBytes(sEncData);
//XElement xParser = null;
//XmlDocument xDoc = new XmlDocument();
try
{
//string Final = "";
string sPwd = null;
string sKey1 = null;
string sKey2 = null;
//System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding();
string soutxml = "";
//soutxml = encoding.GetString(sEncData);
soutxml = ASCIIEncoding.ASCII.GetString(sEncData);
sPwd = soutxml.Substring(18, soutxml.LastIndexOf("</EncPwd>") - 18);
sKey1 = soutxml.Substring(18 + sPwd.Length + 15, soutxml.LastIndexOf("</Key1>") - (18 + sPwd.Length + 15));
sKey2 = soutxml.Substring(18 + sPwd.Length + 15 + sKey1.Length + 13, soutxml.LastIndexOf("</Key2>") - (18 + sPwd.Length + 15 + sKey1.Length + 13));
//xDoc.LoadXml(soutxml);
//xParser = XElement.Parse(soutxml);
//IEnumerable<XElement> elemsValidations =
// from el in xParser.Elements("EmailPwd")
// select el;
#region OldCode
//XmlNodeList objXmlNode = xDoc.SelectNodes("EmailPwd");
//foreach (XmlNode xmllist in objXmlNode)
//{
// XmlNode xmlsubnode;
// xmlsubnode = xmllist.SelectSingleNode("EncPwd");
// xmlsubnode = xmllist.SelectSingleNode("Key1");
// xmlsubnode = xmllist.SelectSingleNode("Key2");
//}
#endregion
//foreach (XElement elemValidation in elemsValidations)
//{
// sPwd = elemValidation.Element("EncPwd").Value;
// sKey1 = elemValidation.Element("Key1").Value;
// sKey2 = elemValidation.Element("Key2").Value;
//}
//byte[] Key1 = encoding.GetBytes(sKey1);
//byte[] Key2 = encoding.GetBytes(sKey2);
//byte[] Data = encoding.GetBytes(sPwd);
byte[] Key1 = ASCIIEncoding.ASCII.GetBytes(sKey1);
byte[] Key2 = ASCIIEncoding.ASCII.GetBytes(sKey2);
byte[] Data = ASCIIEncoding.ASCII.GetBytes(sPwd);
// Decrypt the buffer back to a string.
string Final = DecryptTextFromMemory(Data, Key1, Key2);
return Final;
}
catch (Exception)
{
throw;
}
}
public static byte[] EncryptTextToMemory(string Data,byte[] Key,byte[] IV)
{
try
{
// Create a MemoryStream.
MemoryStream mStream = new MemoryStream();
// Create a CryptoStream using the MemoryStream
// and the passed key and initialization vector (IV).
CryptoStream cStream = new CryptoStream(mStream,
new TripleDESCryptoServiceProvider().CreateEncryptor(Key, IV),
CryptoStreamMode.Write);
// Convert the passed string to a byte array.
//byte[] toEncrypt = new ASCIIEncoding().GetBytes(Data);
byte[] toEncrypt = ASCIIEncoding.ASCII.GetBytes(Data);
// Write the byte array to the crypto stream and flush it.
cStream.Write(toEncrypt, 0, toEncrypt.Length);
cStream.FlushFinalBlock();
// Get an array of bytes from the
// MemoryStream that holds the
// encrypted data.
byte[] ret = mStream.ToArray();
// Close the streams.
cStream.Close();
mStream.Close();
// Return the encrypted buffer.
return ret;
}
catch (CryptographicException e)
{
MessageBox.Show("A Cryptographic error occurred: {0}", e.Message);
return null;
}
}
public static string DecryptTextFromMemory(byte[] Data, byte[] Key, byte[] IV)
{
try
{
// Create a new MemoryStream using the passed
// array of encrypted data.
MemoryStream msDecrypt = new MemoryStream(Data);
// Create a CryptoStream using the MemoryStream
// and the passed key and initialization vector (IV).
CryptoStream csDecrypt = new CryptoStream(msDecrypt,
new TripleDESCryptoServiceProvider().CreateDecryptor(Key, IV),
CryptoStreamMode.Write);
csDecrypt.Write(Data, 0, Data.Length);
//csDecrypt.FlushFinalBlock();
msDecrypt.Position = 0;
// Create buffer to hold the decrypted data.
byte[] fromEncrypt = new byte[msDecrypt.Length];
// Read the decrypted data out of the crypto stream
// and place it into the temporary buffer.
msDecrypt.Read(fromEncrypt, 0, msDecrypt.ToArray().Length);
//csDecrypt.Close();
MessageBox.Show(ASCIIEncoding.ASCII.GetString(fromEncrypt));
//Convert the buffer into a string and return it.
return new ASCIIEncoding().GetString(fromEncrypt);
}
catch (CryptographicException e)
{
MessageBox.Show("A Cryptographic error occurred: {0}", e.Message);
return null;
}
}
}
The same key (Key) and initialization vector (IV) used to encrypt the file must be used to decrypt it. I can't fully check this code currently so there may be one or two small problems but give it a try and let me know if it works, hopefully you get the idea:
public static string DecryptTextFromMemory(byte[] Data, byte[] Key, byte[] IV)
{
try
{
// Create a new MemoryStream using the passed
// array of encrypted data.
MemoryStream msDecrypt = new MemoryStream();
// Create a CryptoStream using the MemoryStream
// and the passed key and initialization vector (IV).
CryptoStream csDecrypt = new CryptoStream(msDecrypt,
new TripleDESCryptoServiceProvider().CreateDecryptor(Key, IV),
CryptoStreamMode.Write);
csDecrypt.Write(Data, 0, Data.Length);
csDecrypt.FlushFinalBlock();
msDecrypt.Position = 0;
// Create buffer to hold the decrypted data.
byte[] fromEncrypt = new byte[msDecrypt.Length];
// Read the decrypted data out of the crypto stream
// and place it into the temporary buffer.
msDecrypt.Read(fromEncrypt, 0, msDecrypt.ToArray().Length);
csDecrypt.Close();
//Convert the buffer into a string and return it.
return new UTF8Encoding().GetString(fromEncrypt);
}
catch (CryptographicException e)
{
MessageBox.Show("A Cryptographic error occurred: {0}", e.Message);
return null;
}
}