2015-02-23 62 views
1

这是为密码生成盐的正确方法吗?Java SecureRandom as salt

 SecureRandom random = new SecureRandom(); 
     byte[] salt = random.generateSeed(64); 

     String decoded = new String(salt, "Cp1252"); 
     System.out.println(decoded); 

我想要生成新的密码(SHA-512),所以我也需要一个盐。
哈希密码将=用户密码+盐......这是正确的?
难道这些奇怪的字符会“破坏”DB(MySQL)吗? (更新:无,因为盐应该是加密/编码/散列并将结果shoudnt使用奇怪的字符)

几个输出:

ã2}wÑ»-ÄKÇæꮃzR4qÉÖÙÚ!ž0ÉW9;*Vß4x») 
àöˆ˜£¿{,J¼…HþTù#+Bv(Fp´G~Aò`^e_ElpíÜžS A!­ñÛz‹[email protected]`ý‡)‡ª€ 
5a£Æ.¥sgöfÈB:4-�y$Óx%Óâyý¾N¨…áq 

如果这些盐也作为encripted SHA-512? (更新:使用Base64库Apache的公共编码编码,见下文)

更新

 SecureRandom random = new SecureRandom(); 
     byte[] saltArr = new byte[64]; 
     random.nextBytes(saltArr); 

     String salt = new String(saltArr, "Cp1252"); 
     System.out.println("SALT:"+salt); 


     byte[] encodedBytes = Base64.encodeBase64(saltArr); 
     System.out.println("Encoded SALT:" + new String(encodedBytes)); 

     byte[] decodedBytes = Base64.decodeBase64(encodedBytes); 
     System.out.println("Decoded SALT:" + new String(decodedBytes, "Cp1252")); 


     //SHA 
     String target = "Test"; 
     MessageDigest sh = MessageDigest.getInstance("SHA-512"); 
     sh.update(target.getBytes()); 
     StringBuffer sb = new StringBuffer(); 
     for (byte b : sh.digest()) sb.append(Integer.toHexString(0xff & b)); 
     System.out.println("Hashed PWD:"+sb); 

     //And then joining them together... 
+0

看看以下问题http://stackoverflow.com/questions/18142745/how-do-i-generate-a-salt-in-java-for-salted-hash – sasankad 2015-02-23 22:51:16

回答

1

首先,这将是足够使用nextBytes(即实际调用PRNG),而不是generateSeed。后者使用种子生成算法,这是一种更复杂的操作,因为它需要一个熵源(800-90A p19-23

盐的主要功能是为了防御字典攻击 与密码散列值和列表针对预先计算的彩虹 表攻击。 (Wikipedia

换句话说,you need a different salt for each password,但盐不是秘密(你会与消化输出一起存储它),你 应该罚款从PRNG输出。由于盐(可能包含全部范围内的字节0x00-0xFF)将作为字符串持久化,所以它应该在Base64(或另一个字符集安全编码,例如基本85, base64更平常)。

* SHA is not an encryption function

SecureRandom random = new SecureRandom(); 
byte[] salt = new byte[64]; 
random.nextBytes(salt); 

String password="god"; 
MessageDigest md = MessageDigest.getInstance("SHA-512"); 
md.update(password.getBytes(Charset.forName("UTF-8"))); 
md.update(salt); 

byte[] digest = md.digest(); 
+0

哦,是啊对不起,有时候我会把混淆与引语混淆......更新,请问你能检查它是否正确吗? – Alpha2k 2015-02-24 07:44:33

+0

是的。但请注意,getBytes()会使用平台的默认字符集将字符串编码为一系列字节。如果您将应用程序迁移到另一个具有不同默认字符集的平台,则相同的密码和salt可能会散列为不同的值;所以我用'getBytes(Charset)'。 还要注意'Integer.toHexString(0xff&b)'并不总是返回两个字符。 – Javier 2015-02-24 10:13:19