Расшифровка с использованием AES256 с BountyCastle .NET завершается неудачно с «проверка Mac в GCM завершилась неудачно» - PullRequest
2 голосов
/ 16 апреля 2019

Я использую библиотеку BountyCastle.NetCore NuGet для расшифровки уже подготовленного зашифрованного сообщения с наших серверов.Мне удалось с успехом использовать как библиотеки криптографии Java (нативная), так и реализацию Python (pycrptodome).В целом наши серверы готовят сообщение следующим образом:

enter image description here

Стратегия дешифрования:

  • Подготовьте секретный ключ 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 не удалась».

Будут приветствоваться любые другие предложения: -)

...