Android14 锁屏密码修改为至少6位

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字符串。

相关推荐
4***997420 小时前
Kotlin序列处理
android·开发语言·kotlin
t***D26420 小时前
Kotlin在服务端开发中的生态建设
android·开发语言·kotlin
wanhengidc20 小时前
云手机中都有哪些安全保护措施?
安全·智能手机
玲珑Felone21 小时前
flutter 状态管理--InheritedWidget、Provider原理解析
android·flutter·ios
BoomHe21 小时前
车载应用配置系统签名
android·android studio
路人甲ing..1 天前
用 Android Studio 自带的模拟 Android Emulator 调试
android·java·ide·ubuntu·kotlin·android studio
路人甲ing..1 天前
Android Studio 模拟器报错 The emulator process for AVD xxxxx has terminated.
android·java·ide·kotlin·android studio
弥巷1 天前
【Android】 View事件分发机制源码分析
android·java
wheeldown1 天前
【Linux】多线程核心速记:线程池 + 单例模式 + 线程安全 + 死锁 + 智能指针
linux·运维·服务器·安全·单例模式
编码小哥1 天前
IPSec 详细介绍
网络·tcp/ip·安全