java android 中的 PBKDF2 密码不匹配

PBKDF2 password mismatch in java android

我是 运行 第一次设置,用户创建密码并将其存储在 sharedpreferences 中(我理解这的含义)唯一的问题是当我 运行用户在登录页面输入的密码,总是会出现不同的密码,因此不会生效。

AFAIK 我正在根据 this 文章正确地对密码进行哈希处理,我乐于接受建议,但这让我发疯了,因为我已经在所有可能的地方调试了应用程序,而且我只能这样做。没看到错误

首次设置代码

package com.example.myapplication;
import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.content.SharedPreferences;
import android.database.sqlite.SQLiteDatabase;
import android.os.Build;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import java.nio.charset.StandardCharsets;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.KeySpec;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;

public class FirstTimeActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //reset login
        SharedPreferences pref = getApplicationContext().getSharedPreferences("DocStorage Preferences", MODE_PRIVATE);
        SharedPreferences.Editor editor = pref.edit();
        editor.remove("isFirstTime");
        editor.remove("PasswordHash");
        editor.commit();

        //message view box
    }

    @RequiresApi(api = Build.VERSION_CODES.KITKAT)
    public void attemptFirstTimeSetup(View v) throws InvalidKeySpecException, NoSuchAlgorithmException {
        if (((CheckBox)findViewById(R.id.riskCheckBox)).isChecked()){

            if (TextUtils.isEmpty(((EditText)findViewById(R.id.SetPassword)).getText().toString()))
            {
                ((EditText)findViewById(R.id.SetPassword)).setError("Can't be blank!");
            }
            else {
                String passwordtopass = ((EditText)findViewById(R.id.SetPassword)).getText().toString();
                String hashedpassword = PBKDF2_Encrypt(passwordtopass);
                SharedPreferences pref = getApplicationContext().getSharedPreferences("DocStorage Preferences", MODE_PRIVATE);
                SharedPreferences.Editor editor = pref.edit();
                editor.putString("isFirstTime","No");
                editor.putString("PasswordHash",hashedpassword);
                editor.commit();

                Intent backToMain = new Intent(this, LoginActivity.class);
                startActivity(backToMain);
            }
        }
        else {
            Toast.makeText(this, "Please check read and check the checkbox before continuing!", Toast.LENGTH_SHORT).show();
        }
    }
   
    @RequiresApi(api = Build.VERSION_CODES.KITKAT)
    public String PBKDF2_Encrypt(String password) throws NoSuchAlgorithmException, InvalidKeySpecException {
        //salting
        SecureRandom random = new SecureRandom();
        byte[] salt = new byte[16];
        random.nextBytes(salt);

        //
        KeySpec spec = new PBEKeySpec(password.toCharArray(), salt, 65536, 128);
        SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
        byte[] hash = factory.generateSecret(spec).getEncoded();
        String finalString = new String(hash, StandardCharsets.UTF_8);
        return finalString;
    }
}

登录activity代码

package com.example.myapplication;
import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Build;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import java.nio.charset.StandardCharsets;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.KeySpec;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;

public class LoginActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_login);
        setTitle("Login page");

        SharedPreferences pref = getApplicationContext().getSharedPreferences("DocStorage Preferences", MODE_PRIVATE);
        String firstTimeCheck = pref.getString("isFirstTime", "Yes");

        if (firstTimeCheck.equals("Yes")) {
            Intent firstTimeActivityIntent = new Intent(this, FirstTimeActivity.class);
            startActivity(firstTimeActivityIntent);
        } else {}
    }

    @RequiresApi(api = Build.VERSION_CODES.KITKAT)
    public void AttemptLogin(View v) throws InvalidKeySpecException, NoSuchAlgorithmException {
        SharedPreferences pref = getApplicationContext().getSharedPreferences("DocStorage Preferences", MODE_PRIVATE);
        String SavedPasswordHash = pref.getString("PasswordHash", "nothing here yet!");

        String passwordtopass2 = ((EditText)findViewById(R.id.passwordtext)).getText().toString();
        String loginPassword = PBKDF2_Encrypt(passwordtopass2);

        if (TextUtils.isEmpty(((EditText) findViewById(R.id.passwordtext)).getText().toString())) {
            ((EditText) findViewById(R.id.passwordtext)).setError("Can't be blank!");
        }
        else {
            if (loginPassword.equals(SavedPasswordHash)) {
                Toast.makeText(this, "Password is correct!", Toast.LENGTH_SHORT).show();

                Intent forwardToMain = new Intent(this, MainActivity.class);
                startActivity(forwardToMain);
            } else {
                Toast.makeText(this, "Password is incorrect!", Toast.LENGTH_SHORT).show();
            }
        }
    }

    @RequiresApi(api = Build.VERSION_CODES.KITKAT)
    public String PBKDF2_Encrypt(String password) throws NoSuchAlgorithmException, InvalidKeySpecException {
        //salting
        SecureRandom random = new SecureRandom();
        byte[] salt = new byte[16];
        random.nextBytes(salt);

        //
        KeySpec spec = new PBEKeySpec(password.toCharArray(), salt, 65536, 128);
        SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
        byte[] hash = factory.generateSecret(spec).getEncoded();
        String finalString = new String(hash, StandardCharsets.UTF_8);
        return finalString;
    }
}

对于我的特定部分。每次是 运行 random.nextBytes() 代码都是 运行 这是随机化输出,这意味着它们在输入验证时永远不会匹配。删除它有效。

random.nextBytes(salt);