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

Я пытаюсь расшифровать зашифрованное шифровальщиком шестнадцатеричное сообщение, используя 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
Типы данных JavaScript
Типы данных JavaScript
В JavaScript существует несколько типов данных, включая примитивные типы данных и ссылочные типы данных. Вот краткое объяснение различных типов данных...
Как сделать движок для футбольного матча? (простой вариант)
Как сделать движок для футбольного матча? (простой вариант)
Футбол. Для многих людей, живущих на земле, эта игра - больше, чем просто спорт. И эти люди всегда мечтают стать футболистом или менеджером. Но, к...
Знайте свои исключения!
Знайте свои исключения!
В Java исключение - это событие, возникающее во время выполнения программы, которое нарушает нормальный ход выполнения инструкций программы. Когда...
CSS Flex: что должен знать каждый разработчик
CSS Flex: что должен знать каждый разработчик
CSS Flex: что должен знать каждый разработчик Модуль flexbox, также известный как гибкий модуль разметки box, помогает эффективно проектировать и...
Введение в раздел &quot;Заголовок&quot; в HTML
Введение в раздел "Заголовок" в HTML
Говорят, что лучшее о человеке можно увидеть только изнутри, и это относится и к веб-страницам HTML! Причина, по которой некоторые веб-страницы не...
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

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