I'm trying to replicate an encryption method based on another C#
method that I found.
The C#
Encryption method EncryptText(word, password)
call to another method AES_Encrypt(byte[] bytesToBeEncrypted, byte[] passwordBytes)
to encrypt plain text:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using System.Security.Cryptography;
using System.IO;
using System.Text;
namespace Rextester
{
public class Program
{
public static void Main(string[] args)
{
var f = EncryptText("763059", "515t3ma5m15B4d35");//(word, password)
Console.WriteLine(f);
}
public static byte[] AES_Encrypt(byte[] bytesToBeEncrypted, byte[] passwordBytes)
{
byte[] encryptedBytes = null;
byte[] saltBytes = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 };
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.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 static 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;
}
}
}
Using word 763059 and password 515t3ma5m15B4d35, the output is the following:
3cHrXxxL1Djv0K2xW4HuCg==
UPDATE:
Now, I created a Java Class
main
where I'm trying to replicate previous code:
public class main {
final static String PASSWORD = "515t3ma5m15B4d35";
final static byte[] SALT = new byte[]{1, 2, 3, 4, 5, 6, 7, 8};
final static int KEY_SIZE = 256;
final static int BLOCK_SIZE = 128;
final static int ITERATIONS = 1000;
public static void main(String[] args) {
System.out.println(encryptText("763059", PASSWORD));
}
public static String encryptText(String word, String password) {
try {
MessageDigest md = MessageDigest.getInstance("SHA-256");
md.update(password.getBytes("UTF-8"));
password = new String(md.digest(), "UTF-8");
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
KeySpec spec = new PBEKeySpec(password.toCharArray(), SALT, ITERATIONS, KEY_SIZE);
SecretKey tmp = factory.generateSecret(spec);
SecretKeySpec skey = new SecretKeySpec(tmp.getEncoded(), "AES");
byte[] iv = new byte[BLOCK_SIZE / 8];
IvParameterSpec ivspec = new IvParameterSpec(iv);
Cipher ci = Cipher.getInstance("AES/CBC/PKCS5Padding");
ci.init(Cipher.ENCRYPT_MODE, skey, ivspec);
byte[] result = ci.doFinal(word.getBytes("UTF-8"));
return DatatypeConverter.printBase64Binary(result);
} catch (NoSuchAlgorithmException | UnsupportedEncodingException | IllegalBlockSizeException | BadPaddingException | InvalidKeyException | InvalidAlgorithmParameterException | NoSuchPaddingException | InvalidKeySpecException ex) {
return null;
}
}
}
UPDATE:
I read about using 256 bits keys in Java, and I found that I need to add Java Cryptography Extensions to allow 256 keys (Because I'm working with JDK7).
Then I added the libreries to the project, also I change the line:
KeySpec spec = new PBEKeySpec(password.toCharArray(), SALT, ITERATIONS, KEY_SIZE);
With the Key Value:
final static int KEY_SIZE = 256;
Now the output is the following:
J1xbKOjIeXbQ9njH+67RNw==
I still can't achieve my goal. Any Suggestion?
PBEKeySpec
expects a char-array. Inside the PBKDF2-provider the char-array is converted back into a byte-array using UTF-8 encoding. The original (used in the C#-code) and the reconverted byte-array will differ concerning values >=0x80
(which are mostly present). This results in different keys and IVs in both codes and thus, in different encrypted data. An alternative isPKCS5S2ParametersGenerator
from Bouncy Castle for the generation of key and IV which expects a byte-array. – Topaco