疑似乱数の英数字文字列を生成する単純なJava アルゴリズムを探していました。私の状況では、世代を超えて「おそらく」一意である一意のセッション/キー識別子として使用されます500K+
(私のニーズでは、それほど洗練されたものは必要ありません)。
理想的には、独自性のニーズに応じて長さを指定できます。たとえば、生成された長さ 12 の文字列は のようになり"AEYGF7K0DM1X"
ます。
疑似乱数の英数字文字列を生成する単純なJava アルゴリズムを探していました。私の状況では、世代を超えて「おそらく」一意である一意のセッション/キー識別子として使用されます500K+
(私のニーズでは、それほど洗練されたものは必要ありません)。
理想的には、独自性のニーズに応じて長さを指定できます。たとえば、生成された長さ 12 の文字列は のようになり"AEYGF7K0DM1X"
ます。
ランダムな文字列を生成するには、文字列が目的の長さに達するまで、許容される記号のセットからランダムに抽出された文字を連結します。
これは、ランダムな識別子を生成するためのかなり単純で非常に柔軟なコードです。重要なアプリケーション ノートについては、以下の情報をお読みください。
public class RandomString {
/**
* Generate a random string.
*/
public String nextString() {
for (int idx = 0; idx < buf.length; ++idx)
buf[idx] = symbols[random.nextInt(symbols.length)];
return new String(buf);
}
public static final String upper = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
public static final String lower = upper.toLowerCase(Locale.ROOT);
public static final String digits = "0123456789";
public static final String alphanum = upper + lower + digits;
private final Random random;
private final char[] symbols;
private final char[] buf;
public RandomString(int length, Random random, String symbols) {
if (length < 1) throw new IllegalArgumentException();
if (symbols.length() < 2) throw new IllegalArgumentException();
this.random = Objects.requireNonNull(random);
this.symbols = symbols.toCharArray();
this.buf = new char[length];
}
/**
* Create an alphanumeric string generator.
*/
public RandomString(int length, Random random) {
this(length, random, alphanum);
}
/**
* Create an alphanumeric strings from a secure generator.
*/
public RandomString(int length) {
this(length, new SecureRandom());
}
/**
* Create session identifiers.
*/
public RandomString() {
this(21);
}
}
8 文字の識別子の安全でないジェネレータを作成します。
RandomString gen = new RandomString(8, ThreadLocalRandom.current());
セッション識別子の安全なジェネレーターを作成します。
RandomString session = new RandomString();
印刷用の読みやすいコードでジェネレーターを作成します。文字列は、より少ない記号を使用することを補うために、完全な英数字文字列よりも長くなります。
String easy = RandomString.digits + "ACEFGHJKLMNPQRUVWXYabcdefhijkprstuvwx";
RandomString tickets = new RandomString(23, new SecureRandom(), easy);
一意である可能性が高いセッション識別子を生成するだけでは十分ではありません。単純なカウンターを使用することもできます。予測可能な識別子が使用されている場合、攻撃者はセッションをハイジャックします。
長さと安全性の間には緊張があります。可能性が少ないため、識別子が短いほど推測しやすくなります。ただし、識別子が長いほど、より多くのストレージと帯域幅を消費します。シンボルのセットを大きくすると効果がありますが、識別子が URL に含まれていたり、手動で再入力したりすると、エンコードの問題が発生する可能性があります。
セッション識別子のランダム性またはエントロピーの根底にあるソースは、暗号化用に設計された乱数ジェネレーターから取得する必要があります。ただし、これらのジェネレーターを初期化すると、計算コストが高くなったり遅くなったりすることがあるため、可能な場合はそれらを再利用するように努力する必要があります。
すべてのアプリケーションにセキュリティが必要なわけではありません。ランダムな割り当ては、複数のエンティティが調整や分割を行わずに共有スペースで識別子を生成するための効率的な方法です。特にクラスター化または分散環境では、調整が遅くなる可能性があり、スペースを分割すると、エンティティが小さすぎたり大きすぎたりする共有になると問題が発生します。
ほとんどの Web アプリケーションで発生するように、攻撃者がそれらを表示および操作できる可能性がある場合は、予測不能にするための措置を講じずに生成された識別子を他の手段で保護する必要があります。攻撃者がアクセス許可なしで識別子を推測できるオブジェクトを保護する別の承認システムが必要です。
予想される識別子の総数を考えると、衝突が発生しにくいように十分な長さの識別子を使用するように注意する必要があります。これは「誕生日のパラドックス」と呼ばれています。衝突の確率 pは、およそ n 2 /(2q x ) です。ここで、nは実際に生成された識別子の数、qはアルファベット内の個別の記号の数、xは識別子の長さです。これは、2 -50以下のように非常に小さい数値である必要があります。
これを計算すると、50 万個の 15 文字の識別子が衝突する可能性は約 2 -52であり、これはおそらく宇宙線などからの検出されないエラーよりも低い可能性があります。
それらの仕様によれば、UUIDは予測できないようには設計されておらず、セッション識別子として使用するべきではありません。
標準形式の UUID は多くのスペースを必要とします。わずか 122 ビットのエントロピーに対して 36 文字です。(「ランダムな」UUID のすべてのビットがランダムに選択されるわけではありません。) ランダムに選択された英数字の文字列は、わずか 21 文字でより多くのエントロピーを詰め込みます。
UUID は柔軟ではありません。それらは標準化された構造とレイアウトを持っています。これは彼らの主な美徳であると同時に主な弱点でもあります。外部の関係者と協力する場合、UUID によって提供される標準化が役立つ場合があります。純粋に内部で使用する場合、非効率になる可能性があります。
Javaは、これを直接行う方法を提供します。ダッシュが必要ない場合は、簡単に削除できます。使用するだけuuid.replace("-", "")
import java.util.UUID;
public class randomStringGenerator {
public static void main(String[] args) {
System.out.println(generateString());
}
public static String generateString() {
String uuid = UUID.randomUUID().toString();
return "uuid = " + uuid;
}
}
uuid = 2d7428a6-b58c-4008-8575-f05549f16316
static final String AB = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
static SecureRandom rnd = new SecureRandom();
String randomString(int len){
StringBuilder sb = new StringBuilder(len);
for(int i = 0; i < len; i++)
sb.append(AB.charAt(rnd.nextInt(AB.length())));
return sb.toString();
}
Apache クラスを使用することに満足している場合は、org.apache.commons.text.RandomStringGenerator
( Apache Commons Text ) を使用できます。
例:
RandomStringGenerator randomStringGenerator =
new RandomStringGenerator.Builder()
.withinRange('0', 'z')
.filteredBy(CharacterPredicates.LETTERS, CharacterPredicates.DIGITS)
.build();
randomStringGenerator.generate(12); // toUpperCase() if you want
Apache Commons Lang 3.6 以降はRandomStringUtils
非推奨です。
これにはApacheCommonsライブラリを使用できます。RandomStringUtils:
RandomStringUtils.randomAlphanumeric(20).toUpperCase();
Dollar の使用は次のように簡単です。
// "0123456789" + "ABCDE...Z"
String validCharacters = $('0', '9').join() + $('A', 'Z').join();
String randomString(int length) {
return $(validCharacters).shuffle().slice(length).toString();
}
@Test
public void buildFiveRandomStrings() {
for (int i : $(5)) {
System.out.println(randomString(12));
}
}
次のようなものを出力します。
DKL1SBH9UJWC
JH7P0IT21EA5
5DTI72EO6SFU
HQUMJTEBNF7Y
1HCR6SKYWGT7
ここにJavaがあります:
import static java.lang.Math.round;
import static java.lang.Math.random;
import static java.lang.Math.pow;
import static java.lang.Math.abs;
import static java.lang.Math.min;
import static org.apache.commons.lang.StringUtils.leftPad
public class RandomAlphaNum {
public static String gen(int length) {
StringBuffer sb = new StringBuffer();
for (int i = length; i > 0; i -= 12) {
int n = min(12, abs(i));
sb.append(leftPad(Long.toString(round(random() * pow(36, n)), 36), n, '0'));
}
return sb.toString();
}
}
実行例は次のとおりです。
scala> RandomAlphaNum.gen(42)
res3: java.lang.String = uja6snx21bswf9t89s00bxssu8g6qlu16ffzqaxxoy
短くて簡単な解決策ですが、小文字と数字のみを使用します。
Random r = new java.util.Random ();
String s = Long.toString (r.nextLong () & Long.MAX_VALUE, 36);
サイズは 36 進数で約 12 桁であり、これ以上改善することはできません。もちろん、複数のインスタンスを追加できます。
驚くべきことに、ここでは誰もそれを提案していませんが、
import java.util.UUID
UUID.randomUUID().toString();
簡単。
これの利点は、UUID が適切で長く、衝突がほぼ不可能であることが保証されていることです。
ウィキペディアにはそれについての良い説明があります:
「 ...次の 100 年間、毎秒 10 億個の UUID を生成した後で初めて、複製が 1 つだけ作成される確率は約 50% になります。」
最初の 4 ビットはバージョン タイプで、2 ビットはバリアントのため、122 ビットのランダムになります。したがって、必要に応じて、最後から切り捨てて UUID のサイズを小さくすることができます。推奨されませんが、500k レコードを簡単に処理するには十分なランダム性があります。
Java 8 の代替手段は次のとおりです。
static final Random random = new Random(); // Or SecureRandom
static final int startChar = (int) '!';
static final int endChar = (int) '~';
static String randomString(final int maxLength) {
final int length = random.nextInt(maxLength + 1);
return random.ints(length, startChar, endChar + 1)
.collect(StringBuilder::new, StringBuilder::appendCodePoint, StringBuilder::append)
.toString();
}
import java.util.Random;
public class passGen{
// Version 1.0
private static final String dCase = "abcdefghijklmnopqrstuvwxyz";
private static final String uCase = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
private static final String sChar = "!@#$%^&*";
private static final String intChar = "0123456789";
private static Random r = new Random();
private static StringBuilder pass = new StringBuilder();
public static void main (String[] args) {
System.out.println ("Generating pass...");
while (pass.length () != 16){
int rPick = r.nextInt(4);
if (rPick == 0){
int spot = r.nextInt(26);
pass.append(dCase.charAt(spot));
} else if (rPick == 1) {
int spot = r.nextInt(26);
pass.append(uCase.charAt(spot));
} else if (rPick == 2) {
int spot = r.nextInt(8);
pass.append(sChar.charAt(spot));
} else {
int spot = r.nextInt(10);
pass.append(intChar.charAt(spot));
}
}
System.out.println ("Generated Pass: " + pass.toString());
}
}
これはパスワードを文字列に追加するだけで...ええ、うまくいきます。調べてみてください... とても簡単です。私はそれを書きました。
public static String generateSessionKey(int length){
String alphabet =
new String("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"); // 9
int n = alphabet.length(); // 10
String result = new String();
Random r = new Random(); // 11
for (int i=0; i<length; i++) // 12
result = result + alphabet.charAt(r.nextInt(n)); //13
return result;
}
ランダムな16進エンコード文字列を生成するこのソリューションを見つけました。提供された単体テストは、私の主なユースケースに耐えられるようです。ただし、提供されている他の回答よりも少し複雑です。
/**
* Generate a random hex encoded string token of the specified length
*
* @param length
* @return random hex string
*/
public static synchronized String generateUniqueToken(Integer length){
byte random[] = new byte[length];
Random randomGenerator = new Random();
StringBuffer buffer = new StringBuffer();
randomGenerator.nextBytes(random);
for (int j = 0; j < random.length; j++) {
byte b1 = (byte) ((random[j] & 0xf0) >> 4);
byte b2 = (byte) (random[j] & 0x0f);
if (b1 < 10)
buffer.append((char) ('0' + b1));
else
buffer.append((char) ('A' + (b1 - 10)));
if (b2 < 10)
buffer.append((char) ('0' + b2));
else
buffer.append((char) ('A' + (b2 - 10)));
}
return (buffer.toString());
}
@Test
public void testGenerateUniqueToken(){
Set set = new HashSet();
String token = null;
int size = 16;
/* Seems like we should be able to generate 500K tokens
* without a duplicate
*/
for (int i=0; i<500000; i++){
token = Utility.generateUniqueToken(size);
if (token.length() != size * 2){
fail("Incorrect length");
} else if (set.contains(token)) {
fail("Duplicate token generated");
} else{
set.add(token);
}
}
}
必要に応じてString文字を変更します。
文字列は不変です。これStringBuilder.append
は、文字列連結よりも効率的です。
public static String getRandomString(int length) {
final String characters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJLMNOPQRSTUVWXYZ1234567890!@#$%^&*()_+";
StringBuilder result = new StringBuilder();
while(length > 0) {
Random rand = new Random();
result.append(characters.charAt(rand.nextInt(characters.length())));
length--;
}
return result.toString();
}
import java.util.Date;
import java.util.Random;
public class RandomGenerator {
private static Random random = new Random((new Date()).getTime());
public static String generateRandomString(int length) {
char[] values = {'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','0','1','2','3',
'4','5','6','7','8','9'};
String out = "";
for (int i=0;i<length;i++) {
int idx=random.nextInt(values.length);
out += values[idx];
}
return out;
}
}
Apache Commonsのライブラリを使用して、英数字の文字列を生成しています。
import org.apache.commons.lang3.RandomStringUtils;
String keyLength = 20;
RandomStringUtils.randomAlphanumeric(keylength);
それは速くて簡単です!
import java.util.*;
import javax.swing.*;
public class alphanumeric {
public static void main(String args[]) {
String nval, lenval;
int n, len;
nval = JOptionPane.showInputDialog("Enter number of codes you require: ");
n = Integer.parseInt(nval);
lenval = JOptionPane.showInputDialog("Enter code length you require: ");
len = Integer.parseInt(lenval);
find(n, len);
}
public static void find(int n, int length) {
String str1 = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
StringBuilder sb = new StringBuilder(length);
Random r = new Random();
System.out.println("\n\t Unique codes are \n\n");
for(int i=0; i<n; i++) {
for(int j=0; j<length; j++) {
sb.append(str1.charAt(r.nextInt(str1.length())));
}
System.out.println(" " + sb.toString());
sb.delete(0, length);
}
}
}
あなたは「シンプル」と言いましたが、他の誰かがより厳しいセキュリティ要件を満たすものを探している場合に備えて、jpwgenを見てみることをお勧めします。jpwgen は Unix のpwgenをモデルにしており、非常に柔軟に設定できます。
パスワードに必須の数字とアルファベットの特殊文字が含まれている場合は、次のコードを使用できます。
private static final String NUMBERS = "0123456789";
private static final String UPPER_ALPHABETS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
private static final String LOWER_ALPHABETS = "abcdefghijklmnopqrstuvwxyz";
private static final String SPECIALCHARACTERS = "@#$%&*";
private static final int MINLENGTHOFPASSWORD = 8;
public static String getRandomPassword() {
StringBuilder password = new StringBuilder();
int j = 0;
for (int i = 0; i < MINLENGTHOFPASSWORD; i++) {
password.append(getRandomPasswordCharacters(j));
j++;
if (j == 3) {
j = 0;
}
}
return password.toString();
}
private static String getRandomPasswordCharacters(int pos) {
Random randomNum = new Random();
StringBuilder randomChar = new StringBuilder();
switch (pos) {
case 0:
randomChar.append(NUMBERS.charAt(randomNum.nextInt(NUMBERS.length() - 1)));
break;
case 1:
randomChar.append(UPPER_ALPHABETS.charAt(randomNum.nextInt(UPPER_ALPHABETS.length() - 1)));
break;
case 2:
randomChar.append(SPECIALCHARACTERS.charAt(randomNum.nextInt(SPECIALCHARACTERS.length() - 1)));
break;
case 3:
randomChar.append(LOWER_ALPHABETS.charAt(randomNum.nextInt(LOWER_ALPHABETS.length() - 1)));
break;
}
return randomChar.toString();
}
AbacusUtilによるワンライナーは次のとおりです。
String.valueOf(CharStream.random('0', 'z').filter(c -> N.isLetterOrDigit(c)).limit(12).toArray())
ランダムだからといって、一意でなければならないというわけではありません。一意の文字列を取得するには、次を使用します。
N.uuid() // E.g.: "e812e749-cf4c-4959-8ee1-57829a69a80f". length is 36.
N.guid() // E.g.: "0678ce04e18945559ba82ddeccaabfcd". length is 32 without '-'
これがScalaソリューションです:
(for (i <- 0 until rnd.nextInt(64)) yield {
('0' + rnd.nextInt(64)).asInstanceOf[Char]
}) mkString("")
Apache Commonsライブラリを使用すると、1 行で実行できます。
import org.apache.commons.lang.RandomStringUtils;
RandomStringUtils.randomAlphanumeric(64);
すべての文字と数字を含む文字配列を作成し、この文字配列からランダムに選択して、独自の文字列パスワードを作成できます。
char[] chars = new char[62]; // Sum of letters and numbers
int i = 0;
for(char c = 'a'; c <= 'z'; c++) { // For letters
chars[i++] = c;
}
for(char c = '0'; c <= '9';c++) { // For numbers
chars[i++] = c;
}
for(char c = 'A'; c <= 'Z';c++) { // For capital letters
chars[i++] = c;
}
int numberOfCodes = 0;
String code = "";
while (numberOfCodes < 1) { // Enter how much you want to generate at one time
int numChars = 8; // Enter how many digits you want in your password
for(i = 0; i < numChars; i++) {
char c = chars[(int)(Math.random() * chars.length)];
code = code + c;
}
System.out.println("Code is:" + code);
}
最適なランダム文字列ジェネレーター メソッド
public class RandomStringGenerator{
private static int randomStringLength = 25 ;
private static boolean allowSpecialCharacters = true ;
private static String specialCharacters = "!@$%*-_+:";
private static boolean allowDuplicates = false ;
private static boolean isAlphanum = false;
private static boolean isNumeric = false;
private static boolean isAlpha = false;
private static final String alphabet = "abcdefghijklmnopqrstuvwxyz";
private static boolean mixCase = false;
private static final String capAlpha = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
private static final String num = "0123456789";
public static String getRandomString() {
String returnVal = "";
int specialCharactersCount = 0;
int maxspecialCharacters = randomStringLength/4;
try {
StringBuffer values = buildList();
for (int inx = 0; inx < randomStringLength; inx++) {
int selChar = (int) (Math.random() * (values.length() - 1));
if (allowSpecialCharacters)
{
if (specialCharacters.indexOf("" + values.charAt(selChar)) > -1)
{
specialCharactersCount ++;
if (specialCharactersCount > maxspecialCharacters)
{
while (specialCharacters.indexOf("" + values.charAt(selChar)) != -1)
{
selChar = (int) (Math.random() * (values.length() - 1));
}
}
}
}
returnVal += values.charAt(selChar);
if (!allowDuplicates) {
values.deleteCharAt(selChar);
}
}
} catch (Exception e) {
returnVal = "Error While Processing Values";
}
return returnVal;
}
private static StringBuffer buildList() {
StringBuffer list = new StringBuffer(0);
if (isNumeric || isAlphanum) {
list.append(num);
}
if (isAlpha || isAlphanum) {
list.append(alphabet);
if (mixCase) {
list.append(capAlpha);
}
}
if (allowSpecialCharacters)
{
list.append(specialCharacters);
}
int currLen = list.length();
String returnVal = "";
for (int inx = 0; inx < currLen; inx++) {
int selChar = (int) (Math.random() * (list.length() - 1));
returnVal += list.charAt(selChar);
list.deleteCharAt(selChar);
}
list = new StringBuffer(returnVal);
return list;
}
}
以前の回答では、 StringBuilder が多く使用されています。簡単だと思いますが、文字ごとの関数呼び出し、配列の拡大などが必要です...
stringbuilder を使用する場合、文字列に必要な容量を指定することをお勧めします。
new StringBuilder(int capacity);
これは、StringBuilder または String の追加を使用せず、辞書も使用しないバージョンです。
public static String randomString(int length)
{
SecureRandom random = new SecureRandom();
char[] chars = new char[length];
for(int i=0; i<chars.length; i++)
{
int v = random.nextInt(10 + 26 + 26);
char c;
if (v < 10)
{
c = (char)('0' + v);
}
else if (v < 36)
{
c = (char)('a' - 10 + v);
}
else
{
c = (char)('A' - 36 + v);
}
chars[i] = c;
}
return new String(chars);
}
多分これは役に立ちます
package password.generater;
import java.util.Random;
/**
*
* @author dell
*/
public class PasswordGenerater {
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
int length= 11;
System.out.println(generatePswd(length));
// TODO code application logic here
}
static char[] generatePswd(int len){
System.out.println("Your Password ");
String charsCaps="ABCDEFGHIJKLMNOPQRSTUVWXYZ";
String Chars="abcdefghijklmnopqrstuvwxyz";
String nums="0123456789";
String symbols="!@#$%^&*()_+-=.,/';:?><~*/-+";
String passSymbols=charsCaps + Chars + nums +symbols;
Random rnd=new Random();
char[] password=new char[len];
for(int i=0; i<len;i++){
password[i]=passSymbols.charAt(rnd.nextInt(passSymbols.length()));
}
return password;
}
}
プロジェクト用に自動生成された英数字文字列を開発するアプリケーションを開発しました。この文字列では、最初の 3 文字はアルファベットで、次の 7 文字は整数です。
public class AlphaNumericGenerator {
public static void main(String[] args) {
java.util.Random r = new java.util.Random();
int i = 1, n = 0;
char c;
String str = "";
for (int t = 0; t < 3; t++) {
while (true) {
i = r.nextInt(10);
if (i > 5 && i < 10) {
if (i == 9) {
i = 90;
n = 90;
break;
}
if (i != 90) {
n = i * 10 + r.nextInt(10);
while (n < 65) {
n = i * 10 + r.nextInt(10);
}
}
break;
}
}
c = (char)n;
str = String.valueOf(c) + str;
}
while(true){
i = r.nextInt(10000000);
if(i > 999999)
break;
}
str = str + i;
System.out.println(str);
}
}