Android 内容提供商保护级别和不同的密钥

2024-02-16

我有一个应用程序提供专业版(付费)和免费版(添加支持)。两个版本都使用相同的密钥存储进行签名,但每个版本都有自己的密钥别名。

现在,我想开发一个与两个版本兼容的插件,通过内容提供商提供数据。数据很敏感,因此我需要只能从我的应用程序(专业版和免费版)访问我的内容提供程序。

使用 android:protectionLevel="signature" 的权限不起作用,因为免费版和专业版没有相同的签名 :/ 。我想我应该使用相同的密钥对我的两个版本进行签名,但我认为 Play 商店中的每个应用程序都需要使用自己的密钥进行签名。

那么,有人知道解决方案吗?有没有办法温和地要求谷歌更改我正在使用的密钥(我可以证明我的身份,因为我没有丢失我的密钥),或者我被卡住了?

编辑:我可以选择取消发布专业版(因为我目前的下载量很少)并使用与免费版本相同的证书重新上传它。如果这样做,我需要更改其包吗?

提前致谢


signature-level 权限很棒,但相当不灵活:应用程序必须使用相同的签名密钥进行签名。在很多情况下,我们想要检查另一个应用程序是否由预期的密钥签名,但该密钥不是our钥匙。就您而言,您有两把钥匙。在其他情况下,人们可能会检查某些合作伙伴应用程序的签名,例如,确认您要向用户发送的 PayPal 应用程序确实是 PayPal 应用程序,而不是取代 PayPal 应用程序的恶意软件。

要验证另一个应用程序的签名,您可以使用PackageManager。例如,这是当前版本的my SignatureUtils class https://github.com/commonsguy/cwac-security/blob/master/security/src/main/java/com/commonsware/cwac/security/SignatureUtils.java from 我的 CWAC-安全库 https://github.com/commonsguy/cwac-security:

/***
  Copyright (c) 2014 CommonsWare, LLC

  Licensed under the Apache License, Version 2.0 (the "License"); you may
  not use this file except in compliance with the License. You may obtain
  a copy of the License at
    http://www.apache.org/licenses/LICENSE-2.0
  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
 */

package com.commonsware.cwac.security;

import android.content.Context;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.Signature;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public class SignatureUtils {
  public static String getOwnSignatureHash(Context ctxt)
                                                        throws NameNotFoundException,
                                                        NoSuchAlgorithmException {
    return(getSignatureHash(ctxt, ctxt.getPackageName()));
  }

  public static String getSignatureHash(Context ctxt, String packageName)
                                                                         throws NameNotFoundException,
                                                                         NoSuchAlgorithmException {
    MessageDigest md=MessageDigest.getInstance("SHA-256");
    Signature sig=
        ctxt.getPackageManager()
            .getPackageInfo(packageName, PackageManager.GET_SIGNATURES).signatures[0];

    return(toHexStringWithColons(md.digest(sig.toByteArray())));
  }

  // based on https://stackoverflow.com/a/2197650/115145

  public static String toHexStringWithColons(byte[] bytes) {
    char[] hexArray=
        { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B',
            'C', 'D', 'E', 'F' };
    char[] hexChars=new char[(bytes.length * 3) - 1];
    int v;

    for (int j=0; j < bytes.length; j++) {
      v=bytes[j] & 0xFF;
      hexChars[j * 3]=hexArray[v / 16];
      hexChars[j * 3 + 1]=hexArray[v % 16];

      if (j < bytes.length - 1) {
        hexChars[j * 3 + 2]=':';
      }
    }

    return new String(hexChars);
  }
}

I use PackageManager得到Signature对于给定的包,给定其应用程序 ID。尽管名字如此,Signature实际上是用于签署应用程序的密钥对的公钥。的输出getSignatureHash()是一组以冒号分隔的十六进制字符对,表示公钥的 SHA256 哈希...与使用 Java 7+ 获得的值相同keytool命令。

在您的情况下,您试图即时确定传入操作是否来自所需的应用程序,以及所需的应用程序是否正确(例如,与重新打包的恶意软件相比)。就你而言,Binder.getCallingUid()将为您提供触发 IPC(触发您的代码)的应用程序的 Linux UID。PackageManager can 为您提供该 UID 的应用程序的应用程序 ID https://stackoverflow.com/questions/12918731/how-to-get-application-package-name-or-uid-which-is-trying-to-bind-my-service-fr(忽略android:sharedUserId场景)。然后,您将查看该应用程序 ID 是否是预期值,如果是,请检查哈希签名密钥是否是预期值。如果任一测试失败,用挥舞手臂的机器人的话来说,“危险,威尔·罗宾逊!危险!” https://en.wikipedia.org/wiki/Danger,_Will_Robinson.

一个重要的警告是,一些开发人员将通过这些应用程序重新签名的渠道发布应用程序。这里最值得注意的是适用于 Android 的 Amazon AppStore,亚马逊有意将您的应用程序包装在他们自己的准 DRM 中,并使用他们代表您生成的密钥对该应用程序进行签名。这与您在其他地方必然使用的密钥不同,因此您可能需要比较多个有效的签名哈希值。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Android 内容提供商保护级别和不同的密钥 的相关文章

随机推荐

  • 更新后自动缩小 Javascript/CSS 文件吗?

    我知道缩小 JS 和 CSS 文件的方法 但是有没有办法在生产系统中自动缩小这些文件 例如 我修改了原始JS文件中的一些内容并更新了生产环境 但是 在使用 JS 文件时 应该使用 JS 文件的自动缩小版本 如果源文件发生更改 最好更新当前的
  • Solr(太阳黑子),最大结果超过 30?

    我通过 Sunspot for Rails 使用 Solr 但我不知道如何返回超过 30 个结果 假设我有这个搜索块 posts Post search do keywords something end 我如何确定太阳黑子应该返回all比
  • Git 别名为新分支的名称添加前缀

    有没有办法编写一个别名 将当前日期添加到新分支的名称中 例如 git branch today new branch name 应该创建新分支22 09 2015 new branch name name 创建一个 git 别名并将其添加到
  • 识别串口/USB设备python

    这个问题的解决方案可能非常简单 但我对动态与设备交互还很陌生 我正在做的是制作一个Python可执行代码 这样用户的计算机上就不必有Idle或任何类型的Python解释器 这意味着我不知道设备将插入哪个USB端口到 该程序需要能够打开与通过
  • 在 Nginx docker 中,我们如何仅从 error.log 中查看日志

    Nginx Docker 文件配置为将 error log 发送到 dev stderr RUN ln sf dev stdout var log nginx access log ln sf dev stderr var log ngin
  • 检查文档是否为ROOT节点

    我需要知道文档元素是否是页面的根节点 例如 lt ROOT Node lt other document lt other document 在 iframe 1 或 2 中执行的 JavaScript 应该知道它们的文档节点是否是根节点
  • 新库中的异步方法与非异步方法[关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 在 NET 4 5 中 有许多方法现在以异步和非异步对的形式出现 例如Flush and FlushAsync 理想情况下 I O 交互在可能的
  • 如何在 mac 上结束 Tkinter python 模块,以便在程序完成后不必强制退出 python 启动器?

    这是我的代码 from Tkinter import app Tk app title example app geometry 400x300 200 200 b Button app text quit command app quit
  • EF - 具有自动迁移功能的新列的默认值

    我首先使用 EF 代码和自动迁移 我想向我的模型添加一个新列 一个布尔列来表示 活动 真 或 非活动 假 如何添加此列并为数据库中已有的行设置默认值 true 通过自动迁移 Tamar 您需要设置默认值 请参阅下一个示例 namespace
  • 如何防止操作栏被切断?

    当我将手机升级到 Marshmallow 后 我制作的所有应用程序的操作栏都被切断了 该应用程序在 Lollipop 和 Kitkat 上运行良好 该应用程序基本上只有一个视图 并且在我更新后的手机上无法正确显示 上半部分被切断 https
  • SSIS LookUp Transformation高级编辑器(修改SQL语句)

    我对SSIS中的查找转换有一个疑问 复选框 修改SQL语句 和参数选项有什么用 提前致谢 泽兰 感谢您的回答高德曼 我有一个场景 比如我的查找 参考 表正在访问 DB2 并且在 DB2 中我们有多个架构 我的要求是将架构名称作为参数传递给查
  • 使用 Maven 生成类路径文件

    我想从 pom xml 依赖项生成一个类路径文件 我需要它 所以在测试期间我有所有依赖项的类路径 稍后打包成一个包 maven dependency plugin不适合我有两个原因 它生成存储库中文件的路径 因此要使用它们首先需要运行的其他
  • 如何在 mips 汇编中迭代字符串

    所以我现在正在做一个项目 我们必须接受一个字符串并将其转换为所有大写字母 然后如果 toUpper 或 toLower 字节不是 0 则转换为小写字母 现在我仍在处理大写字母部分 猜测小写字母几乎相同 但是当我遍历字符串查找大写字母时或者当
  • 为什么将 `this` 分配给 `self` 并运行 `self.method()`?

    我正在阅读来源mongoose https github com LearnBoost mongoose blob master lib collection js L40 Collection prototype onOpen funct
  • Neo4j 合并和原子事务

    我正在运行下面的MERGE从客户端应用程序在 10 个并行线程中查询我的 Neo4j 服务器 newFoo and id所有 10 次运行的参数均相同 MERGE foo Foo id id ON MATCH SET foo newFoo
  • 导出到文件时忽略 Jquery 数据表中标头中的 HTML

    我有一个简单的数据表 我在数据表中添加了一个带有表格标题的自定义工具提示 div 参考 https www w3schools com css tryit asp filename trycss tooltip arrow bottom 当
  • Xcode 4:我的 iPhone 项目已成为 Mac OS 项目..并且我无法更改这一点

    我有两个 iOS 项目 它们在 Xcode 3 下正确构建 并且这些 iPhone 已经在应用商店中销售了一段时间 升级到 Xcode 4 后 Xcode 现在认为这些是 Mac OS 项目 当我选择 项目设置 gt 信息 时 它实际上在顶
  • 如何从带有掩模的轮廓图像中获取像素值?

    我尝试从轮廓图像中提取平均像素值 R G B 然而 我的问题是当我应用下面的代码时 观察到一些奇怪的值 int main cv Mat star imread C Users PC Desktop star starcircle png c
  • Swift 错误“静态成员不能用于类型的实例”

    我想重载我的结构的运算符 但收到消息 静态成员 评级 不能在 GlobalSettings 类型的实例上使用 我已经阅读了这个错误的几个答案 但那里的解决方案对我根本没有帮助 我怎么解决这个问题 struct GlobalSettings
  • Android 内容提供商保护级别和不同的密钥

    我有一个应用程序提供专业版 付费 和免费版 添加支持 两个版本都使用相同的密钥存储进行签名 但每个版本都有自己的密钥别名 现在 我想开发一个与两个版本兼容的插件 通过内容提供商提供数据 数据很敏感 因此我需要只能从我的应用程序 专业版和免费