如何使用 ElGamal 加密/解密文本文件

2024-04-10

我正在尝试使用 ElGamal 来加密和解密文本文件以进行我的研究,但似乎我无法使其正常工作。 我有一组大小从 1kb - 1mb 不等的文本文件,我使用 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)...
        }
    }

对于复制字节:

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 编写

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


这与您的代码不太相关,但是尝试将具有固定宽度块大小的块密码转换为可以通过将输入分成块并加密来在流上工作的块密码在加密上并不安全他们每个人。如果你这样做,你本质上是在做一个美化的单字母替换密码,其中每个“字符”都是一个块宽。这使得攻击者能够恢复您输入的部分结构,从而破坏您通常从这些加密原语获得的保证。作为示例,请参见维基百科对这种特定加密模式的讨论 http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Electronic_codebook_.28ECB.29看看它如何加密 Linux 企鹅 Tux。加密的图像可以立即让您看到输入的结构。

如果你想使用像 ElGamal 这样的分组密码来加密文本流,你应该使用更复杂的结构,比如密码块链 (CBC) http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher-block_chaining_.28CBC.29 or 计数器模式(CTR) http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Counter_.28CTR.29,可证明在合理大小的输入上是密码安全的。如果您使用其中一种模式,攻击者将很难尝试破坏您的安全性。

我很抱歉没有对您的代码提供任何更实质性的内容,但老实说,我认为在尝试调试此系统之前值得备份并选择一个强大的加密系统。否则,您最终会得到一个聪明的攻击者可以挫败的系统。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何使用 ElGamal 加密/解密文本文件 的相关文章

  • 使用spring自动装配时如何传递构造函数参数?

    我们的项目使用 spring DI IoC 所以我使用自动装配来注入 beans 程序在实例化期间需要将参数传递给对象 并且参数是在运行时 而不是在编译时 知道的 如何在使用自动装配时实现这一点 示例代码如下 界面 IMessage pac
  • 用更轻的解决方案替换完整的 ORM(JPA/Hibernate):推荐的加载/保存模式?

    我正在开发一个新的 Java Web 应用程序 并且正在探索保存数据的新方法 对我来说是新方法 我主要有 JPA 和 Hibernate 的经验 但是 除了简单的情况之外 我认为这种完整的 ORM 可能会变得相当复杂 另外 我不太喜欢和他们
  • Spring - Path 的工厂方法

    我正在尝试生成一个代表的 beanjava nio file Path使用静态方法Paths get String path 我当前的 Spring 设置如下
  • 如何对这个字符串进行子串化

    我想得到这个字符串的 4 个部分 String string 10 trillion 896 billion 45 million 56873 我需要的4个部分是 10万亿 8960亿 4500万 和 56873 我所做的是删除所有空格 然
  • 时间序列中的峰值检测

    我目前正在开展一个小项目 我想在其中比较两个时间序列 相似性度量确实很模糊 如果两个时间序列大致具有相同的形状 则它们被认为是相似的 所以我心想 如果它们只需要具有相同的形状 我只需比较两个时间序列的峰值 如果峰值位于相同的位置 那么时间序
  • MyBatis:在一个查询中通过注释收集

    我有一个 xml 映射器 一个选择映射器和一个结果映射器 它工作没有问题 但我想使用注释 我的映射器
  • 如何在 Netbeans 中调试 Java Web 应用程序?

    我曾多次在 Netbeans 中调试 Java 桌面应用程序 但从未调试过 Java Web 应用程序 我尝试以同样的方式调试它 但它不起作用 我制作了一个index html网页 该页面上有一个 表格 用户提交表单后 请求将发送至 ser
  • 在 Java 中连接和使用 Cassandra

    我已经阅读了一些关于 Cassandra 是什么以及它可以做什么的教程 但我的问题是如何在 Java 中与 Cassandra 交互 教程会很好 如果可能的话 有人可以告诉我是否应该使用 Thrift 还是 Hector 哪一个更好以及为什
  • Spring Batch 多线程 - 如何使每个线程读取唯一的记录?

    这个问题在很多论坛上都被问过很多次了 但我没有看到适合我的答案 我正在尝试在我的 Spring Batch 实现中实现多线程步骤 有一个包含 100k 条记录的临时表 想要在 10 个线程中处理它 每个线程的提交间隔为 300 因此在任何时
  • 如何在 Play java 中创建数据库线程池并使用该池进行数据库查询

    我目前正在使用 play java 并使用默认线程池进行数据库查询 但了解使用数据库线程池进行数据库查询可以使我的系统更加高效 目前我的代码是 import play libs Akka import scala concurrent Ex
  • Java - 将节点添加到列表的末尾?

    这是我所拥有的 public class Node Object data Node next Node Object data Node next this data data this next next public Object g
  • 在 java 类和 android 活动之间传输时音频不清晰

    我有一个android活动 它连接到一个java类并以套接字的形式向它发送数据包 该类接收声音数据包并将它们扔到 PC 扬声器 该代码运行良好 但在 PC 扬声器中播放声音时会出现持续的抖动 中断 安卓活动 public class Sen
  • INSERT..RETURNING 在 JOOQ 中不起作用

    我有一个 MariaDB 数据库 我正在尝试在表中插入一行users 它有一个生成的id我想在插入后得到它 我见过this http www jooq org doc 3 8 manual sql building sql statemen
  • 磁模拟

    假设我在 n m 像素的 2D 表面上有 p 个节点 我希望这些节点相互吸引 使得它们相距越远吸引力就越强 但是 如果两个节点之间的距离 比如 d A B 小于某个阈值 比如 k 那么它们就会开始排斥 谁能让我开始编写一些关于如何随时间更新
  • Spring @RequestMapping 带有可选参数

    我的控制器在请求映射中存在可选参数的问题 请查看下面的控制器 GetMapping produces MediaType APPLICATION JSON VALUE public ResponseEntity
  • 无法解析插件 Java Spring

    我正在使用 IntelliJ IDEA 并且我尝试通过 maven 安装依赖项 但它给了我这些错误 Cannot resolve plugin org apache maven plugins maven clean plugin 3 0
  • 如何在PreferenceActivity中添加工具栏

    我已经使用首选项创建了应用程序设置 但我注意到 我的 PreferenceActivity 中没有工具栏 如何将工具栏添加到我的 PreferenceActivity 中 My code 我的 pref xml
  • 禁止的软件包名称:java

    我尝试从数据库名称为 jaane 用户名 Hello 和密码 hello 获取数据 错误 java lang SecurityException Prohibited package name java at java lang Class
  • 在两个活动之间传输数据[重复]

    这个问题在这里已经有答案了 我正在尝试在两个不同的活动之间发送和接收数据 我在这个网站上看到了一些其他问题 但没有任何问题涉及保留头等舱的状态 例如 如果我想从 A 类发送一个整数 X 到 B 类 然后对整数 X 进行一些操作 然后将其发送
  • 使用Caliper时如何指定命令行?

    我发现 Google 的微型基准测试项目 Caliper 非常有趣 但文档仍然 除了一些示例 完全不存在 我有两种不同的情况 需要影响 JVM Caliper 启动的命令行 我需要设置一些固定 最好在几个固定值之间交替 D 参数 我需要指定

随机推荐