2011-06-06 83 views
4

我是一个完整的初学者任何类型的解密。我写了一个我认为应该很安全的课程。你能否给我提出建设性的批评,我该如何改进算法。我的密码解密类有多安全?

package main; 

import java.util.Random; 

public class Main { 

    public static void main(String[] args) { 
     //we will be playing around with this string 
     new Main("1234567890abc"); 
    } 

    private Random rnd; 
    private byte[] randoms; 

    /** 
    * Starts up RNG 
    * Prints out a test 
    */ 
    public Main(String password) { 
     //random long generated from the password 
     long randomLong = randomNumber(password); 
     //Random class using randomLong as seed 
     rnd = new Random(randomLong); 
     randoms = new byte[password.length()]; 
     //Array of random bytes generated with rnd 
     rnd.nextBytes(randoms); 

     System.out.println(randomNumber(password)); 

     String cryped = encrypt(password); 
     String decryped = decrypt(cryped); 

     System.out.println(cryped); 
     System.out.println(decryped); 
    } 

    /** 
    * Encrypts the password. 
    */ 
    private String encrypt(String password) { 
     char[] chars = password.toCharArray();  
     for (int i = 0; i < chars.length; i++) { 
     chars[i] = (char) (chars[i] + randoms[i]); 
     } 
     return String.valueOf(chars); 
    } 

    /** 
    * Decrypts an allready encryped password. 
    */ 
    private String decrypt(String crypted) { 
     char[] chars = crypted.toCharArray(); 
     for (int i = 0; i < chars.length; i++) { 
     chars[i] = (char) (chars[i] - randoms[i]); 
     } 
     return String.valueOf(chars); 
    } 

    /** 
    * Finds a random number BASED ON PASSWORD 
    */ 
    private long randomNumber(String password) 
    { 
     char[] chars = password.toCharArray(); 
     long number = 0; 
     for (char c : chars) { 
     number += c; 
     } 
     number *= chars.length; 
     return number; 
    } 
} 

类是用Java编写的,但应该是可读的任何人。

+2

为什么不把代码放在这里?为了可读性,索引...所有的:) – 2011-06-06 07:58:52

+1

这是功课吗?如果没有,为什么不使用包java.security。*? – 2011-06-06 08:01:47

+0

它不是家庭作业,我不必在任何地方使用它。 – 2011-06-06 08:05:24

回答

10
  1. 不要在现实生活中重塑自己的密码学(这是练习吗?)即使是专家也会犯错误。使用已公开审查的内容。
  2. java随机数发生器不具有密码安全性。用足够长的文本进行加密,会出现模式,可以允许各种信息泄露,包括揭示密码(但参见第三点)和明文。
  3. 您使用密码来为随机数生成器播种。这是一个标准(而且很好)的想法,但是你使用一种不变的排列算法!即您的加密将“sinecure”和“insecure”或其他等同于(也可能是其他)等同形式的密码作为对等密码。对于最多16个字母且密码不超过255的强密码,最高可到达种子为255 * 16 * 16 = 65280;但由于种子的种子比不可到达的种子少,所以可能性更小。在我的键盘上,bruteforcing只显示了9734种不同种子的密码,其中只包含键盘可写字符,不包括换行符(我数95),长度不超过16个字符;每个字母的熵不到1位。
  4. CodeInChaos在他的答案中有一些额外的观察:你使用流密码(甚至更难以正确!)。您还正在加密密码,这表明您可能正在寻找散列而不是加密函数(或者仅仅是一个例子?)。
  5. 顺便说一句,如果你想存储密码; 不要 - 甚至没有加密!看到索尼的失败为什么;您可能会被黑客入侵,您可能会丢失密码数据库,并且攻击者可能会知道您的加密密钥。相反,使用标准的,最佳实践密码散列(如果可能的话,更喜欢标准的预先存在的组件)。这样的系统至少应该使用一个安全的散列,比如sha1或更好;密码应该单独腌制(盐可以以明文形式存储),并且该过程应该在计算上花费昂贵以使蛮力不吸引人。详情请参阅http://chargen.matasano.com/chargen/2007/9/7/enough-with-the-rainbow-tables-what-you-need-to-know-about-s.html
+0

如果你的程序是一个密码管理器,存储密码是可以的。 – CodesInChaos 2011-06-06 10:27:57

9

可怕地以多种方式破碎。

  1. 您的密钥是64位,今天有点小。但这是你现在最担心的问题。
  2. 我看到一个非加密PRNG。你需要使用加密PRNG。
  3. 您正在重新使用流密码中的密钥。流密码因难以正确使用而臭名昭着。在这种操作模式下,它基本上像PRNG生成的一次性键盘一样。一旦你在这种模式下重用密钥,你的密码就会被破坏。
    假设攻击者知道encrypt(p1)encrypt(p2)。然后他可以计算出与p1-p2相同的encrypt(p1)-encrypt(p2)
  4. 您的有效密钥大小是小于64位。字符串中字符的总和是< 2^16 *长度。对于大多数角色来说,它甚至是< 128.所以你的关键通常是一个数字< 1000'000。这对蛮力是微不足道的。
  5. randoms中的每个元素是一个字节,即8位。字符是16位。所以你不会添加modulo 256.因此你泄露了加密密码的信息。

并对其进行改进,完全抛弃自己的算法,并使用众所周知,审查算法。除非你是密码专家,否则发明自己的算法是一个坏主意。甚至专家经常犯错误。

你真的需要密码解密吗(即它是密码存储)还是密码哈希足够?

我的建议是把你的主密码放在密钥派生函数中(PKDF2是一个普通的选择)。然后使用此函数返回的密钥来使用AES加密数据文件的其余部分。

+0

@downvoter这个答案有什么不对? – CodesInChaos 2011-06-06 08:12:36

+0

......根据我所知,没有什么:+1 – 2011-06-06 08:17:45

+0

当你写了1000'000的数字时,我想我会写一个bruteforcer:结果是,最多16个字符,只有9642种不同的可能性:*真的*限制:-) – 2011-06-06 08:54:12