I used the following to encrypt a string using a password
static String algorithm = "PBEWITHSHA256AND128BITAES-CBC-BC";
static byte[] salt = "b9v4n38s".getBytes(StandardCharsets.UTF_8);
static int derivedKeyLength = 128;
static int iterations = 20000;
public static byte[] encrypt(String plainText, String password) throws NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException, InvalidKeySpecException, NoSuchAlgorithmException {
Security.addProvider(new BouncyCastleProvider());
KeySpec spec = new PBEKeySpec(password.toCharArray(), salt, iterations, derivedKeyLength);
SecretKeyFactory f = SecretKeyFactory.getInstance(algorithm);
SecretKey key = f.generateSecret(spec);
Cipher cipher = Cipher.getInstance(algorithm);
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] text = plainText.getBytes(StandardCharsets.UTF_8);
byte[] encrypted = cipher.doFinal(text);
return encrypted;
}
The result of this is base64 encoded and sent as arg[0] to .Net (arg[1] is the same password). Now I'm trying to decrypt that string in .Net with this code
private static string Decrypt(string[] args)
{
int derivedKeyLength = 128;
int iterations = 20000;
string algorithm = "PBEWITHSHA256AND128BITAES-CBC-BC";
byte[] salt = Encoding.UTF8.GetBytes("b9v4n38s");
PbeParametersGenerator pGen = new Pkcs12ParametersGenerator(new Sha256Digest());
pGen.Init(Encoding.UTF8.GetBytes(args[1]), salt, iterations);
ICipherParameters par = pGen.GenerateDerivedParameters("AES256", derivedKeyLength);
IBufferedCipher c = CipherUtilities.GetCipher(algorithm);
c.Init(false, par);
var input = Convert.FromBase64String(args[0]);
byte[] enc = c.DoFinal(input);
var decoded = Encoding.UTF8.GetString(enc);
return decoded;
}
Unfortunately it fails on DoFinal with message Org.BouncyCastle.Crypto.InvalidCipherTextException: 'pad block corrupted'
SecretKeyFactory.getInstance(algorithm) uses the same algorithm string as Cipher.getInstance(algorithm) in java but if I try pGen.GenerateDerivedParameters(algorithm, derivedKeyLength); in .Net it throws Org.BouncyCastle.Security.SecurityUtilityException: 'Algorithm PBEWITHSHA256AND128BITAES-CBC-BC not recognised.'
I'm not set on this algorithm, just looking for a way to encrypt a string in Java and decrypt it in .Net.
A possible C#/BC code to decrypt a ciphertext generated with the posted Java code is:
using System;
using System.Text;
using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Security;
...
private static string algorithm = "PBEWITHSHA256AND128BITAES-CBC-BC";
private static byte[] salt = Encoding.UTF8.GetBytes("b9v4n38s");
private static int iterations = 20000;
public static string Decrypt(string ciphertextB64, string password)
{
IBufferedCipher cipher = CipherUtilities.GetCipher(algorithm);
Asn1Encodable algParams = PbeUtilities.GenerateAlgorithmParameters(algorithm, salt, iterations);
ICipherParameters cipherParams = PbeUtilities.GenerateCipherParameters(algorithm, password.ToCharArray(), algParams);
cipher.Init(false, cipherParams);
byte[] cipherBytes = Convert.FromBase64String(ciphertextB64);
byte[] decrypted = cipher.DoFinal(cipherBytes);
return Encoding.UTF8.GetString(decrypted);
}
Test:
string decrypted = Decrypt("mBy4YwAvUpvoSJhzBnpOCJw2kCayvdYfLJ/12x0BgUKh5m5bvArSheMMs2U5rYyE", "MyPassword");
Console.WriteLine(decrypted); // The quick brown fox jumps over the lazy dog
where the ciphertext was generated with the Java code using the password MyPassword.
Please note that a static salt is generally insecure (except for testing purposes of course).
Related
I have been trying to send data effectively between two applications. One is implemented in C# (Sender) the other in Java (Receiver). The sender has to encrypt data using the transformation "AES/GCM/NOPadding" with a 32-byte key while the receiver has to decrypt using the same parameters. Here is the sender encryption function in C# (using bouncy castle)
public static string Encrypt(string plainText, string msgId)
{
const byte GcmTagSize = 16;
byte[] hashKey;
byte[] secretKey = Encoding.UTF8.GetBytes(msgId);
Console.WriteLine(secretKey.Length);
using (var hasher = SHA512.Create())
{
byte[] digestSeed = hasher.ComputeHash(secretKey);
hashKey = new byte[16];
Array.Copy(digestSeed, hashKey, hashKey.Length);
}
var keyParameter = new KeyParameter(hashKey);
var keyParameters = new AeadParameters(keyParameter, GcmTagSize * 8, secretKey);
var cipher = CipherUtilities.GetCipher("AES/GCM/NoPadding");
cipher.Init(true, keyParameters);
var plainTextData = Encoding.ASCII.GetBytes(plainText);
var cipherText = cipher.DoFinal(plainTextData); //bouncy castle
return Convert.ToBase64String(cipherText);
}
Here is the receiver decryption function in java
private static byte[] decrypt(byte[] message, SecretKey key) throws NoSuchPaddingException, NoSuchAlgorithmException,
IllegalBlockSizeException, BadPaddingException, InvalidAlgorithmParameterException, InvalidKeyException {
Cipher cipher = Cipher.getInstance("AES/GCM/NOPadding"); //NoPadding
byte[] nonce = Arrays.copyOfRange(message, message.length - cipher.getBlockSize(), message.length);
byte[] encryptedKycData = Arrays.copyOf(message, message.length - cipher.getBlockSize());
System.out.println(doEncode(nonce));
System.out.println(doEncode(nonce));
GCMParameterSpec gcmParameterSpec = new GCMParameterSpec(128, nonce);
cipher.init(Cipher.DECRYPT_MODE, key, gcmParameterSpec);
byte[] decryptedValue=cipher.doFinal(encryptedKycData);
return decryptedValue;
}
When I try to decrypt with the java decryption function I get the error
javax.crypto.AEADBadTagException: Tag mismatch
Struggling with this issue and any help would be appreciated.
I have to change java code for decrypt to flutter code. I use library "encrypt" for flutter. my flutter code show
Key length not 128/192/256 bits.
my java spring boot code.
public static String decryptAES256(String str, String secretKey) throws java.io.UnsupportedEncodingException,
NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException,
InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException {
String AES = "AES";
String AES_PADDING = "AES/CBC/PKCS5Padding";
byte[] keyData = java.util.Base64.getDecoder().decode(secretKey);
String iv = secretKey.substring(0, 16);
SecretKey secureKey = new SecretKeySpec(keyData, AES);
Cipher c = Cipher.getInstance(AES_PADDING);
c.init(Cipher.DECRYPT_MODE, secureKey, new IvParameterSpec(iv.getBytes(StandardCharsets.UTF_8)));
byte[] byteStr = Base64.getDecoder().decode(str.getBytes());
return new String(c.doFinal(byteStr), StandardCharsets.UTF_8);
}
my flutter code.
final encData = codefModel.data!.encData!;
final key = en.Key.fromUtf8(decryptKey);
final b64key = en.Key.fromUtf8(base64Url.encode(key.bytes));
final iv = en.IV.fromLength(16);
final encrypter = en.Encrypter(en.AES(b64key, mode: en.AESMode.cbc));
logger.d(encrypter.decrypt64(encData, iv: iv));
From the Java code it can be deduced that the AES key secretKey and the ciphertext str are Base64 encoded. The first 16 bytes of the Base64 encoded key (not of the raw key!) are used as IV.
In the Dart code the key is incorrectly converted and a wrong IV is used. A possible fix is (together with sample data):
const decryptKey = "MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDE=";
const encData = "lo0dOoJrHNRuefPXgkEa6jtDUhV5CguF9MHWTJ4Y8eGP8zHaKJEQIuOTZxstyk3X";
final key = en.Key.fromBase64(decryptKey);
final iv = en.IV(Uint8List.fromList(utf8.encode(decryptKey).sublist(0, 16)));
final encrypter = en.Encrypter(en.AES(key, mode: en.AESMode.cbc));
final decrypted = encrypter.decrypt64(encData, iv: iv); // The quick brown fox jumps over the lazy dog
As test, key and ciphertext can be used in the Java code that returns the same plaintext for them.
Be aware that deriving the IV from the key is generally insecure, since encryptions with the same key automatically lead to the reuse of key/IV pairs. Instead, a random IV should be used for each encryption.
I'm trying to mimic a java encryption routine in C# because the endpoint is java based and will be decrypting the value generated by C#.
I've tried different implementations using AesCryptoServiceProvider and AesManaged from several examples found in SO and around the web but I still can't get the java endpoint to successfully decrypt the value, it errors with {"message":"AUTHENTICATION_ERROR: Error while decrypting the cipher.","status":"Error"}.
Using postman I was able to call the java endpoint and retrieve a document using the
encrypted text generated by the java code posted below, so that part is positively verified.
The endpoint uses the header values to decrypt the text and verify the contents, here are the pertinent code pieces:
java encryption
private static Cipher generateCipher(int mode, String password, String salt, String iv, Integer iterations, Integer keySize) throws Exception {
byte[] saltBytes = salt.getBytes("UTF-8"); byte[]ivBytes = iv.getBytes("UTF-8");
// Derive the key
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
PBEKeySpec spec = new PBEKeySpec(password.toCharArray(), saltBytes, iterations, keySize);
SecretKey secretKey = factory.generateSecret(spec);
SecretKeySpec secret = new SecretKeySpec(secretKey.getEncoded(), "AES");
//encrypt the message
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); cipher.init(mode, secret, new IvParameterSpec(ivBytes));
return cipher;
}
public static String AES_encrypt(String plainText, String password, String salt, String iv, Integer iterations, Integer keySize) throws Exception {
Cipher cipher = generateCipher(Cipher.ENCRYPT_MODE, password, salt, iv, iterations, keySize);
byte[] encryptedTextBytes = cipher.doFinal(plainText.getBytes("UTF-8"));
Base64.Encoder encoder = Base64.getEncoder();
return encoder.encodeToString(encryptedTextBytes);
}
headers
interface_name: interfaceName
strength: 256
salt: salt_sixteen1234
iterate: 100
iv: sixteen_value_12
ciphertext: ECtKO7VluxCPFS/D8LVsb2bOQjhViIZm+O3zfMqSwJOLLTpDL4xdgwmIWr+41n5j
C# encrypt
...
using (var csp = new AesCryptoServiceProvider())
{
ICryptoTransform e = GetCryptoTransform(csp, true, key, salt, iv);
byte[] inputBuffer = Encoding.UTF8.GetBytes(plainText);
byte[] output = e.TransformFinalBlock(inputBuffer, 0, inputBuffer.Length);
string encrypted = Convert.ToBase64String(output);
return encrypted;
}
...
private static ICryptoTransform GetCryptoTransform(AesCryptoServiceProvider csp, bool encrypting, string password, string salt, string iv, int iterations)
{
csp.Mode = CipherMode.CBC;
csp.Padding = PaddingMode.PKCS7;
var spec = new Rfc2898DeriveBytes(Encoding.UTF8.GetBytes(password), Encoding.UTF8.GetBytes(salt), iterations);
byte[] key = spec.GetBytes(16);
csp.IV = Encoding.UTF8.GetBytes(iv);
csp.Key = key;
if (encrypting)
{
return csp.CreateEncryptor();
}
return csp.CreateDecryptor();
}
To test any C# encryption I added a decryption method to your Java code and run successfully a full round (encryption and decryption).
For the C# part I was too lazy to check your code (as #Topaco did it) and used my own code with your credentials to get an output that you can present to the Java decryption method.
Let's start with a longer Security warning: the codes are using a static initialization vector and a static salt and the iteration count
for PBKDF2 key derivation is much too low (a minimum of 10.000 should be used). The codes do not have any exception handling and are for educational purpose only.
Running the C#-code gives a short output:
AES CBC 256 string encryption with PBKDF2 SHA1 key derivation
plaintext: The quick brown fox jumps over the lazy dog
ciphertext: 5HMLSQKEgG+RADgPmf5Eyw0F/GG9sXFuWiHeuZxgpmJP+UoH4MZlvnQDrgnofQy4
Presenting the ciphertext to the Java decryption will give this output:
C# AES encrypt to java 8 decrypt
plaintext: The quick brown fox jumps over the lazy dog
ciphertext: 5HMLSQKEgG+RADgPmf5Eyw0F/GG9sXFuWiHeuZxgpmJP+UoH4MZlvnQDrgnofQy4
decryptedtext: The quick brown fox jumps over the lazy dog
decryption of a ciphertext from C#
ciphertextFromCsharp: 5HMLSQKEgG+RADgPmf5Eyw0F/GG9sXFuWiHeuZxgpmJP+UoH4MZlvnQDrgnofQy4
decryptedtextFromCsharp: The quick brown fox jumps over the lazy dog
Both codes are available for a live self test here (Java: https://repl.it/#javacrypto/JavaAes256EncryptionWithPBKDF2SHA1keyderivation, C#: https://repl.it/#javacrypto/CsharpAes256Pbkdf2Encryption#main.cs).
C#-code:
using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;
public class Program {
public static void Main() {
Console.WriteLine("AES CBC 256 string encryption with PBKDF2 SHA1 key derivation");
// credentials
string plaintext = "The quick brown fox jumps over the lazy dog";
string password = "myPassword";
string saltString = "salt_sixteen1234";
var iterationsCount = 100;
string ivString = "sixteen_value_12";
Encoding enc = Encoding.UTF8;
byte[] saltBytes = enc.GetBytes(saltString);
byte[] iv = enc.GetBytes(ivString);
byte[] key;
try {
// pbkdf2 sha1 key derivation
using (var pbkdf2 = new Rfc2898DeriveBytes(
password,
saltBytes,
iterationsCount,
HashAlgorithmName.SHA1))
{
key = pbkdf2.GetBytes(32);
}
Console.WriteLine("plaintext: {0}", plaintext);
string ciphertext = encrypt(key, iv, plaintext);
Console.WriteLine("ciphertext: {0}", ciphertext);
}
catch(Exception e) {
Console.WriteLine("Error: {0}", e.Message);
}
}
static string encrypt(byte[] key, byte[] IV, string data) {
byte[] encrypted;
using(Aes aesAlg = Aes.Create()) {
aesAlg.Key = key;
aesAlg.IV = IV;
aesAlg.Mode = CipherMode.CBC;
var encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);
// create the streams used for encryption.
using(var msEncrypt = new MemoryStream()) {
using(var csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write)) {
using(var swEncrypt = new StreamWriter(csEncrypt)) {
//Write all data to the stream.
swEncrypt.Write(data);
}
encrypted = msEncrypt.ToArray();
}
}
}
return Convert.ToBase64String(encrypted);
}
}
Java-code:
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
public class Main {
public static void main(String[] args) throws Exception {
System.out.println("C# AES encrypt to java 8 decrypt");
String plaintext = "The quick brown fox jumps over the lazy dog";
String password = "myPassword";
String iv = "sixteen_value_12";
String salt = "salt_sixteen1234";
int iterations = 100;
int keySize = 256;
System.out.println("plaintext: " + plaintext);
String ciphertext = AES_encrypt(plaintext, password, salt, iv, iterations, keySize);
System.out.println("ciphertext: " + ciphertext);
String decryptedtext = AES_decrypt(ciphertext, password, salt, iv, iterations, keySize);
System.out.println("decryptedtext: " + decryptedtext);
System.out.println("\ndecryption of a ciphertext from C#");
String ciphertextFromCsharp = "5HMLSQKEgG+RADgPmf5Eyw0F/GG9sXFuWiHeuZxgpmJP+UoH4MZlvnQDrgnofQy4";
System.out.println("ciphertextFromCsharp: " + ciphertextFromCsharp);
String decryptedtextFromCsharp = AES_decrypt(ciphertextFromCsharp, password, salt, iv, iterations, keySize);
System.out.println("decryptedtextFromCsharp: " + decryptedtextFromCsharp);
}
private static Cipher generateCipher(int mode, String password, String salt, String iv, Integer iterations, Integer keySize) throws Exception {
byte[] saltBytes = salt.getBytes("UTF-8"); byte[]ivBytes = iv.getBytes("UTF-8");
// Derive the key
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
PBEKeySpec spec = new PBEKeySpec(password.toCharArray(), saltBytes, iterations, keySize);
SecretKey secretKey = factory.generateSecret(spec);
SecretKeySpec secret = new SecretKeySpec(secretKey.getEncoded(), "AES");
//encrypt the message
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); cipher.init(mode, secret, new IvParameterSpec(ivBytes));
return cipher;
}
public static String AES_encrypt(String plainText, String password, String salt, String iv, Integer iterations, Integer keySize) throws Exception {
Cipher cipher = generateCipher(Cipher.ENCRYPT_MODE, password, salt, iv, iterations, keySize);
byte[] encryptedTextBytes = cipher.doFinal(plainText.getBytes("UTF-8"));
Base64.Encoder encoder = Base64.getEncoder();
return encoder.encodeToString(encryptedTextBytes);
}
public static String AES_decrypt(String cipherText, String password, String salt, String iv, Integer iterations, Integer keySize) throws Exception {
Base64.Decoder decoder = Base64.getDecoder();
Cipher cipher = generateCipher(Cipher.DECRYPT_MODE, password, salt, iv, iterations, keySize);
return new String(cipher.doFinal(decoder.decode(cipherText)), StandardCharsets.UTF_8);
}
}
I am using AESCrypt (gradle :compile 'com.scottyab:aescrypt:0.0.1')
to encrypt and decrypt the data.
TextView tv=(TextView)findViewById(R.id.demotext);
String encrypted="",decrypted="";
try {
encrypted = AESCrypt.encrypt("password","This is the best thing to go by");
decrypted = AESCrypt.decrypt("password",encrypted);
} catch (GeneralSecurityException e) {
e.printStackTrace();
}
System.out.println("EncryptedData:"+encrypted);
System.out.println("DecryptedData:"+decrypted);
tv.setText("Encrypted:"+encrypted +"\n"+"Decrypted:"+decrypted);
The code works perfectly fine in this case, I get the same input as decrypted text.
But, when I try to use already encrypted string using the same method (AES) from the site http://aesencryption.net/ as shown in the screenshot:
And copy paste that encrypted text like:
decrypted = AESCrypt.decrypt("password","sttA+FbNm3RkTovjHI8CcAdStXiMl45s29Jqle+y+pA=");
And then run the code then I get error saying :
javax.crypto.BadPaddingException: error:1e06b065:Cipher functions:EVP_DecryptFinal_ex:BAD_DECRYPT
But when I use the decrypted text into the same site it works fine as shown in the screenshot below.
private static byte[] decrypt(byte[] raw, byte[] encrypted) throws Exception {
SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE, skeySpec);
byte[] decrypted = cipher.doFinal(encrypted);
return decrypted;
}
Probably due to the algorithm to convert the passphrase 'password' to SecretKeySpec
This is the algorithm in AESCrypt
private static SecretKeySpec GenerateKey (final String password) throws NoSuchAlgorithmException, UnsupportedEncodingException {
final MessageDigest digest = MessageDigest.getInstance (HASH_ALGORITHM);
byte [] bytes = password.getBytes ("UTF-8");
digest.update (bytes, 0, bytes.length);
byte [] key = digest.digest ();
log ("SHA-256 key" key);
SecretKeySpec secretKeySpec = new SecretKeySpec (key, "AES");
secretKeySpec return;
}
And this is the (Java) example aesencryption.net
sha = MessageDigest.getInstance ("SHA-1");
key = sha.digest (key);
key = Arrays.copyOf (key, 16); // Use only first 128 bit
SecretKey = new SecretKeySpec (key, "AES");
The first one applies SHA256 hashing, and the second SHA-1 after completing up to 16 bytes, so the key is different.
I think you are encrypting and decrypting AES in the right way. You do not need to change anything.
But if you want to be compatible with aesencryption.net, you need to implement the same key generation algorithm. The code is not too good. I try to summarize
//Code from aesencryption.net
// Generate key
MessageDigest sha = null;
key = myKey.getBytes ("UTF-8");
sha = MessageDigest.getInstance ("SHA-1");
key = sha.digest (key);
key = Arrays.copyOf (key, 16); // Use only first 128 bit
SecretKey = new SecretKeySpec (key, "AES");
public static String encrypt (String strToEncrypt) {
Cipher cipher = Cipher.getInstance ("AES / ECB / PKCS5Padding");
cipher.init (Cipher.ENCRYPT_MODE, SecretKey);
Base64.encodeBase64String return (cipher.doFinal (strToEncrypt.getBytes ("UTF-8"))));
}
public static String decrypt (String strToDecrypt) {
Cipher cipher = Cipher.getInstance ("AES / ECB / PKCS5PADDING");
cipher.init (Cipher.DECRYPT_MODE, SecretKey);
return new String (cipher.doFinal (Base64.decodeBase64 (strToDecrypt))));
}
I can also provide my own code extracted from an Android app witch requires to store private user data. Data is ciphered with an AES key protected with an user passphrase
public static String SIMMETRICAL_ALGORITHM = "AES";
//Generate cipher key with user provided password
private static String getPassphraseSize16(String key) {
if (TextUtils.isEmpty(key)) {
return null;
}
char controlChar = '\u0014';
String key16 = key + controlChar;
if (key16.length() < 16) {
while (key16.length() < 16) {
key16 += key + controlChar;
}
}
if (key16.length() > 16) {
key16 = key16.substring(key16.length() - 16, key16.length());
}
return key16;
}
//AES cipher with passphrase
public static byte[] encrypt(byte[] message, String passphrase)
throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
String passphrase16 = getPassphraseSize16(passphrase);
SecretKeySpec secretKey = new SecretKeySpec(passphrase16.getBytes(), SIMMETRICAL_ALGORITHM);
Cipher cipher = Cipher.getInstance(SIMMETRICAL_ALGORITHM);
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
byte[] encoded = cipher.doFinal(message);
return encoded;
}
//AES decipher with passphrase
public static byte[] decrypt(byte[] encodedMessage, String key) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
String passphrase16 = getPassphraseSize16(key);
SecretKeySpec secretKey = new SecretKeySpec(passphrase16.getBytes(), SIMMETRICAL_ALGORITHM);
Cipher cipher = Cipher.getInstance(SIMMETRICAL_ALGORITHM);
cipher.init(Cipher.DECRYPT_MODE, secretKey);
byte decoded[] = cipher.doFinal(encodedMessage);
return decoded;
}
I'm using AES encryption/decryption algorithm in my application.
On the server side I use c# to encrypt/decrypt the data.
And on client side(android) I use java to decrypt the data.
C# encryption/decryption code
static readonly string PasswordHash = "52";
static readonly string SaltKey = "dfkjsadfinewdfadsfkmeoinmsdflksdflk";
static readonly string VIKey = "#EUBRHDFBFG8867";
public static string Encrypt(string plainText)
{
byte[] plainTextBytes = Encoding.UTF8.GetBytes(plainText);
byte[] keyBytes = new Rfc2898DeriveBytes(PasswordHash,Encoding.ASCII.GetBytes(SaltKey)).GetBytes(256 / 8);
var symmetricKey = new RijndaelManaged() { Mode = CipherMode.CBC, Padding =PaddingMode.Zeros };
var encryptor = symmetricKey.CreateEncryptor(keyBytes,Encoding.ASCII.GetBytes(VIKey));
byte[] cipherTextBytes;
using (var memoryStream = new MemoryStream())
{
using (var cryptoStream = new CryptoStream(memoryStream, encryptor,CryptoStreamMode.Write))
{
cryptoStream.Write(plainTextBytes, 0, plainTextBytes.Length);
cryptoStream.FlushFinalBlock();
cipherTextBytes = memoryStream.ToArray();
cryptoStream.Close();
}
memoryStream.Close();
}
return Convert.ToBase64String(cipherTextBytes);
}
public static string Decrypt(string encryptedText)
{
byte[] cipherTextBytes = Convert.FromBase64String(encryptedText);
byte[] keyBytes = new Rfc2898DeriveBytes(PasswordHash,Encoding.ASCII.GetBytes(SaltKey)).GetBytes(256 / 8);
var symmetricKey = new RijndaelManaged() { Mode = CipherMode.CBC, Padding =PaddingMode.None }
var decryptor = symmetricKey.CreateDecryptor(keyBytes,Encoding.ASCII.GetBytes(VIKey));
var memoryStream = new MemoryStream(cipherTextBytes);
var 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).TrimEnd("\0".ToCharArray());
}
Java Decryption method
public String decrypt(String dataToDecrypt) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidKeySpecException, IllegalBlockSizeException, BadPaddingException, InvalidAlgorithmParameterException, UnsupportedEncodingException
{
byte[] encryptedCombinedBytes = Base64.decodeBase64(dataToDecrypt.getBytes());
String saltKey = "dfkjsadfinewdfadsfkmeoinmsdflksdflk";
String password = "52";
String IVKey = "#EUBRHDFBFG8867";
PBKDF2Parameters p = new PBKDF2Parameters("HmacSHA256", "ASCII", saltKey.getBytes(), 8);
byte[] mEncryptedPassword = new PBKDF2Engine(p).deriveKey(password);
byte[] ivbytes = Arrays.copyOfRange(IVKey.getBytes(), 0, 16);
SecretKeySpec mSecretKeySpec = new SecretKeySpec(mEncryptedPassword, "AES");
Cipher mCipher = Cipher.getInstance("AES/CBC/NoPadding");
mCipher.init(Cipher.DECRYPT_MODE, mSecretKeySpec, new IvParameterSpec(ivbytes));
byte[] encryptedTextBytes = Arrays.copyOfRange(encryptedCombinedBytes, 16, encryptedCombinedBytes.length);
byte[] decryptedTextBytes = mCipher.doFinal(encryptedTextBytes);
return new String(decryptedTextBytes, "UTF-8");
}
C# decryption method works fine and give the result string.
I cannot figure out the problem in Java decryption code. It runs and give me some garbage value.
EDIT
I can not edit anything on the server side.I just have to replicate the decryption in java decryption.
I dont know how to use passwordHash, saltKey and IVkey
First of all, you've switched the password and the salt around.
Second, PBKDF2 uses HMAC/SHA-1 as default. As far as I know that's also the default for Rfc2898DeriveBytes:
Implements password-based key derivation functionality, PBKDF2, by using a pseudo-random number generator based on HMACSHA1.
You should also never call getBytes without specifying the character set in Java, but this is probably not an issue for your current runtime.
These are comments on the code only; do not use CBC over network connections without integrity/authenticity protection.