Как зашифровать / расшифровать текстовые файлы, используя ElGamal - PullRequest
3 голосов
/ 04 февраля 2011

Я пытаюсь зашифровать и расшифровать текстовые файлы, используя ElGamal для моего исследования, но мне кажется, что я не могу заставить его работать правильно. У меня есть группа текстовых файлов в диапазоне от 1 КБ до 1 МБ, и я использую 512 бит для моего размера ключа. Я уже знаю, что, как и RSA, ELGamal не может зашифровать значения больше, чем его модуль, поэтому в качестве своего первоначального решения я решил разделить каждый файл на куски (которые меньше его модуля), чтобы я мог его зашифровать и, к счастью, это решение работает для шифрования. Моя проблема в том, что, когда я пытался расшифровать его, сгенерированные выходные данные не являются фактическими данными, которые я ожидаю увидеть. Я не знаю, в чем причина моей проблемы, и мне действительно нужно найти решение в течение нескольких дней.

Я покажу вам некоторые фрагменты кода, чтобы прояснить ситуацию.

Я сгенерировал свою пару ключей со следующим

KeyPairGenerator keyGen = KeyPairGenerator.getInstance("ElGamal", "BC";
keyGen.initialize(512);

Я шифрую по телефону

public static void encryptFile(String srcFileName, String destFileName, PublicKey key) throws Exception
{
    encryptDecryptFile(srcFileName,destFileName, key, Cipher.ENCRYPT_MODE);
}

и я расшифровываю, позвонив

public static void decryptFile(String srcFileName, String destFileName, PrivateKey key) throws Exception
{
    encryptDecryptFile(srcFileName,destFileName, key, Cipher.DECRYPT_MODE);
}

Вот определение метода encryptDecryptFile (..)

public static void encryptDecryptFile(String srcFileName, String destFileName, Key key, int cipherMode) throws Exception
    {
        OutputStream outputWriter = null;
        InputStream inputReader = null;
        try
        {
            Cipher cipher = Cipher.getInstance("ElGamal/None/NoPadding", "BC"");
            String textLine = null;
    //buffer(my chunks) depends wether it is encyption or decryption
            byte[] buf = (cipherMode == Cipher.ENCRYPT_MODE? new byte[50] : new byte[64]);
            int bufl;
            // init the Cipher object for Encryption...
            cipher.init(cipherMode, key);

            // start FileIO
            outputWriter = new FileOutputStream(destFileName);
            inputReader = new FileInputStream(srcFileName);
            while ( (bufl = inputReader.read(buf)) != -1)
            {
                byte[] encText = null;
                if (cipherMode == Cipher.ENCRYPT_MODE)
                {
                      encText = encrypt(copyBytes(buf,bufl),(PublicKey)key);
                }
                else
                {
                    if (_log.isDebugEnabled())
                    {
                        System.out.println("buf = " + new String(buf));
                    }
                    encText = decrypt(copyBytes(buf,bufl),(PrivateKey)key);
                }
                outputWriter.write(encText);
                if (_log.isDebugEnabled())
                {
                    System.out.println("encText = " + new String(encText));
                }
            }
            outputWriter.flush();

        }
        catch (Exception e)
        {
            _log.error(e,e);
            throw e;
        }
        finally
        {
            try
            {
                if (outputWriter != null)
                {
                    outputWriter.close();
                }
                if (inputReader != null)
                {
                    inputReader.close();
                }
            }
            catch (Exception e)
            {
                // do nothing...
            } // end of inner try, catch (Exception)...
        }
    }

Для copyBytes:

public static byte[] copyBytes(byte[] arr, int length)
{
    byte[] newArr = null;
    if (arr.length == length)
    {
        newArr = arr;
    }
    else
    {
        newArr = new byte[length];
        for (int i = 0; i < length; i++)
        {
            newArr[i] = (byte) arr[i];
        }
    }
    return newArr;
}

Для encypt (...)

    public static byte[] encrypt(byte[] text, PublicKey key) throws Exception
{
    byte[] cipherText = null;
    try
    {

        Cipher cipher = Cipher.getInstance("ElGamal/None/NoPadding", "BC"");
        if (_log.isDebugEnabled())
        {
            _log.debug("\nProvider is: " + cipher.getProvider().getInfo());
            _log.debug("\nStart encryption with public key");
        }

        // encrypt the plaintext using the public key
        cipher.init(Cipher.ENCRYPT_MODE, key);
        cipherText = cipher.doFinal(text);
    }
    catch (Exception e)
    {
        _log.error(e, e);
        throw e;
    }
    return cipherText;
}

и расшифровать (..)

   public static byte[] decrypt(byte[] text, PrivateKey key) throws Exception
    {
        byte[] dectyptedText = null;
        try
        {
            // decrypt the text using the private key
            Cipher cipher = Cipher.getInstance("ElGamal/None/NoPadding", "BC"");
              cipher.init(Cipher.DECRYPT_MODE, key);
            dectyptedText = cipher.doFinal(text);
        }
        catch (Exception e)
        {
            _log.error(e, e);
            throw e;
        }
        return dectyptedText;

    }

Оригинальный код от Aviran Mondo

Я думаю, это все, что вам нужно, просто скажите, хотите ли вы увидеть полный исходный код. Спасибо,

Ответы [ 2 ]

2 голосов
/ 08 февраля 2011

Наконец-то у меня есть решение, в любом случае, я просто выложу его на всякий случай, если у кого-то возникнет такая же проблема со мной.Все, что вам нужно сделать, это заменить

byte[] buf = (cipherMode == Cipher.ENCRYPT_MODE? new byte[50] : new byte[64]);

в методе encryptDecryptFile (..) на

byte[] buf = (cipherMode == Cipher.ENCRYPT_MODE? new byte[50] : new byte[128]);

, поскольку ElGamal с размером ключа 512 выдает 128b при шифровании 50b.Надеюсь, это достаточно ясно.

2 голосов
/ 04 февраля 2011

Это не совсем связано с вашим кодом, но криптографически небезопасно пытаться превратить блочный шифр с размером блока фиксированной ширины в блочный шифр, который может работать в потоке, просто разбивая входные данные наблокирует и шифрует каждый из них.Если вы делаете это, вы, по сути, делаете прославленный моноалфавитный шифр замещения, где каждый «символ» имеет ширину в один блок.Это позволяет злоумышленнику восстановить части структуры вашего ввода, что разрушает гарантию, которую вы обычно получаете от этих криптографических примитивов.В качестве примера, посмотрите это обсуждение в Википедии об этом конкретном режиме шифрования и посмотрите, как он шифрует Tux Linux Penguin.Зашифрованное изображение сразу позволяет увидеть структуру ввода.

Если вы хотите использовать блочный шифр, такой как ElGamal, для шифрования потока текста, вы должны использовать более сложную конструкцию, такую ​​как блок шифрацепочка (CBC) или режим счетчика (CTR) , которые надежно криптографически безопасны для входов разумного размера.Злоумышленнику будет очень трудно попытаться нарушить вашу безопасность, если вы воспользуетесь одним из этих режимов.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...