rea-reverse

签名证书指纹查看:SHA-1、SHA-256 和 MD5

拖入密钥库(.jks、.keystore、.p12、.pfx)、APK/AAB 或证书文件,就能看到其中每张证书的 SHA-1、SHA-256 和 MD5 指纹,格式直接对应 Firebase、Google 登录、Google 地图 API 密钥和 Facebook 登录的填写要求。不用装 keytool,也不用装 JDK。

密钥库和密码都不会离开你的浏览器. 文件在一个禁止联网的 Web Worker 里本地读取。密码只在这个 Worker 的内存里使用,不保存、不记录、不发送到任何地方,私钥也从不解密。 如何自己验证

在单独页面打开工具(无广告、无统计)

接 Firebase、Google 登录、地图 SDK,或者给 Google Cloud API 密钥加 Android 限制时,都要填同一个东西:给 App 签名的那张证书的 SHA-1(很多时候还要 SHA-256)。Facebook 登录要的“密钥散列”(key hash)其实也是这个 SHA-1,只是换成了 Base64。常规做法是 keytool -list -v,得先装 JDK、开终端;Facebook 那个值还要再接一段 openssl:

keytool -exportcert -alias androiddebugkey -keystore ~/.android/debug.keystore | openssl sha1 -binary | openssl base64

这个页面直接从文件里算出这些值,全程在浏览器里完成。

使用步骤

  1. 找到存着签名证书的文件:调试包用 ~/.android/debug.keystore,发布包用你的上传密钥(.jks、.keystore、.p12),也可以直接用签好名的 APK 或 AAB。
  2. 拖到拖放区,或点“选择文件”。PKCS#12 文件要在“密钥库密码(可选)”里填密码,再点“用这个密码重新读取”;JKS 和 JCEKS 不填密码也能打开。
  3. Firebase、Google 登录和 API 密钥限制要冒号格式的 SHA-1 或 SHA-256;Facebook 登录要 SHA-1 的 Base64。

真实输出示例

我们用 keytool 生成了一个一次性的 JKS 密钥库(命令见下),拖进中文页面,填入密码并点“用这个密码重新读取”,复制了页面显示的内容。排版有压缩(标签和值放在一行,去掉“复制”按钮),所有数值原样保留。剩余天数从采集当天算起。

样本: throwaway-upload.jks:2026-11-02 专门为这个例子用 keytool -genkeypair(JDK 17.0.18)生成的密钥库,没有用于任何其他用途

概览
格式        Java KeyStore(JKS)
文件大小    2.1 KB
内容        1 个条目,1 张证书
私钥        1 个(从不解密)
完整性校验  已用密码校验通过

upload PrivateKeyEntry
创建时间             2026-11-02 00:58:12.609 UTC
主体(Subject)      CN=Throwaway Demo Upload Key,O=rea-reverse.com example
颁发者(Issuer)     CN=Throwaway Demo Upload Key,O=rea-reverse.com example (自签发)
有效期               2026-11-02 00:58:12 UTC → 2054-03-20 00:58:12 UTC 有效 还剩 9999 天
公钥                 RSA · 2048 bit
签名算法             sha256WithRSAEncryption
序列号               57082040024cf61e
公钥固定值(SHA-256,Base64)  L4nMQNnrruDKA4pk2K3MGXyVqHaJqyyWaX90YnbCYBA=

指纹
SHA-1      64:26:AC:84:7A:42:2F:11:AB:44:9D:F1:AF:CD:BF:C2:CB:09:B0:58
  无冒号   6426ac847a422f11ab449df1afcdbfc2cb09b058
  Base64   ZCashHpCLxGrRJ3xr82/wssJsFg=
SHA-256    D7:F9:23:30:3A:A3:CD:4E:4F:0C:17:2A:1E:BE:87:07:3B:52:67:B3:07:25:EE:E6:13:86:0D:35:72:CB:2A:32
  无冒号   d7f923303aa3cd4e4f0c172a1ebe87073b5267b30725eee613860d3572cb2a32
  Base64   1/kjMDqjzU5PDBcqHr6HBztSZ7MHJe7mE4YNNXLLKjI=
MD5        1B:37:F0:0D:79:BD:B8:2D:18:CA:40:E8:33:73:DF:69
  无冒号   1b37f00d79bdb82d18ca40e83373df69
  Base64   GzfwDXm9uC0YykDoM3PfaQ==
…

能读哪些文件

  • Java 密钥库:JKS 和 JCEKS(.jks、.keystore)。这两种格式里的证书是明文存的,所以不填密码也能看到每个别名、条目类型、创建时间和证书链。填了密码,会顺带校验密钥库末尾的完整性摘要。
  • PKCS#12:.p12、.pfx,以及 keytool 按 PKCS#12 写出的 .keystore(JDK 9 起 keytool 默认就是这种格式)。这类文件通常把证书也加密了,需要密码。新算法(PBES2 + AES-256 + PBKDF2-HMAC-SHA256)和老 JDK、openssl pkcs12 -legacy 写出的旧算法(PKCS#12 密钥派生 + RC2-40 或 3DES)都支持。
  • APK 和 AAB:v1(JAR)、v2、v3、v3.1 签名方案里的签名者证书,用的是和 APK 分析器同一套解析代码。同一个签名者出现在多个方案里只显示一次,并标出所有方案;v3 密钥轮换后的新密钥会单独列为一个签名者。
  • 证书文件:PEM(一张或多张)、DER、.crt、.cer 和 .p7b。想看这些证书的全部字段和扩展,用 X.509 证书解析更合适。

结果里有什么

每个条目显示别名、PrivateKeyEntry 或 trustedCertEntry(沿用 keytool 的叫法),以及证书链里每张证书的主体、颁发者、有效期(是否已过期)、密钥算法和长度、签名算法、序列号。每张证书给出 SHA-1、SHA-256、MD5 三种指纹,各有三种写法,都带复制按钮:

写法 用在哪
冒号分隔的十六进制,5E:8F:16:… Firebase 控制台、Google Cloud API 密钥限制、Google 登录的 OAuth 客户端,也是 keytool 的输出格式
不带冒号的十六进制,5e8f16… 只接受纯十六进制串的配置文件和接口
摘要的 Base64 Facebook 登录的“密钥散列”(SHA-1 的 Base64)

页面还会给出公钥 SHA-256 的 Base64 值,也就是 Android 网络安全配置 <pin digest="SHA-256"> 里要填的那个值。

该用哪张证书?用户实际安装的那个包是谁签的,就用谁。启用了 Play 应用签名之后,Google 会用自己保管的密钥重新签名,所以 Play 渠道的包要填 Play 管理中心“应用签名”页面上应用签名密钥的指纹;你本地的上传密钥库对应的是上传密钥。调试包用的是 ~/.android/debug.keystore(别名 androiddebugkey,密码 android),而且每台电脑各不相同。

我们怎么验证的

我们用 Temurin JDK 17.0.18 的 keytool 生成了 JKS、JCEKS、PKCS#12,以及用 -J-Dkeystore.pkcs12.legacy 写出的旧格式 PKCS#12;用 OpenSSL 4.0.3 生成了默认参数、-legacy、-descert 和不加密四种 PKCS#12;密钥覆盖 RSA 2048 和 EC P-256 / P-384,另外做了一条根证书、中间证书、叶子证书的链。单元测试把每个别名、条目类型、指纹、签名算法、密钥长度和序列号都和 keytool -list -v 的输出逐项比对,APK 签名者则和 Android build-tools 36.1.0 里 apksigner verify --print-certs 的输出比对。做这些测试文件时踩过一个坑:用 keytool -importkeystore 转成 PKCS#12 时,如果同时传了 -destkeypass,受信任证书条目会报 “trusted certificate entries are not password-protected”,然后直接不导入。转换之后发现少了某个别名,多半就是这个原因。

密钥库和密码怎么保证不外泄

  • 工具运行在一个单独的框架(iframe)里,来源是 tools.rea-reverse.com;文件在框架里的 Web Worker 中、在你的设备上读取,不会上传。
  • 密码框也在这个框架里,所以它外面的页面(包括广告)读不到你输入的内容。
  • 这个页面在正文下方展示一个广告。广告脚本运行在 rea-reverse.com 上,而框架属于另一个源(origin),浏览器不允许广告脚本或本页的任何其他脚本读取你拖入的文件、输入的密码或读取结果。
  • 框架的内容安全策略拦截它的脚本能发起的所有请求(connect-src 'none',也不加载任何第三方资源)。框架也不能自行打开窗口或让本页跳转。它传给本页的只有自身高度和下面这些统计事件。
  • 密码和文件一起交给这个 Worker,只用来校验完整性摘要或 MAC、解密证书部分,分析结束就丢弃。它不会保存在页面或浏览器存储里,不会写进任何日志,也不会出现在统计事件里。点“读取其他文件”会清空密码框。
  • 私钥直接跳过,从不解密。这个页面没有办法导出或显示私钥。
  • 统计事件只有粗粒度的值:成功或错误码、识别出的格式(jks、pkcs12、apk 等)、完整性校验结果、证书数量区间、文件大小区间和耗时区间。不含别名、名称或指纹。框架把事件交给本页,由本页发送。完整列表见隐私政策。
  • 不想要任何广告和统计?在单独页面打开工具。

如何自己验证

  1. 打开浏览器开发者工具的 Network(网络) 面板,加载本页。发往 tools.rea-reverse.com 的请求就是框架:它的 HTML、样式、字体和脚本,以及 Worker 脚本 /_astro/cert-worker-*.js。发往 Google 域名的请求是本页的广告。
  2. 清空日志,然后拖入密钥库、输入密码。在过滤框里输入 domain:tools.rea-reverse.com:最多只会再出现一次 Worker 脚本 /_astro/cert-worker-*.js(为下一次运行准备的新 Worker),没有任何请求带着你的文件或密码。广告请求可能还会继续,但它们来自本页,不带框架里的任何内容。
  3. 点开来自 tools.rea-reverse.com 的 keystore-certificate-fingerprint/ 文档,查看 Headers:它的 Content-Security-Policy 里有 connect-src 'none' 和 frame-ancestors https://rea-reverse.com。在 Chrome 里,Application(应用)> Frames 也能看到框架的源和策略。Worker 运行在 default-src 'none'; script-src 'self'; connect-src 'none' 这条策略下,浏览器不允许它发出任何网络请求。
  4. 检查隔离:在 Console(控制台) 里,上下文选 top,运行 document.getElementById('tool-frame').contentDocument,结果是 null;frames[0].document 会抛出 SecurityError。广告脚本拿到的也是这个结果。
  5. 或者先打开页面再断网,然后读取密钥库,照样能用。
  6. 和你自己的工具对照:keytool -list -v -keystore my.jks 打印的 SHA-1、SHA-256,apksigner verify --print-certs app.apk 打印的签名者摘要,应该与这里完全一致。

局限

  • 不读 Bouncy Castle 的 BKS、UBER 密钥库,请先用 keytool -importkeystore -srcstoretype BKS -providerpath bcprov.jar … 转换。
  • JCEKS 的密钥(secret key)条目是 Java 序列化对象,遇到第一个就停止列举,后面的条目不会显示。
  • 不支持公钥完整性模式的 PKCS#12,以及 MAC 用 PBMAC1 的文件(显示为“未校验”)。BER 编码(不定长、分段 OCTET STRING)的文件可以读取。
  • APK 签名只列出、不验证。要验证请用 apksigner verify 或 APK 分析器。不显示 Source Stamp 和 v4 签名(.idsig)。
  • JKS 别名按 UTF-8 解码;Java 的 modified UTF-8 只在 NUL 字符和基本多文种平面以外的字符上有差别。

对应的命令行

示例密钥库是这样生成的(JDK 17.0.18)。输出未列出:它只打印密钥长度、有效期和名称,以及一条 JKS 是专有格式的警告。

$ keytool -genkeypair -keystore throwaway-upload.jks -storetype JKS -storepass throwaway-demo -keypass throwaway-demo -alias upload -keyalg RSA -keysize 2048 -validity 10000 -dname "CN=Throwaway Demo Upload Key, O=rea-reverse.com example"

用 keytool 得到同样的指纹(加了 -J-Duser.language=en -J-Duser.timezone=UTC,输出为英文、UTC 时间;有删节)。keytool 不打印 MD5:

$ keytool -list -v -keystore throwaway-upload.jks -storepass throwaway-demo
Keystore type: JKS
Keystore provider: SUN

Your keystore contains 1 entry

Alias name: upload
…
Entry type: PrivateKeyEntry
Certificate chain length: 1
Certificate[1]:
Owner: CN=Throwaway Demo Upload Key, O=rea-reverse.com example
Issuer: CN=Throwaway Demo Upload Key, O=rea-reverse.com example
Serial number: 57082040024cf61e
Valid from: Mon Nov 02 00:58:12 UTC 2026 until: Fri Mar 20 00:58:12 UTC 2054
Certificate fingerprints:
	 SHA1: 64:26:AC:84:7A:42:2F:11:AB:44:9D:F1:AF:CD:BF:C2:CB:09:B0:58
	 SHA256: D7:F9:23:30:3A:A3:CD:4E:4F:0C:17:2A:1E:BE:87:07:3B:52:67:B3:07:25:EE:E6:13:86:0D:35:72:CB:2A:32
Signature algorithm name: SHA256withRSA
Subject Public Key Algorithm: 2048-bit RSA key
Version: 3
…

Facebook 密钥散列就是 SHA-1 的 Base64,和上面 SHA-1 的 Base64 一行相同:

$ keytool -exportcert -alias upload -keystore throwaway-upload.jks -storepass throwaway-demo | openssl sha1 -binary | openssl base64
ZCashHpCLxGrRJ3xr82/wssJsFg=

用 OpenSSL 4.0.3 算 MD5:

$ keytool -list -keystore throwaway-upload.jks -storepass throwaway-demo -alias upload -rfc | openssl x509 -noout -fingerprint -md5
md5 Fingerprint=1B:37:F0:0D:79:BD:B8:2D:18:CA:40:E8:33:73:DF:69

常见问题

怎样获取 Android 签名密钥的 SHA-1 指纹?

把密钥库(调试包是 ~/.android/debug.keystore)或签好名的 APK 拖到本页,复制 SHA-1 一行即可。它和 keytool -list -v 在 Certificate fingerprints 下打印的值相同,见上面的例子。

用 keytool 获取 SHA-1 的命令是什么?

keytool -list -v -keystore my.jks -alias my-alias 会打印这个条目的 SHA1 和 SHA256;调试密钥库的别名是 androiddebugkey,密码是 android。它需要装 JDK,本页不需要。

获取 SHA-1 一定要密钥库密码吗?

JKS 和 JCEKS 不需要,证书没有加密。大多数 PKCS#12 文件需要,因为 keytool 和 OpenSSL 默认会加密证书部分;不填密码时,页面仍会列出条目和别名,并提示证书已加密。

在线工具打开密钥库安全吗?

本页由浏览器里一个没有网络权限的 Web Worker 读取文件,密钥库和密码都不会发往任何地方。私钥从不读取、不解密,只显示证书和指纹。

怎样把 SHA-1 转成 Facebook 的密钥散列?

密钥散列就是同样 20 个字节的 Base64 写法(28 个字符,以 = 结尾),即本页 SHA-1 下的 Base64 一行。命令行里把 keytool -exportcert 的输出交给 openssl sha1 -binary | openssl base64。

这里的 SHA-1 和 Firebase 里填的不一样?

先确认看的是不是给已安装那个包签名的密钥:调试包对应调试密钥库,自己分发的包对应上传密钥,从 Google Play 安装的包对应 Play 管理中心里的应用签名密钥。

更新于

相关教程