One of my web services is about to start receiving responses from another API where the entire body of the response will be encrypted. Having never handled any type of encryption before, I am a bit lost in the weeds. I have a fully fleshed-out example of how to do the decryption, but it is in Java, using Java-native cryptography classes. Can some one please help me translate this to something that will run in .NET, either using BouncyCastle or the native AesGcm class?
Java Example
private static final String ALGORITHM_NAME = "PBKDF2WithHmacSHA512";
private static final String ALGORITHM_STANDARD = "AES";
private static final String CIPHER_TRANSFORMATION = "AES/GCM/NoPadding";
private static final int ITERATION_COUNT = 10000;
private static final int KEY_LENGTH = 256;
private static final GCM_IV_LENGTH = 16;
private static final GCM_TAG_LENGTH = 128;
byte[] apiKeyBytes = Base64.getDecoder().decode(apiKey);
String finalKey = new String(apiKeyBytes, StandardCharsets.UTF_8);
PBEKeySpec spec = new PBEKeySpec(finalKey.toCharArray(), accessId.getBytes(), ITERATION_COUNT, KEY_LENGTH);
SecretKey key = SecretKeyFactory.getInstance(ALGORITHM_NAME).generateSecret(spec);
SecretKeySpec secretKeySpec = new SecretKeySpec(key.getEncoded(), ALGORITHM_STANDARD);
public String decryptContent(String content) throws NoSuchAlgorithmException, NoSuchPaddingException,
InvalidKeyException, IllegalBlockSizeException, BadPaddingException, DecoderException,
InvalidKeySpecException, InvalidAlgorithmParameterException {
byte[] decodedContent = Hex.decodeHex(content);
ByteBuffer byteBuffer = ByteBuffer.wrap(decodedContent)
byte[] ivArray = new byte[GCM_IV_LENGTH];
byteBuffer.get(ivArray);
byte[] encrypted = new byte[byteBuffer.remaining()];
byteBuffer.get(encrypted);
GCMParameterSpec gcmParameterSpec = new GCMParameterSpec(GCM_TAG_LENGTH, ivArray);
Cipher cipher = Cipher.getInstance(CIPHER_TRANSFORMATION);
cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, gcmParameterSpec);
byte[] decryptedOutput = cipher.doFinal(encrypted);
return new String(decryptedOutput, StandardCharsets.UTF_8);
}
I wish that I could even ask better questions for where I need help, but I'm so confused by the vast differences between the Java method and what I have so far in C#. Java for example, doesn't even mention a "nonce."
My current progress in C#
string secret = Encoding.UTF8.GetString(Convert.FromBase64String(APIKEY));
var keyGen = new Rfc2898DeriveBytes(Encoding.UTF8.GetBytes(secret), Encoding.UTF8.GetBytes(ACCESSID), 10000);
AesGcm _aes = new AesGcm(keyGen.GetBytes(256));
var decodedContent = Hex.Decode(cipher).AsSpan<byte>();
var nonce = decodedContent.Slice(0, 16);
var cipherText = decodedContent.Slice(16, 128);
_aes.Decrypt(nonce, cipherText, **TAG?**, **output byte array**);
What am I missing?