AES algorithm value differences between .NET and nodejs, CryptoJS - c#

The below AES algorithm in C# returns an encrypted value that is different from what node js and CryptoJS returns. NodeJS Crypto library and CryptoJS return the same values but .NET's AesCryptoServiceProvider returns a different value. Any ideas?
C# example
private const string AesIV = #"!QAZ2WSX#EDC4RFV";
private const string AesKey = #"5TGB&YHN7UJM(IK<";
public static void Main()
{
try
{
string original = "HelloWorld";
Console.WriteLine(Encrypt(original));
}
catch (Exception e)
{
Console.WriteLine("Error: {0}", e.Message);
}
}
/// <summary>
/// AES Encryption
/// </summary>
private static string Encrypt(string text)
{
// AesCryptoServiceProvider
AesCryptoServiceProvider aes = new AesCryptoServiceProvider();
aes.BlockSize = 128;
aes.KeySize = 128;
aes.IV = Encoding.UTF8.GetBytes(AesIV);
aes.Key = Encoding.UTF8.GetBytes(AesKey);
aes.Mode = CipherMode.CBC;
aes.Padding = PaddingMode.PKCS7;
// Convert string to byte array
byte[] src = Encoding.Unicode.GetBytes(text);
// encryption
using (ICryptoTransform encrypt = aes.CreateEncryptor())
{
byte[] dest = encrypt.TransformFinalBlock(src, 0, src.Length);
// Convert byte array to Base64 strings
return Convert.ToBase64String(dest);
}
}
NodeJS example:
crypto = require "crypto"
algo = 'aes-128-cbc'
keyBuffer = new Buffer("!QAZ2WSX#EDC4RFV")
ivBuffer = new Buffer("5TGB&YHN7UJM(IK<")
cipher = crypto.createCipheriv(algo, keyBuffer, ivBuffer)
textBuffer = new Buffer('HelloWorld')
encrypted = cipher.update(textBuffer)
encryptedFinal = cipher.final()
encryptedText = encrypted.toString('base64') + encryptedFinal.toString('base64')
console.log encryptedText
CryptoJS example:
<script src="http://crypto-js.googlecode.com/svn/tags/3.1.2/build/rollups/aes.js"></script>
<script>
var key = CryptoJS.enc.Utf8.parse('!QAZ2WSX#EDC4RFV');
var iv = CryptoJS.enc.Utf8.parse('5TGB&YHN7UJM(IK<');
var encrypted = CryptoJS.AES.encrypt("HelloWorld", key, { iv: iv });
alert(encrypted);
</script>

Your C# version uses UTF-16LE to convert HelloWorld to plaintext bytes. The NodeJS one (and presumably hence the CryptoJS one) use UTF-8 bytes. Use Encoding.UTF8.GetBytes() in the C# one.

Default padding in NodeJS is PKCS5 (assuming CryptoJS is the same since you said they produce the same result). Your C# code is setting padding to PKCS7.

Related

How to fix invalid key size when decrypting data in C# that was encrypted in php

I am trying to solve an encryption issue I am having between php and c#.
I have encrypted data using the following php and openssl operation.
$encrypt_method = "AES-256-CBC";
$secret_key = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX';
$secret_iv = 'XXXXXXXXXXXXXXXX';
$key = hash ('sha256', $secret_key);
$iv = substr (hash ('sha256', $secret_iv), 0, 16);
$output = openssl_encrypt ($string, $encrypt_method, $key, 0, $iv);
$output = base64_encode ($output);
I have tried a couple of methods in C# to decrypt but this is what I am trying now.
public string Encrypt_Decrypt(string action, string value) {
string secretKey = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
string secretIV = "XXXXXXXXXXXXXXXX";
string key = Hash(secretKey);
string iv = Hash(secretIV).Substring(0,16);
string retValue = "";
if (action == "encrypt") {
retValue = EncryptString(value, key, iv);
}
else if (action == "decrypt") {
retValue = DecryptString(value, key, iv);
}
}
// Hash to match php hash function
public static string Hash(string unhashedString) {
return BitConverter.ToString(new SHA256CryptoServiceProvider().ComputeHash(Encoding.Default.GetBytes(unhashedString))).Replace("-", String.Empty).ToLower();
}
public static string DecryptString(string cipherData, string keyString, string ivString) {
byte[] key = Encoding.UTF8.GetBytes(keyString);
Console.WriteLine(key.Length);
byte[] iv = Encoding.UTF8.GetBytes(ivString);
Console.WriteLine(iv.Length);
byte[] cipherCrypt = Convert.FromBase64String(cipherData);
for (int i = 0; i < cipherCrypt.Length; i++) {
Console.Write(cipherCrypt[i] + " ");
}
try {
RijndaelManaged crypto = new RijndaelManaged();
crypto.Key = key;
crypto.IV = iv;
crypto.Mode = CipherMode.CBC;
crypto.KeySize = 256;
crypto.BlockSize = 128;
crypto.Padding = PaddingMode.None;
ICryptoTransform decryptor = crypto.CreateDecryptor(crypto.Key, crypto.IV);
using (MemoryStream memStream = new MemoryStream(cipherCrypt)) {
using (CryptoStream cryptoStream = new CryptoStream(memStream, decryptor, CryptoStreamMode.Read)) {
using (StreamReader streamReader = new StreamReader(cryptoStream)) {
return streamReader.ReadToEnd();
}
}
}
}
catch (CryptographicException e) {
Console.WriteLine("A Cryptographic error occurred: {0}", e.Message);
return null;
}
}
I have tried a couple different encoding types when getting the byte[] for the operation.
I keep getting the following error:
Specified key is not a valid size for this algorithm.
Not sure what I am missing. Any help is appreciated.
Also, I already read through this and tried what the solution suggestion recommended. I got the same resulting error.
UPDATE - 01
I have updated the code here to reflect the code I have changed.
The key length is 32,
The iv length is 16,
The data coming in at "cipherData" is length 32,
When "cipherData" goes through "FromBase64String(cipherData)" it comes out as a 24 byte array. This is causing an issue for the decryptor which wants a 32 byte array.
There are obviously problems with the key size. The code between PHP and C# seem to match. The problem seems to be that the code is wrong in both cases.
Let's see how long the key actually is:
Start with a 32 byte key (non-encoded).
Hash the key with SHA-256: 32 bytes (non-encoded).
Encode to hex (integrated into PHP's hash() function by default): 64 bytes.
AES only supports the following key sizes: 16, 24 and 32 bytes. openssl_encrypt() will only use the first 32 bytes of the hex key silently. So, you need to use the first 32 bytes in C#.
Note that openssl_encrypt() takes an options argument which denotes that the output is Base64 when OPENSSL_RAW_DATA is not set. It means that the PHP output was encoded twice with Base64. So you need to decode it twice in C#.

Encrypt & Decrypt querystring values using AES 256

I am using the following code to Encrypt/Decrypt a querystring and pass it from one page to another. The resulting output is missing a '+' (see at the bottom of the question). What can I do to make sure the '+' comes thru as I am already using urlencode/urldecode?
//Encryption page
protected void Page_Load(object sender, EventArgs e)
{
string text = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
Response.Write("256:" + Decrypt256(Encrypt256(text)));
Response.Write(string.Format("<br/>{0}", HttpUtility.UrlEncode(Encrypt256(text))));
}
private const string AesIV256 = #"!QAZ2WSX#EDC4RFV";
private const string AesKey256 = #"5TGB&YHN7UJM(IK<5TGB&YHN7UJM(IK<";
private string Encrypt256(string text)
{
// AesCryptoServiceProvider
AesCryptoServiceProvider aes = new AesCryptoServiceProvider();
aes.BlockSize = 128;
aes.KeySize = 256;
aes.IV = Encoding.UTF8.GetBytes(AesIV256);
aes.Key = Encoding.UTF8.GetBytes(AesKey256);
aes.Mode = CipherMode.CBC;
aes.Padding = PaddingMode.PKCS7;
// Convert string to byte array
byte[] src = Encoding.Unicode.GetBytes(text);
// encryption
using (ICryptoTransform encrypt = aes.CreateEncryptor())
{
byte[] dest = encrypt.TransformFinalBlock(src, 0, src.Length);
// Convert byte array to Base64 strings
return Convert.ToBase64String(dest);
}
}
/// <summary>
/// AES decryption
/// </summary>
private string Decrypt256(string text)
{
// AesCryptoServiceProvider
AesCryptoServiceProvider aes = new AesCryptoServiceProvider();
aes.BlockSize = 128;
aes.KeySize = 256;
aes.IV = Encoding.UTF8.GetBytes(AesIV256);
aes.Key = Encoding.UTF8.GetBytes(AesKey256);
aes.Mode = CipherMode.CBC;
aes.Padding = PaddingMode.PKCS7;
// Convert Base64 strings to byte array
byte[] src = System.Convert.FromBase64String(text);
// decryption
using (ICryptoTransform decrypt = aes.CreateDecryptor())
{
byte[] dest = decrypt.TransformFinalBlock(src, 0, src.Length);
return Encoding.Unicode.GetString(dest);
}
}
Decryption page (I use this page to print out what I the decrypted string from the first page and then compare it what I get in the URL:
protected void Page_Load(object sender, EventArgs e)
{
string urlValue = HttpUtility.UrlDecode(Request.QueryString["p"].Trim());
Decrypt256(Encoding.ASCII.GetString(s2));
Response.Write(urlValue + "<br /><br />");
Response.Write("AUwsHc8j/llULnuwVnspNwolBUAhl5GFqC6iOrUN5euZFrOgFVypqTGfhAaooLxa0Fko+9KGtRh3UcQJtzkfSw==");
}
The end result is the following two lines (the first line is the output from the URL). They almost match except the first URL (the encoded/decoded querystring result) is missing the '+' symbol. Any idea how to avoid this?
AUwsHc8j/llULnuwVnspNwolBUAhl5GFqC6iOrUN5euZFrOgFVypqTGfhAaooLxa0Fko 9KGtRh3UcQJtzkfSw==
AUwsHc8j/llULnuwVnspNwolBUAhl5GFqC6iOrUN5euZFrOgFVypqTGfhAaooLxa0Fko+9KGtRh3UcQJtzkfSw==
ok fixed it, simply removed the urldecode method. The decode appears to happen automatically.

Trying to get AES encryption of a string in node.js to match encrypted value in .net

I'm trying to encrypt a value in node.js that I can decrypt in .net. I've been given the code that they use on the .net side of things for encrypting a value and i'm trying to achieve the same encrypted value in my node.js script.
I'm definitely not an encryption buff so please help me figure out where i'm going wrong. My node.js encrypted value is not matching that of the .net encrypted value, and my node.js encrypted value is actually not returning the same value every time I run the script either.
Here's the .net encryption logic:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Security.Cryptography;
using System.IO;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("start:");
string key = "mysecretkey";
string secret = "encryptThisMessage";
string crypto = EncryptString(secret, key);
Console.WriteLine(crypto);
string returnValue = DecryptString(crypto, key);
Console.WriteLine(returnValue);
Console.ReadKey();
}
/// <summary>
/// Encrpyts the sourceString, returns this result as an Aes encrpyted, BASE64 encoded string
/// </summary>
/// <param name="plainSourceStringToEncrypt">a plain, Framework string (ASCII, null terminated)</param>
/// <param name="passPhrase">The pass phrase.</param>
/// <returns>
/// returns an Aes encrypted, BASE64 encoded string
/// </returns>
public static string EncryptString(string plainSourceStringToEncrypt, string passPhrase)
{
//Set up the encryption objects
using (AesCryptoServiceProvider acsp = GetProvider(Encoding.Default.GetBytes(passPhrase)))
{
byte[] sourceBytes = Encoding.ASCII.GetBytes(plainSourceStringToEncrypt);
ICryptoTransform ictE = acsp.CreateEncryptor();
//Set up stream to contain the encryption
MemoryStream msS = new MemoryStream();
//Perform the encrpytion, storing output into the stream
CryptoStream csS = new CryptoStream(msS, ictE, CryptoStreamMode.Write);
csS.Write(sourceBytes, 0, sourceBytes.Length);
csS.FlushFinalBlock();
//sourceBytes are now encrypted as an array of secure bytes
byte[] encryptedBytes = msS.ToArray(); //.ToArray() is important, don't mess with the buffer
//return the encrypted bytes as a BASE64 encoded string
return Convert.ToBase64String(encryptedBytes);
}
}
/// <summary>
/// Decrypts a BASE64 encoded string of encrypted data, returns a plain string
/// </summary>
/// <param name="base64StringToDecrypt">an Aes encrypted AND base64 encoded string</param>
/// <param name="passphrase">The passphrase.</param>
/// <returns>returns a plain string</returns>
public static string DecryptString(string base64StringToDecrypt, string passphrase)
{
//Set up the encryption objects
using (AesCryptoServiceProvider acsp = GetProvider(Encoding.Default.GetBytes(passphrase)))
{
byte[] RawBytes = Convert.FromBase64String(base64StringToDecrypt);
ICryptoTransform ictD = acsp.CreateDecryptor();
//RawBytes now contains original byte array, still in Encrypted state
//Decrypt into stream
MemoryStream msD = new MemoryStream(RawBytes, 0, RawBytes.Length);
CryptoStream csD = new CryptoStream(msD, ictD, CryptoStreamMode.Read);
//csD now contains original byte array, fully decrypted
//return the content of msD as a regular string
return (new StreamReader(csD)).ReadToEnd();
}
}
private static AesCryptoServiceProvider GetProvider(byte[] key)
{
AesCryptoServiceProvider result = new AesCryptoServiceProvider();
result.BlockSize = 128;
result.KeySize = 128;
result.Mode = CipherMode.CBC;
result.Padding = PaddingMode.PKCS7;
result.GenerateIV();
result.IV = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
byte[] RealKey = GetKey(key, result);
result.Key = RealKey;
// result.IV = RealKey;
return result;
}
private static byte[] GetKey(byte[] suggestedKey, SymmetricAlgorithm p)
{
byte[] kRaw = suggestedKey;
List<byte> kList = new List<byte>();
for (int i = 0; i < p.LegalKeySizes[0].MinSize; i += 8)
{
kList.Add(kRaw[(i / 8) % kRaw.Length]);
}
byte[] k = kList.ToArray();
return k;
}
}
}
My node.js script:
var crypto = require('crypto-js');
var key = "mysecretkey";
var secret = "encryptThisMessage";
e1 = crypto.AES.encrypt(secret, key, {mode: crypto.mode.CBC, padding: crypto.pad.Pkcs7});
e2 = crypto.AES.encrypt(secret, key, {mode: crypto.mode.CBC, padding: crypto.pad.Pkcs7});
console.log('e1');
console.log(crypto.enc.Hex.stringify(e1));
console.log(e1.toString());
console.log(e1.salt.toString());
console.log(e1.iv.toString());
console.log(e1.ciphertext.toString());
console.log(e1.ciphertext.toString(crypto.enc.Base64));
console.log('e2');
console.log(e2.toString());
console.log(e2.salt.toString());
console.log(e2.iv.toString());
console.log(e2.ciphertext.toString(crypto.enc.Base64));
When running the encryption piece in the c# code, the value looks like this: (slightly modified for security purposes) dp+8cjr/ajEw5oePdiG+4g==. How can I change my node.js code to output this matched encrypted value?
Output of node.js script:
You are mixing apples and oranges.
When you pass a string as key to CryptoJS, it derives a key and iv that it uses for the decryption. The string is treated as a passphrase, which is salted. Run this code a couple of times in node.js:
var key = "mysecretkey";
var secret = "encryptThisMessage";
e1 = crypto.AES.encrypt(secret, key, {mode: crypto.mode.CBC, padding: crypto.pad.Pkcs7});
console.log("key: " + crypto.enc.Base64.stringify(e1.key));
console.log("iv: " + crypto.enc.Base64.stringify(e1.iv));
console.log("salt: " + crypto.enc.Base64.stringify(e1.salt));
console.log("ciphertext: " + crypto.enc.Base64.stringify(e1.ciphertext));
p = crypto.AES.decrypt(e1, key, {mode: crypto.mode.CBC, padding: crypto.pad.Pkcs7});
console.log("decrypted: " + crypto.enc.Utf8.stringify(p));
Note that it produces different keys and IVs each time, yet it always decrypts back to the original (because e1 carries the salt which lets decrypt derive the same key). Check out this documentation for CryptoJS here.
In your C# code, you are always using the same key and IV. These don't match the key and IV in CryptoJS. Try this code which exactly matches the key and IV that your C# code produces:
var key = crypto.enc.Base64.parse('bXlzZWNyZXRrZXlteXNlYw=='); // Matching C# code's key
var iv = crypto.enc.Base64.parse('AAAAAAAAAAAAAAAAAAAAAA=='); // 16 ZERO bytes, same as C# code
var secret = "encryptThisMessage";
e1 = crypto.AES.encrypt(secret, key, {iv: iv, mode: crypto.mode.CBC, padding: crypto.pad.Pkcs7});
console.log("ciphertext: " + crypto.enc.Base64.stringify(e1.ciphertext));
Note that this time I am not passing CryptoJS a string for the key, to be interpreted as a passphrase, but rather, a CryptoJS word array to be interpreted directly as key bytes. Also, I am passing the IV in the params.
That last bit of code produces the same ciphertext as your C# code. I'm using Base64 here for the key and IV as a convenient shortcut to create word arrays. Use the same key and IV on both ends and it will work.
EDIT:
I thought it interesting to show the CryptoJS -- i.e. OpenSSL -- key derivation in code, so that instead of having CryptoJS match C#, have C# match CryptoJS.
OpenSSL key derivation is described here.
This derives the key and IV -- kept simple for clarity:
public byte[] Derive48(string passphrase, byte[] salt)
{
using (var md5 = new MD5CryptoServiceProvider())
{
var source = Encoding.UTF8.GetBytes(passphrase).Concat(salt).ToArray();
var data = md5.ComputeHash(source);
var output = data;
while (output.Length < 48)
{
data = md5.ComputeHash(data.Concat(source).ToArray());
output = output.Concat(data).ToArray();
}
return output.Take(48).ToArray();
}
}
You can use it like this:
string key = "mysecretkey";
string secret = "encryptThisMessage";
byte[] salt = Convert.FromBase64String("zTEeMVPN2eY=");
string crypto = EncryptString(secret, key, salt);
Console.WriteLine(crypto);
string returnValue = DecryptString(crypto, key, salt);
Console.WriteLine(returnValue);
...
public string EncryptString(string plainSourceStringToEncrypt, string passPhrase, byte[] salt)
{
//Set up the encryption objects
using (AesCryptoServiceProvider acsp = GetProvider(passPhrase, salt))
{
...
private AesCryptoServiceProvider GetProvider(string passphrase, byte[] salt)
{
AesCryptoServiceProvider result = new AesCryptoServiceProvider();
result.BlockSize = 128;
result.KeySize = 128;
result.Mode = CipherMode.CBC;
result.Padding = PaddingMode.PKCS7;
var derived = this.Derive48(passphrase, salt);
result.Key = derived.Take(32).ToArray();
result.IV = derived.Skip(32).Take(16).ToArray();
return result;
}

AES encryption with Crypto-JS and C# Decryption - avoiding "Padding is invalid and cannot be removed."

I am busy creating a Javascript application which integrates with our client's existing C# services.
One of the requirements is to send AES encrypted data, which then is decrypted and used on the server.
However, I cannot send "valid" data, the server always responds with "Padding is invalid and cannot be removed."
Here are their C# Encrypt and Decrypt implementations (this cannot be changed, as they have various subsystems dependent on this:
public static string Encrypt(string input, string password)
{
byte[] utfData = Encoding.UTF8.GetBytes(input);
byte[] saltBytes = Encoding.UTF8.GetBytes(password);
string encryptedString = string.Empty;
using (var aes = new AesManaged())
{
var rfc = new Rfc2898DeriveBytes(password, saltBytes);
aes.BlockSize = aes.LegalBlockSizes[0].MaxSize;
aes.KeySize = aes.LegalKeySizes[0].MaxSize;
aes.Key = rfc.GetBytes(aes.KeySize/8);
aes.IV = rfc.GetBytes(aes.BlockSize/8);
using (ICryptoTransform encryptTransform = aes.CreateEncryptor())
{
using (var encryptedStream = new MemoryStream())
{
using (var encryptor =
new CryptoStream(encryptedStream, encryptTransform, CryptoStreamMode.Write))
{
encryptor.Write(utfData, 0, utfData.Length);
encryptor.Flush();
encryptor.Close();
byte[] encryptBytes = encryptedStream.ToArray();
encryptedString = Convert.ToBase64String(encryptBytes);
}
}
}
}
return encryptedString;
}
public static string Decrypt(string input, string password)
{
byte[] encryptedBytes = Convert.FromBase64String(input);
byte[] saltBytes = Encoding.UTF8.GetBytes(password);
string decryptedString = string.Empty;
using (var aes = new AesManaged())
{
var rfc = new Rfc2898DeriveBytes(password, saltBytes);
aes.BlockSize = aes.LegalBlockSizes[0].MaxSize;
aes.KeySize = aes.LegalKeySizes[0].MaxSize;
aes.Key = rfc.GetBytes(aes.KeySize/8);
aes.IV = rfc.GetBytes(aes.BlockSize/8);
using (ICryptoTransform decryptTransform = aes.CreateDecryptor())
{
using (var decryptedStream = new MemoryStream())
{
var decryptor =
new CryptoStream(decryptedStream, decryptTransform, CryptoStreamMode.Write);
decryptor.Write(encryptedBytes, 0, encryptedBytes.Length);
decryptor.Flush();
decryptor.Close();
byte[] decryptBytes = decryptedStream.ToArray();
decryptedString =
Encoding.UTF8.GetString(decryptBytes, 0, decryptBytes.Length);
}
}
}
return decryptedString;
}
I am using CryptoJS 3.1.2. eg
var encrypted = CryptoJS.AES.encrypt(input, password).toString();
how do I essentially write an equivalent to their "Encrypt()" using CryptoJS
CryptoJS documentation is severely lacking in depth, so it is hard to know what to expect without trying. It is pretty clear though that using the password as salt is not a secure nor standard way to handle salt. So you will have to call the PBKDF2 function yourself, create a key and IV yourself. You also need to create the PBKDF2 in CryptoJS with SHA-1 instead of SHA-256. SHA-256 seems to be the - again undocumented - default in CryptoJS.
The only way to do this is to step through the code, and compare each (binary) value for both the PBKDF2 and AES functions. Please convert to hexadecimals to make a good comparison.

C# and Java DES Encryption value are not identical

I am trying to encrypt the same data using C# and Java. If the data is more than 7 bytes then Java and C#'s encrypted value are not identical.
Input 1: a
java output: FrOzOp/2Io8=
C# output: FrOzOp/2Io8=
Input 2: abc
j : H9A/ahl8K7I=
c#: H9A/ahl8K7I=
Input 3: aaaaaaaa (Problem)
j : Gxl7e0aWPd7j6l7uIEuMxA==
c#: Gxl7e0aWPd7sf1xR6hK4VQ==
Here is the implementation of C# and Java methods.
C# code:
public String saltTxt = "12345678";
public String Encrypt(String txt)
{
byte[] data = Encrypt(Encoding.UTF8.GetBytes(txt));
DESCryptoServiceProvider alg = new DESCryptoServiceProvider();
alg.Key = Encoding.UTF8.GetBytes(saltTxt.ToCharArray(), 0, cprovider.KeySize / 8);
alg.IV = new byte[8];
MemoryStream ms = new MemoryStream();
CryptoStream stem = new CryptoStream( ms, cprovider.CreateEncryptor(),CryptoStreamMode.Write);
stem.Write(txt, 0, txt.Length);
stem.FlushFinalBlock();
data = ms.ToArray();
return Convert.ToBase64String(data);
}
Java Code:
public String saltTxt = "12345678";
public String Encrypt(String str) {
try {
KeySpec myKey = new DESKeySpec(saltTxt.getBytes("UTF8"));
SecretKey key = SecretKeyFactory.getInstance("DES").generateSecret(myKey);
Cipher ecipher = Cipher.getInstance("DES");
ecipher.init(Cipher.ENCRYPT_MODE, key);
byte[] data = str.getBytes("UTF8");
byte[] crypt = ecipher.doFinal(data);
return new BASE64Encoder().encode(crypt);
} catch (Exception ex) {
}
return null;
}
Any idea why it's not working as expected?
The problem was in mode of encryption.
SunJCE provider uses ECB as the default mode, and PKCS5Padding as the default padding scheme for DES, DES-EDE and Blowfish ciphers. (JCA Doc)
and
In .Net, The default operation mode for the symmetric algorithm is CipherMode.CBC and default padding is PaddingMode.PKCS7. (msdn..SymmetricAlgorithm)
The following changes resolve the problem.
// in C#
DESCryptoServiceProvider alg = new DESCryptoServiceProvider();
alg.Mode = CipherMode.ECB; // specified
or
// in java
chiper = Cipher.getInstance("DES/CBC/PKCS5Padding");
don't change in both sides.
You're probably seeing ISO 10126 padding, which appends random bytes to the plaintext to fill it up t oa multiple of the block size.
This behavior is by design.
The code (Java/Android) bellow worke for me.
I used the same approach on C#.
public static String Cripto(String Password)
{
String PasswordCripto = "";
try
{
String encryptionKey = "anyEncryptionString";
MessageDigest messageDigest = MessageDigest.getInstance("MD5");
messageDigest.update(encryptionKey.getBytes("UTF-8"), 0, encryptionKey.length());
byte[] encryptionKeyBytes = messageDigest.digest();
SecretKeySpec Key = new SecretKeySpec(encryptionKeyBytes,"DESede");
Cipher cipher = Cipher.getInstance("DESEDE/ECB/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, Key);
byte[] encryptedBytes = cipher.doFinal(Password.getBytes("UTF-8"));
PasswordCripto = new String(Base64.encode(encryptedBytes, Base64.DEFAULT), "UTF-8");
} catch(Exception e) { }
return PasswordCripto ;
}

Categories

Resources