当前位置: 首页 > 知识库问答 >
问题:

Google如何在API调用中验证SHA1和包名称?

燕烨
2023-03-14

在API控制台中注册Android应用程序以进行Google API访问时,您必须输入您的应用程序SHA1证书指纹和应用程序的包名称。

现在我想知道,当api调用只是简单的HTTP请求时,Google如何验证这些值是正确的(在最简单的情况下,当你不使用他们的api客户端时,可能会附加一些头值)?在进行API调用时,必须提供API密钥,但这不能证明输入的值是正确的。

共有2个答案

司寇飞航
2023-03-14

如果您没有使用Google Utils/SDK/API客户端,则必须手动传递这些标头。

如果您限制了android或ios应用程序的API密钥,则必须传递以下标头-

Android头文件:

{
  'x-android-package': 'com.example',
  'x-android-cert': '50FEC39F742F3DF212BDC2131A99C7D3C82086F6'
}

这里x-android-cert标头的值是不带分号的签名密钥的SHA1指纹。

从密钥库文件中获取SHA1指纹-

keytools-list-v-keystore~/. android/debug.keystore-alias androiddebug key-store pass android-keypass android

要从签名的apk/bundle-获取SHA1指纹-

keytool-printcert-jarfile ~/下载/应用程序发布。aab

keytools-printcert-jarfile~/下载/app-release.apk

iOS标头:

{
  'x-ios-bundle-identifier': 'com.example' 
}

这里com.example是包标识符。

下面是Java中的类,我认为它在本地SDK中也做着同样的工作-

/**
 * Intercepts requests and provides Android-specific headers so that API key restrictions can be
 * enforced.
 */
public class AndroidAuthenticationInterceptor implements Interceptor {

  ...

  @NotNull
  @Override
  public Response intercept(@NotNull Chain chain) throws IOException {
    ...

    final Request.Builder builder = chain.request().newBuilder();
    if (config.packageName != null) {
      builder.addHeader(HttpHeaders.X_ANDROID_PACKAGE, config.packageName);
    }

    if (config.certFingerprint != null) {
      builder.addHeader(HttpHeaders.X_ANDROID_CERT, config.certFingerprint);
    }

    return chain.proceed(builder.build());
  }
}

参考文献-

  1. 限制Google API的Android密钥的使用
  2. 如何找出用于签署应用程序的密钥库?
  3. https://developers.google.com/maps/api-security-best-practices
  4. https://github.com/googlemaps/google-maps-services-java/blob/9852dbae5d2c10897ad7a8dd4befcd171a2cd48e/src/main/java/com/google/maps/android/AndroidAuthenticationInterceptor.java
  5. https://github.com/googlemaps/google-maps-services-java/blob/main/src/main/java/com/google/maps/internal/HttpHeaders.java

易阳朔
2023-03-14

您可以很容易地获得安装的应用程序的包名和sha 1指纹。

private void printSha1() {
    List<ApplicationInfo> mAppList = getPackageManager().getInstalledApplications(0);
    for (ApplicationInfo info :mAppList) {
        Log.d(TAG, "Package Name: " + info.packageName);
        Log.d(TAG, "Sha1: " + getCertificateSHA1Fingerprint(info.packageName));
    }
}

private String getCertificateSHA1Fingerprint(String packageName) {
    PackageManager pm = getPackageManager();
    int flags = PackageManager.GET_SIGNATURES;
    PackageInfo packageInfo = null;
    try {
        packageInfo = pm.getPackageInfo(packageName, flags);
    } catch (PackageManager.NameNotFoundException e) {
        e.printStackTrace();
    }
    Signature[] signatures = packageInfo.signatures;
    byte[] cert = signatures[0].toByteArray();
    InputStream input = new ByteArrayInputStream(cert);
    CertificateFactory cf = null;
    try {
        cf = CertificateFactory.getInstance("X509");
    } catch (CertificateException e) {
        e.printStackTrace();
    }
    X509Certificate c = null;
    try {
        c = (X509Certificate) cf.generateCertificate(input);
    } catch (CertificateException e) {
        e.printStackTrace();
    }
    String hexString = null;
    try {
        MessageDigest md = MessageDigest.getInstance("SHA1");
        byte[] publicKey = md.digest(c.getEncoded());
        hexString = byte2HexFormatted(publicKey);
    } catch (NoSuchAlgorithmException e1) {
        e1.printStackTrace();
    } catch (CertificateEncodingException e) {
        e.printStackTrace();
    }
    return hexString;
}

public static String byte2HexFormatted(byte[] arr) {
    StringBuilder str = new StringBuilder(arr.length * 2);
    for (int i = 0; i < arr.length; i++) {
        String h = Integer.toHexString(arr[i]);
        int l = h.length();
        if (l == 1) h = "0" + h;
        if (l > 2) h = h.substring(l - 2, l);
        str.append(h.toUpperCase());
        if (i < (arr.length - 1)) str.append(':');
    }
    return str.toString();
}

如果运行此代码,它将打印包名及其sha 1。这是您在创建API密钥时提供的两件事,因此谷歌根据它生成的密钥映射这两件事。

正如您所见,可以访问包名及其SHA 1打印,剩下的另一件事是API密钥,您可以通过代码或xml(清单,单独的xml配置文件)将其提供给必要的库或其他应用程序(Google Play服务)。

因此,每当Google为您提供任何东西时,它都可以检查您从API控制台生成密钥时生成的相关映射。

包名称的代码取自此处

 类似资料:
  • 问题内容: 我有一个字符串,一个签名和一个公共密钥,我想验证字符串上的签名。密钥如下所示: 我已经阅读了一段时间的pycrypto文档,但是我不知道如何使用这种密钥制作RSAobj。如果您了解PHP,我将尝试执行以下操作: 另外,如果我对任何术语感到困惑,请告诉我。 问题答案: 标记之间的数据是包含PKCS#1 RSAPublicKey的PKCS#8 PublicKeyInfo的ASN.1 DER

  • 我们有一个java程序,它使用私钥对xml文件进行签名,如下所示: 现在,我必须验证这个签名在C使用cryptocpp。我所尝试的: 我验证了作为xmlString传递的数据与用于在java中创建签名的数据是二进制的。签名是base64编码的,我也尝试使用它进行解码。到目前为止,我总是失败。 如果我使用cryptopp创建带有私钥的签名,那么验证创建的签名就不会有问题。 这里可能有什么问题?我确信

  • 我一直试图在一个我一直在做的网站上使用谷歌reCAPTCHA。验证码加载到网页上,但我无法使用几种方法验证它。我已经使用如何使用Python插件recaptcha客户端进行验证中给出的方法尝试了recaptcha验证?但我认为它已经过时了,因为它不再工作,它指的是挑战,而我试图使用的是谷歌新的“复选框”reCAPTCHA v2,或者我需要在安装recaptcha-client或django-rec

  • 问题内容: 我有一个PHP脚本,应该检查“有效”人名,但是最近破解了一个带有空格的名称,因此我们在验证器中添加了空格。 除了这样做,还有没有办法向CakePHP的验证器添加黑名单以阻止所有“无效”字符,而不是允许“有效”字符? 注意:我知道如何在PHP中执行此操作(通常),但是使用CakePHP的验证器语法是不同的。 问题答案: 我同意其他意见,即验证名称可能不是一个好主意。 对于您可以想到的几乎

  • 问题内容: 我知道该方法存在并且已记录,但是我不知道如何获取MapCanvasProjection对象。 问题答案: 在v2中更轻松-Google API v3的另一个缺陷!

  • 我的项目正在对来自某些第三方软件的某些数据集进行签名验证。使用的签名算法是 。当我使用SDK附带的标准SUN加密提供程序时,一切都很顺利。最近我切换到了Bouncy Castle 1.50,之后,一些以前(即SUN提供者)进行验证的数据集开始失败,而其余的仍然被验证正常。 我探索了两个提供程序的源代码,结果发现SDK的默认提供程序对格式错误的签名有某种保护(同时能够恢复),而Bouncy Cast