Rijndael Encryption/Decryption C# vs PHP - c#

I'm trying to encrypt data on client side(C#) then transmit it to the server through POST and decode it at the server side(PHP).
For this test purpose I'm also attaching to the POST all values were used on the client side to match it for the server
Values are:
Plain Text
Pass Phrase
IV
Generated By Client Encrypted Text
These parameters im re-using at the server side, it is mean i'm using the same plain text, the same pass phrase and the same IV
however results doesn't match
Encrypted text at the client side doesn't match to the encrypted text from server side where both of them were generated from the same input parameters
Here is Console output where you can clearly see what is going on:
https://dl.dropboxusercontent.com/u/15715229/ConsoleOutput.JPG
As You see server generate different hash with use of same "in" parameters...
What am I doing wrong?
here is my code:
C# Code:
static void Main(string[] args)
{
string url = "http://localhost/temp.php";
WebClient web = new WebClient();
string plainText = "This is sentence I want to encrypt";
string passPhrase = "MyPassPhrase";
string IV = DateTime.Now.ToLongTimeString() + "InVector";
Console.WriteLine("");
Console.WriteLine("----- Start Client -----");
Console.WriteLine("Plain text = " + plainText);
Console.WriteLine("PassPhrase = " + passPhrase);
Console.WriteLine("IV = " + IV);
string encryptedText = Encrypt(plainText, passPhrase, IV);
Console.WriteLine("Encrypted Text = " + encryptedText);
string decryptedText = Decrypt(encryptedText, passPhrase, IV);
Console.WriteLine("Decrypted Text = " + decryptedText);
Console.WriteLine("----- End Client -----");
Console.WriteLine("");
NameValueCollection postData = new NameValueCollection();
postData.Add("plainText", plainText);
postData.Add("encryptedText", encryptedText);
postData.Add("passPhrase", passPhrase);
postData.Add("IV", IV);
string webData = Encoding.UTF8.GetString(web.UploadValues(url, "POST", postData));
Console.WriteLine("----- Start Server Respond -----");
Console.WriteLine(webData);
Console.WriteLine("----- End Server Respond -----");
}
public static string Encrypt(string plainText, string passPhrase, string IV)
{
byte[] initVectorBytes = Encoding.UTF8.GetBytes(IV);
byte[] plainTextBytes = Encoding.UTF8.GetBytes(plainText);
byte[] keyBytes = Encoding.UTF8.GetBytes(passPhrase);
RijndaelManaged symmetricKey = new RijndaelManaged();
symmetricKey.Mode = CipherMode.CBC;
ICryptoTransform encryptor = symmetricKey.CreateEncryptor(keyBytes, initVectorBytes);
MemoryStream memoryStream = new MemoryStream();
CryptoStream cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write);
cryptoStream.Write(plainTextBytes, 0, plainTextBytes.Length);
cryptoStream.FlushFinalBlock();
byte[] cipherTextBytes = memoryStream.ToArray();
memoryStream.Close();
cryptoStream.Close();
return Convert.ToBase64String(cipherTextBytes);
}
public static string Decrypt(string cipherText, string passPhrase, string IV)
{
byte[] initVectorBytes = Encoding.UTF8.GetBytes(IV);
byte[] cipherTextBytes = Convert.FromBase64String(cipherText);
byte[] keyBytes = Encoding.UTF8.GetBytes(passPhrase);
RijndaelManaged symmetricKey = new RijndaelManaged();
symmetricKey.Mode = CipherMode.CBC;
ICryptoTransform decryptor = symmetricKey.CreateDecryptor(keyBytes, initVectorBytes);
MemoryStream memoryStream = new MemoryStream(cipherTextBytes);
CryptoStream cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read);
byte[] plainTextBytes = new byte[cipherTextBytes.Length];
int decryptedByteCount = cryptoStream.Read(plainTextBytes, 0, plainTextBytes.Length);
memoryStream.Close();
cryptoStream.Close();
return Encoding.UTF8.GetString(plainTextBytes, 0, decryptedByteCount);
}
My PHP Code:
<?php
if(isset($_POST['plainText']))
{
$plainText = $_POST['plainText'];
$clientEncryptedText = $_POST['encryptedText'];
$passPhrase = $_POST['passPhrase'];
$iv = $_POST['IV'];
echo "Plain text = ".$plainText."\n";
echo "PassPhrase = ".$passPhrase."\n";
echo "IV = ".$iv."\n";
$encryptedText = base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $passPhrase, $plainText, MCRYPT_MODE_CBC, $iv ));
echo "Server Encrypted Text = ".$encryptedText."\n";
echo "Client Encrypted Text = ".$clientEncryptedText."\n";
$decryptedText = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $passPhrase, base64_decode($encryptedText), MCRYPT_MODE_CBC, $iv );
echo "Server Decrypted Text = ".$decryptedText."\n";
$decryptedText = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $passPhrase, base64_decode($clientEncryptedText), MCRYPT_MODE_CBC, $iv );
echo "Decrypted text from Client = ".$decryptedText."\n";
}
else
{
echo "POST is not set";
}
Can you please tell me what am i doing wrong and where? at the client (C#) or at the server (PHP)?
Regards
Vadims Briksins

Your Passphrase is not a key of the appropriate length. Same goes for the IV. Thus, some kind of padding, truncation or hashing will happen. PHP and C# likely do it differently. Also, you don't specify if AES-128 or AES-256 is to be used in C# - thus, you are likely using AES-256 in C#, while decrypting with AES-128. Also C# could, theoretically, also use different block sizes (it likely doesn't). Padding could also differ, which could cause issues later down the road.
Make sure your IV matches the block size used (should be 128 bit = 16 byte) and the passphrase/key matches whatever key size you chose.
If you will be using real passphrases in practice, you need to use something like PBKDF2 to derive keys from them.
You also may want to add integrity checking (e.g. using HMAC with a separate key).
Also, don't implement crypto yourself if you don't have to. Check if SSL/TLS could fix the problem for you, and then use it if possible. You can use hardcoded selfsigned certificates if you want to and it matches your requirements, but using an existing crypto protocol is usually a better idea than building your own.

finally got it sorted. Whole day was fighting with it and now would love to share the code with you.
Code is 100% working - Tested and Verified!
Content of C# CryptoMaster.cs file (Client Side):
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
namespace EncryptionClient
{
class CryptoMaster
{
private string encryptedText;
public void StartEncryption()
{
Console.WriteLine("");
Console.WriteLine("----- Client Start -----");
string plainText = "Hello, this is a message we need to encrypt";
Console.WriteLine("Plain Text = " + plainText);
string passPhrase ="Pass Phrase Can be any length";
string saltValue = DateTime.Now.ToLongTimeString(); //slat should be 8 bite len, in my case im using Time HH:MM:SS as it is dynamic value
string hashAlgorithm = "SHA1";
int passwordIterations = 1;
string initVector = "InitVector Should be 32 bite len";
int keySize = 256;
encryptedText = Encrypt(plainText, passPhrase, saltValue, hashAlgorithm, passwordIterations, initVector, keySize);
Console.WriteLine("Encrypted Text = " + encryptedText);
string decryptedText = Decrypt(encryptedText, passPhrase, saltValue, hashAlgorithm, passwordIterations, initVector, keySize);
Console.WriteLine("Decripted Text = " + decryptedText);
Console.WriteLine("----- Client End -----");
SendDataToWebServer(plainText, passPhrase, saltValue, hashAlgorithm, passwordIterations, initVector, keySize);
}
private void SendDataToWebServer(string plainText, string passPhrase, string saltValue, string hashAlgorithm, int passwordIterations, string initVector, int keySize)
{
NameValueCollection POST = new NameValueCollection();
//NOTE: I'm Including all this data to POST only for TESTING PURPOSE
//and to avoid manual entering of the same data at server side.
//In real live example you have to keep sensative data hidden
POST.Add("plainText", plainText);
POST.Add("passPhrase", passPhrase);
POST.Add("saltValue", saltValue);
POST.Add("hashAlgorithm", hashAlgorithm);
POST.Add("passwordIterations", passwordIterations+"");
POST.Add("initVector", initVector);
POST.Add("keySize", keySize+"");
POST.Add("encryptedText", encryptedText);
WebClient web = new WebClient();
string URL = "http://localhost/Encryptor.php";
Console.WriteLine("");
string serverRespond = Encoding.UTF8.GetString(web.UploadValues(URL, "POST", POST));
Console.WriteLine("----- Server Start -----");
Console.WriteLine(serverRespond);
Console.WriteLine("----- Server End -----");
}
public string Encrypt(string plainText, string passPhrase, string saltValue, string hashAlgorithm, int passwordIterations, string initVector, int keySize)
{
byte[] initVectorBytes = Encoding.ASCII.GetBytes(initVector);
byte[] saltValueBytes = Encoding.ASCII.GetBytes(saltValue);
byte[] plainTextBytes = Encoding.UTF8.GetBytes(plainText);
Rfc2898DeriveBytes password = new Rfc2898DeriveBytes(passPhrase, saltValueBytes, passwordIterations);
byte[] keyBytes = password.GetBytes(keySize / 8);
RijndaelManaged symmetricKey = new RijndaelManaged();
symmetricKey.BlockSize = 256;
symmetricKey.KeySize = 256;
symmetricKey.Padding = PaddingMode.Zeros;
symmetricKey.Mode = CipherMode.CBC;
ICryptoTransform encryptor = symmetricKey.CreateEncryptor(keyBytes, initVectorBytes);
MemoryStream memoryStream = new MemoryStream();
CryptoStream cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write);
cryptoStream.Write(plainTextBytes, 0, plainTextBytes.Length);
cryptoStream.FlushFinalBlock();
byte[] cipherTextBytes = memoryStream.ToArray();
memoryStream.Close();
cryptoStream.Close();
string cipherText = Convert.ToBase64String(cipherTextBytes);
return cipherText;
}
public static string Decrypt(string cipherText, string passPhrase, string saltValue, string hashAlgorithm, int passwordIterations, string initVector, int keySize)
{
byte[] initVectorBytes = Encoding.ASCII.GetBytes(initVector);
byte[] saltValueBytes = Encoding.ASCII.GetBytes(saltValue);
byte[] cipherTextBytes = Convert.FromBase64String(cipherText);
Rfc2898DeriveBytes password = new Rfc2898DeriveBytes(passPhrase, saltValueBytes, passwordIterations);
byte[] keyBytes = password.GetBytes(keySize / 8);
RijndaelManaged symmetricKey = new RijndaelManaged();
symmetricKey.BlockSize = 256;
symmetricKey.KeySize = 256;
symmetricKey.Padding = PaddingMode.Zeros;
symmetricKey.Mode = CipherMode.CBC;
ICryptoTransform decryptor = symmetricKey.CreateDecryptor(keyBytes, initVectorBytes);
MemoryStream memoryStream = new MemoryStream(cipherTextBytes);
CryptoStream cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read);
byte[] plainTextBytes = new byte[cipherTextBytes.Length];
int decryptedByteCount = cryptoStream.Read(plainTextBytes, 0, plainTextBytes.Length);
memoryStream.Close();
cryptoStream.Close();
string plainText = Encoding.UTF8.GetString(plainTextBytes, 0, decryptedByteCount);
return plainText;
}
}
}
Content of PHP Encryptor.PHP file (Server Side):
<?php
error_reporting(0);
if (isset($_POST['plainText'])) {
$plainText = $_POST['plainText'];
$passPhrase = $_POST['passPhrase'];
$saltValue = $_POST['saltValue'];
$hashAlgorithm = $_POST['hashAlgorithm'];
$passwordIterations = $_POST['passwordIterations'];
$initVector = $_POST['initVector'];
$keySize = $_POST['keySize'];
$clientEncryptedText = $_POST['encryptedText'];
$key = getKey($passPhrase,$saltValue, $passwordIterations, $keySize, $hashAlgorithm);
echo "Plain Text = ".$plainText."\n";
echo "Client Encrypted Text = ".$clientEncryptedText."\n";
$encryptedText = base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, $plainText, MCRYPT_MODE_CBC, $initVector));
echo "Server Encrypted Text = ".$encryptedText."\n";
$decryptedText = rtrim(mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $key, base64_decode($encryptedText), MCRYPT_MODE_CBC, $initVector), "\0");
echo "Server Decrypted Text = ".$decryptedText."\n";
$decryptedText = rtrim(mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $key, base64_decode($clientEncryptedText), MCRYPT_MODE_CBC, $initVector), "\0");
echo "Client Decrypted Text = ".$decryptedText;
}
function getKey( $passPhrase, $saltValue, $passwordIterations, $keySize, $hashAlgorithm ) {
$hl = strlen(hash($hashAlgorithm, null, true));
$kb = ceil($keySize / $hl);
$dk = '';
for ( $block = 1; $block <= $kb; $block ++ ) {
$ib = $b = hash_hmac($hashAlgorithm, $saltValue . pack('N', $block), $passPhrase, true);
for ( $i = 1; $i < $passwordIterations; $i ++ )
$ib ^= ($b = hash_hmac($hashAlgorithm, $b, $passPhrase, true));
$dk .= $ib;
}
return substr($dk, 0, $keySize);
}
?>
Console Output can be viewed by this link

Related

Need help converting c# encryption/Decryption to php

C#
public void start()
{
Constants.APIENCRYPTKEY = Convert.ToBase64String(Encoding.Default.GetBytes(Session(32)));
Constants.APIENCRYPTSALT = Convert.ToBase64String(Encoding.Default.GetBytes(Session(16)));
string results = EncryptService("start");
}
private static string Session(int length)
{
Random random = new Random();
const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz";
return new string(Enumerable.Repeat(chars, length)
.Select(s => s[random.Next(s.Length)]).ToArray());
}
public static string DecryptService(string value)
{
string message = value;
string password = Encoding.Default.GetString(Convert.FromBase64String(Constants.APIENCRYPTKEY));
SHA256 mySHA256 = SHA256Managed.Create();
byte[] key = mySHA256.ComputeHash(Encoding.ASCII.GetBytes(password));
byte[] iv = Encoding.ASCII.GetBytes(Encoding.Default.GetString(Convert.FromBase64String(Constants.APIENCRYPTSALT)));
string decrypted = DecryptString(message, key, iv);
return decrypted;
}
public static string DecryptString(string cipherText, byte[] key, byte[] iv)
{
Aes encryptor = Aes.Create();
encryptor.Mode = CipherMode.CBC;
encryptor.Key = key;
encryptor.IV = iv;
MemoryStream memoryStream = new MemoryStream();
ICryptoTransform aesDecryptor = encryptor.CreateDecryptor();
CryptoStream cryptoStream = new CryptoStream(memoryStream, aesDecryptor, CryptoStreamMode.Write);
string plainText = String.Empty;
try
{
byte[] cipherBytes = Convert.FromBase64String(cipherText);
cryptoStream.Write(cipherBytes, 0, cipherBytes.Length);
cryptoStream.FlushFinalBlock();
byte[] plainBytes = memoryStream.ToArray();
plainText = Encoding.ASCII.GetString(plainBytes, 0, plainBytes.Length);
}
finally
{
memoryStream.Close();
cryptoStream.Close();
}
return plainText;
}
public static string EncryptService(string value)
{
string message = value;
string password = Encoding.Default.GetString(Convert.FromBase64String(Constants.APIENCRYPTKEY));
SHA256 mySHA256 = SHA256Managed.Create();
byte[] key = mySHA256.ComputeHash(Encoding.ASCII.GetBytes(password));
byte[] iv = Encoding.ASCII.GetBytes(Encoding.Default.GetString(Convert.FromBase64String(Constants.APIENCRYPTSALT)));
string encrypted = EncryptString(message, key, iv);
int property = Int32.Parse((OnProgramStart.AID.Substring(0, 2)));
string final = encrypted + Security.Obfuscate(property);
return final;
}
public static string EncryptString(string plainText, byte[] key, byte[] iv)
{
Aes encryptor = Aes.Create();
encryptor.Mode = CipherMode.CBC;
encryptor.Key = key;
encryptor.IV = iv;
MemoryStream memoryStream = new MemoryStream();
ICryptoTransform aesEncryptor = encryptor.CreateEncryptor();
CryptoStream cryptoStream = new CryptoStream(memoryStream, aesEncryptor, CryptoStreamMode.Write);
byte[] plainBytes = Encoding.ASCII.GetBytes(plainText);
cryptoStream.Write(plainBytes, 0, plainBytes.Length);
cryptoStream.FlushFinalBlock();
byte[] cipherBytes = memoryStream.ToArray();
memoryStream.Close();
cryptoStream.Close();
string cipherText = Convert.ToBase64String(cipherBytes, 0, cipherBytes.Length);
return cipherText;
}
This is what I got so far in PHP
function decrypt_string($msg='', $salt='', $key='')
{
$key = utf8_encode(base64_decode($key));
$key = hash('sha256', $key);
$salt = utf8_encode(base64_decode($salt));
$salt = EncodingASCII($salt);
$method = 'aes-256-cbc';
$msg = openssl_decrypt($msg, $method, $key, OPENSSL_RAW_DATA, $salt);
return $msg;
}
The encrypt and decrypt works perfect on c#, but I can't get it to decrypt on php. Haven't attempted to make the encrypt in php yet. My c# application calls on the php script with a encrypted data and needs to be decrypted on the php side then encrypted data sent back to the c# application.

PHP Token generation to C#.Net

I am tried to convert the php basic two way encryption code to C# code.the php code can be check with this site -> https://www.the-art-of-web.com/php/two-way-encryption/. I am not sure with the IV generate in my c# code is correct or not .The token which i have get from C# and PHP are in same format but the C# token shows invalid.please check my C# code that I need to change any thing.
PHP CODE:
<?php
$encrypted ="";
function encryptToken($token)
{
$cipher_method = 'aes-128-ctr';
$enc_key = openssl_digest('**********************', 'SHA256', TRUE);
$enc_iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length($cipher_method));
$crypted_token = openssl_encrypt($token, $cipher_method, $enc_key, 0, $enc_iv) . "::" .
bin2hex($enc_iv);
unset($token, $cipher_method, $enc_key, $enc_iv);
return $crypted_token;
}
function createAccessToken(){
$now = date("YmdHis");
$secret = '###################';
$plainText = $now."::".$secret;
$encrypted = encryptToken($plainText);
return $encrypted;
}
$encrypted = createAccessToken();
?>
C# CODE
public string GenerateToken()
{
var Date = DateTime.Now.ToString("yyyyMMddHHmmss");
var secret = "#############################";
string plainText = Date + "::" + secret;
var accessToken = EncryptString(plainText);
return accessToken;
}
public string EncryptString(string plainText)
{
try
{
string password = "************************";
// Create sha256 hash
SHA256 mySHA256 = SHA256Managed.Create();
byte[] key = mySHA256.ComputeHash(Encoding.ASCII.GetBytes(password));
// Instantiate a new Aes object to perform string symmetric encryption
Aes encryptor = Aes.Create();
encryptor.Mode = CipherMode.ECB;
encryptor.Padding = PaddingMode.None;
encryptor.BlockSize = 128;
// Create secret IV
var iv = generateIV();
// Set key and IV
byte[] aesKey = new byte[32];
Array.Copy(key, 0, aesKey, 0, 32);
encryptor.Key = aesKey;
encryptor.IV = iv;
// Instantiate a new MemoryStream object to contain the encrypted bytes
MemoryStream memoryStream = new MemoryStream();
// Instantiate a new encryptor from our Aes object
ICryptoTransform aesEncryptor = encryptor.CreateEncryptor();
// Instantiate a new CryptoStream object to process the data and write it to the
// memory stream
CryptoStream cryptoStream = new CryptoStream(memoryStream, aesEncryptor, CryptoStreamMode.Write);
// Convert the plainText string into a byte array
byte[] plainBytes = Encoding.ASCII.GetBytes(plainText);
// Encrypt the input plaintext string
cryptoStream.Write(plainBytes, 0, plainBytes.Length);
// Complete the encryption process
cryptoStream.FlushFinalBlock();
// Convert the encrypted data from a MemoryStream to a byte array
byte[] cipherBytes = memoryStream.ToArray();
// Close both the MemoryStream and the CryptoStream
memoryStream.Close();
cryptoStream.Close();
// Convert the encrypted byte array to a base64 encoded string
string cipherText = Convert.ToBase64String(cipherBytes, 0, cipherBytes.Length) + "::" + ByteArrayToString(iv);
// Return the encrypted data as a string
return cipherText;
}
catch (Exception)
{
throw;
}
}
private static byte[] generateIV()
{
using (RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider())
{
byte[] nonce = new byte[IV_LENGTH];
rng.GetBytes(nonce);
return nonce;
}
}
Received Tokens
PHP Token
s9kMVUTBLvvjDJNean2kYyEHisYsEQHLQ54+7wV1zHdV1jRsSBFc6PNU0lyZ48VoCjckpm94xEgxKpTRCCXEX8CS/7PYbxZqNBFIZBtZZ3mXnkfA4rvkVEc6XuNXqLGdU3dFxbtWhikAMkHiiUPnPP5hR9UCyj2mAzJqHAwQ1Cn5VkyYWwJEHeyzQR4cwBVr::2e7d77b69ab1185e3d44af142aa6f358
C# token
qFSf2qQ+UHcqAoGUxj43wTO9fLhxfhwf+hYiRKq12amdcICJ6swXvSlV4P1/VYQm6ezNqF+x6LkjMfsxgG1Oyo71+T+mtSs0j5Bmu7eaZr5bDgAMMnZ8WrDKde2fGOgB81Gkj67L/Ka+dT+Ki0j/zsXMN454vqCzdUl0pw91TpwB8UHYni7sMA8JyLgto3Q4::418c68da838e2be51b0e84def5266024

TripleDES Encryption between PHP vs C#/.NET

I have legacy server uses TripleDES encryption in .NET/C#.
Need to decrypt text by using PHP.
I wrote PHP code but it's not able to decrypt message generated form C#.
C# Code
using System;
using System.Data;
using System.IO;
using System.Security.Cryptography;
using System.Text;
namespace testns
{
class Program
{
static void Main(string[] args)
{
string key = "123456789012345678901234";
string iv = "12345678";
string text = "this is just test string";
string e = Program.EncryptTripleDES(text, key, iv);
Console.WriteLine(e);
string d = Program.DecryptTripleDES(e, key, iv);
Console.WriteLine(d);
// Return
// QDIRAeQ/O1hhjN4XqgcETG7IChnybCqZ
// this is just test string
}
private static string EncryptTripleDES(string neqs, string nafKeyCode, string nafIvCode)
{
byte[] rgbKey = Encoding.UTF8.GetBytes(nafKeyCode);
byte[] rgbIV = Encoding.UTF8.GetBytes(nafIvCode);
string sEncrypted = string.Empty;
if (!String.IsNullOrEmpty(neqs))
{
TripleDESCryptoServiceProvider cryptoProvider = new TripleDESCryptoServiceProvider();
cryptoProvider.Mode = CipherMode.CBC;
cryptoProvider.Padding = PaddingMode.None;
byte[] buffer = Encoding.UTF8.GetBytes(neqs);
MemoryStream ms = new MemoryStream();
CryptoStream cs = new CryptoStream(ms, cryptoProvider.CreateEncryptor(rgbKey, rgbIV), CryptoStreamMode.Write);
cs.Write(buffer, 0, buffer.Length);
cs.FlushFinalBlock();
sEncrypted = Convert.ToBase64String(ms.ToArray());
}
return sEncrypted;
}
private static string DecryptTripleDES(string neqs, string nafKeyCode, string nafIvCode)
{
byte[] rgbKey = Encoding.UTF8.GetBytes(nafKeyCode);
byte[] rgbIV = Encoding.UTF8.GetBytes(nafIvCode);
string decryptedText = string.Empty;
if (!String.IsNullOrEmpty(neqs))
{
TripleDESCryptoServiceProvider cryptoProvider = new TripleDESCryptoServiceProvider();
cryptoProvider.Mode = CipherMode.CBC;
cryptoProvider.Padding = PaddingMode.None;
byte[] buffer = Convert.FromBase64String(neqs);
MemoryStream ms = new MemoryStream(buffer);
CryptoStream cs = new CryptoStream(ms, cryptoProvider.CreateDecryptor(rgbKey, rgbIV), CryptoStreamMode.Read);
StreamReader sr = new StreamReader(cs);
decryptedText = sr.ReadToEnd();
//(new Logs()).LogException(decryptedText);
}
return decryptedText;
}
}
}
PHP Code
$key = '123456789012345678901234';
$iv = '12345678';
$text = 'this is just test string';
$e = openssl_encrypt($text, 'des-ede3-cbc', $key, 0, $iv);
echo $e . "<br /><br />";
$d = openssl_decrypt($e, 'des-ede3-cbc', $key, 0, $iv);
echo $d . "<br /><br />";
// Return
// QDIRAeQ/O1hhjN4XqgcETG7IChnybCqZqN3DpVbYFwk=
// this is just test string
Got from PHP
QDIRAeQ/O1hhjN4XqgcETG7IChnybCqZqN3DpVbYFwk=
Got from C#
QDIRAeQ/O1hhjN4XqgcETG7IChnybCqZ
As you an see it's almost the same for PHP has extra qN3DpVbYFwk= characters.
What I am doing wrong? It is something to do with padding?
Thanks
It looks like the problem is that you have turned padding off (PaddingMode.None) in your C# code and Padding is turned on (by default) in your PHP code.
The OpenSSL library methods openssl_encrypt and openssl_decrypt have padding turned on by default when you pass 0 as the options parameter. The default padding is PKCS#7.
So to solve your issue you will either need to add PaddingMode.PKCS7 to your C# code (which I personally recommend):
cryptoProvider.Padding = PaddingMode.PKCS7;
Or you turn off the padding in PHP using OPENSSL_ZERO_PADDING. Remember that in PHP you will need to add the flag OPENSSL_ZERO_PADDING to both openssl_encrypt and openssl_decrypt.
example:
$e = openssl_encrypt($text, 'des-ede3-cbc', $key, OPENSSL_ZERO_PADDING, $iv);
Important
Remember the padding options must be set on both encrypt and decrypt modes.

C# RIJNDAEL decrypt

I try to decrypt request params for JDownloader CNL Feature.
http://jdownloader.org/knowledge/wiki/glossary/cnl2
In this sample the iv and the key is '31323334353637383930393837363534' and i try to decrypt this value 'DRurBGEf2ntP7Z0WDkMP8e1ZeK7PswJGeBHCg4zEYXZSE3Qqxsbi5EF1KosgkKQ9SL8qOOUAI'
The php code in sample to encrypt is the following
I know i need to decode the key from hex to string, that means the correct key is 1234567890987654
function base16Encode($arg){
$ret="";
for($i=0;$i<strlen($arg);$i++){
$tmp=ord(substr($arg,$i,1));
$ret.=dechex($tmp);
}
return $ret;
}
$key="1234567890987654";
$transmitKey=base16Encode($key);
$link="http://rapidshare.com/files/285626259/jDownloader.dmg\r\nhttp://rapidshare.com/files/285622259/jDownloader2.dmg";
$cp = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', 'cbc', '');
#mcrypt_generic_init($cp, $key,$key);
$enc = mcrypt_generic($cp, $link);
mcrypt_generic_deinit($cp);
mcrypt_module_close($cp);
$crypted=base64_encode($enc);
echo $crypted;
My last try to decrypt is the following c# code but i have some troble with lenght of input.
public static String DecryptRJ(string input, string iv, string key )
{
key = key.DecodeBase16(); // Extension method
byte[] initVectorBytes = Encoding.UTF8.GetBytes(iv);
byte[] cipherTextBytes = Encoding.UTF8.GetBytes(input);
byte[] keyBytes = Encoding.UTF8.GetBytes(key);
RijndaelManaged symmetricKey = new RijndaelManaged();
symmetricKey.Mode = CipherMode.CBC;
symmetricKey.BlockSize = 256;
symmetricKey.KeySize = 256;
ICryptoTransform decryptor = symmetricKey.CreateDecryptor(keyBytes, initVectorBytes);
MemoryStream memoryStream = new MemoryStream(cipherTextBytes);
CryptoStream cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read);
byte[] plainTextBytes = new byte[cipherTextBytes.Length];
int decryptedByteCount = cryptoStream.Read(plainTextBytes, 0, plainTextBytes.Length);
memoryStream.Close();
cryptoStream.Close();
return Encoding.UTF8.GetString(plainTextBytes, 0, decryptedByteCount);
}
One more Information this PHP Code works fine and can decode and decrypt correct.
function decrypt($data, $_key){
echo '<br><hr><br>';
out($data);
$plain=base64_decode($data);
out($plain);
echo 'init';
//$e = mcrypt_decrypt ( $_cp , $_key , $plain , 'cbc' );
$e = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $_key, $plain, 'cbc', $_key);
out($e);
echo 'end';
}
Ok now i can decrypt the encrypted sample data (see php code or http://jdownloader.org/knowledge/wiki/glossary/cnl2) Code C# is this
public static string DecryptDLCData(string data, string _key, Encoding encoding = null)
{
if (encoding == null)
encoding = Encoding.Default;
data = data.DecodeBase64(encoding);
RijndaelManaged rijndaelCipher = new RijndaelManaged();
rijndaelCipher.Mode = CipherMode.CBC;
rijndaelCipher.Padding = PaddingMode.Zeros;
rijndaelCipher.KeySize = 256;
rijndaelCipher.BlockSize = 128;
byte[] pwdBytes = Encoding.Default.GetBytes(_key);
byte[] keyBytes = new byte[16];
int len = pwdBytes.Length;
if (len > keyBytes.Length) len = keyBytes.Length;
Array.Copy(pwdBytes, keyBytes, len);
rijndaelCipher.Key = keyBytes;
rijndaelCipher.IV = keyBytes;
var transform = rijndaelCipher.CreateDecryptor();
byte[] plainText = Encoding.Default.GetBytes(data);
byte[] cipherBytes = transform.TransformFinalBlock(plainText, 0, plainText.Length);
return Encoding.UTF8.GetString(cipherBytes);
}

Java encode and .NET decode

The encryption is in java:
String salt = "DC14DBE5F917C7D03C02CD5ADB88FA41";
String password = "25623F17-0027-3B82-BB4B-B7DD60DCDC9B";
char[] passwordChars = new char[password.length()];
password.getChars(0,password.length(), passwordChars, 0);
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
KeySpec spec = new PBEKeySpec(passwordChars, salt.getBytes(), 2, 256);
SecretKey sKey = factory.generateSecret(spec);
byte[] raw = _sKey.getEncoded();
String toEncrypt = "The text to be encrypted.";
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding", "BC");
cipher.init(Cipher.ENCRYPT_MODE, skey);
AlgorithmParameters params = cipher.getParameters();
byte[] initVector = params.getParameterSpec(IvParameterSpec.class).getIV();
byte[] encryptedBytes = cipher.doFinal(toEncrypt.getBytes());
While the decryption is in c#:
string hashAlgorithm = "SHA1";
int passwordIterations = 2;
int keySize = 256;
byte[] saltValueBytes = Encoding.ASCII.GetBytes( salt );
byte[] cipherTextBytes = Convert.FromBase64String( cipherText );
PasswordDeriveBytes passwordDB = new PasswordDeriveBytes(password, saltValueBytes, hashAlgorithm passwordIterations );
byte[] keyBytes = passwordDB.GetBytes( keySize / 8 );
RijndaelManaged symmetricKey = new RijndaelManaged();
symmetricKey.Mode = CipherMode.CBC;
ICryptoTransform decryptor = symmetricKey.CreateDecryptor( keyBytes, initVector );
MemoryStream memoryStream = new MemoryStream( cipherTextBytes );
CryptoStream cryptoStream = new CryptoStream( memoryStream, decryptor, CryptoStreamMode.Read );
byte[] plainTextBytes = new byte[ cipherTextBytes.Length ];
int decryptedByteCount = cryptoStream.Read( plainTextBytes, 0, plainTextBytes.Length );
memoryStream.Close();
cryptoStream.Close();
string plainText = Encoding.UTF8.GetString( plainTextBytes, 0, decryptedByteCount );
The decryption failed with exception "Padding is invalid and cannot be removed."
Any idea what might be the problem?
This generally indicates that decryption has failed. I suggest you check the output of the key generation functions, to see if you are actually using the same key. I notice, for instance, that the Java code implies you are using a SHA1-based HMAC, whereas the .NET code implies you are using an unkeyed SHA1 hash to generate the key.
Alternatively, it could be a mismatch in the padding. I don't see where you are explicitly setting the PaddingMode to PKCS7 in the .NET code.

Categories

Resources