|
dev
newsgroups
|
|||||||||||||||||||||||
|
|||||||||||||||||||||||
How to decrypt a string?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; } 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. -- Show quoteHTH, Kevin Spencer Microsoft MVP Software Composer http://unclechutney.blogspot.com The shortest distance between 2 points is a curve. "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; > } "Kevin Spencer" <unclechut***@nothinks.com> writes: That won't work, I'm afraid. My program needs to encrypt a string and> 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. 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. Not at all. The MemoryStream already contains a string. In essence, you are
converting a string to another string. -- Show quoteHTH, Kevin Spencer Microsoft MVP Software Composer http://unclechutney.blogspot.com The shortest distance between 2 points is a curve. "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. Kevin Spencer <unclechut***@nothinks.com> wrote:
> Not at all. The MemoryStream already contains a string. In essence, you are No. Encryption works on binary data, and it's not safe to treat > converting a string to another string. 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 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. -- Show quoteHTH, Kevin Spencer Microsoft MVP Software Composer http://unclechutney.blogspot.com The shortest distance between 2 points is a curve. "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 On Feb 9, 11:03 am, "Kevin Spencer" <unclechut***@nothinks.com> wrote: It starts off as a string, but encryption will turn it into arbitrary> In this case, it's not arbitrary data. It's a string. The methods are > strongly-typed to encrypt and decrypt string data. 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 I'll take your word for it, Jon. :-)
-- Show quoteKevin Spencer Microsoft MVP Software Composer http://unclechutney.blogspot.com The shortest distance between 2 points is a curve. "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 > |
|||||||||||||||||||||||