
本文详解 aadhaar 纸质离线 e-kyc 规范中手机号哈希(m= 字段)的生成逻辑,基于 uidai 官方规则,使用 php 实现多层 sha-256 哈希计算,并提供可直接运行的代码、关键注意事项及验证方法。
本文详解 aadhaar 纸质离线 e-kyc 规范中手机号哈希(m= 字段)的生成逻辑,基于 uidai 官方规则,使用 php 实现多层 sha-256 哈希计算,并提供可直接运行的代码、关键注意事项及验证方法。
在 Aadhaar 纸质离线 e-KYC(Paperless Offline e-KYC)XML 文件中,用户手机号并非明文存储,而是以哈希值形式嵌入
对 MobileNumber + SharePhrase(即“手机号+授权口令”)执行 n 次嵌套 SHA-256 哈希,其中 n 等于 Aadhaar 号码最后一位数字;若末位为 0,则仅执行 1 次哈希。
注意:此处的 SharePhrase 即用户下载 XML 时设置的 4–8 位密码(也称 Passcode / XML Password),不是 Aadhaar 注册时的生物识别 PIN 或虚拟 ID 密码。
✅ PHP 实现代码(兼容 PHP 7.2+)
<?php
/**
* 生成 Aadhaar 离线 e-KYC 中手机号对应的哈希值 (m=)
* @param string $mobile 手机号(纯数字,10 位,如 "1234567890")
* @param string $sharePhrase XML 下载密码(如 "Lock@487" 或 "4567")
* @param string $aadhaarLastDigit Aadhaar 号末位数字(取自 RefID 字段最后 1 位,如 "3632" → '2')
* @return string 小写十六进制 SHA-256 哈希字符串
*/
function generateMobileHash(string $mobile, string $sharePhrase, string $aadhaarLastDigit): string
{
// 标准化输入:去除空格、确保末位为数字
$mobile = trim(preg_replace('/\D/', '', $mobile));
$aadhaarLastDigit = (string)abs((int)$aadhaarLastDigit[0]);
if (strlen($mobile) !== 10 || !ctype_digit($mobile)) {
throw new InvalidArgumentException('Mobile number must be exactly 10 digits.');
}
if (!is_numeric($aadhaarLastDigit) || strlen($aadhaarLastDigit) !== 1) {
throw new InvalidArgumentException('Aadhaar last digit must be a single digit (0–9).');
}
$input = $mobile . $sharePhrase;
$hash = hash('sha256', $input); // 第一次哈希
$iterations = (int)$aadhaarLastDigit;
if ($iterations === 0) {
$iterations = 1; // UIDAI 明确规定:末位为 0 时执行 1 次
}
for ($i = 1; $i < $iterations; $i++) {
$hash = hash('sha256', $hash);
}
return $hash;
}
// ✅ 示例调用(对应问题中的案例)
$mobile = '1234567890';
$sharePhrase = 'Lock@487';
$aadhaarRefId = '3632'; // RefID 字段(最后 4 位),取末位 '2'
$lastDigit = $aadhaarRefId[-1]; // PHP 7.1+ 支持负索引
$computedHash = generateMobileHash($mobile, $sharePhrase, $lastDigit);
echo "Computed m= hash: " . $computedHash . "\n";
// 输出应与 XML 中 <UidData m="..."> 的值完全一致(区分大小写,全小写)
?>⚠️ 关键注意事项
- SharePhrase 必须精确匹配:大小写、特殊字符(如 @, #)均敏感。用户下载 XML 时输入的密码必须原样传入,不可 URL 解码或 trim 空格(除非原始密码含空格)。
-
Aadhaar 末位取值来源是 RefID 字段:XML 文件根节点
的 refId 属性(格式如 XXXXXXXXXXXX3632),取其最后 1 位数字,而非整个 Aadhaar 号。 - 哈希次数 ≠ 末位数值 × 2:问题描述中 “Sha256(Sha256(...))*2” 是误读;正确逻辑是 嵌套调用 n 次 hash('sha256', $data),即 n 层 SHA-256,非乘法或拼接。
- 输出必须为小写十六进制:PHP hash() 默认返回小写,符合 XML 规范;若使用 sha256() 函数需手动转小写。
- 无盐值、无可逆性:该哈希为单向计算,仅用于比对 XML 中的 m= 值,不可反推手机号或口令。
? 验证建议
将生成的哈希值与离线 XML 文件中
立即学习“PHP免费学习笔记(深入)”;
<UidData a="XXXXXXXXXXXX" m="a7f8e9d0c1b2..."/>
若两者完全一致,则手机号哈希验证通过,表明用户提供的手机号与 SharePhrase 及 Aadhaar 末位逻辑吻合。
掌握此逻辑,开发者即可安全集成 Aadhaar 离线 KYC 的移动端身份核验能力,无需依赖网络或中心化服务,真正实现隐私优先的本地化验证。











