Android14 锁屏密码修改为至少6位
一、前言
最近在搞欧盟 EN18031 无线安全认证,需要优化系统安全。
其实目前还不知道具体需要啥优化,无非是加密和安全那些;
如果是自己的应用保存的密码,进行加密保存就行;
目前认证方提示锁屏密码可以加强,其实这个在EN18031草案好像是建议优化并非强制;
还得做点啥吧,所以最近分析实现了Android原生的锁屏密码修改为至少6位的实现。
Android锁屏密码、pin码、图案密码,默认都是最少四位;
锁屏密码和pin码锁屏的区别:pin码使能是0-9数值,普通锁屏密码可以任意字母+数值。
如果需要修改为最少6位,只要修改两个地方就行了。
看起来很简单,实际需要详细分析Settings锁屏逻辑,最后是修改framework的默认定义。
修改效果:
目前网上搜索的知识和AI的实现都是不行的。
网上的建议修改:
frameworks/base/core/java/android/app/admin/DevicePolicyManager.java
// 修改设备策略中的最小密码长度默认值
public static final int DEFAULT_PASSWORD_MIN_LENGTH = 6; // 原值为4
frameworks/base/core/java/com/android/internal/widget/LockPatternUtils.java
// 同时修改PIN码最小长度的常量定义
public static final int MIN_PASSWORD_LENGTH = 6; // 原值为4
public static final int MAX_PASSWORD_LENGTH = 16; // 保持不变
frameworks/base/packages/Settings/src/com/android/settings/password/ChooseLockPassword.java
// 修改密码输入提示文本
private void updatePasswordHint() {
// 原提示:mPasswordEntry.setHint(getString(R.string.password_quality_hint, 4));
mPasswordEntry.setHint(getString(R.string.password_quality_hint, 6));
}
// 修改密码长度验证错误提示
private boolean validatePassword(String password) {
if (password.length() < 6) {
// 原提示:mPasswordEntry.setError(getString(R.string.password_too_short, 4));
mPasswordEntry.setError(getString(R.string.password_too_short, 6));
return false;
}
return true;
}
看起来挺容易的,并且比较可行,但是在Android13、14 源码里面的同样的类找不到这些方法和变量。
所以需要实现这个功能还得具体代码分析,本文简单分析一下具体实现和过程。
这种问题基本没啥人修改和研究,这里简单记录下。
二、修改Android14 锁屏密码修改为至少6位分析实现代码
先说实现代码,因为有些人可能不想看具体分析过程。
1、实现代码
framework\base\core\java\com\android\internal\widget\LockPatternUtils.java
/**
* Utilities for the lock pattern and its settings.
*/
public class LockPatternUtils {
private static final String TAG = "LockPatternUtils";
/**
* The minimum number of dots in a valid pattern.
*/
- public static final int MIN_LOCK_PATTERN_SIZE = 4;
+ public static final int MIN_LOCK_PATTERN_SIZE = 6;
/**
* The minimum size of a valid password.
*/
- public static final int MIN_LOCK_PASSWORD_SIZE = 4;
+ public static final int MIN_LOCK_PASSWORD_SIZE = 6;
...
}
上面两个的修改分别就是对于锁屏图片和锁屏密码、pin码的位数。
就是这么简单,但是过程需要时间分析。
2、修改过程分析
有AI搜的关键字一个都没有,大概看了下这里看起来有点关系。
public class IccLockSettings extends SettingsPreferenceFragment ... {
private static final int MIN_PIN_LENGTH = 4; //修改为6
private static final int MAX_PIN_LENGTH = 8;
}
测试了一下不行,搜索后才发现Icc是sim卡管理作用的,和锁屏没啥关系。
所以只能一步步分析了。
(1)找到界面对应的代码
正常界面如下:
Settings应用代码,res\zh-rCh文件夹找到字符串:
<string name="lockpassword_pin_too_short_autoConfirm_extra_message" msgid="3271351502900762571">"{count,plural, =1{PIN 码必须至少包含 # 位数,不过为提高安全性,建议使用 {minAutoConfirmLen} 位数的 PIN 码}other{PIN 码必须至少为 # 位数,不过为提高安全性,建议使用 {minAutoConfirmLen} 位数的 PIN 码}}"</string>
找到 lockpassword_pin_too_short_autoConfirm_extra_message 字符串的Java代码:
Settings\src\com\android\settings\password\ChooseLockPassword.java
所以主要判断逻辑估计就在 ChooseLockPassword 这个类里面的了。
找到那里定义4的地方就可以了!?
(2) ChooseLockPassword.java 简单分析
public class ChooseLockPassword extends SettingsActivity {
private static final String TAG = "ChooseLockPassword";
public static class ChooseLockPasswordFragment extends InstrumentedFragment...{
private static final int MIN_AUTO_PIN_REQUIREMENT_LENGTH = 6;
...
//1、锁屏相关的布局
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.choose_lock_password, container, false);
}
}
//2、这里是收集各种输入异常的集合
String[] convertErrorCodeToMessages() {
List<String> messages = new ArrayList<>();
//3、遍历所有异常提示
for (PasswordValidationError error : mValidationErrors) {
switch (error.errorCode) {
case CONTAINS_INVALID_CHARACTERS:
messages.add(getString(R.string.lockpassword_illegal_character));
break;
...
case TOO_SHORT: //4、输入太短
String message = StringUtil.getIcuPluralsString(getContext(),
error.requirement,
mIsAlphaMode
? R.string.lockpassword_password_too_short
: R.string.lockpassword_pin_too_short);
if (LockPatternUtils.isAutoPinConfirmFeatureAvailable()
&& !mIsAlphaMode
&& error.requirement < MIN_AUTO_PIN_REQUIREMENT_LENGTH) {
Map<String, Object> arguments = new HashMap<>();
arguments.put("count", error.requirement); //5、这里应该是4 !
arguments.put("minAutoConfirmLen", MIN_AUTO_PIN_REQUIREMENT_LENGTH); // 6、这里是数值 6
message = StringUtil.getIcuPluralsString(getContext(),
arguments,
R.string.lockpassword_pin_too_short_autoConfirm_extra_message);
}
messages.add(message);//7、PIN 码必须至少包含4个字符串...的提示语
break;
...
return messages.toArray(new String[0]);
}
//8、所以关键是找到 mValidationErrors 错误列表里面的 error.requirement的数值
//下面这个方法是ChooseLockPasswordFragment 的验证输入代码逻辑
//密码输入框EditText每次输入都会调用这里,检测密码是否符合要求
//LockscreenCredential 对象已经封装了密码数据
boolean validatePassword(LockscreenCredential credential) {
final byte[] password = credential.getCredential();
//9、最关键的判断:PasswordMetrics.validatePassword
mValidationErrors = PasswordMetrics.validatePassword(
mMinMetrics, mMinComplexity, !mIsAlphaMode, password);
//这个基本不会进入!
if (mValidationErrors.isEmpty() && mLockPatternUtils.checkPasswordHistory(
password, getPasswordHistoryHashFactor(), mUserId)) {
mValidationErrors =
Collections.singletonList(new PasswordValidationError(RECENTLY_USED));
}
//10、符合要求返回返回 isEmpty() true?
//因为这里是收集异常信息啊,没有异常表示输入的符合要求!
return mValidationErrors.isEmpty();
}
//重点追第九点。
}
(3)PasswordMetrics.java
framework/base/core/java/android/app/admin/PasswordMetrics.java
这个类主要作用是: 密码复杂度量化评估 。
import static com.android.internal.widget.LockPatternUtils.MIN_LOCK_PASSWORD_SIZE; //关键哦
public final class PasswordMetrics implements Parcelable {
private static final String TAG = "PasswordMetrics";
...
//1、这里主要就是收集一个错误信息的列表并返回
public static List<PasswordValidationError> validatePassword(
PasswordMetrics adminMetrics, int minComplexity, boolean isPin, byte[] password) {
if (hasInvalidCharacters(password)) { //2、非法字符
return Collections.singletonList(
new PasswordValidationError(CONTAINS_INVALID_CHARACTERS, 0));
}
final PasswordMetrics enteredMetrics = computeForPasswordOrPin(password, isPin);
return validatePasswordMetrics(adminMetrics, minComplexity, enteredMetrics);
}
/**
* Validates password metrics against minimum metrics and complexity
*
* @param adminMetrics - minimum metrics to satisfy admin requirements.
* @param minComplexity - minimum complexity imposed by the requester. //3、最短要求
* @param actualMetrics - metrics for password to validate.
* @return a list of password validation errors.
An empty list means the password is OK. //4、如果列表为空,表示就是输入符合要求
*
* TODO: move to PasswordPolicy
*/
public static List<PasswordValidationError> validatePasswordMetrics(
PasswordMetrics adminMetrics, int minComplexity, PasswordMetrics actualMetrics) {
final ComplexityBucket bucket = ComplexityBucket.forComplexity(minComplexity);
// Make sure credential type is satisfactory.
// TODO: stop relying on credential type ordering.
if (actualMetrics.credType < adminMetrics.credType
|| !bucket.allowsCredType(actualMetrics.credType)) {
return Collections.singletonList(new PasswordValidationError(WEAK_CREDENTIAL_TYPE, 0));
}
...
//5、创建错误列表集
final ArrayList<PasswordValidationError> result = new ArrayList<>();
if (actualMetrics.length > MAX_PASSWORD_LENGTH) {
result.add(new PasswordValidationError(TOO_LONG, MAX_PASSWORD_LENGTH));
}
final PasswordMetrics minMetrics = applyComplexity(adminMetrics,
actualMetrics.credType == CREDENTIAL_TYPE_PIN, bucket);
// Clamp required length between maximum and minimum valid values.
//设置字符串最大长度和最小长度的要求,MAX_PASSWORD_LENGTH =16
//6、MIN_LOCK_PASSWORD_SIZE = 4 ,这个就是我们需要修改的默认值
minMetrics.length = Math.min(MAX_PASSWORD_LENGTH,
Math.max(minMetrics.length, MIN_LOCK_PASSWORD_SIZE));
minMetrics.removeOverlapping();
//7、字符串长度对比
comparePasswordMetrics(minMetrics, bucket, actualMetrics, result);
return result;
}
}
从上面MIN_LOCK_PASSWORD_SIZE 导入的位置,就可以确定最小长度的定义的代码在 LockPatternUtils
(4)LockPatternUtils.java
LockPatternUtils
是 Android 系统中负责管理锁屏安全相关功能的核心工具类;
主要处理图案锁、PIN 码、密码等锁屏方式的验证、存储、设置及状态管理;
是连接锁屏界面与系统安全策略的关键组件。
framework\base\core\java\com\android\internal\widget\LockPatternUtils.java
/**
* Utilities for the lock pattern and its settings.
*/
public class LockPatternUtils {
private static final String TAG = "LockPatternUtils";
private static final boolean FRP_CREDENTIAL_ENABLED = true;
//定义最小锁屏密码的地方
/**
* The minimum number of dots in a valid pattern.
*/
public static final int MIN_LOCK_PATTERN_SIZE = 4;
/**
* The minimum size of a valid password.
*/
public static final int MIN_LOCK_PASSWORD_SIZE = 4;
/**
* The minimum number of dots the user must include in a wrong pattern attempt for it to be
* counted.
*/
public static final int MIN_PATTERN_REGISTER_FAIL = MIN_LOCK_PATTERN_SIZE;
}
一顿分析后,最后修改这里就OK了。
三、其他
1、修改Android14 锁屏密码修改为至少6位分析实现代码小结
具体分析过程是从Settings应用一路分析到framework 的LockPatternUtils.java
最后把下面这两个地方修改为6 就可以了。
framework\base\core\java\com\android\internal\widget\LockPatternUtils.java
/**
* The minimum number of dots in a valid pattern.
*/
public static final int MIN_LOCK_PATTERN_SIZE = 4;
/**
* The minimum size of a valid password.
*/
public static final int MIN_LOCK_PASSWORD_SIZE = 4;
2、只是把4修改成6,Settings中显示的锁屏字符串提示需要修改吗?
其实不用修改,至于为啥?
有兴趣的可以自行看看Settings中判断messageh和PasswordMetrics.comparePasswordMetrics提示字符串的地方。
修改前后效果对比:
pin码效果:
密码设置和这个差不多,就不展示了。
图案锁屏设置效果:
系统代码已经有完善判断,不需要再额外适配修改Settings res字符串。