Tenho uma aplicação Node.js com acesso a banco de dados. A string de conexão é obtida de um arquivo JSON e a parte da senha dentro da string de conexão contém salt, nonce e a cifra, que é criptografada por AES-GCM. O segredo para criptografar + descriptografar a senha usa uma derivação de chave do SCrypt dentro da biblioteca interna de criptografia do Node.js. Até agora, tudo bem, a criptografia e a descriptografia funcionam perfeitamente.
Entretanto, para outro caso de uso, tenho que usar essa string de conexão agora de um aplicativo C# e não consigo descriptografar a string de senha.
O método falha com o seguinte erro:
A tag de autenticação computada não corresponde à tag de autenticação de entrada
Já rastreei a derivação da chave. Não consegui encontrar uma implementação .NET que correspondesse à derivação da chave do nodejs.
Aqui está meu código - Node.js:
decrypt(encryptedText) {
const decoded = Buffer.from(encryptedText, "base64").toString("utf8");
const [saltHex, ivHex, authTagHex, encryptedHex] = decoded.split(":");
const salt = Buffer.from(saltHex, "hex");
const secretByte = Buffer.from(this.secretKey, "utf-8");
const key = crypto.scryptSync(salt, secretByte, 32, { cost: 16384, blockSize: 8, parallelization: 1 });
const iv = Buffer.from(ivHex, "hex");
const authTag = Buffer.from(authTagHex, "hex");
const decipher = crypto.createDecipheriv("aes-256-gcm", key, iv);
decipher.setAuthTag(authTag);
let decrypted = decipher.update(encryptedHex, "hex", "utf8");
decrypted += decipher.final("utf8");
return decrypted;
}
Código C#:
public static String DecryptAESGCM(Dictionary<string, byte[]> encrypted, string secret)
{
byte[] secretByte = Encoding.UTF8.GetBytes(secret);
//clsLogger.Log(Encoding.UTF8.GetString(encrypted.GetValueOrDefault("salt")), enumLogLevel.INFO);
// Derive key
byte[] derivedKey = SCrypt.ComputeDerivedKey(secretByte, encrypted.GetValueOrDefault("salt"), 16384, 8, 1, 1, 32);
using (AesGcm aes = new AesGcm(derivedKey, encrypted.GetValueOrDefault("tag").Length))
{
byte[] plainText = new byte[encrypted.GetValueOrDefault("cipher").Length];
aes.Decrypt(encrypted.GetValueOrDefault("nonce"), encrypted.GetValueOrDefault("cipher"), encrypted.GetValueOrDefault("tag"), plainText);
return Encoding.UTF8.GetString(plainText);
}
}
O dicionário em C# é um armazenamento de valor-chave com byte[]
salt, nonce, tag e cifra.
Já tentei várias bibliotecas diferentes para reproduzir a chave derivada e garanti que salt e secret tenham os mesmos valores em node.js e c# antes da função ser chamada, mas as chaves derivadas são sempre diferentes.
Alguém teve um caso semelhante e conseguiu resolver ou tem alguma ideia de como?
Obrigado antecipadamente!
Robin