I am trying to convert the following Java encryption snippet to C#
private final String encryptToken(String str) {
byte[] generateIV = generateIV(16);
Cipher instance = Cipher.getInstance("AES/CBC/PKCS5Padding");
instance.init(1, new SecretKeySpec(new byte[]{55, 66, 53, 68, 55, 66, 67, 50, 52, 66, 53, 67, 52, 69, 51, 65, 56, 48, 70, 66, 66, 67, 50, 65, 49, 49, 53, 54, 69, 52, 51, 55}, "AES/CBC/PKCS5Padding"), new IvParameterSpec(generateIV));
Charset charset = Charsets.UTF_8;
if (str != null) {
byte[] bytes = str.getBytes(charset);
Intrinsics.checkExpressionValueIsNotNull(bytes, "(this as java.lang.String).getBytes(charset)");
byte[] doFinal = instance.doFinal(bytes);
StringBuilder sb = new StringBuilder();
sb.append(new String(generateIV, Charsets.UTF_8));
String encodeToString = Base64.encodeToString(doFinal, 0);
Intrinsics.checkExpressionValueIsNotNull(encodeToString, "Base64.encodeToString(cipherText, Base64.DEFAULT)");
if (encodeToString != null) {
sb.append(StringsKt.trim((CharSequence) encodeToString).toString());
return sb.toString();
}
throw new TypeCastException("null cannot be cast to non-null type kotlin.CharSequence");
}
throw new TypeCastException("null cannot be cast to non-null type java.lang.String");
}
Here is my C# code:
public static string Encrypt(string token)
{
byte[] IV;
byte[] encrypted;
byte[] key = new byte[] { 55, 66, 53, 68, 55, 66, 67, 50, 52, 66, 53, 67, 52, 69, 51, 65, 56, 48, 70, 66, 66, 67, 50, 65, 49, 49, 53, 54, 69, 52, 51, 55 };
using (Aes aesAlg = Aes.Create())
{
aesAlg.Key = key;
aesAlg.IV = GenerateIv(16);
IV = aesAlg.IV;
aesAlg.Mode = CipherMode.CBC;
aesAlg.Padding = PaddingMode.PKCS7;
var encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);
using (var msEncrypt = new MemoryStream())
{
using (var csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
{
using (var swEncrypt = new StreamWriter(csEncrypt))
{
swEncrypt.Write(Encoding.UTF8.GetBytes(token));
}
encrypted = msEncrypt.ToArray();
StringBuilder sb = new StringBuilder();
sb.Append(Encoding.UTF8.GetString(IV));
string encodedString = Convert.ToBase64String(encrypted);
sb.Append(encodedString.ToString());
return sb.ToString();
}
}
}
return "";
}
I am using the result of the encryption routine to authorize against an API that I do not have control over. Using my C# code, the API returns "unauthorized" which is a result of my encryption routine not being quite correct.
I note that the Java method uses PKCS5 padding, but the only option available in .NET is PKCS7. However reading this previous article, I understand they are the same, and therefore it shouldn't matter.
If I use a temporary IV of h62PmLFO5Yq4SxQw and a token of 4a97adfc-d25c-485b-84af-86c93ff28b20, the Java code returns: h62PmLFO5Yq4SxQwgoOqOLrjcZmnYbKxEDhl1hsDeCGUmEv8kwwP337JfYyvjuXgaDdND9vqSeAd9NpH and my C# code returns: h62PmLFO5Yq4SxQwfUXW396ss2Pzopk0FHC/7A==
Is anyone able to advise in any obvious differences between the Java code and mine?
byte[] bytes = System.Text.UTF8Encoding.UTF8.GetBytes(utf8string);sb.append(new String(generateIV, Charsets.UTF_8));this code is not translated at all. It is an intrinsically dubious piece of code, of course, since there is no reason to assumegenerateIVcontains a valid UTF-8 sequence, unlessgenerateIV()somehow restricts its output, but there you go.