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);
我是 运行 第一次设置,用户创建密码并将其存储在 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);