C# returns the following base64 encoded string:
joxzS5XnP63ymrhy6t4ogWK9TxwfwD83
below is the code in c#
us
ing System.IO;
using System;
using System.Text;
using System.Security.Cryptography;
class Program
{
static void Main()
{
// Read in every line in the file.
using (StreamReader reader = new StreamReader("input.txt"))
{
string abc = "string to encrypt";
Program p = new Program();
string value = p.Encrypt(abc, true);
Console.Write(value);
}
}
public string Encrypt(string toEncrypt, bool useHashing)
{
byte[] keyArray;
byte[] toEncryptArray = UTF8Encoding.UTF8.GetBytes(toEncrypt);
//System.Configuration.AppSettingsReader settingsReader = new AppSettingsReader();
// Get the key from config file
string key = "encrypt key";
//System.Windows.Forms.MessageBox.Show(key);
if (useHashing)
{
MD5CryptoServiceProvider hashmd5 = new MD5CryptoServiceProvider();
keyArray = hashmd5.ComputeHash(UTF8Encoding.UTF8.GetBytes(key));
hashmd5.Clear();
}
else
keyArray = UTF8Encoding.UTF8.GetBytes(key);
TripleDESCryptoServiceProvider tdes = new TripleDESCryptoServiceProvider();
tdes.Key = keyArray;
tdes.Mode = CipherMode.ECB;
tdes.Padding = PaddingMode.PKCS7;
ICryptoTransform cTransform = tdes.CreateEncryptor();
byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);
tdes.Clear();
return Convert.ToBase64String(resultArray, 0, resultArray.Length);
}
}
I am using MCrypt library in PHP which returns
ThPKJ1BPJLeUwJtIT/zAs3ocZ2s6SU+M
PHP code:
$str = "string to encrypt";
$input = utf8_encode($str);
$key = "encrypt key";
echo apiEncode($input, $key);
function apiEncode($data, $secret)
{
//Generate a key from a hash
$key = md5(utf8_encode($secret), true);
//Create init vector
$iv = mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_3DES, MCRYPT_MODE_ecb), MCRYPT_RAND);
//Pad for PKCS7
$blockSize = mcrypt_get_block_size('tripledes', 'ecb');
$len = strlen($data);
$pad = $blockSize - ($len % $blockSize);
$data .= str_repeat(chr($pad), $pad);
//Encrypt data
$encData = mcrypt_encrypt('tripledes', $key, $data, 'ecb'); //, $iv);
return base64_encode($encData);
}
apart from the above I have tried various other solutions found at so
tripledes encryption not yielding same results in PHP and C#
TripleDES Encrypting in C# and PHP not coming out the same (PKCS7, ECB)?
Your C# code does not set an IV, thus your IV will be a block of zeroes. I do not know PHP, but I strongly suspect that mcrypt_create_iv() creates a non-trivial IV.
Apart from that, you should consider CBC-mode instead of ECB-mode.
Considering the Security vulnerabilities of DES and TripleDES, implemented AES/RIJNDAEL_256 algo at both the sides.
C#
public String DecryptRJ256(string cypher, string KeyString, string IVString)
{
string sRet = string.Empty;
RijndaelManaged rj = new RijndaelManaged();
UTF8Encoding encoding = new UTF8Encoding();
byte[] decbuff = Convert.FromBase64String(cypher);
try
{
byte[] Key = encoding.GetBytes(KeyString);
byte[] IV = encoding.GetBytes(IVString);
rj.Padding = PaddingMode.PKCS7;
rj.Mode = CipherMode.CBC;
rj.KeySize = 256;
rj.BlockSize = 256;
rj.Key = Key;
rj.IV = IV;
MemoryStream ms = new MemoryStream(decbuff);
using (CryptoStream cs = new CryptoStream(ms, rj.CreateDecryptor(Key, IV), CryptoStreamMode.Read))
{
using (StreamReader sr = new StreamReader(cs))
{
sRet = sr.ReadToEnd();
}
}
}
finally
{
rj.Clear();
}
return sRet;
}
public string Encrypt(string message, string KeyString, string IVString)
{
byte[] Key = ASCIIEncoding.UTF8.GetBytes(KeyString);
byte[] IV = ASCIIEncoding.UTF8.GetBytes(IVString);
string encrypted = null;
RijndaelManaged rj = new RijndaelManaged();
rj.BlockSize = 256;
rj.Key = Key;
rj.IV = IV;
rj.Mode = CipherMode.CBC;
try
{
MemoryStream ms = new MemoryStream();
using (CryptoStream cs = new CryptoStream(ms, rj.CreateEncryptor(Key, IV), CryptoStreamMode.Write))
{
using (StreamWriter sw = new StreamWriter(cs))
{
sw.Write(message);
sw.Close();
}
cs.Close();
}
byte[] encoded = ms.ToArray();
encrypted = Convert.ToBase64String(encoded);
ms.Close();
}
catch (CryptographicException e)
{
Console.WriteLine("A Cryptographic error occurred: {0}", e.Message);
return null;
}
catch (UnauthorizedAccessException e)
{
Console.WriteLine("A file error occurred: {0}", e.Message);
return null;
}
catch (Exception e)
{
Console.WriteLine("An error occurred: {0}", e.Message);
}
finally
{
rj.Clear();
}
return encrypted;
}
PHP
public function apiEncode($text, $key, $iv)
{
// to append string with trailing characters as for PKCS7 padding scheme
$block = mcrypt_get_block_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CBC);
$padding = $block - (strlen($text) % $block);
$text .= str_repeat(chr($padding), $padding);
$crypttext = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, $text, MCRYPT_MODE_CBC, $iv);
return base64_encode($crypttext);
}
publc function apiDecode($text, $key, $iv){
$text = base64_decode($text);
$crypttext = mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $key, $text, MCRYPT_MODE_CBC, $iv);
return $crypttext;
}
Related
I am decrypting a message in C#, this message is encrypted in PHP using below code:-
public function __construct($sEncryptionKey)
{
$this->link = mcrypt_module_open('tripledes', '', 'ecb', '');
$this->sInitializationVector = mcrypt_create_iv(mcrypt_enc_get_iv_size($this->link), MCRYPT_RAND);
$this->iKeySize = mcrypt_enc_get_key_size($this->link);
$sEncryptionKey = substr(md5($sEncryptionKey), 0, $this->iKeySize);
mcrypt_generic_init($this->link, $sEncryptionKey, $this->sInitializationVector);
}
public function encrypt($sDataToEncrypt)
{
return base64_encode(mcrypt_generic($this->link, $sDataToEncrypt));
}
And I am using below decryption function in c# for decryption:-
public string Decrypt(string toDecrypt, string key, bool useHashing)
{
byte[] keyArray;
byte[] toEncryptArray = Convert.FromBase64String(toDecrypt);
if (useHashing)
{
MD5CryptoServiceProvider hashmd5 = new MD5CryptoServiceProvider();
keyArray = hashmd5.ComputeHash(UTF8Encoding.UTF8.GetBytes(key));
hashmd5.Clear();
}
else
{
keyArray = UTF8Encoding.UTF8.GetBytes(key);
}
TripleDESCryptoServiceProvider tdes = new TripleDESCryptoServiceProvider();
tdes.Key = keyArray;
tdes.Mode = CipherMode.ECB;
tdes.Padding = PaddingMode.Zeros;
ICryptoTransform cTransform = tdes.CreateDecryptor();
byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);
tdes.Clear();
var strValue = UTF8Encoding.UTF8.GetString(resultArray);
return UTF8Encoding.UTF8.GetString(resultArray);
}
I tried with few changes and getting below results:-
1.) PaddingMode.PKCS7 with no hashing = "Specified key is not a valid size for this algorithm."
2.) PaddingMode.PKCS7 with hashing = "Bad Data."
3.) PaddingMode.Zeros with no hashing = "Specified key is not a valid size for this algorithm."
4.) PaddingMode.Zeros with hashing = "�8�f����q6IGs�" some unknown characters
I think 4'th one will work, but not sure what I am doing wrong.
Found a solution, need to do changes in MD5 hashing, below are whole code if someone stuck in same situation :-
public string Decrypt(string toDecrypt, string key, bool useHashing)
{
TripleDESCryptoServiceProvider tdes = new TripleDESCryptoServiceProvider();
byte[] keyArray;
byte[] toEncryptArray = Convert.FromBase64String(toDecrypt);
string keyArrayStr = "";
if (useHashing)
{
MD5 md5 = MD5CryptoServiceProvider.Create();
byte[] dataMd5 = md5.ComputeHash(Encoding.Default.GetBytes(key));
StringBuilder sb = new StringBuilder();
for (int i = 0; i < dataMd5.Length; i++)
sb.AppendFormat("{0:x2}", dataMd5[i]);
keyArrayStr = sb.ToString().Substring(0, tdes.Key.Length);
keyArray = UTF8Encoding.UTF8.GetBytes(keyArrayStr);
}
else
{
keyArray = UTF8Encoding.UTF8.GetBytes(key);
}
tdes.Key = keyArray;
tdes.Mode = CipherMode.ECB;
tdes.Padding = PaddingMode.Zeros;
ICryptoTransform cTransform = tdes.CreateDecryptor();
byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);
tdes.Clear();
var strValue = UTF8Encoding.UTF8.GetString(resultArray);
return UTF8Encoding.UTF8.GetString(resultArray);
}
I use RJ256 to login, since the return string is fairly small, it works (PHP gives encrypted string and C# needs to decrypt).
The data gets decrypted and fully works. Although, now I am transferring a 79KB string from PHP (Encrypted) to C# (Needs to Decrypt) and I get this error:
http://i.imgur.com/M4sgEct.png
This error only happens when the string is a bit larger than normally.
Here is my PHP code to encrypt:
private function _encrypt($data)
{
$iv = "sfhfskfsusfdsfd79fd8s79sdf789f79";
$key = "da4b9237bacccdf1";
// to append string with trailing characters as for PKCS7 padding scheme
$block = mcrypt_get_block_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CBC);
$padding = $block - (strlen($data) % $block);
$data .= str_repeat(chr($padding), $padding);
$crypttext = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, $data, MCRYPT_MODE_CBC, $iv);
// this is not needed here
//$crypttext = urlencode($crypttext);
return base64_encode($crypttext);
}
Here is my C# Code to decrypt:
public static dynamic DecryptRJ256(string cypher, bool isJson = true, bool getBytes = false)
{
string sRet;
var encoding = new UTF8Encoding();
var key = encoding.GetBytes("da4b9237bacccdf1");
var iv = encoding.GetBytes("sfhfskfsusfdsfd79fd8s79sdf789f79");
using (var rj = new RijndaelManaged())
{
try
{
rj.Padding = PaddingMode.PKCS7;
rj.Mode = CipherMode.CBC;
rj.KeySize = 256;
rj.BlockSize = 256;
rj.Key = key;
rj.IV = iv;
var ms = new MemoryStream(Decode(cypher));
using (var cs = new CryptoStream(ms, rj.CreateDecryptor(key, iv), CryptoStreamMode.Read))
{
using (var sr = new StreamReader(cs))
{
sRet = sr.ReadLine();
}
}
}
finally
{
rj.Clear();
}
}
// ReSharper disable once AssignNullToNotNullAttribute
return (isJson ? JsonConvert.DeserializeObject<dynamic>(sRet) : (getBytes ? Encoding.UTF8.GetBytes(sRet) : (dynamic)sRet));
}
How can I make it work?
How about this:
public static byte[] DecryptRJ256(string prm_key, string prm_iv, string prm_text_to_decrypt)
{
var sEncryptedString = prm_text_to_decrypt;
var myRijndael = new RijndaelManaged();
myRijndael.Padding = PaddingMode.Zeros;
myRijndael.Mode = CipherMode.CBC;
myRijndael.KeySize = 256;
myRijndael.BlockSize = 256;
byte[] key;
byte[] IV;
key = Encoding.ASCII.GetBytes(prm_key);
IV = Encoding.ASCII.GetBytes(prm_iv);
var decryptor = myRijndael.CreateDecryptor(key, IV);
var sEncrypted = Convert.FromBase64String(sEncryptedString);
var fromEncrypt = new byte[sEncrypted.Length];
var msDecrypt = new MemoryStream(sEncrypted);
var csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read);
csDecrypt.Read(fromEncrypt, 0, fromEncrypt.Length);
//Return (System.Text.Encoding.ASCII.GetString(fromEncrypt))
return fromEncrypt;
}
I am facing some issues in AES encryption using PHP and decode the same using C #. My reference site.
Here is the PHP code:
function encrypt_string($input, $key)
{
$iv = mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC), MCRYPT_RAND);
return preg_replace('/=/', "", base64_encode($iv . mcrypt_encrypt(MCRYPT_RIJNDAEL_128, hash("sha256", $key, true), $input, MCRYPT_MODE_CBC, $iv)));
}
function decrypt_string($input, $key)
{
$input .= "=";
$data = base64_decode($input);
$iv = substr($data, 0, mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC));
return rtrim(mcrypt_decrypt(MCRYPT_RIJNDAEL_128,hash('sha256', $key, true),substr($data, mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC)),MCRYPT_MODE_CBC,$iv),"\0");
}
Here is C# code that I tried:
private static byte[] sha256_data(string input)
{
SHA256 hash = SHA256Managed.Create();
Encoding encode = Encoding.UTF8;
return hash.ComputeHash(encode.GetBytes(input));
}
private string encode_data(string data, string key)
{
byte[] buff;
RijndaelManaged rij = new RijndaelManaged();
rij.BlockSize = 256;
rij.KeySize = 256;
rij.GenerateIV();
rij.Key = sha256_data(key);
rij.Mode = CipherMode.CBC;
ICryptoTransform encoder = rij.CreateEncryptor(rij.Key, rij.IV);
using (MemoryStream mem = new MemoryStream())
{
using (CryptoStream crypt = new CryptoStream(mem, encoder, CryptoStreamMode.Write))
{
byte[] temp = Encoding.UTF8.GetBytes(data);
crypt.Write(temp, 0, temp.Length);
}
buff = mem.ToArray();
}
return Convert.ToBase64String(result);
}
private string decode_data(string input, string key)
{
RijndaelManaged rij = new RijndaelManaged();
rij.KeySize = 256;
rij.BlockSize = 256;
rij.Key = sha256_data(key);
rij.GenerateIV();
rij.Mode = CipherMode.CBC;
rij.Padding = PaddingMode.PKCS7;
ICryptoTransform decrypter = rij.CreateDecryptor();
byte[] buff;
using (MemoryStream mem = new MemoryStream())
{
using (CryptoStream cstream = new CryptoStream(mem, decrypter, CryptoStreamMode.Write))
{
byte[] data = Convert.FromBase64String(input);
cstream.Write(data, 0, data.Length);
}
buff = mem.ToArray();
}
return Encoding.UTF8.GetString(buff);
}
What am i doing wrong?
when you decode you must parse the IV that was used for encoding not generate a new one.
I have almost lost my hair, mind and everything else! I have been trying to convert this PHP function to C#:
function encrypt_decrypt($action, $string) {
$output = false;
$key = 'My strong secret key';
// initialization vector
$iv = md5(md5($key));
$output = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, md5($key), $string, MCRYPT_MODE_CBC, $iv);
$output = bin2hex($output);
return $output;
}
I have been working with Rijandel Class:
function encrypt_decrypt(string password) {
UTF8Encoding encoding = new UTF8Encoding();
// For consistency with PHP function, MD5Encrypt applies MD5 encryption and does a bin2hex
byte[] Key = Encoding.ASCII.GetBytes(MD5Encrypt(password).ToLower());
byte[] IV = Encoding.ASCII.GetBytes(MD5Encrypt(MD5Encrypt(password).ToLower()).ToLower());
RijndaelManaged rj = new RijndaelManaged();
rj.BlockSize = 256;
rj.KeySize = 256;
rj.Key = Key;
rj.IV = IV;
rj.Mode = CipherMode.CBC;
MemoryStream ms = new MemoryStream();
using (CryptoStream cs = new CryptoStream(ms, rj.CreateEncryptor(Key, IV), CryptoStreamMode.Write))
{
using (StreamWriter sw = new StreamWriter(cs))
{
sw.Write(message);
sw.Close();
}
cs.Close();
}
byte[] encoded = ms.ToArray();
string output = "";
foreach (var ele in encoded)
{
output += ele.ToString("X2");
}
return output;
}
I have been validating the output of the PHP code with that from the C# code and they do not match. (http://writecodeonline.com/php/). Any feedback would be appreciated.
There are multiple issues to be kept in mind while doing this like converting binary, checking encoding and padding issues. Since we cannot see your complete code we are helpless in this case. Check this tutorial for further info: http://blog.djekldevelopments.co.uk/?p=334
Try this instead:
using (RijndaelManaged myRijndael = new RijndaelManaged())
{
myRijndael.Key = Encoding.UTF8.GetBytes(password);
string strIv16 = "\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0";
myRijndael.IV = Encoding.UTF8.GetBytes(strIv16);
// Encrypt the string to an array of bytes.
byte[] encrypted = EncryptStringToBytes(message, myRijndael.Key, myRijndael.IV);
string output = Convert.ToBase64String(encrypted);
}
I was using a REST service written in PHP in my android app without much trouble. Now I'm trying to use it in a Windows Phone app and I'm getting crazy already!
What I know so far: Silverlight will accept only Aes in CBC mode and PKCS7 padding.
What I get: "Padding is invalid and can not be removed" exception at (see full code at the bottom):
plaintext = srDecrypt.ReadToEnd();
If I crypt and decrypt in C#, using the same configs, it works fine. When I try to decript in C# from a PHP crypted string, it fails with the error mentioned above.
My PHP script do the following:
function encrypt128($message) {
$vector = "DB96A56CCA7A69FC";
$key = "6DBC44F54CA3CFDEDDCA140CA46A99C1"; // PHP md5 function leaves it in lower case, so I just copied the key from C# debug.
//PKCS7 Padding
$block = mcrypt_get_block_size('rijndael_128', 'cbc');
$pad = $block - (strlen($message) % $block);
$message.= str_repeat(chr($pad), $pad);
$cipher = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', 'cbc', '');
mcrypt_generic_init($cipher, $key, $vector);
$result = mcrypt_generic($cipher, $message);
mcrypt_generic_deinit($cipher);
return base64_encode($result);
}
And in C# (Silverlight / Windows Phone 7) I use the following to decrypt:
//Where buffer is the string data I got after calling the PHP REST service.
DecryptStringFromBytes(Convert.FromBase64String(buffer), MD5Core.GetHash("7a272d3e41372c547a272d3e41372c54"), System.Text.Encoding.UTF8.GetBytes("DB96A56CCA7A69FC"));
static string DecryptStringFromBytes(byte[] cipherText, byte[] Key, byte[] IV)
{
// Check arguments.
if (cipherText == null || cipherText.Length <= 0)
throw new ArgumentNullException("cipherText");
if (Key == null || Key.Length <= 0)
throw new ArgumentNullException("Key");
if (IV == null || IV.Length <= 0)
throw new ArgumentNullException("Key");
// Declare the string used to hold
// the decrypted text.
string plaintext = null;
// Create an RijndaelManaged object
// with the specified key and IV.
using (AesManaged rijAlg = new AesManaged())
{
rijAlg.Key = Key;
rijAlg.IV = IV;
// Create a decrytor to perform the stream transform.
ICryptoTransform decryptor = rijAlg.CreateDecryptor(rijAlg.Key, rijAlg.IV);
// Create the streams used for decryption.
using (MemoryStream msDecrypt = new MemoryStream(cipherText))
{
using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
{
using (StreamReader srDecrypt = new StreamReader(csDecrypt))
{
// Read the decrypted bytes from the decrypting stream
// and place them in a string.
plaintext = srDecrypt.ReadToEnd();
}
}
}
}
return plaintext;
}
The big question is: what am I doing wrong?
Thanks in advance!
So here is the answer:
I droped the MD5 crap out of PHP and C#, and they are now working properly.
Just in case you dropped here looking for the same answer, here is a sample code. Don't forget to make your own key and iv (although those bellow will work, is not recommended to use!)
PHP:
function encrypt128($message) {
$vector = "0000000000000000";
$key = "00000000000000000000000000000000";
$block = mcrypt_get_block_size('rijndael_128', 'cbc');
$pad = $block - (strlen($message) % $block);
$message .= str_repeat(chr($pad), $pad);
$cipher = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', 'cbc', '');
mcrypt_generic_init($cipher, $key, $vector);
$result = mcrypt_generic($cipher, $message);
mcrypt_generic_deinit($cipher);
return base64_encode($result);
}
C#:
byte[] cripted = EncryptStringToBytes("Test", System.Text.Encoding.UTF8.GetBytes("00000000000000000000000000000000"), System.Text.Encoding.UTF8.GetBytes("0000000000000000"));
Encrypt/Decrypt using PHP:
class Cipher {
private $key, $iv;
function __construct() {
$this->key = "edrtjfjfjlldldld";
$this->iv = "56666852251557009888889955123458";
}
function encrypt($text) {
$block = mcrypt_get_block_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CBC);
$padding = $block - (strlen($text) % $block);
$text .= str_repeat(chr($padding), $padding);
$crypttext = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $this->key, $text, MCRYPT_MODE_CBC, $this->iv);
return base64_encode($crypttext);
}
function decrypt($input) {
$dectext = mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $this->key, base64_decode($input), MCRYPT_MODE_CBC, $this->iv);
return $dectext;
}
}
Encrypt/Decrypt using C#:
public class RijndaelSimple
{
const string iv = "56666852251557009888889955123458";
const string key = "edrtjfjfjlldldld";
static public String EncryptRJ256(string plainText)
{
var encoding = new UTF8Encoding();
var Key = encoding.GetBytes(key);
var IV = encoding.GetBytes(iv);
byte[] encrypted;
using (var rj = new RijndaelManaged())
{
try
{
rj.Padding = PaddingMode.PKCS7;
rj.Mode = CipherMode.CBC;
rj.KeySize = 256;
rj.BlockSize = 256;
rj.Key = Key;
rj.IV = IV;
var ms = new MemoryStream();
using (var cs = new CryptoStream(ms, rj.CreateEncryptor(Key, IV), CryptoStreamMode.Write))
{
using (var sr = new StreamWriter(cs))
{
sr.Write(plainText);
}
encrypted = ms.ToArray();
}
}
finally
{
rj.Clear();
}
}
return Convert.ToBase64String(encrypted);
}
static public String DecryptRJ256(string input)
{
byte[] cypher = Convert.FromBase64String(input);
var sRet = "";
var encoding = new UTF8Encoding();
var Key = encoding.GetBytes(key);
var IV = encoding.GetBytes(iv);
using (var rj = new RijndaelManaged())
{
try
{
rj.Padding = PaddingMode.PKCS7;
rj.Mode = CipherMode.CBC;
rj.KeySize = 256;
rj.BlockSize = 256;
rj.Key = Key;
rj.IV = IV;
var ms = new MemoryStream(cypher);
using (var cs = new CryptoStream(ms, rj.CreateDecryptor(Key, IV), CryptoStreamMode.Read))
{
using (var sr = new StreamReader(cs))
{
sRet = sr.ReadLine();
}
}
}
finally
{
rj.Clear();
}
}
return sRet;
}
}