我的密码解密课程的安全性如何?

时间:2011-06-06 07:56:32

标签: cryptography encryption password-protection

我是任何解密的完全初学者。我写了一篇我认为应该非常安全的课程。你能否给我建设性的批评,我怎么能改进算法。

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 个答案:

答案 0 :(得分:10)

  1. 不要在现实生活中重塑自己的密码学(这是一种练习吗?)即使是专家也会犯错误。使用经过公开审查的内容。
  2. java随机数生成器不具有加密安全性。有足够长的文本加密,模式将出现,可以允许各种信息泄露,包括泄露密码(但见第三点)和明文。
  3. 您使用密码为随机数生成器播种。这是一个标准(和精细)的想法,但你使用一个不变的排列算法!即,您的加密处理“sinecure”和“不安全”或其他字母作为等效字体(也可能是其他密码)。对于最多16个字母且没有超过255的代码点的强密码,最高可达种子为255 * 16 * 16 = 65280;但由于存在低于此值但无法到达的种子,因此可能性更小。在我的键盘上,强制显示只有9734种不同的密码种子,仅由键盘可写字符组成,不包括最多16个字符的换行符(I计数95);每个字母的熵小于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

答案 1 :(得分:9)

可怕地以多种方式打破。

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

  6. 为了改进它,完全抛弃你自己的算法并使用一个众所周知的,经过审查的算法。除非您是加密专家,否则创建自己的算法是个坏主意。甚至专家也会经常犯错误。

    你真的需要密码解密(即它是密码存储),还是密码散列不够?

    我的建议是将您的主密码放在密钥派生函数中(PKDF2是一种常见的选择)。然后使用此函数返回的密钥,使用AES加密数据文件的其余部分。