Reputation: 177
I am using a Java based configuration management tool called Zuul which supports encrypting sensitive configuration information using various encryption schemes.
I have configured it to use below scheme for my data
AES (Bouncy Castle)
Now when reading my configuration data back, I need to decrypt the information before I can use it and the documentation provides below information around this topic.
The encrypted values produced by Jasypt (and thus Zuul) are are prefixed with the salt (usually 8 or 16 bytes depending on the algorithm requirements). They are then Base64 encoded. Decrypting the results goes something like this:
More details here: Zull Encryption wiki
Based on above details, I have written below code (and my knowledge around security is very limited)
public static string Decrypt(string cipher, string password)
{
const int saltLength = 16;
const int iterations = 1000;
byte[] cipherBytes = Convert.FromBase64String(cipher);
byte[] saltBytes = cipherBytes.Take(saltLength).ToArray();
byte[] encryptedBytes = cipherBytes.Skip(saltLength).ToArray();
Rfc2898DeriveBytes key = new Rfc2898DeriveBytes(password, saltBytes, iterations);
byte[] keyBytes = key.GetBytes(16);
AesCryptoServiceProvider aesAlg = new AesCryptoServiceProvider();
aesAlg.KeySize = 256;
aesAlg.BlockSize = 128;
aesAlg.Key = key.GetBytes(aesAlg.KeySize / 8);
aesAlg.IV = key.GetBytes(aesAlg.BlockSize / 8);
ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);
MemoryStream msDecrypt = new MemoryStream(encryptedBytes);
CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read);
StreamReader srDecrypt = new StreamReader(csDecrypt);
return srDecrypt.ReadToEnd();
}
I configured Zuul to use below password for the encryption
SimplePassword
And now I have an encrypted string given to me by Zuul and I need to decrypt it
p8C9hAHaoo0F25rMueT0+u0O6xYVpGIkjHmWqFJmTOvpV8+cipoDFIUnaOFF5ElQ
When I try to decrypt this string using above code, I get below exception
System.Security.Cryptography.CryptographicException : Padding is invalid and cannot be removed.
As I mentioned earlier, my knowledge around this topic is limited and I am not able to figure out if the information provided in the documentation is not enough, if I am doing something wrong while writing the decryption routine or should I be using bouncy castle for decryption as well.
Any help with this will be much appreciated.
Upvotes: 4
Views: 2655
Reputation: 177
I resorted to Bouncy Castle for decryption instead since that is used by Zuul as well.
Here is the code that works
public static string Decrypt(string cipher, string password)
{
const int saltLength = 16;
const int iterations = 1000;
const string algSpec = "AES/CBC/NoPadding";
const string algName = "PBEWITHSHA256AND128BITAES-CBC-BC";
byte[] cipherBytes = Convert.FromBase64String(cipher);
byte[] saltBytes = cipherBytes.Take(saltLength).ToArray();
byte[] encryptedBytes = cipherBytes.Skip(saltLength).ToArray();
char[] passwordChars = password.ToCharArray();
Asn1Encodable defParams = PbeUtilities.GenerateAlgorithmParameters(algName, saltBytes, iterations);
IWrapper wrapper = WrapperUtilities.GetWrapper(algSpec);
ICipherParameters parameters = PbeUtilities.GenerateCipherParameters(algName, passwordChars, defParams);
wrapper.Init(false, parameters);
byte[] keyText = wrapper.Unwrap(encryptedBytes, 0, encryptedBytes.Length);
return Encoding.Default.GetString(keyText);
}
Upvotes: 0
Reputation: 14160
According to Zuul documentation they are deriving both key and iv from the password/salt. So you should derive 256+128 bits (i.e. 48 bytes), and use first 32 bytes as the key, and next 16 bytes as IV. And this should be done in one operation, not as consequent calls to key.DeriveBytes.
Upvotes: 1