Decrypting AES from C#, Encrypted from Java - c#

We are using below code to encrypt in Java
public encrypt(String text) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidKeySpecException {
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
KeySpec spec = new PBEKeySpec(passPhrase.toCharArray(), SALT, ITERATION_COUNT, KEY_LENGTH); //256 bit
SecretKey tmp = factory.generateSecret(spec);
SecretKey secret = new SecretKeySpec(tmp.getEncoded(), "AES");
this.ecipher = Cipher.getInstance("AES");
this.ecipher.init(Cipher.ENCRYPT_MODE, secret);
byte[] bytes = encrypt.getBytes("UTF-8");
byte[] encrypted = this.ecipher.doFinal(bytes);
return Base64.encodeBase64String(encrypted);
}
Our vendor is using C# to decrypt the data
His code
string Decrypt(string textToDecrypt, string key)
{
RijndaelManaged rijndaelCipher = new RijndaelManaged();
rijndaelCipher.Mode = CipherMode.ECB;
rijndaelCipher.KeySize = 0x80;
rijndaelCipher.BlockSize = 0x80;
byte[] encryptedData = Convert.FromBase64String(textToDecrypt);
byte[] pwdBytes = Encoding.UTF8.GetBytes(key);
byte[] keyBytes = new byte[0x10];
int len = pwdBytes.Length;
if (len > keyBytes.Length) {
len = keyBytes.Length;
}
Array.Copy(pwdBytes, keyBytes, len);
rijndaelCipher.Key = keyBytes;
byte[] plainText = rijndaelCipher.CreateDecryptor().TransformFinalBlock(encryptedData, 0, encryptedData.Length);
return Encoding.UTF8.GetString(plainText);
}
But he's unable to decrypt the data. He's getting some garbage data.
Any idea how to decrypt using C# for Java Encryption part.

First off, Don't have any allusions of security with your java code. ECB mode not a good choice.
Second, the problem with the C# code is that it's using the raw bytes of the passphase for the key rather than PBKDF2WithHmacSHA1 which the java code is using. The class in C# to do the key generation is Rfc2898DeriveBytes

Related

AES256 JAVA encryption doesn't match C# encryption

I have been requested to encrypt some data while talking to my partner's JAVA API, and he sent me the following details about encryption algorithm:
Algorithm : AES256
Key Size : 256 bits
Encryption Mode: CBC (16 bits blocks, PKCS5Padding with 0)
Output Type : Base-64
Password: 0xA8703827AE586460105696504327B7BB0806FEAE96BD664F89E36868FBB48E3D
IV: is a byte[16] with 0 values
I used the below code, but I didn't get a matched result with him:
public byte[] AES_Encrypt(byte[] bytesToBeEncrypted, byte[] passwordBytes)
{
byte[] encryptedBytes = null;
byte[] saltBytes = new byte[16] { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
using (MemoryStream ms = new MemoryStream())
{
using (RijndaelManaged aes = new RijndaelManaged())
{
aes.KeySize = 256;
aes.BlockSize = 128;
var key = new Rfc2898DeriveBytes(passwordBytes, saltBytes, 1000);
aes.Key = key.GetBytes(aes.KeySize / 8);
aes.IV = key.GetBytes(aes.BlockSize / 8);
aes.Padding = PaddingMode.PKCS7;
aes.Mode = CipherMode.CBC;
using (var cs = new CryptoStream(ms, aes.CreateEncryptor(), CryptoStreamMode.Write))
{
cs.Write(bytesToBeEncrypted, 0, bytesToBeEncrypted.Length);
cs.Close();
}
encryptedBytes = ms.ToArray();
}
}
return encryptedBytes;
}
public string EncryptText(string input, string password)
{
byte[] bytesToBeEncrypted = Encoding.UTF8.GetBytes(input);
byte[] passwordBytes = Encoding.UTF8.GetBytes(password);
passwordBytes = SHA256.Create().ComputeHash(passwordBytes);
byte[] bytesEncrypted = AES_Encrypt(bytesToBeEncrypted, passwordBytes);
string result = Convert.ToBase64String(bytesEncrypted);
return result;
}
So, when we tried to encrypt Hello, How are you?, I got a different result and I should get the same result he had as he will decrypt my sent data on his side and will process it. The given example should have this result: TJTojNoVgoqnhCj4uTv1jLBiZU7r+s/0Bm234bHU+S0=
I did some testing and now able to match your expected result.
2 changes to be done.
IV
IV is the easiest, as you said IV = 0, so set IV as follows:
aes.IV = new byte[16];
In AES, IV is 16 bytes. The above would create a byte array of 16 bytes with each value initialized to zero.
Key
The password you have given starts with "0x" - this essentially means that this is hexadecimal representation of the password string. I converted this password to byte array using this
string password = "A8703827AE586460105696504327B7BB0806FEAE96BD664F89E36868FBB48E3D";
Please note I removed the starting "0x" from the above
byte[] passwordBytes = StringToByteArray(password);
The above converts the hexadecimal password representation to a byte array.
In your AES_Encrypt method, directly assign this byte[] as the Key
aes.Key = passwordBytes;
Now, my result is TJTojNoVgoqnhCj4uTv1jLBiZU7r+s/0Bm234bHU+S0= which exactly matches with your expected output.

Decrypt PCLCrypto data from Xamarin Portable in C# Console

By encrypting data using PCLCrypto following this tutorial:
http://www.c-sharpcorner.com/UploadFile/4088a7/using-cryptography-in-portable-xamarin-formswindows-phone/
The only change I made is the salt, that is set by my self:
byte[] salt = new byte[16];
salt = Encoding.UTF8.GetBytes("We##%ds51&s9$$$8");
And I am unable to decrypt the result in a Console application:
public static string Decrypt(string text, byte[] key, int keysize = 128, int blocksize = 128, CipherMode cipher = CipherMode.CBC, PaddingMode padding = PaddingMode.PKCS7)
{
AesCryptoServiceProvider aes = new AesCryptoServiceProvider();
aes.BlockSize = blocksize;
aes.KeySize = keysize;
aes.Mode = cipher;
aes.Padding = padding;
byte[] iv = new byte[16];
iv = Encoding.UTF8.GetBytes("We##%ds51&s9$$$8");
byte[] src = Convert.FromBase64String(text);
using (ICryptoTransform decrypt = aes.CreateDecryptor(key, iv))
{
byte[] dest = decrypt.TransformFinalBlock(src, 0, src.Length);
decrypt.Dispose();
return Encoding.UTF8.GetString(dest);
}
}
What am I doing wrong?
Thanks!

AES 128 Cross-Platform Swift / C#

I've been trying to encrypt and decrypt on both iOS and .NET but I haven't been very successful. I've used this question but I get the error:
Specified initialisation vector (IV) does not match the block size for this algorithm.
Here's my encryption code for Swift using CryptoSwift:
let encrypt = try! "oauth_token".AES_encrypt("my key here (is 32 characters long)", iv: "1234567890123456")
func AES_encrypt(key: String, iv: String) throws -> String {
let data = self.dataUsingEncoding(NSUTF8StringEncoding)
let enc = try AES(key: key, iv: iv, blockMode:.CBC).encrypt(data!.arrayOfBytes(), padding: PKCS7())
let encData = NSData(bytes: enc, length: Int(enc.count))
let base64String: String = encData.base64EncodedStringWithOptions(NSDataBase64EncodingOptions(rawValue: 0));
let result = String(base64String)
return result
}
And my decryption code for .NET:
public static byte[] AES_Decrypt(byte[] bytesToBeDecrypted, byte[] key, byte[] iv)
{
byte[] decryptedBytes = null;
using (MemoryStream ms = new MemoryStream())
{
using (RijndaelManaged AES = new RijndaelManaged())
{
AES.KeySize = 256;
AES.BlockSize = 128;
AES.Key = key;
AES.IV = iv;
AES.Mode = CipherMode.CBC;
using (var cs = new CryptoStream(ms, AES.CreateDecryptor(), CryptoStreamMode.Write))
{
cs.Write(bytesToBeDecrypted, 0, bytesToBeDecrypted.Length);
cs.Close();
}
decryptedBytes = ms.ToArray();
}
}
return decryptedBytes;
}
byte[] encrypted_text = Convert.FromBase64String("secret token");
byte[] key = Convert.FromBase64String("32 character key");
byte[] iv = Convert.FromBase64String("0123456789012345");
string plaintext = Convert.ToBase64String(AES_Decrypt(encrypted_text, key, iv));
The block size is 16 bytes (AES.blockSize). Either you're using old version or your AES_encrypt() have some problem (AES_encrypt is not part of CryptoSwift).
Simple example from README:
let input: NSData // data to encrypt
let encrypted = try? input.encrypt(AES(key: "secret0key000000", iv:"0123456789012345"))
or this
// Encrypt string and get Base64 representation of result
let base64: String = try? "my secret string".encrypt(AES(key: "secret0key000000", iv: "0123456789012345"))

The input is not a valid Base-64 string as it contains a non-base 64 character in C#?

I am using the following methods for encryption and decryption of request and response in WCF Web service :
public static string Decrypt(string textToDecrypt, string key)
{
System.Text.UTF8Encoding encoding = new System.Text.UTF8Encoding();
RijndaelManaged rijndaelCipher = new RijndaelManaged();
rijndaelCipher.Mode = CipherMode.CBC;
rijndaelCipher.Padding = PaddingMode.PKCS7;
rijndaelCipher.KeySize = 0x80;
rijndaelCipher.BlockSize = 0x80;
string decodedUrl = HttpUtility.UrlDecode(textToDecrypt);
byte[] encryptedData = Convert.FromBase64String(decodedUrl);
byte[] pwdBytes = Encoding.UTF8.GetBytes(key);
byte[] keyBytes = new byte[0x10];
int len = pwdBytes.Length;
if (len > keyBytes.Length)
{
len = keyBytes.Length;
}
Array.Copy(pwdBytes, keyBytes, len);
rijndaelCipher.Key = keyBytes;
rijndaelCipher.IV = keyBytes;
byte[] plainText = rijndaelCipher.CreateDecryptor().TransformFinalBlock(encryptedData, 0, encryptedData.Length);
return encoding.GetString(plainText);
}
public static string Encrypt(string textToEncrypt, string key)
{
RijndaelManaged rijndaelCipher = new RijndaelManaged();
rijndaelCipher.Mode = CipherMode.CBC;
rijndaelCipher.Padding = PaddingMode.PKCS7;
rijndaelCipher.KeySize = 0x80;
rijndaelCipher.BlockSize = 0x80;
byte[] pwdBytes = Encoding.UTF8.GetBytes(key);
byte[] keyBytes = new byte[0x10];
int len = pwdBytes.Length;
if (len > keyBytes.Length)
{
len = keyBytes.Length;
}
Array.Copy(pwdBytes, keyBytes, len);
rijndaelCipher.Key = keyBytes;
rijndaelCipher.IV = keyBytes;
ICryptoTransform transform = rijndaelCipher.CreateEncryptor();
byte[] plainText = Encoding.UTF8.GetBytes(textToEncrypt);
return Convert.ToBase64String(transform.TransformFinalBlock(plainText, 0, plainText.Length));
}
By using methods data encrypted and decrypted successfully. After that I encrypt JSON Object Successfully but facing issue in decryption
I am using following data :
for Encryption
Encrypt("{\"password\":\"Password123\",\"username\":\"Jhon.Trrot\"}", "demo")
for Decryption
Decrypt(encString, "demo");
When I removed : and , it worked perfectly but with : and , getting this error:
The server encountered an error processing the request. The exception message is 'The input is not a valid Base-64 string as it contains a non-base 64 character, more than two padding characters, or a non-white space character among the padding characters. '.
You are forgetting to URL encode your base 64 output in the encryption method.

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