Java中的加密

Java中的加密,java,distribution,aes,encryption,Java,Distribution,Aes,Encryption,我有一个文本配置文件。此文件需要加密并随产品一起提供,以便最终用户无法更改值 我已经研究了AES,并遇到了这个简单的例子 import java.security.*; import javax.crypto.*; import javax.crypto.spec.*; import java.io.*; /** * This program generates a AES key, retrieves its raw bytes, and * then reinstantiates a

我有一个文本配置文件。此文件需要加密并随产品一起提供,以便最终用户无法更改值

我已经研究了AES,并遇到了这个简单的例子


import java.security.*;
import javax.crypto.*;
import javax.crypto.spec.*;
import java.io.*;

/**
 * This program generates a AES key, retrieves its raw bytes, and
 * then reinstantiates a AES key from the key bytes.
 * The reinstantiated key is used to initialize a AES cipher for
 * encryption and decryption.
 */
public class AES
{

    /**
     * Turns array of bytes into string
     *
     * @param buf   Array of bytes to convert to hex string
     * @return  Generated hex string
     */
    public static String asHex(byte buf[])
    {
        StringBuilder strbuf = new StringBuilder(buf.length * 2);
        int i;

        for (i = 0; i < buf.length; i++)
        {
            if (((int) buf[i] & 0xff) < 0x10)
            {
                strbuf.append("0");
            }

            strbuf.append(Long.toString((int) buf[i] & 0xff, 16));
        }

        return strbuf.toString();
    }

    public static void main(String[] args) throws Exception
    {

        String message = "This is just an example";

        // Get the KeyGenerator

        KeyGenerator kgen = KeyGenerator.getInstance("AES");
        kgen.init(128); // 192 and 256 bits may not be available


        // Generate the secret key specs.
        SecretKey skey = kgen.generateKey();
        byte[] raw = skey.getEncoded();

        SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");


        // Instantiate the cipher

        Cipher cipher = Cipher.getInstance("AES");

        cipher.init(Cipher.ENCRYPT_MODE, skeySpec);

        byte[] encrypted = cipher.doFinal(message.getBytes());
        System.out.println("encrypted string: " + asHex(encrypted));

        cipher.init(Cipher.DECRYPT_MODE, skeySpec);
        byte[] original = cipher.doFinal(encrypted);
        String originalString = new String(original);
        System.out.println("Original string: " + originalString + " " + asHex(original));
    }
}

这是一个好方法吗?我可以以字符串的形式获取配置文件,对其进行编码,然后将编码的字节写入文件。然后我可以分发编码文件

但另一方面,我该如何破译它呢?如何分发密钥规范,以便能够对其进行解密


谢谢

您可以将证书作为一个单独的jar文件分发,其中包含所有签名信息。但您需要确保证书在其他机器上使用时无效。

如果您的目标是真正做到这一点,以便用户无法更改该文件,则可以计算该文件的简单哈希

硬编码“salt”以添加到哈希中,然后将哈希存储在第二个配置文件中


用户可以看到该文件,但任何更改都会更改哈希。在不知道秘密盐的情况下,他们无法生成新的散列。

真的没有万无一失的方法来解决这个问题。我注意到一些较大的软件公司(Adobe、Microsoft、Symantec)要求用户对其服务器进行身份验证,以执行n向握手以确保密钥有效。这是可行的,但它带来了另一组问题。。。例如,用户需要访问internet,用户需要将串行数据传输到新的计算机,等等

在我的一个项目中,我将加密密钥存储在用户计算机的注册表中。当然,我的项目不是绝密项目,也不会阻止更精明的用户在注册表中搜索密钥。这仍然比在源代码中硬编码加密密钥要好,尤其是当我必须对项目进行版本控制时

(转载我的评论略为删节的版本作为答案,因为它获得了几票,我确信这就是答案。)


你面临着与电影和游戏行业相同的问题,答案是:你能做的最好的事情就是让用户难以更改文件;你不能让它变得不可能。解密密钥必须存在于代码中的某个地方(或者硬件中,如果您也生产硬件的话),在那里可以通过反向工程获得。您也可以加密密钥,但第二个密钥必须存储在代码中,依此类推。如果您决定在代码中存储文件的散列,并使用它来验证文件是否被篡改,那么您将遇到类似的问题,因为有人可能会在您的可执行文件中更改散列(编辑:或简单地更改代码以完全跳过散列检查)


正如@limc所提到的,您可以使用一些中央验证方案,以及它们带来的所有问题和用户敌意。我认为@Jacques先生的建议是你最好的选择,除非你真的需要100%防黑客(在这种情况下,我认为你有一个大问题),因为它将阻止绝大多数用户(直到有人发布破解,即…)

你正面临与电影和游戏行业相同的问题,答案是:你所能做的就是让用户很难更改文件;你不能让它变得不可能。解密密钥必须存在于代码中的某个地方(或者硬件中,如果您也生产硬件的话),在那里可以通过反向工程获得。您也可以加密密钥,但第二个密钥必须存储在代码中,依此类推。如果您决定在代码中存储文件的哈希值,并使用它检查文件是否被篡改,您也会遇到类似的问题。我想您可以做的一个选择是在每次应用程序联机时进行联机检查,即机器+文件哈希。但你只是转移话题,让它变得更难一点。问题是——有人会有多大决心篡改你的文件?如果您要限制发行版,那么我不会花费太多时间。这也取决于你的观众。@diagonalbatman Out经销商在日本。他们在那里的安全问题上很疯狂,所以必须尽可能地安全。我们有一个服务器-客户端模型,因此应用程序可以访问服务器。感谢您的回复。对于使用硬编码到客户端的密钥对许可证文件进行哈希处理,您有什么看法。客户端将被混淆,因此无法反编译。然后,我们将对许可证文件进行签名,使其在创建后不会被更改?…但是,如果确定足够,他们可以对可执行文件进行反向工程,并找到散列(必须在可执行文件中硬编码,或动态生成)。您建议的方法应该会阻止绝大多数用户,但它并不安全(正如我在对问题的评论中提到的,我认为不可能为此创建一个完全安全的方案)。或者他们可以修改代码,这样就不会检查散列,检查代码总是返回true。他们可以等到配置文件解码后再替换自己的配置文件。我不认为试图阻止这些类型的攻击是在这个特定问题的范围内。“这是有效的”-考虑到破解的PS拷贝(或通用MS/Adobe软件)的数量,我不会同意;)一般来说,只要有足够的时间和知识,每个软件方案(也可能是硬件方案,但至少要困难得多)都可以被打破。