用免费开放的华为安全检测功能,评估App运行设备安全
前言
系统完整性检测,是App需具备的一个实用功能。我们都知道,在系统不完整的手机上,例如被root过,运行App将面临被恶意攻击、窃取隐私等威胁,尤其是商城类App,购买环节的环境安全性至关重要,因此在App中增加能快速检测手机系统风险的功能必不可少。
这一重要功能目前是免费,其基本的技术原理是,App集成华为HMS Core的SDK,调用免费提供的安全检测服务,在TEE可信执行环境中评估,得到的检测结果经过X.509数字证书签名,双重保障下,检测到的结果真实可信、不会被恶意更改~
功能运行起来的效果:
以下是开发过程,分享给大家。
开发前准备
1.1 Android studio安装
还没装开发工具的小伙伴下载指路:Android studio官网下载
1.2 在AppGallery Connect中配置相关信息
在开发应用前,需在AppGallery Connect中配置相关信息。具体操作步骤
1.3 配置华为maven仓地址
打开Android Studio项目级“build.gradle”文件:
添加HUAWEI agcp插件以及Maven代码库:
- 在“buildscript > repositories”中配置HMS Core SDK的Maven仓地址。
- 在“allprojects > repositories”中配置HMS Core SDK的Maven仓地址。
- 如果App中添加了“agconnect-services.json”文件则需要在“buildscript > dependencies”中增加agcp配置。
buildscript {repositories {google()jcenter()// 配置HMS Core SDK的Maven仓地址。maven {url 'https://developer.huawei.com/repo/'}}dependencies {...// 增加agcp配置。classpath 'com.huawei.agconnect:agcp:1.4.2.300'}
}allprojects {repositories {google()jcenter()// 配置HMS Core SDK的Maven仓地址。maven {url 'https://developer.huawei.com/repo/'}}
}
这里需要说明的是,Maven仓地址只能在IDE中配置。需要添加多个Maven代码库的话,将华为公司的Maven仓地址配置在最后哦。
1.4 添加编译依赖
打开应用级的“build.gradle”文件:
在文件头apply plugin: 'com.android.application'下一行添加如下配置:
apply plugin: 'com.huawei.agconnect'
在“dependencies”中添加如下编译依赖:
dependencies {implementation 'com.huawei.hms:safetydetect:5.0.5.302'
}
1.5 配置混淆脚本
如果你自己开发时要用到AndResGuard,那就还需要在应用级的“build.gradle”文件中加入AndResGuard允许清单,代码可以参考官网的混淆配置。
代码开发
2.1 创建SafetyDetectClient 并生成nonce值
这里的nonce值会被包含在后面的检测结果里,我们要通过校验nonce值,来确定返回结果是对应我们的请求的、没有被重放攻击。要注意nonce值需满足:
l 一个nonce值只能被使用一次;
l 长度在16~66字节间;
l 建议从发送到您的服务器的数据中派生nonce值。
2.2 请求系统完整性检测接口
1) SysIntegrity API有两个参数:第1个参数是nonce值,可以从上一步骤获取;第2个参数是appid,可以从agconnect-services.json 文件中读取:
Ø 登录AppGallery Connect网站,-点击“我的项目”。
Ø 在项目列表中找到您的项目,在项目中点击需要配置签名证书指纹的应用。
Ø 在“项目设置 > 常规” > “应用”,可以查看。
2) 这里设定的是,用户在购买会员时,调用系统完整性检测接口,以检测支付环境是否存在风险。实际编码中,在MemberCenterAct.java类中的列表点击事件处理方法,调用SafetyDetectUtil 类的detectSysIntegrity的接口,具体代码:
private void onAdapterItemClick(int position) {// 调用系统完整性检测接口以检测支付环境风险SafetyDetectUtil.detectSysIntegrity(this, new ICallBack<Boolean>() {@Overridepublic void onSuccess(Boolean baseIntegrity) {if (baseIntegrity) {// 系统完整性未遭到破坏,可以继续购买buy(productInfo);} else {// 系统完整性遭到破坏,弹出提示框,来提醒用户,并让用户选择是否继续showRootTipDialog(productInfo);}}…});
}
3) 在商场App中,把系统完整性检测接口的调用放到SafetyDetectUtil.java这个工具类中来实现,封装在detectSysIntegrity的方法中,具体示例代码如下:
public static void detectSysIntegrity(final Activity activity, final ICallBack<? super Boolean> callBack) {// 生成 nonce值byte[] nonce = ("Sample" + System.currentTimeMillis()).getBytes(StandardCharsets.UTF_8); // 从app目录下的agconnect-services.json文件中读取app_id字段String appId = AGConnectServicesConfig.fromContext(activity).getString("client/app_id");// 获取 Safety Detect 服务客户端,调用sysIntegrity API,并添加成功事件监听
SysIntegrityRequest sysintegrityrequest = new SysIntegrityRequest();sysintegrityrequest.setAppid(appId);sysintegrityrequest.setNonce(nonce);//PS256 or RS256sysintegrityrequest.setAlg("RS256"); Task task = mClient.sysIntegrity(sysintegrityrequest);task.addOnSuccessListener(new OnSuccessListener<SysIntegrityResp>() {@Overridepublic void onSuccess(SysIntegrityResp response) {//Safety Detect 服务接口成功响应。可以通过 SysIntegrityResp 类的 getResult 方法来获取检测结果String jwsStr = response.getResult();
VerifyResultHandler verifyResultHandler = new VerifyResultHandler(jwsStr, callBack);//将检测结果发送至开发者的服务器进行验证verifyJws(activity, jwsStr, verifyResultHandler);}});
}
4) 这里在verifyJws 方法中请求App Server的相关接口,来对检测结果进行验证。这个方法的第3个参数是一个 VerifyResultHandler 类对象, 它实现了一个回调接口,以便在服务器验证结束后,对返回的结果进行后续的处理。接下来介绍如何在App Server中验证检测结果。
2.3 在App Server中验证检测结果
App在获得TSMS Server返回的检测结果后,将其发送到App Server,由App Server使用HUAWEI CBG根证书来对结果中的签名和证书链进行校验,从而确认本次系统完整性检测结果是否有效。
App Server侧读取证书并验证 JWS 字符串的示例代码如下:
1) 解析 JWS字符串,获取其中的 header、payload和signature
public JwsVerifyResp verifyJws(JwsVerifyReq jwsVerifyReq) {// 获取端侧发送到服务器侧的jws信息String jwsStr = jwsVerifyReq.getJws(); // 解析JWS, 分段, 该JWS固定为三段,使用"."号分隔String[] jwsSplit = jwsStr.split("\\."); try {// 解析JWS, Base64解码, 并构造JWSObjectJWSObject jwsObject = new JWSObject(new Base64URL(jwsSplit[0]), new Base64URL(jwsSplit[1]), new Base64URL(jwsSplit[2]));// 验证JWS并设置验证结果boolean result = VerifySignatureUtil.verifySignature(jwsObject);
// 服务器侧检测结果验证响应消息体JwsVerifyResp jwsVerifyResp = new JwsVerifyResp(); jwsVerifyResp.setResult(result);} catch (ParseException | NoSuchAlgorithmException e) {RUN_LOG.catching(e);}return jwsVerifyResp;
}
2) 这里使用VerifySignatureUtil工具类中的verifySignature方法完成相关信息的验证,包括JWS签名算法、证书链、签名证书主机名、JWS签名等,示例代码:
public static boolean verifySignature(JWSObject jws) throws NoSuchAlgorithmException {JWSAlgorithm jwsAlgorithm = jws.getHeader().getAlgorithm();// 1. 验证JWS签名算法if ("RS256".equals(jwsAlgorithm.getName())) {// 进行证书链校验,并根据签名算法获取 Signature 类实例,用来验证签名return verify(Signature.getInstance("SHA256withRSA"), jws);}return false;
}
private static boolean verify(Signature signature, JWSObject jws) {// 提取JWS头部证书链信息, 并转换为合适的类型, 以便进行后续操作X509Certificate[] certs = extractX509CertChain(jws);// 2. 校验证书链try {verifyCertChain(certs);} catch (Exception e) {return false;}// 3. 校验签名证书(叶子证书)域名信息, 该域名固定为sysintegrity.platform.hicloud.comtry {new DefaultHostnameVerifier().verify("sysintegrity.platform.hicloud.com", certs[0]);} catch (SSLException e) {return false;}// 4. 验证JWS签名信息,使用签名证书里的公钥来验证PublicKey pubKey = certs[0].getPublicKey();try {// 使用签名证书里的公钥初始化 Signature 实例signature.initVerify(pubKey);// 从 JWS 提取签名输入,并输入到 Signature 实例signature.update(jws.getSigningInput());// 使用Signature 实例来验证签名信息return signature.verify(jws.getSignature().decode());} catch (InvalidKeyException | SignatureException e) {return false;}
}
3) 这里的extractX509CertChain方法,实现了从JWS Header中提取证书链的过程,详细代码如下:
private static X509Certificate[] extractX509CertChain(JWSObject jws) {List<X509Certificate> certs = new ArrayList<>();List<com.nimbusds.jose.util.Base64> x509CertChain = jws.getHeader().getX509CertChain();try {CertificateFactory certFactory = CertificateFactory.getInstance("X.509");certs.addAll(x509CertChain.stream().map(cert -> {try {return (X509Certificate) certFactory.generateCertificate( new ByteArrayInputStream(cert.decode()) );} catch (CertificateException e) {RUN_LOG.error("X5c extract failed!");}return null;}).filter(Objects::nonNull).collect(Collectors.toList()));} catch (CertificateException e) {RUN_LOG.error("X5c extract failed!");}return (X509Certificate[]) certs.toArray();
}
4) 这里的verifyCertChain方法,实现了证书链校验的过程,具体实现如下:
private static void verifyCertChain(X509Certificate[] certs) throws CertificateException, NoSuchAlgorithmException,InvalidKeyException, NoSuchProviderException, SignatureException {// 逐一验证证书有效期及证书的签发关系for (int i = 0; i < certs.length - 1; ++i) { certs[i].checkValidity();PublicKey pubKey = certs[i + 1].getPublicKey();certs[i].verify(pubKey);}// 使用预置的 HUAWEI CBG 根证书, 来验证证书链中的最后一张证书PublicKey caPubKey = huaweiCbgRootCaCert.getPublicKey();certs[certs.length - 1].verify(caPubKey);
}
5) 华为根证书的加载是在VerifySignatureUtil工具类的静态代码段中实现的。示例代码如下:
static {// 加载预置的 HUAWEI CBG 根证书File filepath = "~/certs/Huawei_cbg_root.cer"; try (FileInputStream in = new FileInputStream(filepath)) {CertificateFactory cf = CertificateFactory.getInstance("X.509");huaweiCbgRootCaCert = (X509Certificate) cf.generateCertificate(in);} catch (IOException | CertificateException e) {RUN_LOG.error("HUAWEI CBG root cert load failed!");}
}
至此,我们已经在App Server侧完成了对检测结果的验证,验证通过的结果将返回给端侧进行后续业务处理。
2.4 获取系统完整性检测结果
1) 在上一步骤完成后,App就可以从payload中获取可信的系统完整性检测结果。我们在前述的VerifyResultHandler类的回调接口中,解析系统完整性检测结果,示例代码如下:
private static final class VerifyResultHandler implements ICallBack<Boolean> {private final String jwsStr;private final ICallBack<? super Boolean> callBack;private VerifyResultHandler(String jwsStr, ICallBack<? super Boolean> callBack) {this.jwsStr = jwsStr;this.callBack = callBack;}@Overridepublic void onSuccess(Boolean verified) {if (verified) {// 服务器侧验证通过,提取系统完整性检测结果 String payloadDetail = new String(Base64.decode(jwsStr.split("\\.")[1].getBytes(StandardCharsets.UTF_8), Base64.URL_SAFE), StandardCharsets.UTF_8);try {final boolean basicIntegrity = new JSONObject(payloadDetail).getBoolean("basicIntegrity");// 通过回调返回系统完整性检测结果callBack.onSuccess(basicIntegrity);} catch (JSONException e) {…}} …}
}
2) 具体的检测报文的样例如下:
{"apkCertificateDigestSha256": ["osaUtTsdAvezjQBaW3IhN3/fsc6NQ5KwKuAQXcfrxb4="],"apkDigestSha256": "vFcmE0uw5s+4tFjXF9rVycxk2xR1rXiZFHuuBFzTVy8=","apkPackageName": "com.example.mockthirdapp","basicIntegrity": false,"detail": ["root","unlocked"],"nonce": "UjJScmEyNGZWbTV4YTJNZw==","timestampMs": 1604048377137,
"advice": "RESTORE_TO_FACTORY_ROM"
}
3) 当检测结果中basicIntegrity字段为false时,表示存在风险,App就可以对用户作风险提示。
结后语
官网开发指南,各位小伙伴们可以自行查阅参考。除了系统完整性检测(SysIntegrity),还有其他4个功能的代码,都是支持Java/Kotlin两种开发语言:华为官网的示例代码Java/Kotlin,下载后,根据提示说明进行操作就可运行。
>>访问华为开发者联盟官网,了解更多相关内容
>>获取开发指导文档
>>华为移动服务开源仓库地址:GitHub、Gitee
关注我们,第一时间了解华为移动服务最新技术资讯~
用免费开放的华为安全检测功能,评估App运行设备安全相关推荐
- GitHub免费开放所有核心功能;告别纸币-央行牵头数字货币
行 业 要 闻 Industry News ▲▲▲ 0 1 一次登录,终身免费:GitHub宣布向所有人免费开放所有核心功能 每个私有库合作人数不设限,所有核心功能向所有人免费开放,这是 GitH ...
- 测一测!中科视拓免费开放口罩人脸检测与识别技术
全民抗疫形势下,口罩已成为复工复产的标配.对于人脸识别技术厂商而言,两个应用需求应运而生: 1.检测人脸是否佩戴口罩: 2.在戴口罩的情况下依旧能够实现高精度人脸识别. 疫情初期,中科视拓紧急研发口罩 ...
- 百度免费开放长语音识别功能
近日,百度AI开放平台向开发者免费开放长语音识别功能,通过SDK调用服务,可将长语音转换为文字.据了解,新版本SDK解除了对时间的限制,开发者无需再将长语音切割成60秒以内的分段,进行调用,提升了转写 ...
- API 接口监控产品全新改版,免费开放全部功能
作为 EOLINKER 研发管理体系的重要一环,EOLINKER 接口监控即 AMT 产品将在 3月4日 迎来全新变化,AMT 产品将正式命名为 EOLINKER-API Beacon --API-烽 ...
- 【数据堂开放数据】活体检测数据免费开放
人证核验.人脸通行.刷脸支付.远程身份验证.手机刷脸解锁等任务研究者的福音来啦! 数据堂自有版权数据产品 60 人活体检测数据限时免费开放. 链接:https://www.datatang.com/w ...
- 【口罩人脸检测/识别】中科视拓免费开放口罩人脸检测与识别技术解读
原文:中科视拓免费开放口罩人脸检测与识别技术 思路 通过掺入了20%以上戴口罩的人脸识别数据集训练专门戴口罩识别模型,然后调整整个识别的Pipeline为先检测是否戴口罩,如果判断为带口罩则使用戴口罩 ...
- 如何保障手机钱包账户安全?iCard App集成系统完整性检测功能,从登录环节防范风险
iCard是保加利亚一款热门的手机钱包App,为30多个欧洲国家和地区提供银行卡管理.收付款.购物支付.国际转账.外币兑换等服务,已拥有超过12年行业经验和庞大的用户群体.因此,如何保障用户账户和资金 ...
- 阿里将投入1000亿元助力共同富裕;字节大战腾讯元宇宙;微软Outlook网页版将提供语气检测功能 | EA周报...
EA周报 2021年9月3日 每个星期7分钟,元宝带你喝一杯IT人的浓缩咖啡,了解天下事.掌握IT核心技术. 周报看点 1.阿里将投入1000亿元助力共同富裕 2.雷军:小米汽车正式注册,注册资金10 ...
- 银河水滴打响步态识别商用第一枪!3大产品1.35亿订单,工业视觉平台免费开放...
李根 发自 凹非寺 量子位 报道 | 公众号 QbitAI 你知道么?每个人的走路的步态都是独一无二的. 之前,你可能在<碟中谍>中看过步态识别技术,被用于高级别机密的身份验证. 但从今 ...
最新文章
- 第三课 弹性盒模型知识点
- 可视化篇(四)——— python绘制双y轴、箱线图、概率分布三种图形及案例
- 工厂模式(简单工厂模式)快速理解
- [转]Delphi过程函数传递参数的几种方式
- ArcGIS JS API 4 —— GET https://static.arcgis.com/fonts/simsun-regular/37888-38143.pbf 404
- linux完全卸载mysql_mysql完全卸载教程(图文详细)
- vue主动刷新页面及列表数据删除后的刷新方法
- InDesign入门教程,如何链接图形?
- Linux内核调用SPI平台级驱动_实现OLED的显示功能
- 过滤器 拦截器 controller 页面 的执行顺序
- MySQL数据库选型
- oracle sql 正则表达式
- html毕业答辩ppt,毕业答辩ppt
- 白盒测试的测试用例设计方法
- 阿里云活动价格点击购买时价格上涨的解决办法
- 【机器学习】数据驱动方法在电网稳定分析应用浅谈
- 计算机系统软件与工具软件
- Iphone IPA软件制作教程
- UltraEdit专业文本十六进制编辑器IDM UltraEdit v24.10.0.24 中文注册版 免费下载
- 虚拟服务器至强,解析新至强:选对平台是虚拟化的关键