Как расшифровать шестнадцатеричный текст шифровальщика на чистом С#

Я пытаюсь расшифровать зашифрованное шифровальщиком шестнадцатеричное сообщение, используя 20-й раунд смешивания IV с ключом MyKey.

Сообщения:

bad85d9e7f5aff959b6b332b44af2cc554d8a6eb

Я делаю это на чистом С#, и он должен вернуть сообщение: Hola Mundo

using System;
using System.Text;

public class Program
{
    public static void Main(string[] args)
    {
        // Hexadecimal text
        string hexText = "bad85d9e7f5aff959b6b332b44af2cc554d8a6eb";

        // Convert hexadecimal text to byte array
        byte[] encryptedData = new byte[hexText.Length / 2];

        for (int i = 0; i < encryptedData.Length; i++)
        {
            encryptedData[i] = Convert.ToByte(hexText.Substring(i * 2, 2), 16);
        }

        // IV length
        int ivLength = 1;

        // Key loop iterations
        int keyIterations = 20;

        // Encryption key
        string encryptionKey = "MyKey";

        // Convert encryption key to byte array
        byte[] keyData = Encoding.UTF8.GetBytes(encryptionKey);

        // Create an array to store the IV
        byte[] ivData = new byte[ivLength];

        // Copy the first `ivLength` bytes of the encrypted data to the IV array
        Array.Copy(encryptedData, 0, ivData, 0, ivLength);

        // Create an array to store the encrypted message
        byte[] messageData = new byte[encryptedData.Length - ivLength];

        // Copy the remaining bytes of the encrypted data to the message data array
        Array.Copy(encryptedData, ivLength, messageData, 0, messageData.Length);

        // Create an array to store the decrypted message
        byte[] decryptedData = new byte[messageData.Length];

        // Perform the decryption
        for (int i = 0; i < messageData.Length; i++)
        {
            decryptedData[i] = (byte)(messageData[i] ^ keyData[i % keyData.Length]);
            for (int j = 0; j < keyIterations; j++)
            {
                decryptedData[i] = (byte)(decryptedData[i] ^ ivData[j % ivData.Length]);
            }
        }

        // Convert the decrypted data to a string and print it
        string decryptedMessage = Encoding.UTF8.GetString(decryptedData);
        Console.WriteLine("Decrypted message: " + decryptedMessage);
    }
}

Теперь, когда я пытаюсь, он возвращает: �$�#���Jf=�I���

Какую ошибку я делаю в коде или неправильно его реализую?

Я проверил текст на следующем сайте, чтобы убедиться, что он в порядке: https://ruletheweb.co.uk/cgi-bin/saber.cgi

Если я правильно помню, киберсабер основан на RC4. RC4 изменяет ключ при шифровании или расшифровке. Я не вижу, чтобы ваш код делал это.

500 - Internal Server Error 13.02.2023 01:32
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
1
67
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

CipherSaber использует в качестве IV первые 10 байт зашифрованного сообщения. Остальное - настоящий зашифрованный текст. IV добавляется к ключу (предоставляя ввод для настройки ключа), который используется в качестве ввода для настройки ключа CipherSaber, см. CipherSaber, Техническое описание, 1-й раздел.

В опубликованном коде применяется длина IV, равная 1, вместо 10, что неверно определяет IV (и, следовательно, ввод настройки ключа) и фактический зашифрованный текст. Правильное определение IV и фактического зашифрованного текста:

private static (byte[], byte[]) SeparateIvCiphertext(byte[] ivCiphertext)
{
    int ivLen = 10;
    byte[] iv = new byte[ivLen];
    Buffer.BlockCopy(ivCiphertext, 0, iv, 0, iv.Length);

    byte[] ciphertext = new byte[ivCiphertext.Length - iv.Length];
    Buffer.BlockCopy(ivCiphertext, iv.Length, ciphertext, 0, ciphertext.Length);

    return (iv, ciphertext);
}

и ключевого ввода настройки:

private static byte[] GetKeySetupInput(byte[] key, byte[] iv)
{
    byte[] keySetupInput = new byte[key.Length + iv.Length];
    Buffer.BlockCopy(key, 0, keySetupInput, 0, key.Length);
    Buffer.BlockCopy(iv, 0, keySetupInput, key.Length, iv.Length);

    return keySetupInput;
}

Кроме того, само расшифрование, по-видимому, реализовано неправильно или, по крайней мере, не полностью. CipherSaber использует RC4 в качестве алгоритма шифрования/дешифрования, который можно разделить на настройку ключа и фактическое шифрование/дешифрование:

  • Упомянутый веб-сайт выполняет расшифровку с использованием CipherSaber-2. По сравнению с исходным CipherSaber (называемым CipherSaber-1) используется модифицированная настройка ключа, в которой настройка ключа CipherSaber-1/RC4 повторяется несколько раз, 20 раз в случае публикуемых данных. Описание настройки ключа CipherSaber-1/RC4 можно найти здесь, Алгоритм планирования ключей (KSA), возможная реализация для CipherSaber-2:

    private static byte[] sBox = new byte[256];
    
    private static void KeySetup(byte[] input, int iterations)
    {
        for (int i = 0; i < 256; i++)
        {
            sBox[i] = (byte)i;
        }
    
        int j = 0;
        for (int cs2loop = 0; cs2loop < iterations; cs2loop++) // CipherSaber-2 modification
        {
            for (int i = 0; i < 256; i++)
            {
                j = (j + sBox[i] + input[i % input.Length]) % 256;
                Swap(ref sBox[i], ref sBox[j]);
            }
        }
    }
    
    private static void Swap(ref byte val1, ref byte val2)
    {
        if (val1 == val2) return;
        val1 = (byte)(val1 ^ val2); 
        val2 = (byte)(val2 ^ val1); 
        val1 = (byte)(val1 ^ val2);
    }
    

    Цикл, помеченный модификацией CipherSaber-2 в фрагменте кода, является модификацией по сравнению с CipherSaber-1/RC4!

  • Фактическое шифрование/дешифрование описано здесь, Алгоритм псевдослучайной генерации (PRGA), возможная реализация:

    private static byte[] Process(byte[] input)
    {
        int i = 0, j = 0;
        byte[] result = new byte[input.Length];
    
        for (int k = 0; k < input.Length; k++)
        {
            i = (i + 1) % 256;
            j = (j + sBox[i]) % 256;
            Swap(ref sBox[i], ref sBox[j]);
            result[k] = (byte)(sBox[(sBox[i] + sBox[j]) % 256] ^ input[k]);
        }
        return result;
    }
    

    Обратите внимание, что этот алгоритм используется как для шифрования, так и для дешифрования.


При этом отправленное зашифрованное сообщение можно расшифровать следующим образом:

using System;
using System.Text;

...

byte[] key = Encoding.UTF8.GetBytes("MyKey");
byte[] encryptedData = Convert.FromHexString("bad85d9e7f5aff959b6b332b44af2cc554d8a6eb");
(byte[] iv, byte[] ciphertext) = SeparateIvCiphertext(encryptedData);
byte[] keySetupInput = GetKeySetupInput(key, iv);

int iterations = 20;
KeySetup(keySetupInput, iterations);
byte[] plaintext = Process(ciphertext);

Console.WriteLine(Encoding.UTF8.GetString(plaintext)); // Hola Mundo

который дает Hola Mundo в виде открытого текста.

Спасибо, код работает нормально, и теперь я понимаю свою ошибку.

Aegis 14.02.2023 05:50

Другие вопросы по теме