Я использую библиотеку BountyCastle.NetCore NuGet для расшифровки уже подготовленного зашифрованного сообщения с наших серверов.Мне удалось с успехом использовать как библиотеки криптографии Java (нативная), так и реализацию Python (pycrptodome).В целом наши серверы готовят сообщение следующим образом:
Стратегия дешифрования:
Подготовьте секретный ключ AES-256, расшифровав код cryptographyKey с помощью base64.
Подготовьте текстовые байты шифра с помощью base64, расшифровав тело сообщения.
- Удалите тег иззашифрованный текст.
- Подготовьте AAD, скопировав первые 16 байтов из зашифрованного текста.
- Подготовьте NONCE (IV), скопировав байты 4 - 16 из AAD.
- Затем расшифруйте с помощьюAES - GCM, длина тега = 16 байт;с вводом
из 1, 3, 4, 5.
Применение общего алгоритма на основе этого примера , моя реализация выглядит следующим образом:
Примечание : я не применил тег в приведенном ниже коде, потому что это больше этап проверки, и я не смог пройти расшифровку сообщения.
public string Decrypt(string cryptoKey, string cypherText)
{
string sR = string.Empty;
try
{
// Prepare the AES-256 secret key by decoding the cryptographyKey
var keyBytes = Convert.FromBase64String(cryptoKey);
// Prepare the Cypher bytes by decoding the cypher text
var cypherBytes = Convert.FromBase64String(cypherText);
// <------AAD----->
// [---][--NONCE--][-----Encrypted Message-----][---TAG---]
// <-------------------CypherText------------------------->
// Prepare the AAD - first AAD_LENGTH from cypher
var aad = new Byte[AAD_LENGTH];
Array.Copy(cypherBytes, 0, aad, 0, AAD_LENGTH);
// Prepare NONCE - bytes 4-16 from AAD
var nonce = new Byte[NONCE_LENGTH];
Array.Copy(aad, AAD_LENGTH - NONCE_LENGTH, nonce, 0, NONCE_LENGTH);
// Extract the encrypted message within the body - between AAD and TAG section
var encryptedMsgSize = cypherBytes.Length - TAG_LENGTH - AAD_LENGTH;
var encryptedMsg = new Byte[encryptedMsgSize];
Array.Copy(cypherBytes, AAD_LENGTH, encryptedMsg, 0, encryptedMsgSize);
GcmBlockCipher cipher = new GcmBlockCipher(new AesEngine());
AeadParameters parameters = new AeadParameters(new KeyParameter(keyBytes), 128, nonce);
cipher.Init(false, parameters);
cipher.ProcessAadBytes(cypherBytes, 0, AAD_LENGTH);
byte[] plainBytes = new byte[cipher.GetOutputSize(encryptedMsg.Length)];
Int32 retLen = cipher.ProcessBytes(encryptedMsg, 0, encryptedMsg.Length, plainBytes, 0);
cipher.DoFinal(plainBytes, retLen);
sR = Encoding.UTF8.GetString(plainBytes).TrimEnd("\r\n\0".ToCharArray());
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
Console.WriteLine(ex.StackTrace);
}
return sR;
}
Несмотря на попыткумного разных комбинаций, установка разных параметров и т. д., он всегда выдает исключение в строке:
cipher.DoFinal(plainBytes, retLen);
с «проверка Mac в GCM не удалась».
Будут приветствоваться любые другие предложения: -)