1

パスワードを安全に保管するために、ハッシュアルゴリズムで使用するソルトを Java で生成しようとしています。次のコードを使用して、ランダム ソルトを作成しています。

private static String getSalt() throws NoSuchAlgorithmException {
    SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
    byte[] salt = new byte[16];
    sr.nextBytes(salt);
    System.out.println(salt.toString());
    return salt.toString();
}

私のハッシュアルゴリズムで使用するために、完全に安全でランダムに生成されたソルトを生成する必要があります。ただし、コードを実行すると、毎回同じソルトが出力され続けます...生成されるソルトがまったくランダムではないことを示しています。

明らかなセキュリティ上の理由から、各ユーザーには一意のソルトが必要ですが、新しいアカウントが作成されるたびにこのコードを使用すると、すべてのユーザーが同じソルトを持つことになり、そもそもそれを持つ目的が無効になります。

私の質問はこれです:なぜこれは私に同じソルトを与え続けるのですか?コードが実行されるたびに生成されるソルトが完全にランダムになるようにするにはどうすればよいですか?

編集:

修正され、適切に動作するハッシュプログラム全体のソースコードを含めたいと思いました。これは、アカウントの作成時にハッシュを生成し、システムにログインするときにパスワードをチェックすることをシミュレートする単純なプロトタイプです。

package hashingwstest;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Random;
import java.util.Scanner;


public class HashingWSTest {

    public static void main(String[] args) throws NoSuchAlgorithmException {
        Scanner sc = new Scanner(System.in);
        System.out.print("Enter Password: ");
        String passwordToHash = sc.nextLine();

        byte[] bytes = getBytes();
        String salt = new String(bytes);

        String securePassword = hash256(passwordToHash, salt);
        System.out.println("Hash successfully generated");

        System.out.print("Enter your password again: ");
        String checkPassword = sc.nextLine();
        String checkHash = hash256(checkPassword,salt);
        if (checkHash.equals(securePassword)) {
            System.out.println("MATCH");
        }
        else {
            System.out.println("NO MATCH");
        }
    }

    private static String hash256(String passwordToHash, String salt) {
        String generatedPassword = null;
        try {
            MessageDigest md = MessageDigest.getInstance("SHA-256");
            md.update(salt.getBytes());
            byte[] bytes = md.digest(passwordToHash.getBytes());
            StringBuilder sb = new StringBuilder();

            for (int i=0; i<bytes.length; i++) {
                sb.append(Integer.toString((bytes[i] & 0xff) + 0x100, 16).substring(1));
            }
            generatedPassword = sb.toString();
        }
        catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return generatedPassword;
    }

    private static byte[] getBytes() throws NoSuchAlgorithmException {
        SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
        byte[] bytes = new byte[16];
        sr.nextBytes(bytes);
        return bytes;
    }
}
4

4 に答える 4

2

salt.toStringバイト配列の内容を返していませんが、hashCode

リクエストごとに に置き換えると、sr.nextInt()異なる値が返されます。バイト配列の内容を印刷すると、違いに気付くでしょう

于 2015-01-28T12:37:30.477 に答える
0

の javadoc からjava.security.SecureRandom.getInstance(String):

返された SecureRandom オブジェクトはシードされていません。返されたオブジェクトをシードするには、setSeed メソッドを呼び出します。

したがって、明白な答えは を呼び出すことsetSeedです。ただし、シードは簡単に推測できるため、時間を使用するだけでは問題が発生する可能性があります。

別のアプローチは、安全なランダムインスタンスを共有することです(スレッドセーフであるため

于 2015-01-28T12:32:39.927 に答える
0

メソッドを使用できます

/**
 * Reseeds this random object, using the eight bytes contained
 * in the given <code>long seed</code>. The given seed supplements,
 * rather than replaces, the existing seed. Thus, repeated calls
 * are guaranteed never to reduce randomness.
 *
 * <p>This method is defined for compatibility with
 * <code>java.util.Random</code>.
 *
 * @param seed the seed.
 *
 * @see #getSeed
 */
public void setSeed(long seed)

現在時刻などを渡す

于 2015-01-28T12:32:54.610 に答える