By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
424,495 Members | 1,208 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 424,495 IT Pros & Developers. It's quick & easy.

TripleDES String Encrypt/Decrypt Problem

P: n/a
I'm having trouble encrypting/decrypting a simple string using the
System.Security.Cryptography.TripleDESCryptoServic eProvider, etc...

The encryption works, but the decryption does not properly decrypt
several of the first few characters.

Here's the code:

class TMyCipher
{
public string Encipher(string s, string key)
{
byte[] bKey = ASCIIEncoding.ASCII.GetBytes(key);
TripleDESCryptoServiceProvider TripleDesProv = new
TripleDESCryptoServiceProvider();
ICryptoTransform ict = TripleDesProv.CreateEncryptor(bKey,null);
byte[] bInput = ASCIIEncoding.ASCII.GetBytes(s);
byte[] bOutput = ict.TransformFinalBlock(bInput,0,bInput.Length);
System.Console.WriteLine(System.Text.Encoding.ASCI I.GetString(bOutput,0,bOutput.Length));
return Convert.ToBase64String(bOutput,0,bOutput.Length);
}

public string Decipher(string ciphertext, string key)
{
byte[] bKey = ASCIIEncoding.ASCII.GetBytes(key);
TripleDESCryptoServiceProvider TripleDesDec = new
TripleDESCryptoServiceProvider();
ICryptoTransform Decryptor =
TripleDesDec.CreateDecryptor(bKey,null);
System.Console.WriteLine(ciphertext);
byte[] eInput = Convert.FromBase64String(ciphertext);
System.Console.WriteLine(System.Text.Encoding.ASCI I.GetString(eInput,0,eInput.Length));
byte[] eOutput =
Decryptor.TransformFinalBlock(eInput,0,eInput.Leng th);
return System.Text.Encoding.ASCII.GetString(eOutput,0,eOu tput.Length);
}
}

string ClearText = "test-text-this-is-text";

string sKey = "mykey";
sKey = sKey.PadRight(16,' ');
byte[] bKey = ASCIIEncoding.ASCII.GetBytes(sKey);
TMyCipher ciph = new TMyCipher();
string ciphertext = ciph.Encipher(ClearText,sKey);
System.Console.WriteLine(ciphertext);
string sFinal = ciph.Decipher(ciphertext,sKey);
System.Console.WriteLine("Final: " + sFinal);

The result:

G)♠SK|YS
M♀H)←b ↨\
r2xpLw1HKQbTy/zZh9MKTYzIqZtiCRfc
r2xpLw1HKQbTy/zZh9MKTYzIqZtiCRfc
G)♠SK|YS
M♀H)←b ↨\
Final: I'|htT<#t-this-is-text
Nov 15 '05 #1
Share this Question
Share on Google+
8 Replies


P: n/a
<wk****@yahoo.com> wrote:
I'm having trouble encrypting/decrypting a simple string using the
System.Security.Cryptography.TripleDESCryptoServic eProvider, etc...

The encryption works, but the decryption does not properly decrypt
several of the first few characters.


<snip>

The problem is that you're giving it more in one block than you should.
Rather than using the transform directly, I suggest you use the
CryptoStream API. That way you don't need to worry about block sizes
etc.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
Nov 15 '05 #2

P: n/a
Jon Skeet [C# MVP] <sk***@pobox.com> wrote in message news:<MP************************@msnews.microsoft. com>...

The problem is that you're giving it more in one block than you should.
Rather than using the transform directly, I suggest you use the
CryptoStream API. That way you don't need to worry about block sizes
etc.


Thank you. I've tried to implement a simple solution using a
CryptoStream, but the results are almost identical:

My ClearText String
d!U#CP↕?XgN☼q%♀U∟o→
ZCHVo3eIQ1AShz+UWOdOj3GlDNUcbxoN <-- After Base64 Encoding.

d!U#CP↕?XgN☼q%♀U∟o→
My CleSRText String <-- After Decryption.
^^^^

Here's my code. Thanks again.

static void Main(string[] args)
{
string sKey = "MyKey";
sKey = sKey.PadRight(16,' ');
string sInit = "123456";
byte[] bInit = ASCIIEncoding.ASCII.GetBytes(sInit);
string ClearText = "My ClearText String";
byte[] bKey = ASCIIEncoding.ASCII.GetBytes(sKey);
byte[] buffer = ASCIIEncoding.ASCII.GetBytes(ClearText);
byte[] rbuffer;

System.Console.WriteLine(ClearText);
TripleDESCryptoServiceProvider tdc = new
TripleDESCryptoServiceProvider();
ICryptoTransform icp = tdc.CreateEncryptor(bKey,bInit);
System.IO.MemoryStream ms = new System.IO.MemoryStream();
CryptoStream cs = new CryptoStream(ms,icp,CryptoStreamMode.Write);
cs.Write(buffer,0,buffer.Length);
cs.Close();
rbuffer = ms.ToArray();
System.Console.WriteLine(ASCIIEncoding.ASCII.GetSt ring(rbuffer,0,rbuffer.Length));
string CipherText =
Convert.ToBase64String(rbuffer,0,rbuffer.Length);
System.Console.WriteLine(CipherText);
System.Console.ReadLine();
ms.Close();

System.IO.MemoryStream dms = new System.IO.MemoryStream();
byte[] eBuffer = Convert.FromBase64String(CipherText);
System.Console.WriteLine(ASCIIEncoding.ASCII.GetSt ring(eBuffer,0,eBuffer.Length));
dms.Write(eBuffer,0,eBuffer.Length);
dms.Seek(0,System.IO.SeekOrigin.Begin);

TripleDESCryptoServiceProvider ddc = new
TripleDESCryptoServiceProvider();
ICryptoTransform dcp = ddc.CreateDecryptor(bKey,bInit);
CryptoStream dcs = new CryptoStream(dms,dcp,CryptoStreamMode.Read);
byte[] cBuffer = new byte[eBuffer.Length];
dcs.Read(cBuffer,0,eBuffer.Length);
dcs.Close();
System.Console.WriteLine(ASCIIEncoding.ASCII.GetSt ring(cBuffer,0,cBuffer.Length));
dms.Close();
string cText = ASCIIEncoding.ASCII.GetString(cBuffer,0,cBuffer.Le ngth);
System.Console.WriteLine(cText);
System.Console.ReadLine();
}
Nov 15 '05 #3

P: n/a
You need to use CryptoStream.FlushFinalBlock before closing the crypto
stream after writing.

<wk****@yahoo.com> wrote in message
news:2e**************************@posting.google.c om...
Jon Skeet [C# MVP] <sk***@pobox.com> wrote in message news:<MP************************@msnews.microsoft. com>...

The problem is that you're giving it more in one block than you should.
Rather than using the transform directly, I suggest you use the
CryptoStream API. That way you don't need to worry about block sizes
etc.


Thank you. I've tried to implement a simple solution using a
CryptoStream, but the results are almost identical:

My ClearText String
d!U#CP↕?XgN☼q%♀U∟o→
ZCHVo3eIQ1AShz+UWOdOj3GlDNUcbxoN <-- After Base64 Encoding.

d!U#CP↕?XgN☼q%♀U∟o→
My CleSRText String <-- After Decryption.
^^^^

Here's my code. Thanks again.

static void Main(string[] args)
{
string sKey = "MyKey";
sKey = sKey.PadRight(16,' ');
string sInit = "123456";
byte[] bInit = ASCIIEncoding.ASCII.GetBytes(sInit);
string ClearText = "My ClearText String";
byte[] bKey = ASCIIEncoding.ASCII.GetBytes(sKey);
byte[] buffer = ASCIIEncoding.ASCII.GetBytes(ClearText);
byte[] rbuffer;

System.Console.WriteLine(ClearText);
TripleDESCryptoServiceProvider tdc = new
TripleDESCryptoServiceProvider();
ICryptoTransform icp = tdc.CreateEncryptor(bKey,bInit);
System.IO.MemoryStream ms = new System.IO.MemoryStream();
CryptoStream cs = new CryptoStream(ms,icp,CryptoStreamMode.Write);
cs.Write(buffer,0,buffer.Length);
cs.Close();
rbuffer = ms.ToArray();

System.Console.WriteLine(ASCIIEncoding.ASCII.GetSt ring(rbuffer,0,rbuffer.Len
gth)); string CipherText =
Convert.ToBase64String(rbuffer,0,rbuffer.Length);
System.Console.WriteLine(CipherText);
System.Console.ReadLine();
ms.Close();

System.IO.MemoryStream dms = new System.IO.MemoryStream();
byte[] eBuffer = Convert.FromBase64String(CipherText);
System.Console.WriteLine(ASCIIEncoding.ASCII.GetSt ring(eBuffer,0,eBuffer.Len
gth)); dms.Write(eBuffer,0,eBuffer.Length);
dms.Seek(0,System.IO.SeekOrigin.Begin);

TripleDESCryptoServiceProvider ddc = new
TripleDESCryptoServiceProvider();
ICryptoTransform dcp = ddc.CreateDecryptor(bKey,bInit);
CryptoStream dcs = new CryptoStream(dms,dcp,CryptoStreamMode.Read);
byte[] cBuffer = new byte[eBuffer.Length];
dcs.Read(cBuffer,0,eBuffer.Length);
dcs.Close();
System.Console.WriteLine(ASCIIEncoding.ASCII.GetSt ring(cBuffer,0,cBuffer.Len
gth)); dms.Close();
string cText = ASCIIEncoding.ASCII.GetString(cBuffer,0,cBuffer.Le ngth);
System.Console.WriteLine(cText);
System.Console.ReadLine();
}

Nov 15 '05 #4

P: n/a
<wk****@yahoo.com> wrote:
Thank you. I've tried to implement a simple solution using a
CryptoStream, but the results are almost identical:


Well, one of the problems which may well be everything in fact is that
you're using Stream.Read and assuming that it will completely fill the
buffer you've specified. You're also assuming that the encrypted length
is the same as the unencrypted length.

Rather than using CryptoStreamMode.Read, I find it easier to use
CryptoStreamMode.Write again, and write into a memory stream.

Here's some working code I wrote for someone else the other day - it
uses a straight DESCryptoServiceProvider, but I'm sure you can change
that part.

using System;
using System.IO;
using System.Text;
using System.Security.Cryptography;

public class Working
{
DESCryptoServiceProvider provider;

Working()
{
provider = new DESCryptoServiceProvider();
provider.GenerateKey();
provider.GenerateIV();
}

byte[] Encrypt (string text)
{
byte[] encodedText = Encoding.UTF8.GetBytes (text);
ICryptoTransform transform = provider.CreateEncryptor();

using (MemoryStream ms = new MemoryStream())
{
using (CryptoStream cs = new CryptoStream
(ms, transform, CryptoStreamMode.Write))
{
cs.Write (encodedText, 0, encodedText.Length);
cs.FlushFinalBlock();
}

return ms.ToArray();
}
}

string Decrypt (byte[] data)
{
ICryptoTransform transform = provider.CreateDecryptor();
using (MemoryStream ms = new MemoryStream())
{
using (CryptoStream cs = new CryptoStream (ms,
transform, CryptoStreamMode.Write))
{
cs.Write (data, 0, data.Length);
cs.FlushFinalBlock();
}
return Encoding.UTF8.GetString (ms.ToArray());
}
}

static void Main()
{
Working w = new Working();

Console.WriteLine (w.Decrypt(w.Encrypt
("Some text to be encrypted and then decrypted")));
}
}
--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
Nov 15 '05 #5

P: n/a
Bret Mulvey <br***@online.microsoft.com> wrote:
You need to use CryptoStream.FlushFinalBlock before closing the crypto
stream after writing.


Actually, if you close a CryptoStream without flushing the final block,
it'll flush it for you. Not a bad idea to make it clear though.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
Nov 15 '05 #6

P: n/a

"Jon Skeet [C# MVP]" <sk***@pobox.com> wrote in message
news:MP************************@msnews.microsoft.c om...
Bret Mulvey <br***@online.microsoft.com> wrote:
You need to use CryptoStream.FlushFinalBlock before closing the crypto
stream after writing.


Actually, if you close a CryptoStream without flushing the final block,
it'll flush it for you. Not a bad idea to make it clear though.


That's what I thought, but I tried his example and reproduced problem. Using
Close without FlushFinalBlock corrupted the data, and with FlushFinalBlock
before Close it resolved the problem. I was able to see this in his code as
well as a separate example I created.

In a decompilation of CryptoStream.Close I can clearly see where it calls
FlushFinalBlock, but only conditionally. Perhaps the TripleDES encryptor
doesn't correctly set this flag.
Nov 15 '05 #7

P: n/a

"Bret Mulvey" <br***@online.microsoft.com> wrote in message
news:3f********@news.microsoft.com...

"Jon Skeet [C# MVP]" <sk***@pobox.com> wrote in message
news:MP************************@msnews.microsoft.c om...
Bret Mulvey <br***@online.microsoft.com> wrote:
You need to use CryptoStream.FlushFinalBlock before closing the crypto
stream after writing.
Actually, if you close a CryptoStream without flushing the final block,
it'll flush it for you. Not a bad idea to make it clear though.


That's what I thought, but I tried his example and reproduced problem.

Using Close without FlushFinalBlock corrupted the data, and with FlushFinalBlock
before Close it resolved the problem. I was able to see this in his code as well as a separate example I created.

In a decompilation of CryptoStream.Close I can clearly see where it calls
FlushFinalBlock, but only conditionally. Perhaps the TripleDES encryptor
doesn't correctly set this flag.


Never mind, I can't back this up. I just re-ran my test that illustrated
this and it's not behaving the same so I must have made some other change.
It does look like the problem is on the reading side.
Nov 15 '05 #8

P: n/a
your problem is that you do not provide "good" IV in

TripleDesProv.CreateEncryptor(bKey, null);

if you put the same array for encr and decr, it works fine:
private byte[] bIV;
...
bIV = str2bytes("tXesterX");

// and use

ict = tProvider.CreateEncryptor(bKey, bIV);

// and

ict = tProvider.CreateDecryptor(bKey, bIV);

*** Sent via Developersdex http://www.developersdex.com ***
Don't just participate in USENET...get rewarded for it!
Nov 16 '05 #9

This discussion thread is closed

Replies have been disabled for this discussion.