Java'da nasıl şifre oluşturabilirim?


176

Bir veritabanında depolama için parolaları karma gerekir. Bunu Java'da nasıl yapabilirim?

Düz metin şifresini almayı, rastgele bir tuz eklemeyi ve sonra tuz ve karma şifreyi veritabanında saklamayı umuyordum.

Daha sonra bir kullanıcı oturum açmak istediğinde, gönderilen şifresini alabilir, hesap bilgilerinden rasgele tuz ekleyebilir, hash edebilir ve hesap bilgileri ile saklanan hash şifresine denk olup olmadığını görebilirim.


11
@YGL bu aslında günümüzde GPU saldırılarının çok ucuz olduğu bir rekombinasyon değil, SHA ailesi aslında tuzla bile şifre karmaşası (çok hızlı) için çok kötü bir seçim. Bcrypt, scrypt veya PBKDF2 kullanın
Eran Medan

11
Bu soru neden kapatıldı? Bu gerçek bir mühendislik problemi için bir sorudur ve cevaplar paha biçilmezdir. OP bir kütüphane istemiyor, mühendislik problemini nasıl çözeceğini soruyor.
stackoverflowuser2010

12
Harika. Bu sorunun 52 yukarı oyu var ve birisi bunu "konu dışı" olarak kapatmaya karar veriyor.
stackoverflowuser2010

1
Evet, Meta'da daha önce bu kapanış meselesi hakkında yayınladım, yine de oldukça kötü bir şekilde dövüldüm.
Chris Dutrow

8
Bu soru yeniden açılmalıdır. Kısa bir kod çözümü ile açıklanan sorunu (şifre kimlik doğrulaması) çözmek için bir programın nasıl yazılacağı hakkında bir soru. Tetikleyici "kütüphane" kelimesini görmek, bir soruyu refleks olarak kapatmayı haklı çıkarmaz; bir kütüphane tavsiyesi istemiyor, şifreleri nasıl karmalayacağını soruyor. Düzenleme: Orada düzeltildi.
erickson

Yanıtlar:


157

Bunu yapmak için Java çalışma zamanında yerleşik olarak bulunan bir özelliği kullanabilirsiniz. Java 6'daki SunJCE, parola karması için kullanılacak iyi bir algoritma olan PBKDF2'yi destekler.

byte[] salt = new byte[16];
random.nextBytes(salt);
KeySpec spec = new PBEKeySpec("password".toCharArray(), salt, 65536, 128);
SecretKeyFactory f = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
byte[] hash = f.generateSecret(spec).getEncoded();
Base64.Encoder enc = Base64.getEncoder();
System.out.printf("salt: %s%n", enc.encodeToString(salt));
System.out.printf("hash: %s%n", enc.encodeToString(hash));

PBKDF2 şifre kimlik doğrulaması için kullanabileceğiniz bir yardımcı program sınıfı:

import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.KeySpec;
import java.util.Arrays;
import java.util.Base64;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;

/**
 * Hash passwords for storage, and test passwords against password tokens.
 * 
 * Instances of this class can be used concurrently by multiple threads.
 *  
 * @author erickson
 * @see <a href="http://stackoverflow.com/a/2861125/3474">StackOverflow</a>
 */
public final class PasswordAuthentication
{

  /**
   * Each token produced by this class uses this identifier as a prefix.
   */
  public static final String ID = "$31$";

  /**
   * The minimum recommended cost, used by default
   */
  public static final int DEFAULT_COST = 16;

  private static final String ALGORITHM = "PBKDF2WithHmacSHA1";

  private static final int SIZE = 128;

  private static final Pattern layout = Pattern.compile("\\$31\\$(\\d\\d?)\\$(.{43})");

  private final SecureRandom random;

  private final int cost;

  public PasswordAuthentication()
  {
    this(DEFAULT_COST);
  }

  /**
   * Create a password manager with a specified cost
   * 
   * @param cost the exponential computational cost of hashing a password, 0 to 30
   */
  public PasswordAuthentication(int cost)
  {
    iterations(cost); /* Validate cost */
    this.cost = cost;
    this.random = new SecureRandom();
  }

  private static int iterations(int cost)
  {
    if ((cost < 0) || (cost > 30))
      throw new IllegalArgumentException("cost: " + cost);
    return 1 << cost;
  }

  /**
   * Hash a password for storage.
   * 
   * @return a secure authentication token to be stored for later authentication 
   */
  public String hash(char[] password)
  {
    byte[] salt = new byte[SIZE / 8];
    random.nextBytes(salt);
    byte[] dk = pbkdf2(password, salt, 1 << cost);
    byte[] hash = new byte[salt.length + dk.length];
    System.arraycopy(salt, 0, hash, 0, salt.length);
    System.arraycopy(dk, 0, hash, salt.length, dk.length);
    Base64.Encoder enc = Base64.getUrlEncoder().withoutPadding();
    return ID + cost + '$' + enc.encodeToString(hash);
  }

  /**
   * Authenticate with a password and a stored password token.
   * 
   * @return true if the password and token match
   */
  public boolean authenticate(char[] password, String token)
  {
    Matcher m = layout.matcher(token);
    if (!m.matches())
      throw new IllegalArgumentException("Invalid token format");
    int iterations = iterations(Integer.parseInt(m.group(1)));
    byte[] hash = Base64.getUrlDecoder().decode(m.group(2));
    byte[] salt = Arrays.copyOfRange(hash, 0, SIZE / 8);
    byte[] check = pbkdf2(password, salt, iterations);
    int zero = 0;
    for (int idx = 0; idx < check.length; ++idx)
      zero |= hash[salt.length + idx] ^ check[idx];
    return zero == 0;
  }

  private static byte[] pbkdf2(char[] password, byte[] salt, int iterations)
  {
    KeySpec spec = new PBEKeySpec(password, salt, iterations, SIZE);
    try {
      SecretKeyFactory f = SecretKeyFactory.getInstance(ALGORITHM);
      return f.generateSecret(spec).getEncoded();
    }
    catch (NoSuchAlgorithmException ex) {
      throw new IllegalStateException("Missing algorithm: " + ALGORITHM, ex);
    }
    catch (InvalidKeySpecException ex) {
      throw new IllegalStateException("Invalid SecretKeyFactory", ex);
    }
  }

  /**
   * Hash a password in an immutable {@code String}. 
   * 
   * <p>Passwords should be stored in a {@code char[]} so that it can be filled 
   * with zeros after use instead of lingering on the heap and elsewhere.
   * 
   * @deprecated Use {@link #hash(char[])} instead
   */
  @Deprecated
  public String hash(String password)
  {
    return hash(password.toCharArray());
  }

  /**
   * Authenticate with a password in an immutable {@code String} and a stored 
   * password token. 
   * 
   * @deprecated Use {@link #authenticate(char[],String)} instead.
   * @see #hash(String)
   */
  @Deprecated
  public boolean authenticate(String password, String token)
  {
    return authenticate(password.toCharArray(), token);
  }

}

11
İle bayt-onaltılık dönüşümlerden biraz dikkatli olmak isteyebilirsiniz BigInteger: önde gelen sıfırlar kaldırılır. Hızlı hata ayıklama için sorun değil, ancak üretim etkisinde bu etki nedeniyle hatalar gördüm.
Thomas Pornin

24
@ thomas-pornin , neredeyse orada olan bir kod bloğuna değil, neden bir kütüphaneye ihtiyacımız olduğunu vurgular . Kabul edilen cevabın böylesine önemli bir konuda soruyu cevaplamaması korkutucu.
Nilzor

9
Java 8 ile başlayarak PBKDF2WithHmacSHA512 algoritmasını kullanın. Biraz daha güçlüdür.
iwan.z

1
Not mevcut alg sonraki sürümlerinde silinmez: java_4: PBEWithMD5AndDES, DESede, DES java_5 / 6/7: PBKDF2WithHmacSHA1, PBE, PBEWithSHA1AndRC2_40, PBEWithSHA1And, PBEWithMD5AndTriple java_8 (sadece Java 5): PBEWithHmacSHA224AndAES_128, PBEWithHmacSHA384AndAES_128, PBEWithHmacSHA512AndAES_128, RC4_40, PBKDF2WithHmacSHA256 , PBEWithHmacSHA1AndAES_128, RC4_128, PBKDF2WithHmacSHA224, PBEWithHmacSHA256AndAES_256, RC2_128, PBEWithHmacSHA224AndAES_256, PBEWithHmacSHA384AndAES_256, PBEWithHmacSHA512AndAES_256, PBKDF2WithHmacSHA512, PBEWithHmacSHA256AndAES_128, PBKDF2WithHmacSHA384, PBEWithHmacSHA1AndAES_256
iwan.z

4
@TheTosters Evet, yanlış parolalar için yürütme süresi daha uzun olacaktır ; daha spesifik olarak, yanlış şifreler doğru şifrelerle aynı zaman alacaktır. Zamanlama saldırılarını önler , ancak bu durumda bu tür bir güvenlik açığından yararlanmanın pratik bir yolunu düşünemediğimi itiraf etmeliyim. Ama köşeleri kesmiyorsun. Sadece göremediğim için, daha zekice bir zihin olmayacağı anlamına gelmez.
erickson

97

İşte tam olarak ne istediğinizi yapan iki yöntem ile tam bir uygulama :

String getSaltedHash(String password)
boolean checkPassword(String password, String stored)

Mesele şu ki, bir saldırgan hem veritabanınıza hem de kaynak kodunuza erişse bile, şifreler hala güvenlidir.

import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import java.security.SecureRandom;
import org.apache.commons.codec.binary.Base64;

public class Password {
    // The higher the number of iterations the more 
    // expensive computing the hash is for us and
    // also for an attacker.
    private static final int iterations = 20*1000;
    private static final int saltLen = 32;
    private static final int desiredKeyLen = 256;

    /** Computes a salted PBKDF2 hash of given plaintext password
        suitable for storing in a database. 
        Empty passwords are not supported. */
    public static String getSaltedHash(String password) throws Exception {
        byte[] salt = SecureRandom.getInstance("SHA1PRNG").generateSeed(saltLen);
        // store the salt with the password
        return Base64.encodeBase64String(salt) + "$" + hash(password, salt);
    }

    /** Checks whether given plaintext password corresponds 
        to a stored salted hash of the password. */
    public static boolean check(String password, String stored) throws Exception{
        String[] saltAndHash = stored.split("\\$");
        if (saltAndHash.length != 2) {
            throw new IllegalStateException(
                "The stored password must have the form 'salt$hash'");
        }
        String hashOfInput = hash(password, Base64.decodeBase64(saltAndHash[0]));
        return hashOfInput.equals(saltAndHash[1]);
    }

    // using PBKDF2 from Sun, an alternative is https://github.com/wg/scrypt
    // cf. http://www.unlimitednovelty.com/2012/03/dont-use-bcrypt.html
    private static String hash(String password, byte[] salt) throws Exception {
        if (password == null || password.length() == 0)
            throw new IllegalArgumentException("Empty passwords are not supported.");
        SecretKeyFactory f = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
        SecretKey key = f.generateSecret(new PBEKeySpec(
            password.toCharArray(), salt, iterations, desiredKeyLen));
        return Base64.encodeBase64String(key.getEncoded());
    }
}

Depolıyoruz 'salt$iterated_hash(password, salt)'. Tuz 32 rastgele bayttır ve amacı iki farklı kişi aynı şifreyi seçerse, saklanan şifrelerin hala farklı görünmesidir.

Bu iterated_hashtemelde hash(hash(hash(... hash(password, salt) ...))), parolaları tahmin etmek, onları hash etmek ve veritabanındaki hashları aramak için veritabanınıza erişimi olan potansiyel bir saldırgan için çok pahalı hale getirir. iterated_hashBir kullanıcı her oturum açtığında bunu hesaplamanız gerekir , ancak zaman hesaplama karmalarının yaklaşık% 100'ünü harcayan saldırgana kıyasla bu kadar pahalıya mal olmaz.


14
Nag için üzgünüm, ama bunu neden mevcut bir kütüphane üzerinden seçmeliyim? Bir kütüphane muhtemelen kapsamlı bir şekilde gözden geçirilme şansına sahiptir. 14 oylamadan her birinin kodu herhangi bir sorun için analiz ettiğinden şüpheliyim.
Joachim Sauer

2
@JoachimSauer Bu sadece bir kütüphane (javax.crypto) kullanıyor, ancak haklısınız - boş şifreler desteklenmiyor. Açık hale getirmek için bir istisna eklendi. Teşekkürler!
Martin Konicek

3
Muhtemelen char[] passwordbunun yerine imza yöntemlerini değiştirmeniz gerekir String password.
assylias

2
Her ne kadar referans oybirliğiyle anlaşma almıyor. Ayrıca bakınız: security.stackexchange.com/a/20369/12614
assylias

3
Dizelerde .equals () öğesinin kısa devre yapmadığından emin misiniz (yani: eşit olmayan iki bayt bulduğunda döngüyü durdur)? Bunu yaparsa, parola karması hakkında bilgi sızdırması riski vardır.
bobpoekert


7

Sen kullanabilirsiniz Shiro kütüphanenin (eski JSecurity ) uygulanmasını tarafından açıklanan şeyin OWASP .

Ayrıca JASYPT kütüphanesinin benzer bir yardımcı programı var gibi görünüyor .


Bu aslında ne kullanıyordum. Ancak Shiro'yu kullanmamaya karar verdiğimizden, tüm Shiro kütüphanesini tek bir pakete dahil etmek zorunda kalmama konusunda bazı endişeler vardı.
Chris Dutrow

Sadece bir şifre karma yardımcı programdan oluşan bir kütüphane bilmiyorum. Bağımlılıklar bir endişe ise, muhtemelen kendi başınıza dönmeniz daha iyidir. Erickson'ın cevabı bana oldukça iyi görünüyor. Ya da SHA'yı güvenli bir şekilde kullanmayı tercih ederseniz, referans verdiğim OWASP bağlantısından kodu kopyalayın.
laz

7

Karmaları kullanarak hesaplayabilirsiniz MessageDigest, ancak güvenlik açısından bu yanlıştır. Karmalar, kolayca kırılabildikleri için şifreleri saklamak için kullanılmazlar.

Parolalarınızı saklamak için bcrypt, PBKDF2 ve scrypt gibi başka bir algoritma kullanmalısınız. Buraya bakın .


3
Veritabanında tuz saklamadan şifreyi nasıl girersiniz?
ZZ Coder

9
Kullanıcı adını tuz olarak kullanmak ölümcül bir kusur değildir, ancak hiçbir yerde bir kriptografik RNG'den bir tuz kullanmak kadar iyi değildir. Ve tuzun veritabanında saklanması kesinlikle sorun değildir. Tuz gizli değildir.
erickson

1
Kullanıcı adı ve e-posta da veritabanında saklanmaz mı?
Chris Dutrow

@ZZ Coder, @erickson doğru, bir şekilde kolayca hesaplanabilen gökkuşağı tablosuna yol açacak tüm şifreler için bir tuz olacağını varsaydım.
Bozho

13
Kullanıcı adını (veya e-posta gibi başka bir kimliği) tuz olarak kullanmayla ilgili bir sorun, kullanıcının yeni bir şifre belirlemesine gerek kalmadan kimliği değiştirememenizdir.
Lawrence Dol

6

Ayrıca Bcrypt ve PBKDF2 diğer yanıtlar sözü, ben bakarak tavsiye ederim scrypt

MD5 ve SHA-1, nispeten hızlı oldukları için tavsiye edilmez, bu nedenle "saat başına kira" dağıtılmış bilgi işlem (örn. EC2) veya modern bir üst düzey GPU kullanılarak, kaba kuvvet / sözlük saldırılarını kullanarak parolaları nispeten düşük maliyetlerle ve makul şekilde "kırabilir" zaman.

Bunları kullanmanız gerekiyorsa, en azından algoritmayı önceden tanımlanmış önemli miktarda (1000+) tekrarlayın.


6

Cevap Erickson'a PBKDF2'nin cevap olduğuna tamamen katılıyorum .

Bu seçeneğe sahip değilseniz veya yalnızca bir karma kullanmanız gerekiyorsa, Apache Commons DigestUtils, JCE kodunu doğru yapmaktan çok daha kolaydır: https://commons.apache.org/proper/commons-codec/apidocs/org/apache /commons/codec/digest/DigestUtils.html

Bir karma kullanırsanız, sha256 veya sha512 ile gidin. Bu sayfa şifre işleme ve karma hakkında iyi tavsiyelere sahiptir (şifre işleme için karma işlemeyi önermediğini unutmayın): http://www.daemonology.net/blog/2009-06-11-cryptographic-right-answers.html


sadece sayı daha büyük olduğu için SHA512'nin SHA256'dan (bu amaç için) daha iyi olmadığını belirtmek gerekir.
19'da Azsgy

5

Sen kullanabilirsiniz Bahar Güvenlik Kripto (sadece sahiptir 2 opsiyonel derleme bağımlılıkları destekler), PBKDF2 , BCrypt , scrypt ve Argon2 şifre şifreleme.

Argon2PasswordEncoder argon2PasswordEncoder = new Argon2PasswordEncoder();
String aCryptedPassword = argon2PasswordEncoder.encode("password");
boolean passwordIsValid = argon2PasswordEncoder.matches("password", aCryptedPassword);
SCryptPasswordEncoder sCryptPasswordEncoder = new SCryptPasswordEncoder();
String sCryptedPassword = sCryptPasswordEncoder.encode("password");
boolean passwordIsValid = sCryptPasswordEncoder.matches("password", sCryptedPassword);
BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
String bCryptedPassword = bCryptPasswordEncoder.encode("password");
boolean passwordIsValid = bCryptPasswordEncoder.matches("password", bCryptedPassword);
Pbkdf2PasswordEncoder pbkdf2PasswordEncoder = new Pbkdf2PasswordEncoder();
String pbkdf2CryptedPassword = pbkdf2PasswordEncoder.encode("password");
boolean passwordIsValid = pbkdf2PasswordEncoder.matches("password", pbkdf2CryptedPassword);

4

NIST tavsiyesi PBKDF2'den daha önce bahsedilmiş olsa da , 2013'ten 2015'e kadar açık bir şifre karma yarışması olduğunu belirtmek isterim . Sonunda, önerilen şifre karma fonksiyonu olarak Argon2 seçildi.

Kullanabileceğiniz orijinal (yerel C) kitaplık için oldukça iyi kabul görmüş bir Java bağlaması vardır .

Ortalama kullanım durumunda, Argon2 üzerinden PBKDF2'yi seçerseniz veya bunun tersi olursa, güvenlik açısından önemli olduğunu düşünmüyorum. Güçlü güvenlik gereksinimleriniz varsa, değerlendirmenizde Argon2'yi göz önünde bulundurmanızı öneririz.

Parola karıştırma işlevlerinin güvenliği hakkında daha fazla bilgi için bkz. Security.se .


@zaph Cevabı daha objektif olacak şekilde düzenledim. NIST tavsiyesinin her zaman en iyi seçenek olmayabileceğini lütfen unutmayın ( bir örnek için buraya bakın ) - elbette bu, başka bir yerde önerilen herhangi bir şey için de geçerlidir. Bu yüzden bu cevabın bu soruya bir değer verdiğini düşünüyorum.
Qw3ry

2

Burada MD5 karma ve diğer karma yöntemler için iki bağınız var:

Javadoc API: https://docs.oracle.com/javase/1.5.0/docs/api/java/security/MessageDigest.html

Eğitim: http://www.twmacinta.com/myjava/fast_md5.php


3
Sadece şifre karma için yavaş daha iyi olduğunu unutmayın. Karma işlevinin binlerce yinelemesini "anahtar güçlendirme" tekniği olarak kullanmalısınız. Ayrıca, tuz şarttır.
erickson

Baytların uzunluğu hala aynı olacağından, bir kalite karma algoritmasının çoklu yinelemelerinin bir yineleme ile aynı güvenliği üreteceği izlenimi altındaydım.
Chris Dutrow

@ erickson Saldırganları açıkça yavaşlatmak daha iyi olur.
deamon

6
Anahtar güçlendirme hakkında: Önceden hesaplanmış karmaları kullanılamaz hale getirmek için tuzlar mevcuttur. Ancak saldırganların önceden hesaplamaları gerekmez. Saldırganlar sadece doğru olanı bulana kadar dizeleri + tuz "anında" hash olabilir. Ancak, karmalarınız için binlerce kez yinelerseniz, aynı şeyi yapmaları gerekecektir. Sunucunuz bu kadar sık ​​gerçekleşmediği için 10 bin yinelemeden fazla etkilenmeyecektir. Saldırganların bilgi işlem gücünün 10k katı gerekir.
zockman

2
@Simon bugün MD5, GPU kaba kuvvet / sözlük saldırıları kullanılarak saniyeler içinde kırılabildiği için parola karması için işe yaramaz olarak kabul edilir. Buraya bakın: codahale.com/how-to-safely-store-a-password
Eran Medan

1

Tüm standart karma şemaları arasında, LDAP ssha kullanımı en güvenli olanıdır,

http://www.openldap.org/faq/data/cache/347.html

Ben sadece orada belirtilen algoritmaları takip ediyorum ve karma yapmak için MessageDigest kullanın.

Tuzu, önerdiğiniz gibi veritabanınızda saklamanız gerekir.


1
SSHA karma işlevini yinelemediğinden çok hızlıdır. Bu, saldırganların şifreleri daha hızlı denemelerini sağlar. Bcrypt, PBBKDF1 ve PBKDF2 gibi daha iyi algoritmalar, saldırganları 8 harflik bir parola alanına bile zorlamadan önce parolanın süresinin dolması gereken noktaya yavaşlatmak için "anahtar güçlendirme" tekniklerini kullanır.
erickson

Tüm bu mekanizmaların sorunu, müşteri desteği alamamanızdır. Karma parola ile ilgili sorun, başka bir algoritma ile parola karma işlemini destekleyememenizdir. Ssha ile en azından tüm LDAP istemcileri destekliyor.
ZZ Coder

"En güvenli" değildir, sadece "oldukça uyumludur". bcrypt / scrypt kaynakların yoğunluğundan çok daha fazladır.
eckes

1

2020'den itibaren, kullanımdaki en güvenilir ve esnek algoritma,

herhangi bir donanım göz önüne alındığında gücünü en yüksek seviyeye getirmesi muhtemel olan,

olduğu Argon2id veya Argon2i .

Hedef karma süresi ve kullanılan donanım göz önüne alındığında optimize edilmiş güç parametrelerini bulmak için gerekli kalibrasyon aracını sağlar.

  • Argon2i açgözlü hashing konusunda uzmanlaşmış
  • Argon2d CPU açgözlü hash konusunda uzmanlaşmış
  • Argon2id her iki yöntemi de kullanır.

Bellek açgözlü karmaşası, çatlama için GPU kullanımına karşı yardımcı olacaktır.

Bahar güvenliği / Bouncy Castle uygulaması optimize edilmez ve saldırganın ne kullanabileceği göz önüne alındığında nispeten hafta. cf: Bahar belgeleri

Şu anda uygulamada parola kırıcıların kullanacağı paralellik / optimizasyonlardan faydalanmayan Bouncy kalesi kullanılıyor, bu nedenle saldırgan ve savunucu arasında gereksiz bir asimetri var.

Java için kullanılan en güvenilir uygulama mkammerer'ın ,

Rust ile yazılmış resmi yerel uygulamanın bir sargı kavanozu / kütüphanesi.

İyi yazılmış ve kullanımı basit.

Gömülü sürüm Linux, windows ve OSX için yerel derlemeler sağlar.

Örnek olarak, jpmorganchase tarafından Quorum , Ethereum kripto para birimi uygulaması için kullanılan tessera güvenlik projesinde kullanılmaktadır .

İşte tessera örnek kodu.

Kalibrasyon de.mkammerer.argon2.Argon2Helper # findIterations kullanılarak yapılabilir.

SCRYPT ve Pbkdf2 algoritması basit bir karşılaştırma ölçütü yazarak da kalibre edilebilir, ancak mevcut minimum güvenli yineleme değerleri daha yüksek karma süreleri gerektirecektir.


0

Ben udemy bir videodan eğildi ve daha güçlü rastgele şifre olarak düzenlenmiş

}

private String pass() {
        String passswet="1234567890zxcvbbnmasdfghjklop[iuytrtewq@#$%^&*" ;

        char icon1;
        char[] t=new char[20];

         int rand1=(int)(Math.random()*6)+38;//to make a random within the range of special characters

            icon1=passswet.charAt(rand1);//will produce char with a special character

        int i=0;
        while( i <11) {

             int rand=(int)(Math.random()*passswet.length());
             //notice (int) as the original value of Math>random() is double

             t[i] =passswet.charAt(rand);

             i++;
                t[10]=icon1;
//to replace the specified item with icon1
         }
        return new String(t);
}






}

Düzeltilmeye açıkım, ama hash ederken rastgele sayılar kullanmamalısınız. Böylece hash fonksiyonunuz deterministik kalır; bir dizeyi birden çok kez karma yaparsanız, o dizede her zaman aynı karma değerini alırsınız.
duldi
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.