【问题标题】:How to encrypt/decrypt text files using ElGamal如何使用 ElGamal 加密/解密文本文件
【发布时间】:2011-06-21 03:51:46
【问题描述】:

我正在尝试使用 ElGamal 加密和解密文本文件以进行研究,但似乎无法使其正常工作。 我有一组 1kb - 1mb 的文本文件,我使用 512bit 作为我的密钥大小。我已经知道,就像 RSA 一样,ELGamal 不能加密超过其模数的值,所以作为我的初始解决方案,我决定将每个文件分成块(小于其模数)以便我能够加密它幸运的是,这些解决方案适用于加密。我的问题是,当我尝试解密它时,生成的输出不是我期望看到的实际输出。我不知道我的问题的原因是什么,我真的需要在几天内找到解决方案。

我将向您展示我的一些代码 sn-ps 只是为了说明清楚。

我使用以下内容生成了我的密钥对

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)...
        }
    }

对于复制字节:

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;
}

对于密码(...)

    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 的原始代码

我认为这就是您所需要的,如果您想查看完整的源代码,请告诉我。 谢谢,

【问题讨论】:

    标签: java elgamal


    【解决方案1】:

    我终于有了解决方案,无论如何我会把它放在这里以防万一有人也和我有同样的问题。你所要做的就是更换

    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]);
    

    因为使用 512 密钥大小的 ElGamal 在加密 50b 时会产生 128b。我希望这已经足够清楚了。

    【讨论】:

      【解决方案2】:

      这与您的代码不太相关,但是尝试将具有固定宽度块大小的块密码转换为可以通过仅将输入拆分为流来处理的块密码在密码学上是不安全的块并加密它们中的每一个。如果你这样做,你基本上是在做一个美化的单字母替换密码,其中每个“字符”都是一个块宽。这允许攻击者恢复您输入的部分结构,这破坏了您通常从这些加密原语中获得的保证。例如,请参阅this Wikipedia discussion of this particular mode of encryption 并了解它如何加密 Tux the Linux Penguin。加密后的图像可以立即让您看到输入的结构。

      如果您想使用像 ElGamal 这样的分组密码来加密文本流,您应该使用更复杂的结构,例如 cipher block chaining (CBC)counter mode (CTR),它们在合理大小的输入上可证明是加密安全的。如果您使用其中一种模式,攻击者将很难尝试破坏您的安全。

      我很抱歉没有对您的代码发表任何实质性的意见,但老实说,我认为在尝试调试此系统之前备份并选择一个强大的加密系统是值得的。否则你最终会得到一个聪明的攻击者可以破坏的系统。

      【讨论】:

      • 您好,感谢您的回复,但我想我必须更具体一点。我非常感谢您提供这样的提示,但我主要关心的实际上并不是算法本身的安全性。我的研究重点是关于输入类型(可能是所有字母、数字、字母数字符号或四个的组合 - 我使用组合输入类型作为我的控制)如何影响算法的速度,我的测试算法之一是 elgamal .如果有人能给我一个建议,我会很高兴,再次感谢您的快速响应 templatetypedef。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-06-17
      • 1970-01-01
      • 2011-10-09
      • 1970-01-01
      • 2014-10-24
      • 1970-01-01
      • 2014-01-18
      相关资源
      最近更新 更多