Level Extreme platform
Subscription
Corporate profile
Products & Services
Support
Legal
Français
VFPEncryption.fll implementation
Message
From
15/10/2014 05:43:14
 
 
To
14/10/2014 14:34:04
General information
Forum:
ASP.NET
Category:
Coding, syntax and commands
Environment versions
Environment:
VB 9.0
OS:
Windows Server 2008
Network:
Windows 2003 Server
Database:
MS SQL Server
Application:
Desktop
Miscellaneous
Thread ID:
01609313
Message ID:
01609402
Views:
131
This message has been marked as the solution to the initial question of the thread.
>>>>>In a VFP application I use VFPEncryption.fll to encrypt a password string.
>>>>>Now I need to be able to use the password from a .NET application (C#), so I need to decrypt the string that is saved in the table using C#. I wonder if there is an equivalent code for the decryption when the string was encrypted with VFPEncryption?
>>>>>
>>>>>The only workaround would be to create a com object from VFP, but if there is an easier solution I would be glad.
>>>>
>>>>
>>>>Depending on what you're using you may be able to use RijndaelManaged http://msdn.microsoft.com/en-us/library/system.security.cryptography.rijndaelmanaged(v=vs.110).aspx
>>>
>>>Thanks, that seems to be the right way. However I do not understand how to deal with the "Salt" variable, since in the VFPEncryption we don't use that. We only have the string and the password, however the class in .NET requires the salt to be 8 bytes.
>>>
>>>var algorithm = new RijndaelManaged { KeySize = 256, BlockSize = 128 };
>>>var key = new Rfc2898DeriveBytes(password, Encoding.ASCII.GetBytes(""));
>>>
>>>In the second line it says "Salt is not at least eight bytes". When I put in 8 spaces or 8 zeros it does not throw an error, but the resulting string is completely incorrect. Do you have any idea what could be the "Default" salt?
>>
>>
>>I'll have a look at it in the morning
>>
>>But first, before I can say anything useful - I have to see the vfp code used to both encrypt and decrypt
>>
>>UPDATE
>>
>>And an example - with hex output
>
>The code is just using the defaults (the security requirements are very low):
>AES256
>ECB
>
>LOCAL lcString, lcKey, lcEncryptedString
>lcString = "Hello World"
>lcKey = "abcdefghijasdflkgdfkisluguslijon"
>lcEncryptedString = Encrypt (lcString, lcKey) && Result: ÕÖì/ŸŒ@‘PŒ{'VûGuï…‰È*RÞÖ¸‚þ.÷}
>lcString = Decrypt(lcEncryptedString, lcKey) && Result: Hello World
>
(1) you don't need Rfc2898DeriveBytes()
(2) I've changed the vfp code - added the defaults - reads better for me
function EncryptionTest_Christian2()

	set library to D:\tmp\In\vfpencryption90\vfpencryption.fll additive
	
	
	local nEncryptionType, nEncryptionMode, nPaddingType, nKeySize, nBlockSize, cIV
	
	nEncryptionType = 2 &&  = Rijndael\AES 256 (requires a 32 character Key) *Default
	nEncryptionMode = 0 &&	= ECB *Default
	nPaddingType	= 0 &&	= Zeroes (NULLs) *Default
	nKeySize		= 32	&& 
	nBlockSize		= 32
	cIV 			= replicate(chr(0), nBlockSize)
	
	LOCAL lcString, lcKey, lcEncryptedString
	lcString = "Hello World"
	lcKey = "abcdefghijasdflkgdfkisluguslijon"
	lcEncryptedString = Encrypt (lcString, lcKey, ;
				nEncryptionType, nEncryptionMode, nPaddingType, nKeySize, nBlockSize, cIV) && Result: ÕÖì/ŸŒ@‘PŒ{'VûGuï…‰È*RÞÖ¸‚þ.÷}
	lcString = Decrypt(lcEncryptedString, lcKey, ;
					nEncryptionType, nEncryptionMode, nPaddingType, nKeySize, nBlockSize, cIV	) && Result: Hello World
		
	?strconv(lcEncryptedString,15)
	_cliptext = strconv(lcEncryptedString,15)
	?lcString 
(3) The code in C#
(a) The padding with zeroes is not the best of ideas. The decryption leaves the trailing zeroes which have to be trimmed - and what if the original had trailing zeroes ?
Better use PKCS7

(b) You have to store the encryped value in a byte[] array - not a string
	static class Encryption_Christian_Test
	{

		internal static void Go()
		{
			string original = @"Hello World";
			string key = @"abcdefghijasdflkgdfkisluguslijon";

			byte[] encrypted = Encryption_Christian.Encrypt(original, key);
			string encryptedHex = HexBits.ToHex(encrypted);
			string expected = @"D5D6EC2F9F8C4091508C7B2756FB4775EF168589C80B2A52DED6B882FE2EF77D";
			Console.WriteLine("Encrypt >> OK: {0} Value: {1}", expected == encryptedHex, encryptedHex);

			string decrypted = Encryption_Christian.Decrypt(encrypted, key);
			// decrypted = padded with hex zeroes
			// better use PaddingMode.PKCS7

			decrypted = decrypted.TrimEnd(new char[1]); // to get the hex zeroes off at the end
			Console.WriteLine("Decrypt >> OK: {0} Value: {1}", original == decrypted, decrypted);


		}
	}
	internal static class Encryption_Christian
	{

		static RijndaelManaged Cryptor;


		static int BitsPerByte = 8;

		static int BlockSizeBytes = 32;

		static byte[] IV = new byte[BlockSizeBytes];

		static int KeySizeBytes = 32;

		static Encryption_Christian()
		{
			Cryptor = new RijndaelManaged();
			Cryptor.BlockSize = BlockSizeBytes * BitsPerByte;
			Cryptor.KeySize = KeySizeBytes * BitsPerByte;
			Cryptor.Mode = CipherMode.ECB;
			Cryptor.Padding = PaddingMode.Zeros;

		}

		static internal byte[] Encrypt(string s, string key)
		{
			byte[] keyBytes = ToBytes(key);
			byte[] encrypted;

			using (MemoryStream output = new MemoryStream())
			{
				using (ICryptoTransform encryptor = Cryptor.CreateEncryptor(keyBytes, IV))
				{
					using (CryptoStream crypto = new CryptoStream(output, encryptor, CryptoStreamMode.Write))
					{
						using (StreamWriter input = new StreamWriter(crypto))
						{
							input.Write(s);
							input.Flush(); // just in case

						}

					}

				}
				encrypted = output.ToArray();
			}

			return encrypted;
		}
		internal static string Decrypt(byte[] encrypted, string key)
		{
			byte[] keyBytes = ToBytes(key);

			string decrypted;
			using (MemoryStream input = new MemoryStream(encrypted))
			{
				using (ICryptoTransform decryptor = Cryptor.CreateDecryptor(keyBytes, IV))
				{
					using (CryptoStream crypto = new CryptoStream(input, decryptor, CryptoStreamMode.Read))
					{
						using (StreamReader output = new StreamReader(crypto))
						{
							decrypted = output.ReadToEnd();
						}

					}

				}

			}

			return decrypted;
		}
		static byte[] ToBytes(string s)
		{
			
			byte[] result = Encoding.Default.GetBytes(s);
			if (s.Length != result.Length)
				throw new ArgumentException("wrong resulting byte[] conversion length", "s");
			return result;
		}

	}
	internal static class HexBits
	{

		internal static string ToHex(byte[] bytes)
		{
			StringBuilder sb = new StringBuilder(bytes.Length << 1);
			for (int i = 0; i < bytes.Length; i++)
				sb.Append(bytes[i].ToString("X2"));
			return sb.ToString();
		}
	}
Gregory
Previous
Next
Reply
Map
View

Click here to load this message in the networking platform