深入理解Android M 锁屏密码存储方式

发布时间 - 2026-01-11 00:39:27    点击率:

Android M 之前锁屏密码的存储

在 Android M 之前,锁屏密码的存储格式很简单,其使用了 64 位随机数作为 salt 值,此 salt 值被存储在 SQLite 数据库 /data/system/locksettings.db 中。密码在存储的时候,会将输入的密码加上此随机数组成新的字符串。然后对新的字符串分别进行 SHA-1 和 MD5 加密,将加密后的密文通过 MD5 + SHA-1 的方式进行字符串拼接,组成新的密文存储在 /data/system/password.key 中,共有 72 位。其加密后的形式如下:

/data/system # cat password.keyB40C2F6FE4E89F3386D4E689B135304410D64951914FB35770FDAC58B694177B29297A80

而密码的详细信息,存储在 /data/system/device_policies.xml 中,内容类似如下:

/data/system # cat device_policies.xml

其中主要用到的两个字段 quality 是密码的类型,简单密码和复杂密码的值不同,length 是密码的长度,其他字段存储密码中各种字符的数量。

Android M 中锁屏密码的存储

在 Android M 中,锁屏密码的存储格式发生了变化,其默认的存储格式在/system/gatekeeper/include/gatekeeper/password_handle.h 中描述如下:

typedef uint64_t secure_id_t;typedef uint64_t salt_t;/** * structure for easy serialization * and deserialization of password handles. */static const uint8_t HANDLE_VERSION = 2;struct __attribute__ ((__packed__)) password_handle_t {  // fields included in signature  uint8_t version;  secure_id_t user_id;  uint64_t flags;  // fields not included in signature  salt_t salt;  uint8_t signature[32];  bool hardware_backed;};

其中 version 默认是 2,user_id 是 Android 用户 id ,signature 存储的便是密文,hardware_backed 存储的是加密方式,0 表示密文是软件加密,而 1 表示密文是通过 TEE 环境进行加密得到的。

密码加密后默认以 password_handle_t 格式存储在/data/system/gatekeeper.password.key 中。密码的生成和校验,在 HAL 层是通过 system/core/gatekeeperd/gatekeeperd.cpp 中的函数实现的。其在系统启动时被注册为 gatekeeperd 服务,服务在启动的时候会调用 GateKeeperProxy()对象,此类的构造函数会去查找 TEE module,如果找到,则通过 TEE 设备进行加解密,如果没有找到,则通过一个软件设备进行加解密。

这里主要分析下通过软甲设备解密的逻辑。解密时,会调用到system/core/gatekeeperd/gatekeeperd.cpp 中的以下函数:

int verify(uint32_t uid, const uint8_t *enrolled_password_handle,      
uint32_t enrolled_password_handle_length,      
const uint8_t *provided_password, uint32_t provided_password_length,      
bool *request_reenroll)

在此函数中,由于没有使用 TEE,所以会调用到软件设备验证 system/core/gatekeeperd/SoftGateKeeperDevice.cpp 中的:

int SoftGateKeeperDevice::verify(uint32_t uid,  
uint64_t challenge, const uint8_t *enrolled_password_handle,  
uint32_t enrolled_password_handle_length, const uint8_t *provided_password,  
uint32_t provided_password_length, uint8_t **auth_token, uint32_t *auth_token_length,  
bool *request_reenroll)

函数进行校验,此函数对传进来的信息进行处理后交到system/gatekeeper/gatekeeper.cpp 中的

void GateKeeper::Verify(const VerifyRequest &request, VerifyResponse *response)

进行处理,在这里对参数进行一系列处理和重新组织后再交给

bool GateKeeper::DoVerify(const password_handle_t *expected_handle, const SizedBuffer &password)

进行校验,在此函数中,再调用

bool GateKeeper::CreatePasswordHandle(SizedBuffer *password_handle_buffer, salt_t salt,  
secure_id_t user_id, uint64_t flags, uint8_t handle_version, const uint8_t *password,  
uint32_t password_length)

将上面提到的 /data/system/gatekeeper.password.key

文件中存储的信息进行解析,然后调用

ComputePasswordSignature(password_handle->signature, sizeof(password_handle->signature),      
password_key, password_key_length, to_sign, sizeof(to_sign), salt);

函数将输入的密码进行加密,从这里可以看到,输入的密码要加密成密文只需要用到存储的密码中的 salt 值,此函数在system/core/gatekeeperd/SoftGateKeeper.h 中,其调用 crypto 库中的

crypto_scrypt(password, password_length, reinterpret_cast(&salt),    
sizeof(salt), N, r, p, signature, signature_length);

将输入的密码存储在 signature 中并返回。此函数最终会通过 SHA256 进行加密,参数中的 N, r, p 默认为如下值:

static const uint64_t N = 16384;static const uint32_t r = 8;static const uint32_t p = 1;

通过以上处理后对输入的密码加密后得到的密文与手机中存储的密文进行比较后返回校验结果,从而判断输入的密码的正确与否。

在 Android M 中,改变了之前直接在 Java 层进行密码校验的方式,将密码的校验通过 HAL 层的服务进行处理,同时加入对 TEE 的支持,使得锁屏密码的安全性大大提升,同时也可以方便的支持其他的安全特性,提升了整个系统的安全性。

以上这篇深入理解Android M 锁屏密码存储方式就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持。


# android  # 锁屏密码  # Android手势密码--设置和校验功能的实现代码  # Android 快速使用正则表达式  # 校验身份证号的实例  # android 关于利用签名的SHA1进行安全校验的方法之一(推荐)  # Android调用密码锁屏校验的流程代码详解  # 在此  # 给大家  # 的是  # 加解密  # 随机数  # 在这  # 其他的  # 希望能  # 很简单  # 如果没有  # 可以看到  # 此类  # 只需要  # 这篇  # 会去  # 会将  # 成新  # 小编  # 启动时  # 大家多多 


相关栏目: 【 网站优化151355 】 【 网络推广146373 】 【 网络技术251813 】 【 AI营销90571


相关推荐: 如何在服务器上三步完成建站并提升流量?  uc浏览器二维码扫描入口_uc浏览器扫码功能使用地址  重庆市网站制作公司,重庆招聘网站哪个好?  Laravel如何从数据库删除数据_Laravel destroy和delete方法区别  logo在线制作免费网站在线制作好吗,DW网页制作时,如何在网页标题前加上logo?  如何在 Pandas 中基于一列条件计算另一列的分组均值  Python函数文档自动校验_规范解析【教程】  Laravel如何实现模型的全局作用域?(Global Scope示例)  什么是javascript作用域_全局和局部作用域有什么区别?  瓜子二手车官方网站在线入口 瓜子二手车网页版官网通道入口  Laravel Telescope怎么调试_使用Laravel Telescope进行应用监控与调试  三星网站视频制作教程下载,三星w23网页如何全屏?  如何用y主机助手快速搭建网站?  在线制作视频的网站有哪些,电脑如何制作视频短片?  敲碗10年!Mac系列传将迎来「触控与联网」双革新  使用spring连接及操作mongodb3.0实例  如何快速选择适合个人网站的云服务器配置?  Laravel中Service Container是做什么的_Laravel服务容器与依赖注入核心概念解析  Python制作简易注册登录系统  Laravel如何处理文件下载请求?(Response示例)  Laravel软删除怎么实现_Laravel Eloquent SoftDeletes功能使用教程  如何用PHP工具快速搭建高效网站?  如何在万网自助建站中设置域名及备案?  如何用腾讯建站主机快速创建免费网站?  如何在阿里云虚拟主机上快速搭建个人网站?  Laravel如何配置和使用缓存?(Redis代码示例)  Windows10如何更改计算机工作组_Win10系统属性修改Workgroup  Laravel如何自定义错误页面(404, 500)?(代码示例)  音响网站制作视频教程,隆霸音响官方网站?  网站制作怎么样才能赚钱,用自己的电脑做服务器架设网站有什么利弊,能赚钱吗?  ai格式如何转html_将AI设计稿转换为HTML页面流程【页面】  如何自定义safari浏览器工具栏?个性化设置safari浏览器界面教程【技巧】  如何在阿里云购买域名并搭建网站?  Linux网络带宽限制_tc配置实践解析【教程】  黑客如何通过漏洞一步步攻陷网站服务器?  javascript中对象的定义、使用以及对象和原型链操作小结  如何在橙子建站中快速调整背景颜色?  头像制作网站在线观看,除了站酷,还有哪些比较好的设计网站?  如何撰写建站申请书?关键要点有哪些?  JavaScript中如何操作剪贴板_ClipboardAPI怎么用  桂林网站制作公司有哪些,桂林马拉松怎么报名?  Laravel如何发送邮件_Laravel Mailables构建与发送邮件的简明教程  Laravel如何处理CORS跨域问题_Laravel项目CORS配置与解决方案  原生JS实现图片轮播切换效果  高防服务器租用如何选择配置与防御等级?  Bootstrap整体框架之CSS12栅格系统  Python高阶函数应用_函数作为参数说明【指导】  PHP怎么接收前端传的文件路径_处理文件路径参数接收方法【汇总】  如何为不同团队 ID 动态生成多个非值班状态按钮  如何用PHP快速搭建高效网站?分步指南