2

I want to generate a string (I call this a "salt" but it's probably not the right term) consisting of only letters and numbers by means of 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);

The result is bad because it includes things like "?#....." which I don't want.

How can I generate a random string that like like 9c021ac3d11381d9fb2a56b59495f66e ?

Erwin Bolwidt
  • 30,799
  • 15
  • 56
  • 79
mengyingye
  • 23
  • 1
  • 4
  • possible duplicate of [How to generate a random alpha-numeric string?](http://stackoverflow.com/questions/41107/how-to-generate-a-random-alpha-numeric-string) – ceekay May 13 '15 at 08:19
  • The author wants to generate a random string consisting of letters and numbers. That is not a salt, so I removed the term mostly (leaving an explanatory note). This makes the question answerable, but it's probably too broad still because the OP makes no effort in his code to restrict the random string to letters and numbers, so it's not surprising that the outcome does not restrict itself to letters and numbers. – Erwin Bolwidt May 13 '15 at 09:47

4 Answers4

1

Why not use Base64 encoding to convert the salt? Look for Apache Commons Codec, Base64 class.

You can then convert the byte array to a String using

Base64.encodeBase64String( salt );
TT.
  • 15,774
  • 6
  • 47
  • 88
  • Yes, Base64 = 10 digits + 26 small letters + 26 capital letters + 2 special chars. So almost fit. Those two special chars can also be URL safe. Java 8 has consolidated the BASE64 encoding in an ultimate Base64 class. – Joop Eggen May 13 '15 at 09:59
  • @JoopEggen Yeah apart from the special chars(+ / and =)... Maybe not entirely what the OP wants. Probably best if the OP uses the SO duplicate-link... – TT. May 13 '15 at 10:14
1

You can turn the bytes in a BigInteger and do a base 62 (=10+26+26) conversion on it.

// 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();
}
Joop Eggen
  • 107,315
  • 7
  • 83
  • 138
0

"9c021ac3d11381d9fb2a56b59495f66e" looks like the hexadecimal representation of your salt.

To convert salt you could use:

String str = bytesToHex(salt);

final protected static char[] hexArray = "0123456789abcdef".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);
}

If speed is not important, you can also use:

String printHexBinary(byte[]) from javax.xml.bind.DataTypeConverter

Burkhard
  • 14,596
  • 22
  • 87
  • 108
0

Below class will generate the salt. You can choose the alphabets and numbers for your salt also.

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();
        }
}
Sunil
  • 482
  • 6
  • 12