2015-05-13 249 views
0

我想通過java.security.SecureRandom生成一個只包含字母和數字的字符串(我稱之爲「鹽」,但它可能不是正確的術語) 。使用只包含字母和數字的java.security.SecureRandom生成一個字符串

Random ran = new SecureRandom(); 
byte [] salt = new byte[32]; 
ran.nextBytes(salt); 
String str = new String(salt,"utf-8"); 
System.out.println(str); 

結果不好,因爲它包含了我不想要的「?#.....」之類的東西。

如何生成一個像9c021ac3d11381d9fb2a56b59495f66e一樣的隨機字符串?

+0

可能重複的[如何生成一個隨機的字母數字字符串?](http://stackoverflow.com/questions/41107/how-to-generate-a-random-alpha-numeric-string) – ceekay

+0

作者想要生成一個由字母和數字組成的隨機字符串。這不是鹽,所以我主要刪除了這個詞(留下一個解釋性說明)。這使得問題可以回答,但可能過於寬泛,因爲OP在他的代碼中沒有努力將隨機字符串限制爲字母和數字,所以結果不會限制爲字母和數字並不奇怪。 –

回答

0

「9c021ac3d11381d9fb2a56b59495f66e」看起來像鹽的十六進制表示。

鹽轉換可以使用:

String str = bytesToHex(salt); 

final protected static char[] hexArray = "abcdef".toCharArray(); 
public static String bytesToHex(byte[] bytes) { 
    char[] hexChars = new char[bytes.length * 2]; 
    for (int j = 0; j < bytes.length; j++) { 
     int v = bytes[j] & 0xFF; 
     hexChars[j * 2] = hexArray[v >>> 4]; 
     hexChars[j * 2 + 1] = hexArray[v & 0x0F]; 
    } 
    return new String(hexChars); 
} 

如果速度並不重要,你也可以使用:從javax.xml.bind.DataTypeConverter

0

下面類

字符串printHexBinary(字節[])將產生鹽。你也可以選擇你的鹽的字母和數字。

public class SaltGenerator { 
      private static SecureRandom prng; 
      private static final Logger LOG = LoggerFactory 
        .getLogger(AuthTokenGenerator.class); 
      static { 
       try { 
        // Initialize SecureRandom 
        prng = SecureRandom.getInstance("SHA1PRNG"); 
       } catch (NoSuchAlgorithmException e) { 
        LOG.info("ERROR while intantiating Secure Random: " + prng); 
      } 
     } 
     /** 
     * @return 
     */ 
     public static String getToken() { 
      try { 
       LOG.info("About to Generate Token in getToken()"); 
       String token; 
       // generate a random number 
       String randomNum = Integer.toString(prng.nextInt()); 
       // get its digest 
       MessageDigest sha = MessageDigest.getInstance("SHA-1"); 
       byte[] result = sha.digest(randomNum.getBytes()); 
       token = hexEncode(result); 
       LOG.info("Token in getToken(): " + token); 
       return token; 
      } catch (NoSuchAlgorithmException ex) { 
       return null; 
      } 
     } 
     /** 
     * @param aInput 
     * @return 
     */ 
     private static String hexEncode(byte[] aInput) { 
      StringBuilder result = new StringBuilder(); 
      char[] digits = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 
        'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z' }; 
      for (byte b : aInput) { 
       result.append(digits[(b & 0xf0) >> 4]); 
       result.append(digits[b & 0x0f]); 
      } 
      return result.toString(); 
     } 
} 
1

爲什麼不使用Base64編碼轉換鹽?尋找Apache Commons Codec,Base64類。

然後,可以將字節數組轉換爲使用

Base64.encodeBase64String(salt); 
+0

是的,Base64 = 10個數字+26個小寫字母+26個大寫字母+2個特殊字符。所以幾乎適合。這兩個特殊字符也可以是URL安全的。 Java 8在最終的Base64類中整合了BASE64編碼。 –

+0

@JoopEggen是除了特殊字符(+ /和=)...也許不完全是OP想要的。如果OP使用SO重複鏈接,可能是最好的... –

1

可以打開在一個BigInteger字節字符串,做一個基座62(= 10 + 26 + 26)在其上的轉換。

// Digits listed, so maybe look-alike chars (zero and oh) can be handled. 
private static final String digits = "0123...ABC...abc...z"; 

String humanReadable(byte[] bytes) { 

    // Ensure that we have a byte array which is a positive big-endian. 
    if (bytes.length != 0 && bytes[0] < 0) { 
     byte[] ubytes = new byte[bytes.length + 1]; 
     System.arraycopy(bytes, 0, ubytes, 1, bytes.length); 
     bytes = ubytes; 
    } 

    BigInteger n = new BigInteger(bytes); 
    StringBuilder sb = new StringBuilder(48); 
    final BigInteger DIGIT_COUNT = BigInteger.valueOf(digits.length()); 
    while (n.signum() != 0) { 
     int index = n.mod(DIGITS).intValue(); 
     sb.append(digits.charAt(index)); 
     n = n.div(DIGITS); 
    } 
    return sb.toString(); 
} 
相關問題