Home All Groups Group Topic Archive Search About

How to decrypt a string?

Author
8 Feb 2007 9:01 AM
Ralph Moritz
Hi group,

I'm trying to encrypt & then decrypt a string using symmetric
encryption. The encryption seems to work fine, but when trying to
decrypt, I get a System.IndexOutOfRangeException. Please would someone
be kind enough to point out my mistake? Please see my code (C++/CLI)
below.

TIA,
Ralph


System::String^ Quantum::Util::EncryptString(System::String^ str)
{
    using namespace System::IO;
    using namespace System::Security::Cryptography;

    MemoryStream^ ms = gcnew MemoryStream;
    RijndaelManaged^ rm = gcnew RijndaelManaged;
    CryptoStream^ cs = gcnew CryptoStream(ms, rm->CreateEncryptor(m_key, m_iv),
        CryptoStreamMode::Write);
    StreamWriter^ sw = gcnew StreamWriter(cs);

    try {
        sw->Write(str);
    } finally {
        sw->Close();
        cs->Close();
        ms->Close();
    }

    return System::Convert::ToBase64String(ms->ToArray());
}

System::String^ Quantum::Util::DecryptString(System::String^ str)
{
    using namespace System::IO;
    using namespace System::Security::Cryptography;

    MemoryStream^ ms = gcnew MemoryStream;
    RijndaelManaged^ rm = gcnew RijndaelManaged;
    CryptoStream^ cs = gcnew CryptoStream(ms, rm->CreateDecryptor(m_key, m_iv),
        CryptoStreamMode::Read);
    StreamWriter^ sw = gcnew StreamWriter(ms);
    StreamReader^ sr = gcnew StreamReader(cs);

    System::String^ cleartext;
    try {
        array<System::Byte>^ bytes = System::Convert::FromBase64String(str);
        sw->Write(bytes);
        cleartext = sr->ReadToEnd();
    } finally {
        sw->Close();
        sr->Close();
        cs->Close();
        ms->Close();
    }

    return cleartext;
}

Author
8 Feb 2007 12:30 PM
Kevin Spencer
To use the CryptoStream class, you create an instance of the class from a
stream, as you have done. Then you use a StreamWriter to write your input to
the CryptoStream, which you have also done. This writes the encrypted string
to the stream you initialized the CryptoStream with. At this point, your
MemoryStream contains a string; it is a stream of text. So, rather than
using the Convert.ToBase64String method, just create a StreamReader to read
the string from your MemoryStream.

--
HTH,

Kevin Spencer
Microsoft MVP
Software Composer
http://unclechutney.blogspot.com

The shortest distance between 2 points is a curve.

Show quote
"Ralph Moritz" <m*@ralphm.info> wrote in message
news:uk5ytrpk8.fsf@ralphm.info...
> Hi group,
>
> I'm trying to encrypt & then decrypt a string using symmetric
> encryption. The encryption seems to work fine, but when trying to
> decrypt, I get a System.IndexOutOfRangeException. Please would someone
> be kind enough to point out my mistake? Please see my code (C++/CLI)
> below.
>
> TIA,
> Ralph
>
>
> System::String^ Quantum::Util::EncryptString(System::String^ str)
> {
> using namespace System::IO;
> using namespace System::Security::Cryptography;
>
> MemoryStream^ ms = gcnew MemoryStream;
> RijndaelManaged^ rm = gcnew RijndaelManaged;
> CryptoStream^ cs = gcnew CryptoStream(ms, rm->CreateEncryptor(m_key,
> m_iv),
> CryptoStreamMode::Write);
> StreamWriter^ sw = gcnew StreamWriter(cs);
>
> try {
> sw->Write(str);
> } finally {
> sw->Close();
> cs->Close();
> ms->Close();
> }
>
> return System::Convert::ToBase64String(ms->ToArray());
> }
>
> System::String^ Quantum::Util::DecryptString(System::String^ str)
> {
> using namespace System::IO;
> using namespace System::Security::Cryptography;
>
> MemoryStream^ ms = gcnew MemoryStream;
> RijndaelManaged^ rm = gcnew RijndaelManaged;
> CryptoStream^ cs = gcnew CryptoStream(ms, rm->CreateDecryptor(m_key,
> m_iv),
> CryptoStreamMode::Read);
> StreamWriter^ sw = gcnew StreamWriter(ms);
> StreamReader^ sr = gcnew StreamReader(cs);
>
> System::String^ cleartext;
> try {
> array<System::Byte>^ bytes = System::Convert::FromBase64String(str);
> sw->Write(bytes);
> cleartext = sr->ReadToEnd();
> } finally {
> sw->Close();
> sr->Close();
> cs->Close();
> ms->Close();
> }
>
> return cleartext;
> }
Author
8 Feb 2007 1:34 PM
Ralph Moritz
"Kevin Spencer" <unclechut***@nothinks.com> writes:

> To use the CryptoStream class, you create an instance of the class from a
> stream, as you have done. Then you use a StreamWriter to write your input to
> the CryptoStream, which you have also done. This writes the encrypted string
> to the stream you initialized the CryptoStream with. At this point, your
> MemoryStream contains a string; it is a stream of text. So, rather than
> using the Convert.ToBase64String method, just create a StreamReader to read
> the string from your MemoryStream.

That won't work, I'm afraid. My program needs to encrypt a string and
write it to a config file. When the program starts up, it checks for
the existence of a config file, and tries to read the encrypted
connection string from the file. The problem I discovered early on is
that mixing text and binary data is a BAD IDEA, so I have to Base64
encode the string before writing it to the config file. Logically
then, it follows that I need to Base64 decode the string before
attempting to decrypt it.
Author
8 Feb 2007 4:09 PM
Kevin Spencer
Not at all. The MemoryStream already contains a string. In essence, you are
converting a string to another string.

--
HTH,

Kevin Spencer
Microsoft MVP
Software Composer
http://unclechutney.blogspot.com

The shortest distance between 2 points is a curve.

Show quote
"Ralph Moritz" <m*@ralphm.info> wrote in message
news:usldg93iv.fsf@ralphm.info...
> "Kevin Spencer" <unclechut***@nothinks.com> writes:
>
>> To use the CryptoStream class, you create an instance of the class from a
>> stream, as you have done. Then you use a StreamWriter to write your input
>> to
>> the CryptoStream, which you have also done. This writes the encrypted
>> string
>> to the stream you initialized the CryptoStream with. At this point, your
>> MemoryStream contains a string; it is a stream of text. So, rather than
>> using the Convert.ToBase64String method, just create a StreamReader to
>> read
>> the string from your MemoryStream.
>
> That won't work, I'm afraid. My program needs to encrypt a string and
> write it to a config file. When the program starts up, it checks for
> the existence of a config file, and tries to read the encrypted
> connection string from the file. The problem I discovered early on is
> that mixing text and binary data is a BAD IDEA, so I have to Base64
> encode the string before writing it to the config file. Logically
> then, it follows that I need to Base64 decode the string before
> attempting to decrypt it.
Author
8 Feb 2007 7:27 PM
Jon Skeet [C# MVP]
Kevin Spencer <unclechut***@nothinks.com> wrote:
> Not at all. The MemoryStream already contains a string. In essence, you are
> converting a string to another string.

No. Encryption works on binary data, and it's not safe to treat
arbitrary binary data as if it were valid text data.

The OP is quite right to convert the encrypted bytes into a string
using Base64 and then convert the Base64 data back into bytes before
decryption.

What he's doing wrong is using StreamWriter.Write(bytes) instead of
just writing the converted data directly into the MemoryStream.

The encryption is:
Plaintext String -> Encrypted bytes -> Base64

The decrypion should thus be:
Base64 -> Encrypted bytes -> Plaintext String

Currently it's

Base64 -> Encrypted bytes -> ToString() -> Plaintext String

The call to ToString() is in the StreamWriter.Write(object) call.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet   Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Author
9 Feb 2007 11:03 AM
Kevin Spencer
Hi Jon,

In this case, it's not arbitrary data. It's a string. The methods are
strongly-typed to encrypt and decrypt string data.

--
HTH,

Kevin Spencer
Microsoft MVP
Software Composer
http://unclechutney.blogspot.com

The shortest distance between 2 points is a curve.

Show quote
"Jon Skeet [C# MVP]" <sk***@pobox.com> wrote in message
news:MPG.20358a0e69737cc698d836@msnews.microsoft.com...
> Kevin Spencer <unclechut***@nothinks.com> wrote:
>> Not at all. The MemoryStream already contains a string. In essence, you
>> are
>> converting a string to another string.
>
> No. Encryption works on binary data, and it's not safe to treat
> arbitrary binary data as if it were valid text data.
>
> The OP is quite right to convert the encrypted bytes into a string
> using Base64 and then convert the Base64 data back into bytes before
> decryption.
>
> What he's doing wrong is using StreamWriter.Write(bytes) instead of
> just writing the converted data directly into the MemoryStream.
>
> The encryption is:
> Plaintext String -> Encrypted bytes -> Base64
>
> The decrypion should thus be:
> Base64 -> Encrypted bytes -> Plaintext String
>
> Currently it's
>
> Base64 -> Encrypted bytes -> ToString() -> Plaintext String
>
> The call to ToString() is in the StreamWriter.Write(object) call.
>
> --
> Jon Skeet - <sk***@pobox.com>
> http://www.pobox.com/~skeet   Blog: http://www.msmvps.com/jon.skeet
> If replying to the group, please do not mail me too
Author
9 Feb 2007 11:24 AM
Jon Skeet [C# MVP]
On Feb 9, 11:03 am, "Kevin Spencer" <unclechut***@nothinks.com> wrote:
> In this case, it's not arbitrary data. It's a string. The methods are
> strongly-typed to encrypt and decrypt string data.

It starts off as a string, but encryption will turn it into arbitrary
binary data. An encrypted version of a UTF-8 string isn't necessarily
(and often won't be) a valid UTF-8 encoded string. Converting
encrypted data into a string just using Encoding.UTF8 (or the like) is
very, very likely to lose data. It's like trying to load up the
contents of a jpeg file as a string, pass that to someone else to
write out, and then expecting it to still load. It just won't work (in
the general case).

Base64 is absolutely the way to go here.

Jon
Author
9 Feb 2007 9:44 PM
Kevin Spencer
I'll take your word for it, Jon. :-)

--

Kevin Spencer
Microsoft MVP
Software Composer
http://unclechutney.blogspot.com

The shortest distance between 2 points is a curve.

Show quote
"Jon Skeet [C# MVP]" <sk***@pobox.com> wrote in message
news:1171020253.363695.126490@m58g2000cwm.googlegroups.com...
> On Feb 9, 11:03 am, "Kevin Spencer" <unclechut***@nothinks.com> wrote:
>> In this case, it's not arbitrary data. It's a string. The methods are
>> strongly-typed to encrypt and decrypt string data.
>
> It starts off as a string, but encryption will turn it into arbitrary
> binary data. An encrypted version of a UTF-8 string isn't necessarily
> (and often won't be) a valid UTF-8 encoded string. Converting
> encrypted data into a string just using Encoding.UTF8 (or the like) is
> very, very likely to lose data. It's like trying to load up the
> contents of a jpeg file as a string, pass that to someone else to
> write out, and then expecting it to still load. It just won't work (in
> the general case).
>
> Base64 is absolutely the way to go here.
>
> Jon
>

AddThis Social Bookmark Button