2011-02-28 67 views
3

我有一个文本配置文件。该文件需要加密并随产品一起提供,以便最终用户不能更改这些值。在Java中的加密

我已经看过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)); 
    } 
} 

 

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

另一方面,我将如何解读它?如何分发关键规格以便能够被破译?

谢谢

+7

你面临着与电影和游戏行业相同的问题,答案是:你所能做的最好的事情就是让用户修改文件;你不能让它变得不可能。解密密钥必须位于代码中的某处(或者在硬件中,如果您也生产硬件),它可以通过逆向工程获得。您也可以加密密钥,但第二个密钥必须存储在您的代码中,依此类推。如果您决定将文件的散列存储在代码中,并使用它来检查文件是否被篡改,则会出现类似的问题。 – 2011-02-28 17:02:36

+0

我想你有一个选择是每次应用程序联机时在线检查一台机器+文件散列。但你只是提出这个问题,并让它更难一点。 问题是 - 如何确定有人会篡改你的文件?如果你的发行版有限,那么我不会花费太多时间。这也取决于你的观众。 – diagonalbatman 2011-02-28 17:13:01

+0

@diagonalbatman出售经销商在日本。他们对这里的安全非常感兴趣,所以它必须尽可能安全。我们有一个服务器客户端模型,因此应用程序可以访问服务器。 – user489041 2011-02-28 17:15:35

回答

2

您可以将证书作为单独的jar文件与所有签名信息一起分发。但是你需要确保证书在其他机器上使用时变得无效。

2

如果您的目标是真正地让用户无法更改文件,那么您可以计算一个简单的文件散列。

硬编码“盐”添加到您的散列,然后将散列存储在第二个配置文件中。

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

+2

...但是,如果他们足够确定,他们可以对可执行文件进行逆向工程并找到散列(必须在可执行文件中硬编码或者动态生成)。但是,您建议的方法应该会阻止绝大多数用户,但它不是安全的(正如我对问题的评论中所提到的,我认为不可能为此创建完全安全的方案)。 – 2011-02-28 17:19:37

+1

或者他们可以修改代码,以便它不检查散列,检查代码始终返回true。 – 2011-02-28 17:40:22

+0

他们可以等到配置文件解码后替换自己的配置文件。我不认为试图阻止这些类型的攻击是在这个具体问题的范围之内。 – MrJacqes 2011-02-28 17:56:44

2

真的没有万无一失的方法来解决这个问题。我注意到一些较大的软件公司(Adobe,Microsoft,Symantec)要求用户对其服务器进行身份验证,以执行n路握手以确保密钥有效。这有效,但它引入了另一套问题...例如,用户需要互联网接入,用户需要将串行传输到新电脑等...

在我工作过的其中一个项目中,我将加密密钥存储在用户计算机的注册表中。当然,我的项目并不是绝密项目,它并不妨碍更精明的用户在注册表中搜索密钥。这仍然比在源代码中对加密密钥进行硬编码更好,特别是如果我必须版本控制项目。

+0

“That works” - 考虑到破解PS副本(或一般MS/Adob​​e软件)的数量,我不会订阅;) 通常有足够的时间和知识的每个软件方案(也可能是太它至少更难)可以被打破。 – Voo 2011-02-28 18:28:10

5

(转贴作为一个答案我的意见略有删节的版本,因为它得到了一些票,我很确信这答案。)

您都面临着同样的问题,因为电影和游戏行业,答案是:你可以做的最好的就是让供用户更改文件;你不能使它不可能。解密密钥必须位于代码中的某处(或者在硬件中,如果您也生产硬件),它可以通过逆向工程获得。您也可以加密密钥,但第二个密钥必须存储在您的代码中,依此类推。如果您决定在代码中存储文件的散列并使用它来验证文件未被篡改,那么您会得到类似的问题,因为然后有人可以在可执行文件中更改散列(编辑:或者直接更改该代码完全跳过哈希检查)。

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