Hasilkan Kata Sandi Acak Aman di Java

Java Top

Saya baru saja mengumumkan kursus Learn Spring baru , yang berfokus pada dasar-dasar Spring 5 dan Spring Boot 2:

>> LIHAT KURSUSnya

1. Perkenalan

Dalam tutorial ini, kita akan melihat berbagai metode yang dapat kita gunakan untuk menghasilkan kata sandi acak yang aman di Java.

Dalam contoh kami, kami akan membuat kata sandi sepuluh karakter, masing-masing dengan minimal dua karakter huruf kecil, dua karakter huruf besar, dua digit, dan dua karakter khusus.

2. Menggunakan Passay

Passay adalah perpustakaan penegakan kebijakan sandi. Khususnya, kita dapat menggunakan pustaka untuk menghasilkan kata sandi menggunakan seperangkat aturan yang dapat dikonfigurasi.

Dengan bantuan implementasi CharacterData default , kita dapat merumuskan aturan yang diperlukan untuk kata sandi. Selanjutnya, kami dapat merumuskan implementasi CharacterData khusus agar sesuai dengan kebutuhan kami :

public String generatePassayPassword() { PasswordGenerator gen = new PasswordGenerator(); CharacterData lowerCaseChars = EnglishCharacterData.LowerCase; CharacterRule lowerCaseRule = new CharacterRule(lowerCaseChars); lowerCaseRule.setNumberOfCharacters(2); CharacterData upperCaseChars = EnglishCharacterData.UpperCase; CharacterRule upperCaseRule = new CharacterRule(upperCaseChars); upperCaseRule.setNumberOfCharacters(2); CharacterData digitChars = EnglishCharacterData.Digit; CharacterRule digitRule = new CharacterRule(digitChars); digitRule.setNumberOfCharacters(2); CharacterData specialChars = new CharacterData() { public String getErrorCode() { return ERROR_CODE; } public String getCharacters() { return "[email protected]#$%^&*()_+"; } }; CharacterRule splCharRule = new CharacterRule(specialChars); splCharRule.setNumberOfCharacters(2); String password = gen.generatePassword(10, splCharRule, lowerCaseRule, upperCaseRule, digitRule); return password; }

Di sini, kami telah membuat implementasi CharacterData khusus untuk karakter khusus. Hal ini memungkinkan kami untuk membatasi kumpulan karakter valid yang diperbolehkan.

Selain itu, kami menggunakan implementasi default CharacterData untuk aturan kami yang lain.

Sekarang, mari kita periksa generator kita terhadap pengujian unit. Misalnya, kita dapat memeriksa keberadaan dua karakter khusus:

@Test public void whenPasswordGeneratedUsingPassay_thenSuccessful() { RandomPasswordGenerator passGen = new RandomPasswordGenerator(); String password = passGen.generatePassayPassword(); int specialCharCount = 0; for (char c : password.toCharArray()) if (c >= 33 

Perlu dicatat bahwa meskipun Passay adalah open source, ia memiliki lisensi ganda di bawah LGPL dan Apache 2 . Seperti halnya perangkat lunak pihak ketiga, kami harus memastikan untuk mematuhi lisensi ini saat kami menggunakannya dalam produk kami. Situs web GNU memiliki lebih banyak informasi tentang LGPL dan Java.

3. Menggunakan RandomStringGenerator

Selanjutnya, mari kita lihat RandomStringGenerator di Apache Commons Text. Dengan RandomStringGenerator, kita dapat menghasilkan string Unicode yang berisi sejumlah titik kode yang ditentukan.

Sekarang, kita akan membuat instance generator dengan menggunakan kelas RandomStringGenerator.Builder . Tentu saja, kami juga dapat memanipulasi properti generator.

Dengan bantuan pembangun, kita dapat dengan mudah mengubah implementasi default keacakan. Selain itu, kami juga dapat menentukan karakter yang diizinkan dalam string:

public String generateRandomSpecialCharacters(int length) { RandomStringGenerator pwdGenerator = new RandomStringGenerator.Builder().withinRange(33, 45) .build(); return pwdGenerator.generate(length); } 

Sekarang, salah satu batasan dalam menggunakan RandomStringGenerator adalah kurangnya kemampuan untuk menentukan jumlah karakter di setiap set, seperti di Passay. Namun, kita dapat mengelaknya dengan menggabungkan hasil dari beberapa set:

public String generateCommonTextPassword() { String pwString = generateRandomSpecialCharacters(2).concat(generateRandomNumbers(2)) .concat(generateRandomAlphabet(2, true)) .concat(generateRandomAlphabet(2, false)) .concat(generateRandomCharacters(2)); List pwChars = pwString.chars() .mapToObj(data -> (char) data) .collect(Collectors.toList()); Collections.shuffle(pwChars); String password = pwChars.stream() .collect(StringBuilder::new, StringBuilder::append, StringBuilder::append) .toString(); return password; }

Selanjutnya, mari kita validasi kata sandi yang dibuat dengan memverifikasi huruf kecil:

@Test public void whenPasswordGeneratedUsingCommonsText_thenSuccessful() { RandomPasswordGenerator passGen = new RandomPasswordGenerator(); String password = passGen.generateCommonTextPassword(); int lowerCaseCount = 0; for (char c : password.toCharArray()) 

Secara default, RandomStringGenerator menggunakan ThreadLocalRandom untuk keacakan. Sekarang, penting untuk diingat bahwa ini tidak menjamin keamanan kriptografi .

Namun, kita dapat mengatur sumber keacakan menggunakan usingRandom (TextRandomProvider). Misalnya, kami dapat menggunakan SecureTextRandomProvider untuk keamanan kriptografi:

public String generateRandomSpecialCharacters(int length) { SecureTextRandomProvider stp = new SecureTextRandomProvider(); RandomStringGenerator pwdGenerator = new RandomStringGenerator.Builder() .withinRange(33, 45) .usingRandom(stp) .build(); return pwdGenerator.generate(length); }

4. Menggunakan RandomStringUtils

Pilihan lain yang bisa kita gunakan adalah kelas RandomStringUtils di Apache Commons Lang Library. Kelas ini memperlihatkan beberapa metode statis yang dapat kita gunakan untuk pernyataan masalah kita.

Mari kita lihat bagaimana kami dapat memberikan rentang poin kode yang dapat diterima untuk kata sandi:

 public String generateCommonLangPassword() { String upperCaseLetters = RandomStringUtils.random(2, 65, 90, true, true); String lowerCaseLetters = RandomStringUtils.random(2, 97, 122, true, true); String numbers = RandomStringUtils.randomNumeric(2); String specialChar = RandomStringUtils.random(2, 33, 47, false, false); String totalChars = RandomStringUtils.randomAlphanumeric(2); String combinedChars = upperCaseLetters.concat(lowerCaseLetters) .concat(numbers) .concat(specialChar) .concat(totalChars); List pwdChars = combinedChars.chars() .mapToObj(c -> (char) c) .collect(Collectors.toList()); Collections.shuffle(pwdChars); String password = pwdChars.stream() .collect(StringBuilder::new, StringBuilder::append, StringBuilder::append) .toString(); return password; }

Untuk memvalidasi kata sandi yang dibuat, mari verifikasi jumlah karakter numerik:

@Test public void whenPasswordGeneratedUsingCommonsLang3_thenSuccessful() { RandomPasswordGenerator passGen = new RandomPasswordGenerator(); String password = passGen.generateCommonsLang3Password(); int numCount = 0; for (char c : password.toCharArray()) 

Di sini, RandomStringUtils menggunakan Random secara default sebagai sumber keacakan. Namun, ada metode di dalam pustaka yang memungkinkan kita menentukan sumber keacakan:

String lowerCaseLetters = RandomStringUtils. random(2, 97, 122, true, true, null, new SecureRandom());

Sekarang, kami dapat memastikan keamanan kriptografik menggunakan instance SecureRandom . Namun, fungsionalitas ini tidak dapat diperluas ke metode lain di perpustakaan. Di samping catatan, Apache menganjurkan penggunaan RandomStringUtils hanya untuk kasus penggunaan sederhana.

5. Menggunakan Metode Utilitas Kustom

Kita juga dapat menggunakan kelas SecureRandom untuk membuat kelas utilitas kustom untuk skenario kita. Sebagai permulaan, mari buat string karakter khusus dengan panjang dua:

public Stream getRandomSpecialChars(int count) { Random random = new SecureRandom(); IntStream specialChars = random.ints(count, 33, 45); return specialChars.mapToObj(data -> (char) data); }

Juga, perhatikan bahwa 33 dan 45 menunjukkan kisaran karakter Unicode. Sekarang, kami dapat menghasilkan banyak aliran sesuai kebutuhan kami. Kemudian kita dapat menggabungkan set hasil untuk menghasilkan kata sandi yang diperlukan:

public String generateSecureRandomPassword() { Stream pwdStream = Stream.concat(getRandomNumbers(2), Stream.concat(getRandomSpecialChars(2), Stream.concat(getRandomAlphabets(2, true), getRandomAlphabets(4, false)))); List charList = pwdStream.collect(Collectors.toList()); Collections.shuffle(charList); String password = charList.stream() .collect(StringBuilder::new, StringBuilder::append, StringBuilder::append) .toString(); return password; } 

Sekarang, mari kita validasi kata sandi yang dibuat untuk jumlah karakter khusus:

@Test public void whenPasswordGeneratedUsingSecureRandom_thenSuccessful() { RandomPasswordGenerator passGen = new RandomPasswordGenerator(); String password = passGen.generateSecureRandomPassword(); int specialCharCount = 0; for (char c : password.toCharArray()) c = 2); 

6. Kesimpulan

Dalam tutorial ini, kami dapat menghasilkan kata sandi, sesuai dengan persyaratan kami, menggunakan pustaka yang berbeda.

Seperti biasa, contoh kode yang digunakan dalam artikel tersedia di GitHub.

Jawa bawah

Saya baru saja mengumumkan kursus Learn Spring baru , yang berfokus pada dasar-dasar Spring 5 dan Spring Boot 2:

>> LIHAT KURSUSnya