2011-06-06 84 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