I'm facing an issue trying to Decrypt a string which has been encrypted in Java with the following properties (Java code)
public static Builder getDefaultBuilder(String key, String salt, byte[] iv) {
return new Builder()
.setIv(iv)
.setKey(key)
.setSalt(salt)
.setKeyLength(128)
.setKeyAlgorithm("AES")
.setCharsetName("UTF8")
.setIterationCount(1)
.setDigestAlgorithm("SHA1")
.setBase64Mode(Base64.DEFAULT)
.setAlgorithm("AES/CBC/PKCS5Padding")
.setSecureRandomAlgorithm("SHA1PRNG")
.setSecretKeyType("PBKDF2WithHmacSHA1");
}
This is my code so far (C#)
public string DecryptText(string encryptedString)
{
using (myRijndael = new RijndaelManaged())
{
myRijndael.Key = Convert.FromBase64String(encryptionKey);
myRijndael.IV = new byte[16];
myRijndael.Mode = CipherMode.CBC;
myRijndael.Padding = PaddingMode.PKCS7;
Byte[] ourEnc = Convert.FromBase64String(encryptedString);
string ourDec = DecryptStringFromBytes(ourEnc, myRijndael.Key, myRijndael.IV);
return ourDec;
}
}
protected string DecryptStringFromBytes(byte[] cipherText, byte[] Key, byte[] IV)
{
// Check arguments.
if (cipherText == null || cipherText.Length <= 0)
throw new ArgumentNullException("cipherText");
if (Key == null || Key.Length <= 0)
throw new ArgumentNullException("Key");
if (IV == null || IV.Length <= 0)
throw new ArgumentNullException("Key");
// Declare the string used to hold
// the decrypted text.
string plaintext = null;
// Create an RijndaelManaged object
// with the specified key and IV.
using (RijndaelManaged rijAlg = new RijndaelManaged())
{
rijAlg.Key = Key;
rijAlg.IV = IV;
// Create a decrytor to perform the stream transform.
ICryptoTransform decryptor = rijAlg.CreateDecryptor(rijAlg.Key, rijAlg.IV);
// Create the streams used for decryption.
using (MemoryStream msDecrypt = new MemoryStream(cipherText))
{
using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
{
using (StreamReader srDecrypt = new StreamReader(csDecrypt))
{
// Read the decrypted bytes from the decrypting stream
// and place them in a string.
plaintext = srDecrypt.ReadToEnd();
}
}
}
}
return plaintext;
}
But when I try to decrypt I get the following exception "System.Security.Cryptography.CryptographicException: 'Specified key is not a valid size for this algorithm.'
".
The origin of the Java code resides here
https://github.com/simbiose/Encryption/blob/master/Encryption/main/se/simbio/encryption/Encryption.java
This is the Java code when encrypting
public String encrypt(String data) throws UnsupportedEncodingException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidAlgorithmParameterException, InvalidKeyException, InvalidKeySpecException, BadPaddingException, IllegalBlockSizeException {
if (data == null) return null;
SecretKey secretKey = getSecretKey(hashTheKey(mBuilder.getKey()));
byte[] dataBytes = data.getBytes(mBuilder.getCharsetName());
Cipher cipher = Cipher.getInstance(mBuilder.getAlgorithm());
cipher.init(Cipher.ENCRYPT_MODE, secretKey, mBuilder.getIvParameterSpec(), mBuilder.getSecureRandom());
return Base64.encodeToString(cipher.doFinal(dataBytes), mBuilder.getBase64Mode());
}
private SecretKey getSecretKey(char[] key) throws NoSuchAlgorithmException, UnsupportedEncodingException, InvalidKeySpecException {
SecretKeyFactory factory = SecretKeyFactory.getInstance(mBuilder.getSecretKeyType());
KeySpec spec = new PBEKeySpec(key, mBuilder.getSalt().getBytes(mBuilder.getCharsetName()), mBuilder.getIterationCount(), mBuilder.getKeyLength());
SecretKey tmp = factory.generateSecret(spec);
return new SecretKeySpec(tmp.getEncoded(), mBuilder.getKeyAlgorithm());
}
private char[] hashTheKey(String key) throws UnsupportedEncodingException, NoSuchAlgorithmException {
MessageDigest messageDigest = MessageDigest.getInstance(mBuilder.getDigestAlgorithm());
messageDigest.update(key.getBytes(mBuilder.getCharsetName()));
return Base64.encodeToString(messageDigest.digest(), Base64.NO_PADDING).toCharArray();
}
I've been struggling with this for two day since I haven't really worked a lot with encryption, so any help would be greatly appreciated.
Thanks!
Update:
Whole class
public sealed class MyCryptoClass
{
protected RijndaelManaged myRijndael;
private static string encryptionKey = "random";
// Singleton pattern used here with ensured thread safety
protected static readonly MyCryptoClass _instance = new MyCryptoClass();
public static MyCryptoClass Instance
{
get { return _instance; }
}
public MyCryptoClass()
{
}
public string DecryptText(string encryptedString)
{
using (myRijndael = new RijndaelManaged())
{
myRijndael.Key = Convert.FromBase64String(encryptionKey);
myRijndael.IV = new byte[16];
myRijndael.Mode = CipherMode.CBC;
myRijndael.Padding = PaddingMode.PKCS7;
Byte[] ourEnc = Convert.FromBase64String(encryptedString);
string ourDec = DecryptStringFromBytes(ourEnc, myRijndael.Key, myRijndael.IV);
return ourDec;
}
}
public string EncryptText(string plainText)
{
using (myRijndael = new RijndaelManaged())
{
myRijndael.Key = HexStringToByte(encryptionKey);
myRijndael.IV = HexStringToByte(initialisationVector);
myRijndael.Mode = CipherMode.CBC;
myRijndael.Padding = PaddingMode.PKCS7;
byte[] encrypted = EncryptStringToBytes(plainText, myRijndael.Key, myRijndael.IV);
string encString = Convert.ToBase64String(encrypted);
return encString;
}
}
protected byte[] EncryptStringToBytes(string plainText, byte[] Key, byte[] IV)
{
// Check arguments.
if (plainText == null || plainText.Length <= 0)
throw new ArgumentNullException("plainText");
if (Key == null || Key.Length <= 0)
throw new ArgumentNullException("Key");
if (IV == null || IV.Length <= 0)
throw new ArgumentNullException("Key");
byte[] encrypted;
// Create an RijndaelManaged object
// with the specified key and IV.
using (RijndaelManaged rijAlg = new RijndaelManaged())
{
rijAlg.Key = Key;
rijAlg.IV = IV;
// Create a decrytor to perform the stream transform.
ICryptoTransform encryptor = rijAlg.CreateEncryptor(rijAlg.Key, rijAlg.IV);
// Create the streams used for encryption.
using (MemoryStream msEncrypt = new MemoryStream())
{
using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
{
using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
{
//Write all data to the stream.
swEncrypt.Write(plainText);
}
encrypted = msEncrypt.ToArray();
}
}
}
// Return the encrypted bytes from the memory stream.
return encrypted;
}
protected string DecryptStringFromBytes(byte[] cipherText, byte[] Key, byte[] IV)
{
// Check arguments.
if (cipherText == null || cipherText.Length <= 0)
throw new ArgumentNullException("cipherText");
if (Key == null || Key.Length <= 0)
throw new ArgumentNullException("Key");
if (IV == null || IV.Length <= 0)
throw new ArgumentNullException("Key");
// Declare the string used to hold
// the decrypted text.
string plaintext = null;
// Create an RijndaelManaged object
// with the specified key and IV.
using (RijndaelManaged rijAlg = new RijndaelManaged())
{
rijAlg.Key = Key;
rijAlg.IV = IV;
// Create a decrytor to perform the stream transform.
ICryptoTransform decryptor = rijAlg.CreateDecryptor(rijAlg.Key, rijAlg.IV);
// Create the streams used for decryption.
using (MemoryStream msDecrypt = new MemoryStream(cipherText))
{
using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
{
using (StreamReader srDecrypt = new StreamReader(csDecrypt))
{
// Read the decrypted bytes from the decrypting stream
// and place them in a string.
plaintext = srDecrypt.ReadToEnd();
}
}
}
}
return plaintext;
}
public static void GenerateKeyAndIV()
{
// This code is only here for an example
RijndaelManaged myRijndaelManaged = new RijndaelManaged();
myRijndaelManaged.Mode = CipherMode.CBC;
myRijndaelManaged.Padding = PaddingMode.PKCS7;
myRijndaelManaged.GenerateIV();
myRijndaelManaged.GenerateKey();
string newKey = ByteArrayToHexString(myRijndaelManaged.Key);
string newinitVector = ByteArrayToHexString(myRijndaelManaged.IV);
}
protected static byte[] HexStringToByte(string hexString)
{
try
{
int bytesCount = (hexString.Length) / 2;
byte[] bytes = new byte[bytesCount];
for (int x = 0; x < bytesCount; ++x)
{
bytes[x] = Convert.ToByte(hexString.Substring(x * 2, 2), 16);
}
return bytes;
}
catch
{
throw;
}
}
public static string ByteArrayToHexString(byte[] ba)
{
StringBuilder hex = new StringBuilder(ba.Length * 2);
foreach (byte b in ba)
hex.AppendFormat("{0:x2}", b);
return hex.ToString();
}
}
Since your MyCryptoClass.encryptionKey corresponds to your Encryption.Builder.mKey you have to generate the secret key on the C#-side i.e. you have to implement on the C# side a counterpart for each Java-method involved in this process. These Java-methods are getSecretKey(char[] key), hashTheKey(String key) and also third.part.android.util.Base64.encodeToString(byte[] input, int flags).
Possible C#-Counterpart of the Java-method getSecretKey(char[] key):
private static byte[] GetSecretKey()
{
string hashedKey = GetHashedKey();
byte[] saltBytes = Encoding.UTF8.GetBytes(salt); // builder.mCharsetName = "UTF8";
int iterations = 1; // builder.mIterationCount = 1
byte[] secretKey = null;
using (Rfc2898DeriveBytes rfc2898 = new Rfc2898DeriveBytes(hashedKey, saltBytes, iterations)) // builder.mSecretKeyType = "PBKDF2WithHmacSHA1";
{
secretKey = rfc2898.GetBytes(16); // builder.mKeyLength = 128;
//Console.WriteLine("Key: " + ByteArrayToHexString(secretKey));
}
return secretKey;
}
This method derives a secret key using PBKDF2WithHmacSHA1 with a key, salt, iterationcount and key length as input. The key (more precisely password) used here is a base64-encoded SHA1-hash from MyCryptoClass.encryptionKey provided by GetHashedKey() (see below).
Possible C#-Counterpart of the Java-method hashTheKey(String key):
private static string GetHashedKey()
{
string hashBase64 = String.Empty;
using (SHA1Managed sha1 = new SHA1Managed()) // builder.mDigestAlgorithm = "SHA1";
{
byte[] hash = sha1.ComputeHash(Encoding.UTF8.GetBytes(encryptionKey)); // builder.mCharsetName = "UTF8";
hashBase64 = Base64ThirdPartAndroid(hash, true);
//Console.WriteLine("Hash (base64): " + hashBase64);
}
return hashBase64;
}
This method derives a SHA1-hash from MyCryptoClass.encryptionKey and base64-encodes that hash. For the base64-encoding the method Base64ThirdPartAndroid(byte[] arr, bool withoutPadding) (see below) is used.
Possible C#-Counterpart of the Java-method third.part.android.util.Base64.encodeToString(byte[] input, int flags) ( https://github.com/simbiose/Encryption/blob/master/Encryption/main/third/part/android/util/Base64.java):
private static string Base64ThirdPartAndroid(byte[] arr, bool withoutPadding)
{
string base64String = System.Convert.ToBase64String(arr);
if (withoutPadding) base64String = base64String.TrimEnd('='); // Remove trailing "="-characters
base64String += "\n"; // Append LF (10)
//Console.WriteLine("Array as base64 encoded string: " + base64String);
return base64String;
}
In the Java code third.part.android.util.Base64.encodeToString(byte[] input, int flags) is used with flags = Base64.NO_PADDING which removes the "="-character at the end of the base64-encoded string. Additionally a line feed (LF, \n, ASCII value: 10) is appended. If a Base64-Encoding is used which doesn't remove the "="-characters or without a terminating line feed, the decryption will fail since the hash is the base of the later generated secret key which have to match on the encryption and on the decryption side. To the best of my knowledge there is no Base64-encoding on the C# side with the necessary characteristics. However, if there is such an encoding you can use it of course.
Add all three C#-counterparts to your MyCryptoClass class.
Additionally (to the static field encryptionKey) add the static fields initialisationVector, salt and secretKey to your MyCryptoClass-class and assign the following values for testing purposes:
private static string encryptionKey = "A7zb534OPq59gU7q";
private static string salt = "JV5k9GoH";
private static byte[] initialisationVector = Encoding.UTF8.GetBytes("l4iG63jN9Dcg6537");
private static byte[] secretKey = GetSecretKey();
The type of the parameters corresponds to the type in the Java code (encryptionKey and salt are strings, the initialisationVector is a byte-array). The secret key generated by GetSecretKey() is stored in the byte-array secretKey.
In your C# DecryptText- and EncryptText-method set myRijndael.Key and myRijndael.IV to
myRijndael.Key = secretKey;
myRijndael.IV = initialisationVector;
Test the modifications as follows:
With your Java encrypt-method encrypt the following plain text:
Test: The quick brown fox jumps over the lazy dog...
using the key/salt/iv above with
mBuilder = Builder.getDefaultBuilder("A7zb534OPq59gU7q","JV5k9GoH","l4iG63jN9Dcg6537".getBytes("UTF-8"));
The encrypted text is:
mL4ajZtdRgD8CtGSfJGkT24Ebw4SrGUGKQI6bvBw1ziCO/J7SeLiyIw41zumTHMMD9GOYK+kR79CVcpoaHT9TQ==
Decrypting this using the C# DecryptText-method gives again the plain text. Below are two test cases:
static void Main(string[] args)
{
// Test 1: Encrypted text from C#
MyCryptoClass mcc = MyCryptoClass.Instance;
string encryptedText = mcc.EncryptText("This is a plain text which needs to be encrypted...");
Console.WriteLine("Encrypted text (base64): " + encryptedText);
string decryptedText = mcc.DecryptText(encryptedText);
Console.WriteLine("Decrypted text: " + decryptedText);
// Test 2: Encrypted text from Java
string javaEncryptedText = "mL4ajZtdRgD8CtGSfJGkT24Ebw4SrGUGKQI6bvBw1ziCO/J7SeLiyIw41zumTHMMD9GOYK+kR79CVcpoaHT9TQ==";
Console.WriteLine("Encrypted text from Java (base64): " + javaEncryptedText);
string javaDecryptedText = mcc.DecryptText(javaEncryptedText);
Console.WriteLine("Decrypted text from Java: " + javaDecryptedText);
}
Following is Full C# class which i were able to work as it is like java class
At the moment i have only checked encryption part
public sealed class MyCryptoClass
{
protected AesManaged myRijndael;
private static string encryptionKey = "MyKey";
private static string salt = "Mysalt";
private static byte[] initialisationVector = new byte[16];
//private static byte[] initialisationVector = Encoding.UTF8.GetBytes("l4iG63jN9Dcg6537");
private static byte[] secretKey = GetSecretKey();
// Singleton pattern used here with ensured thread safety
protected static readonly MyCryptoClass _instance = new MyCryptoClass();
public static MyCryptoClass Instance
{
get { return _instance; }
}
public MyCryptoClass()
{
}
public string DecryptText(string encryptedString)
{
using (myRijndael = new AesManaged())
{
myRijndael.Key = Convert.FromBase64String(encryptionKey);
myRijndael.IV = new byte[16];
myRijndael.Mode = CipherMode.CBC;
myRijndael.Padding = PaddingMode.PKCS7;
Byte[] ourEnc = Convert.FromBase64String(encryptedString);
string ourDec = DecryptStringFromBytes(ourEnc, myRijndael.Key, myRijndael.IV);
return ourDec;
}
}
public string EncryptText(string plainText)
{
using (myRijndael = new AesManaged())
{
myRijndael.Key = secretKey;
myRijndael.IV = initialisationVector;
myRijndael.Mode = CipherMode.CBC;
myRijndael.Padding = PaddingMode.PKCS7;
byte[] encrypted = EncryptStringToBytes(plainText, myRijndael.Key, myRijndael.IV);
string encString = Convert.ToBase64String(encrypted);
return encString;
}
}
protected byte[] EncryptStringToBytes(string plainText, byte[] Key, byte[] IV)
{
// Check arguments.
if (plainText == null || plainText.Length <= 0)
throw new ArgumentNullException("plainText");
if (Key == null || Key.Length <= 0)
throw new ArgumentNullException("Key");
if (IV == null || IV.Length <= 0)
throw new ArgumentNullException("Key");
byte[] encrypted;
// Create an RijndaelManaged object
// with the specified key and IV.
using (RijndaelManaged rijAlg = new RijndaelManaged())
{
rijAlg.Key = Key;
rijAlg.IV = IV;
// Create a decrytor to perform the stream transform.
ICryptoTransform encryptor = rijAlg.CreateEncryptor(rijAlg.Key, rijAlg.IV);
// Create the streams used for encryption.
using (MemoryStream msEncrypt = new MemoryStream())
{
using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
{
using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
{
//Write all data to the stream.
swEncrypt.Write(plainText);
}
encrypted = msEncrypt.ToArray();
}
}
}
// Return the encrypted bytes from the memory stream.
return encrypted;
}
protected string DecryptStringFromBytes(byte[] cipherText, byte[] Key, byte[] IV)
{
// Check arguments.
if (cipherText == null || cipherText.Length <= 0)
throw new ArgumentNullException("cipherText");
if (Key == null || Key.Length <= 0)
throw new ArgumentNullException("Key");
if (IV == null || IV.Length <= 0)
throw new ArgumentNullException("Key");
// Declare the string used to hold
// the decrypted text.
string plaintext = null;
// Create an RijndaelManaged object
// with the specified key and IV.
using (RijndaelManaged rijAlg = new RijndaelManaged())
{
rijAlg.Key = Key;
rijAlg.IV = IV;
// Create a decrytor to perform the stream transform.
ICryptoTransform decryptor = rijAlg.CreateDecryptor(rijAlg.Key, rijAlg.IV);
// Create the streams used for decryption.
using (MemoryStream msDecrypt = new MemoryStream(cipherText))
{
using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
{
using (StreamReader srDecrypt = new StreamReader(csDecrypt))
{
// Read the decrypted bytes from the decrypting stream
// and place them in a string.
plaintext = srDecrypt.ReadToEnd();
}
}
}
}
return plaintext;
}
public static void GenerateKeyAndIV()
{
// This code is only here for an example
AesManaged myRijndaelManaged = new AesManaged();
myRijndaelManaged.Mode = CipherMode.CBC;
myRijndaelManaged.Padding = PaddingMode.PKCS7;
myRijndaelManaged.GenerateIV();
myRijndaelManaged.GenerateKey();
string newKey = ByteArrayToHexString(myRijndaelManaged.Key);
string newinitVector = ByteArrayToHexString(myRijndaelManaged.IV);
}
protected static byte[] HexStringToByte(string hexString)
{
try
{
int bytesCount = (hexString.Length) / 2;
byte[] bytes = new byte[bytesCount];
for (int x = 0; x < bytesCount; ++x)
{
bytes[x] = Convert.ToByte(hexString.Substring(x * 2, 2), 16);
}
return bytes;
}
catch
{
throw;
}
}
public static string ByteArrayToHexString(byte[] ba)
{
StringBuilder hex = new StringBuilder(ba.Length * 2);
foreach (byte b in ba)
hex.AppendFormat("{0:x2}", b);
return hex.ToString();
}
private static byte[] GetSecretKey()
{
string hashedKey = GetHashedKey();
byte[] saltBytes = Encoding.UTF8.GetBytes(salt); // builder.mCharsetName = "UTF8";
int iterations = 1; // builder.mIterationCount = 1
byte[] secretKey = null;
using (Rfc2898DeriveBytes rfc2898 = new Rfc2898DeriveBytes(hashedKey, saltBytes, iterations)) // builder.mSecretKeyType = "PBKDF2WithHmacSHA1";
{
secretKey = rfc2898.GetBytes(16); // builder.mKeyLength = 128;
//Console.WriteLine("Key: " + ByteArrayToHexString(secretKey));
}
return secretKey;
}
private static string GetHashedKey()
{
string hashBase64 = String.Empty;
using (SHA1Managed sha1 = new SHA1Managed()) // builder.mDigestAlgorithm = "SHA1";
{
byte[] hash = sha1.ComputeHash(Encoding.UTF8.GetBytes(encryptionKey)); // builder.mCharsetName = "UTF8";
hashBase64 = Base64ThirdPartAndroid(hash, true);
//hashBase64 = Base64ThirdPartAndroid(hash, true);
//Console.WriteLine("Hash (base64): " + hashBase64);
}
return hashBase64;
}
private static string Base64ThirdPartAndroid(byte[] arr, bool withoutPadding)
{
string base64String = System.Convert.ToBase64String(arr);
if (withoutPadding) base64String = base64String.TrimEnd('='); // Remove trailing "="-characters
base64String += "\n"; // Append LF (10)
//Console.WriteLine("Array as base64 encoded string: " + base64String);
return base64String;
}
}
this method is 100% working for encryption
public static string AESDecrypt(string text, string secretKey)
{
try
{
SHA1 sha = new SHA1CryptoServiceProvider();
RijndaelManaged aes = new RijndaelManaged();
byte[] finalKey = new byte[16]; // Used to generate finalKey
byte[] byteDataToDecrypt = Convert.FromBase64String(text); // Converting Base64 data to Byte Array
byte[] byteSecretKey = Encoding.UTF8.GetBytes(secretKey); // Converting secret key in byte array
byte[] hashSecretKey = sha.ComputeHash(byteSecretKey); // geneating hash in byte array of secret key
Array.Copy(hashSecretKey, finalKey, 16); // copying fist 16 bytes from hashed secret key to finaly key which to use in algo
aes.KeySize = 128;
aes.Padding = PaddingMode.PKCS7;
aes.Mode = CipherMode.ECB;
aes.Key = finalKey;
using (ICryptoTransform decrypt = aes.CreateDecryptor(aes.Key, null)) //Passing IV as NULL because IV is not present in the Java Code
{
byte[] dest = decrypt.TransformFinalBlock(byteDataToDecrypt, 0, byteDataToDecrypt.Length);
decrypt.Dispose();
return Encoding.UTF8.GetString(dest);
}
}
catch (Exception ex)
{
throw ex;
}
}
Related
I have one java code that needs to be converted to c# code.
Java Util class
public class EncryptorDecryptorUtil {
private int keySize;
private Cipher cipher;
public EncryptorDecryptorUtil(int keySize)
{
this.keySize = keySize;
try
{
this.cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
}
catch (NoSuchAlgorithmException e)
{
e.printStackTrace();
}
catch (NoSuchPaddingException e)
{
e.printStackTrace();
}
}
public String decrypt(String salt, String iv, String passphrase, String EncryptedText)
{
String decryptedValue = null;
try
{
byte[] saltBytes = hexStringToByteArray(salt);
SecretKeySpec sKey = (SecretKeySpec)generateKeyFromPassword(
passphrase, saltBytes);
byte[] ivBytes = hexStringToByteArray(iv);
IvParameterSpec ivParameterSpec = new IvParameterSpec(ivBytes);
this.cipher.init(2, sKey, ivParameterSpec);
byte[] decordedValue = new BASE64Decoder()
.decodeBuffer(EncryptedText);
byte[] decValue = this.cipher.doFinal(decordedValue);
decryptedValue = new String(decValue);
}
catch (Exception e)
{
e.printStackTrace();
}
return decryptedValue;
}
public static SecretKey generateKeyFromPassword(String password, byte[] saltBytes)
throws GeneralSecurityException
{
KeySpec keySpec = new PBEKeySpec(password.toCharArray(), saltBytes,
100, 128);
SecretKeyFactory keyFactory =
SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
SecretKey secretKey = keyFactory.generateSecret(keySpec);
return new SecretKeySpec(secretKey.getEncoded(), "AES");
}
public static byte[] hexStringToByteArray(String s)
{
System.out.println("s:::::::"+s);
int len = s.length();
byte[] data = new byte[len / 2];
for (int i = 0; i < len; i += 2) {
data[(i / 2)] =
((byte)((Character.digit(s.charAt(i), 16) << 4) + Character.digit(s.charAt(i + 1), 16)));
}
return data;
}
}
Java Main methods
public class EncryptionDecryption {
#SuppressWarnings("unchecked")
public static void main(String[] args) {
JSONObject json = new JSONObject();
json.put("applicationNo","PNB00000000000004016");
json.put("custID","PNB000000004016");
String input = json.toJSONString();
String password = "46ea428a97ba4c3094fc66e112d1d678";
EncryptionDecryption enc = new EncryptionDecryption();
String encryptMessage= enc.encryptMessage(input, password);
System.out.println("Encrypted Message :"+encryptMessage);
String encrypt2Message = "8b7a1e90d701f55c49e22135eed31c94 89f9af1e83e8c83bdf603f5428ba6f14 0R2A2JDkY8tFR1FZojY7Su9CVI9zjw4yjr/lRElwU75MF5e0LxgOb+Y/DOyVFNd89Ra4YADIZdopLZ5a59Z2BgEjMpSn27tqnGfFvWtfm+eh+A/aVcB2YwfD9rdsd67x6xUb8kmfL7qnO/uxaHyQtqlvwpNRBVjyfRlk1wPfaxyOQa0oEiWRmUXYxEoJ651EhYtHeHKmII7qzDgcioIYUlsBgZUjOu0sNEdiwSvvHbw=";
String decryptMessage = enc.decryptMessage(encrypt2Message, password);
System.out.println("decryptMessage Message :"+decryptMessage);
}
public String encryptMessage(String txtToEncrypt, String passphrase)
{
System.out.println("encryptMessage :txtToEncrypt :"+txtToEncrypt);
String combineData = "";
try
{
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
String saltHex = getRandomHexString(32);
String ivHex = getRandomHexString(32);
byte[] salt = hexStringToByteArray(saltHex);
byte[] iv = hexStringToByteArray(ivHex);
SecretKeySpec sKey = (SecretKeySpec)generateKeyFromPassword(
passphrase, salt);
cipher.init(1, sKey, new IvParameterSpec(iv));
byte[] utf8 = txtToEncrypt.getBytes("UTF-8");
byte[] enc = cipher.doFinal(utf8);
combineData = saltHex + " " + ivHex + " " +
new BASE64Encoder().encode(enc);
}
catch (Exception e)
{
e.printStackTrace();
}
combineData = combineData.replaceAll("\n", "").replaceAll("\t", "").replaceAll("\r", "");
return combineData;
}
public String decryptMessage(String str, String myKey)
{
String decrypted = null;
try
{
if ((str != null) && (str.contains(" ")))
{
String salt = str.split(" ")[0];
String iv = str.split(" ")[1];
String encryptedText = str.split(" ")[2];
EncryptorDecryptorUtil dec = new EncryptorDecryptorUtil(128);
decrypted = dec.decrypt(salt, iv, myKey, encryptedText);
}
else
{
decrypted = str;
}
}
catch (Exception e)
{
e.printStackTrace();
}
return decrypted;
}
public static String getRandomHexString(int numchars)
{
Random r = new Random();
StringBuilder sb = new StringBuilder();
while (sb.length() < numchars) {
sb.append(Integer.toHexString(r.nextInt()));
}
return sb.toString().substring(0, numchars);
}
public static byte[] hexStringToByteArray(String s)
{
int len = s.length();
byte[] data = new byte[len / 2];
for (int i = 0; i < len; i += 2) {
data[(i / 2)] =
((byte)((Character.digit(s.charAt(i), 16) << 4) + Character.digit(s.charAt(i + 1), 16)));
}
return data;
}
public static SecretKey generateKeyFromPassword(String password, byte[] saltBytes)
throws GeneralSecurityException
{
KeySpec keySpec = new PBEKeySpec(password.toCharArray(), saltBytes,
100, 128);
SecretKeyFactory keyFactory =
SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
SecretKey secretKey = keyFactory.generateSecret(keySpec);
return new SecretKeySpec(secretKey.getEncoded(), "AES");
}
}
I have tried below code in .net
public static byte[] hexStringToByteArray(string hexString)
{
byte[] data = new byte[hexString.Length / 2];
for (int index = 0; index < data.Length; index++)
{
string byteValue = hexString.Substring(index * 2, 2);
data[index] = byte.Parse(byteValue, NumberStyles.HexNumber, CultureInfo.InvariantCulture);
}
return data;
}
public string generateKey(String password, byte[] saltBytes)
{
int iterations = 100;
var rfc2898 =
new System.Security.Cryptography.Rfc2898DeriveBytes(password, saltBytes, iterations);
byte[] key = rfc2898.GetBytes(16);
String keyB64 = Convert.ToBase64String(key);
return keyB64;
}
Decrypt method in c#
public string DecryptAlter(string salt, string iv, string passphrase, string EncryptedText)
{
string decryptedValue = null;
try
{
byte[] saltBytes = hexStringToByteArray(salt);
string sKey = generateKey(passphrase, saltBytes);
byte[] ivBytes = hexStringToByteArray(iv);
byte[] keyBytes = System.Convert.FromBase64String(sKey);
AesManaged aesCipher = new AesManaged();
aesCipher.IV = ivBytes;
aesCipher.KeySize = 128;
aesCipher.BlockSize = 128;
aesCipher.Mode = CipherMode.ECB;
aesCipher.Padding = PaddingMode.PKCS7;
byte[] b = System.Convert.FromBase64String(EncryptedText);
ICryptoTransform decryptTransform = aesCipher.CreateDecryptor(keyBytes, ivBytes);
byte[] plainText = decryptTransform.TransformFinalBlock(b, 0, b.Length);
var res = System.Text.Encoding.UTF8.GetString(plainText);
return res;
}
catch (Exception e)
{
var k = e.Message;
}
return "";
}
Its not working. Please help me
The Encryption password is “46ea428a97ba4c3094fc66e112d1d678”
Encrypted Text - 4cdf7b17b7db00d7911498dec913d3e4 1e55c4e950b772685ccfdb831c82fede SCQXvM7GeKxP0jLtX5xbuF0WvBC/C81wwxtYNduUe9lVzaYztaJ8ifivjaCBWd7O2zSa+/A+vtFfdSWSnN5+RcjWka42QQl4f+yZ8C1Y/efIsUlDVXBXmSEjSUp/4sflXNz7qg62Ka+atpj0aiG6QvU+T5tnafmsDhx/M3zE+Tg=
Now need to decrypt it.
This is what I got so far to guide you towards a final solution. The encrypted message contains a salt and iv that need to be extracted then used to decrypt the message.
using System;
using System.Globalization;
using System.Security.Cryptography;
public class Program
{
public static void Main()
{
string password = "46ea428a97ba4c3094fc66e112d1d678";
string encrypt2Message = "8b7a1e90d701f55c49e22135eed31c94 89f9af1e83e8c83bdf603f5428ba6f14 0R2A2JDkY8tFR1FZojY7Su9CVI9zjw4yjr/lRElwU75MF5e0LxgOb+Y/DOyVFNd89Ra4YADIZdopLZ5a59Z2BgEjMpSn27tqnGfFvWtfm+eh+A/aVcB2YwfD9rdsd67x6xUb8kmfL7qnO/uxaHyQtqlvwpNRBVjyfRlk1wPfaxyOQa0oEiWRmUXYxEoJ651EhYtHeHKmII7qzDgcioIYUlsBgZUjOu0sNEdiwSvvHbw=";
string[] pieces = encrypt2Message.Split(' ');
string salt = pieces[0];
string iv = pieces[1];
string encmessage = pieces[2];
string decryptMessage = DecryptAlter( salt, iv, password, encmessage);
Console.WriteLine("decryptMessage Message :"+decryptMessage);
}
public static byte[] hexStringToByteArray(string hexString)
{
byte[] data = new byte[hexString.Length / 2];
for (int index = 0; index < data.Length; index++)
{
string byteValue = hexString.Substring(index * 2, 2);
data[index] = byte.Parse(byteValue, NumberStyles.HexNumber, CultureInfo.InvariantCulture);
}
return data;
}
public static string generateKey(String password, byte[] saltBytes)
{
int iterations = 100;
var rfc2898 =
new System.Security.Cryptography.Rfc2898DeriveBytes(password, saltBytes, iterations);
byte[] key = rfc2898.GetBytes(16);
String keyB64 = Convert.ToBase64String(key);
return keyB64;
}
public static string DecryptAlter(string salt, string iv, string passphrase, string EncryptedText)
{
string decryptedValue = null;
try
{
byte[] saltBytes = hexStringToByteArray(salt);
string sKey = generateKey(passphrase, saltBytes);
byte[] ivBytes = hexStringToByteArray(iv);
byte[] keyBytes = System.Convert.FromBase64String(sKey);
AesManaged aesCipher = new AesManaged();
aesCipher.IV = ivBytes;
aesCipher.KeySize = 128;
aesCipher.BlockSize = 128;
aesCipher.Mode = CipherMode.CBC;
aesCipher.Padding = PaddingMode.PKCS7;
byte[] b = System.Convert.FromBase64String(EncryptedText);
ICryptoTransform decryptTransform = aesCipher.CreateDecryptor(keyBytes, ivBytes);
byte[] plainText = decryptTransform.TransformFinalBlock(b, 0, b.Length);
var res = System.Text.Encoding.UTF8.GetString(plainText);
return res;
}
catch (Exception e)
{
Console.WriteLine(e.Message);
Console.WriteLine(e.StackTrace);
}
return "";
}
}
public string decryptMessage()
{
string str="some encrypted message";
string myKey = "46ea428a97ba4c3094fc66e112d1d678";
string decrypted = null;
try
{
if ((str != null) && (str.Contains(' ')))
{
string salt = str.Split(' ')[0];
string iv = str.Split(' ')[1];
String encryptedText = str.Split(' ')[2];
decrypted = DecryptAlter(salt, iv, myKey, encryptedText);
return decrypted;
}
else
{
decrypted = str;
return decrypted;
}
}
catch (Exception e)
{
}
return decrypted;
}
public string DecryptAlter(string salt, string iv, string passphrase, string EncryptedText)
{
string decryptedValue = null;
try
{
byte[] saltBytes = hexStringToByteArray(salt);
string sKey = generateKey(passphrase, saltBytes);
byte[] ivBytes = hexStringToByteArray(iv);
byte[] keyBytes = System.Convert.FromBase64String(sKey);
AesManaged aesCipher = new AesManaged();
aesCipher.IV = ivBytes;
aesCipher.KeySize = 128;
aesCipher.BlockSize = 128;
aesCipher.Mode = CipherMode.CBC;
aesCipher.Padding = PaddingMode.PKCS7;
byte[] b = System.Convert.FromBase64String(EncryptedText);
ICryptoTransform decryptTransform = aesCipher.CreateDecryptor(keyBytes, ivBytes);
byte[] plainText = decryptTransform.TransformFinalBlock(b, 0, b.Length);
var res = System.Text.Encoding.UTF8.GetString(plainText);
return res;
}
catch (Exception e)
{
var k = e.Message;
}
return "";
}
I received an encrypted string from Java, and I can see the Java encrypted source code.
I wrote the decryption code in C#. But always report an error at "FlushFinalBlock". Error message: "System.Security.Cryptography.CryptographicException. Additional information: Incorrect data."
Can any body point out where the problem is in my C# code?
this is java code:
private static byte[] coderByDES(byte[] plainText, String key, int mode)
throws InvalidKeyException, InvalidKeySpecException,
NoSuchAlgorithmException, NoSuchPaddingException,
BadPaddingException, IllegalBlockSizeException,
UnsupportedEncodingException {
SecureRandom sr = new SecureRandom();
byte[] resultKey = makeKey(key);
DESKeySpec desSpec = new DESKeySpec(resultKey);
SecretKey secretKey = SecretKeyFactory.getInstance("DES").generateSecret(desSpec);
Cipher cipher = Cipher.getInstance("DES");
cipher.init(mode, secretKey, sr);
return cipher.doFinal(plainText);
}
private static byte[] makeKey(String key)
throws UnsupportedEncodingException {
byte[] keyByte = new byte[8];
byte[] keyResult = key.getBytes("UTF-8");
for (int i = 0; i < keyResult.length && i < keyByte.length; i++) {
keyByte[i] = keyResult[i];
}
return keyByte;
}
private static String byteArr2HexStr(byte[] arrB) {
int iLen = arrB.length;
StringBuilder sb = new StringBuilder(iLen * 2);
for (int i = 0; i < iLen; i++) {
int intTmp = arrB[i];
while (intTmp < 0) {
intTmp = intTmp + 256;
}
if (intTmp < 16) {
sb.append("0");
}
sb.append(Integer.toString(intTmp, 16));
}
return sb.toString();
}
this is C# code:
public static string DecryptForDES(string input, string key)
{
byte[] inputByteArray = HexStr2ByteArr(input);
byte[] buffArray = null;
using (DESCryptoServiceProvider des = new DESCryptoServiceProvider())
{
des.Key = Encoding.UTF8.GetBytes(key);
des.IV = Encoding.UTF8.GetBytes(key);
des.Mode = System.Security.Cryptography.CipherMode.ECB;
des.Padding = PaddingMode.PKCS7;
System.IO.MemoryStream ms = new System.IO.MemoryStream();
using (CryptoStream cs = new CryptoStream(ms, des.CreateDecryptor(), CryptoStreamMode.Write))
{
cs.Write(inputByteArray, 0, inputByteArray.Length);
cs.FlushFinalBlock();//
cs.Close();
}
buffArray = ms.ToArray();
ms.Close();
}
string str = string.Empty;
if (buffArray != null)
{
str = Encoding.UTF8.GetString(buffArray);
}
return str;
}
public static byte[] HexStr2ByteArr(string strIn)
{
byte[] arrB = Encoding.UTF8.GetBytes(strIn);
int iLen = arrB.Length;
byte[] arrOut = new byte[iLen / 2];
byte[] arrTmp = new byte[2];
for (int i = 0; i < iLen; i = i + 2)
{
string strTmp = Encoding.UTF8.GetString(arrB, i, 2);
arrOut[i / 2] = (byte)Convert.ToInt32(strTmp, 16);
}
return arrOut;
}
Both, the Java encryption part and the C# decryption part work on my machine if the passwords match. Otherwise a System.Security.Cryptography.CryptographicException: 'Bad Data' is thrown. To get the password match replace in the C#-method DecryptForDES
des.Key = Encoding.UTF8.GetBytes(key);
with
des.Key = MakeKey(key);
with the C#-method:
private static byte[] MakeKey(String key)
{
byte[] keyByte = new byte[8];
byte[] keyResult = Encoding.UTF8.GetBytes(key);
for (int i = 0; i<keyResult.Length && i<keyByte.Length; i++) {
keyByte[i] = keyResult[i];
}
return keyByte;
}
corresponding to the Java-method makeKey(String key).
Moreover, remove in the C#-method DecryptForDES
des.IV = Encoding.UTF8.GetBytes(key);
since the ECB-mode doesn't use an IV.
In the following testcase
coderByDES("This is a plain text that needs to be encrypted...", "This is the key used for encryption...", Cipher.ENCRYPT_MODE);
returns the byte-array
a47b1b2c90fb3b7a0ab1f51f328ff55aae3c1eb7789c31c28346696a8b1f27c7413c14e68fe977d3235b5a6f63c07d7a95d912ff22f17ad6
and
DecryptForDES("a47b1b2c90fb3b7a0ab1f51f328ff55aae3c1eb7789c31c28346696a8b1f27c7413c14e68fe977d3235b5a6f63c07d7a95d912ff22f17ad6", "This is the key used for encryption...");
returns the correct plain text.
By the way: As Flydog57 already stated DES is insecure (https://en.wikipedia.org/wiki/Data_Encryption_Standard). And also the ECB mode is not secure (https://crypto.stackexchange.com/questions/20941/why-shouldnt-i-use-ecb-encryption).
Better choices are AES (https://en.wikipedia.org/wiki/Advanced_Encryption_Standard) with CBC or GCM mode (https://crypto.stackexchange.com/questions/2310/what-is-the-difference-between-cbc-and-gcm-mode).
Recently i've post a question about this topic but the thing turns a little weird when i tried to decrypt an AES String that was encoded on UTF8
In the following lines i read the String AES encrypted wich returns the following String: RnLObq9hdUDGp9S2pxC1qjQXekuf9g6i/5bQfKilYn4=
public static final String AesKey256 ="ZzRtNDNuY3J5cHRrM3kuLi4=";
//This reads the String and stores on res.getContents()
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
IntentResult res= IntentIntegrator.parseActivityResult(requestCode, resultCode,data);
if(res!=null){
if (res.getContents() == null) {
Toast.makeText(this,"Captura cancelada",Toast.LENGTH_SHORT).show();
}else{
try {
String cadena= decrypt(res.getContents());
out.setText(cadena);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
//provide the res.getContents() to decrypt method, wich its the String i've recently read
private String decrypt(String cadena)throws Exception{
SecretKeySpec keySpec= generateKey(AesKey256); //HERE
Cipher c= Cipher.getInstance(AES_MODE);
c.init(Cipher.DECRYPT_MODE,keySpec);
byte[] decodedValue= Base64.decode(cadena, Base64.DEFAULT);
byte[] decValue= c.doFinal(decodedValue);/* c.doFinal(decodedValue);*/
String decryptedValue= new String((decValue), "UTF-8");
return decryptedValue;
}
private SecretKeySpec generateKey(String password) throws NoSuchAlgorithmException, UnsupportedEncodingException {
final MessageDigest digest= MessageDigest.getInstance("SHA-256");
byte[] bytes= password.getBytes("UTF-8");
digest.update(bytes,0,bytes.length);
byte[] key= digest.digest();
SecretKeySpec secretKeySpec= new SecretKeySpec(key, "AES");
return secretKeySpec;
}
I am only using the decryption method but it still returning this characters:
i've spent hours looking for a solution, but nothing works for now... hope someone can give me a hand!
Best Regards!
EDIT
THIS IS HOW IT WAS ENCRYPTED IN C#
private const string AesIV256 = "IVFBWjJXU1gjRURDNFJGVg==";
private const string AesKey256 = "ZzRtNDNuY3J5cHRrM3kuLi4=";
public static string Encrypt(string text)
{
var sToEncrypt = text;
var rj = new RijndaelManaged()
{
Padding = PaddingMode.Zeros,
Mode = CipherMode.ECB,
KeySize = 256,
BlockSize = 256,
};
var key = Convert.FromBase64String(AesKey256);
var IV = Convert.FromBase64String(AesIV256);
var encryptor = rj.CreateEncryptor(key, IV);
var msEncrypt = new MemoryStream();
var csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write);
var toEncrypt = Encoding.UTF8.GetBytes(sToEncrypt);
csEncrypt.Write(toEncrypt, 0, toEncrypt.Length);
csEncrypt.FlushFinalBlock();
var encrypted = msEncrypt.ToArray();
return (Convert.ToBase64String(encrypted));
}
Made it!
After a long time of searching thanks to all you guys who answered this post i used the bouncy castle library and i've decrypt the desired String by doing the following:
public static String decrypt(String valueToDecrypt) throws Exception {
AESCrypt enc = new AESCrypt();
return new String(enc.decryptInternal(valueToDecrypt)).trim();
}
private byte[] decryptInternal(String code) throws Exception {
if (code == null || code.length() == 0) {
throw new Exception("Empty string");
}
byte[] decrypted = null;
try {
byte[] key= SecretKey.getBytes("UTF-8");
PaddedBufferedBlockCipher c = new PaddedBufferedBlockCipher(new RijndaelEngine(256), new ZeroBytePadding());
CipherParameters params= new KeyParameter(key);`
// false because its going to decrypt
c.init(false,params);
decrypted= GetData(c,(Base64.decode(code,Base64.DEFAULT));
} catch (Exception e) {
throw new Exception("[decrypt] " + e.getMessage());
}
return decrypted;
}
private static byte[] GetData(PaddedBufferedBlockCipher cipher, byte[] data) throws InvalidCipherTextException
{
int minSize = cipher.getOutputSize(data.length);
byte[] outBuf = new byte[minSize];
int length1 = cipher.processBytes(data, 0, data.length, outBuf, 0);
int length2 = cipher.doFinal(outBuf, length1);
int actualLength = length1 + length2;
byte[] cipherArray = new byte[actualLength];
for (int x = 0; x < actualLength; x++) {
cipherArray[x] = outBuf[x];
}
return cipherArray;
}
I even use the AES algorithm to encrypt and decrypt files, but according to my research, the performance of this algorithm is slower than the RC4 algorithm in Java.
I'm use this code for encrypt files in C#
public static class RC4
{
public static byte[] Encrypt(byte[] key, byte[] data)
{
return EncryptOutput(key, data).ToArray();
}
private static byte[] EncryptInitalize(byte[] key)
{
byte[] s = Enumerable.Range(0, 256)
.Select(i => (byte)i)
.ToArray();
for (int i = 0, j = 0; i < 256; i++)
{
j = (j + key[i % key.Length] + s[i]) & 255;
Swap(s, i, j);
}
return s;
}
private static IEnumerable<byte> EncryptOutput(byte[] key, IEnumerable<byte> data)
{
byte[] s = EncryptInitalize(key);
int i = 0;
int j = 0;
return data.Select((b) =>
{
i = (i + 1) & 255;
j = (j + s[i]) & 255;
Swap(s, i, j);
return (byte)(b ^ s[(s[i] + s[j]) & 255]);
});
}
private static void Swap(byte[] s, int i, int j)
{
byte c = s[i];
s[i] = s[j];
s[j] = c;
}
}
I need to encrypt a file in C # and decrypt this file with java, but found no implementation for both languages.
This solution implemented by Michael Remijan showed better performance to decrypt files using AES. Encrypt and Decrypt files for I implemented just a string conversion to byte array.
Java Code
package org.ferris.aes.crypto;
import java.io.UnsupportedEncodingException;
import java.security.Key;
import java.security.spec.KeySpec;
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 org.apache.commons.codec.binary.Base64;
/**
*
* #author Michael Remijan mjremijan#yahoo.com #mjremijan
*/
public class AesBase64Wrapper {
private static String IV = "IV_VALUE_16_BYTE";
private static String PASSWORD = "PASSWORD_VALUE";
private static String SALT = "SALT_VALUE";
public String encryptAndEncode(String raw) {
try {
Cipher c = getCipher(Cipher.ENCRYPT_MODE);
byte[] encryptedVal = c.doFinal(getBytes(raw));
String s = getString(Base64.encodeBase64(encryptedVal));
return s;
} catch (Throwable t) {
throw new RuntimeException(t);
}
}
public String decodeAndDecrypt(String encrypted) throws Exception {
byte[] decodedValue = Base64.decodeBase64(getBytes(encrypted));
Cipher c = getCipher(Cipher.DECRYPT_MODE);
byte[] decValue = c.doFinal(decodedValue);
return new String(decValue);
}
private String getString(byte[] bytes) throws UnsupportedEncodingException {
return new String(bytes, "UTF-8");
}
private byte[] getBytes(String str) throws UnsupportedEncodingException {
return str.getBytes("UTF-8");
}
private Cipher getCipher(int mode) throws Exception {
Cipher c = Cipher.getInstance("AES/CBC/PKCS5Padding");
byte[] iv = getBytes(IV);
c.init(mode, generateKey(), new IvParameterSpec(iv));
return c;
}
private Key generateKey() throws Exception {
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
char[] password = PASSWORD.toCharArray();
byte[] salt = getBytes(SALT);
KeySpec spec = new PBEKeySpec(password, salt, 65536, 128);
SecretKey tmp = factory.generateSecret(spec);
byte[] encoded = tmp.getEncoded();
return new SecretKeySpec(encoded, "AES");
}
}
C# Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Security.Cryptography;
namespace EncryptDecryptTest
{
class Program
{
class AesBase64Wrapper
{
private static string IV = "IV_VALUE_16_BYTE";
private static string PASSWORD = "PASSWORD_VALUE";
private static string SALT = "SALT_VALUE";
public static string EncryptAndEncode(string raw)
{
using (var csp = new AesCryptoServiceProvider())
{
ICryptoTransform e = GetCryptoTransform(csp, true);
byte[] inputBuffer = Encoding.UTF8.GetBytes(raw);
byte[] output = e.TransformFinalBlock(inputBuffer, 0, inputBuffer.Length);
string encrypted = Convert.ToBase64String(output);
return encrypted;
}
}
public static string DecodeAndDecrypt(string encrypted)
{
using (var csp = new AesCryptoServiceProvider())
{
var d = GetCryptoTransform(csp, false);
byte[] output = Convert.FromBase64String(encrypted);
byte[] decryptedOutput = d.TransformFinalBlock(output, 0, output.Length);
string decypted = Encoding.UTF8.GetString(decryptedOutput);
return decypted;
}
}
private static ICryptoTransform GetCryptoTransform(AesCryptoServiceProvider csp, bool encrypting)
{
csp.Mode = CipherMode.CBC;
csp.Padding = PaddingMode.PKCS7;
var spec = new Rfc2898DeriveBytes(Encoding.UTF8.GetBytes(PASSWORD), Encoding.UTF8.GetBytes(SALT), 65536);
byte[] key = spec.GetBytes(16);
csp.IV = Encoding.UTF8.GetBytes(IV);
csp.Key = key;
if (encrypting)
{
return csp.CreateEncryptor();
}
return csp.CreateDecryptor();
}
}
static void Main(string[] args)
{
string encryptMe;
string encrypted;
string decrypted;
encryptMe = "please encrypt me";
Console.WriteLine("encryptMe = " + encryptMe);
encrypted = AesBase64Wrapper.EncryptAndEncode(encryptMe);
Console.WriteLine("encypted: " + encrypted);
decrypted = AesBase64Wrapper.DecodeAndDecrypt(encrypted);
Console.WriteLine("decrypted: " + decrypted);
Console.WriteLine("press any key to exit....");
Console.ReadKey();
}
}
}
Based on your comments, I am assuming you want to know how to speed up your encryption / decryption process, and changing the main algorithm is not mandatory.
You could look at different modes for AES. For example, AES in counter (CTR) mode is significantly faster than cipher block chaining (CBC) which is often used.
Try creating your cipher like
Cipher myCipher = Cipher.getInstance("AES/CTR/NoPadding");
and you should see a performance increase. Additionally, using NoPadding will keep the size the same as the plaintext.
(Yes, I know that CTR mode turn AES into a stream cipher, never mind my comment)
UPDATE
I have used this in the past along these lines:
Key key = new SecretKeySpec(yourKeyValue, "AES");
Cipher enc = Cipher.getInstance("AES/CTR/NoPadding");
enc.init(Cipher.ENCRYPT_MODE, key);
// Get the IV that was generated
byte[] iv = enc.getIV();
// Encrypt your data
...
Cipher dec = Cipher.getInstance("AES/CTR/NoPadding");
dec.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(iv));
// Decrypt your data
...
I have a PHP servor which decrypt data in 3DES with the CFB Mode
I encrypt in PHP :
$montant = "500";
$message_crypte = mcrypt_encrypt(MCRYPT_3DES, "N4y1FRDRJ7wn7eJNnWaahCIS", $montant, ,CRYPT_MODE_CFB, "NCNPJDcR");
$montant = base64_encode($message_crypte);
This script in PHP is OK with other system.
And I want to encrypt in Java :
public class CryptData {
private KeySpec keySpec;
private SecretKey key;
private IvParameterSpec iv;
public CryptData(String keyString, String ivString) {
try {
final MessageDigest md = MessageDigest.getInstance("md5");
final byte[] digestOfPassword = md.digest(Base64
.decodeBase64(keyString.getBytes("ISO-8859-1")));
final byte[] keyBytes = Arrays.copyOf(digestOfPassword, 24);
for (int j = 0, k = 16; j < 8;) {
keyBytes[k++] = keyBytes[j++];
}
//keySpec = new DESedeKeySpec(keyBytes);
keySpec = new DESedeKeySpec(keyString.getBytes());
key = SecretKeyFactory.getInstance("DESede")
.generateSecret(keySpec);
iv = new IvParameterSpec(ivString.getBytes());
} catch (Exception e) {
e.printStackTrace();
}
}
public String encrypt(String value) {
try {
Cipher ecipher = Cipher.getInstance("DESede/CFB/NoPadding");
//"SunJCE");
ecipher.init(Cipher.ENCRYPT_MODE, key, iv);
if (value == null)
return null;
// Encode the string into bytes using utf-8
byte[] valeur = value.getBytes("ISO-8859-1");
//byte[] utf8 = value.getBytes();
// Encrypt
byte[] enc = ecipher.doFinal(valeur);
// Encode bytes to base64 to get a string
return new String(Base64.encodeBase64(enc), "ISO-8859-1");
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
I have not the same result in PHP and in Java
How modify Java treatment to obtain the same result as PHP?
The answer is:
Cipher ecipher = Cipher.getInstance("DESede/CFB8/NoPadding");
I need to use "CFB8"