iOS App 备案的特征信息-证书中公钥和签名提取

1,875 阅读2分钟

一、一般情况

iOS备案时特征信息可根据阿里云腾讯云提供的方法获取

二、特殊情况

Xcode 自动管理的证书特征信息不能通过在证书文件里下载获取 不能下载

1、通过Web调试获取Xcode自动管理的证书

① 打开web调试,打开证书页面

调试信息

② 找到对应的发布证书,复制certificateContent内容

③ 创建一个certificate.txt文件,将certificateContent复制到文件内

④ 在内容前插入-----BEGIN CERTIFICATE-----,内容后插入-----END CERTIFICATE-----

⑤ 修改文件后缀为.cer保存。

制作证书

⑥ 查看证书,复制公钥和签名即可。

2、从描述文件(.mobilevision)提取证书

描述文件位置:/Users/your_mac/Library/MobileDevice/Provisioning Profiles

.mobilevision文件包含证书,设备信息等。

方法一:在终端打印出描述文件信息

1、在终端打印证书信息

security cms -D -i path/to/your.mobileprovision

描述文件信息

  1. 复制<key>DeveloperCertificates</key><data>里的数据,此数据就是证书base64串
  2. 按照通过Web调试获取Xcode自动管理的证书中第③到⑥步骤获取公钥和签名

PS:需要注意的是描述文件中可能包含多个证书,请注意识别你需要的证书

方法二:python代码自动导出公钥和签名

import plistlib
import OpenSSL.crypto
from cryptography.hazmat.primitives.serialization import load_pem_public_key
from cryptography.hazmat.primitives.serialization import Encoding, PublicFormat
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.backends import default_backend

def extract_plist_from_mobileprovision(mobileprovision_path):
    with open(mobileprovision_path, 'rb') as f:
        data = f.read()
        # 查找 plist 文件的起始和结束位置
        start_marker = b'<?xml'
        end_marker = b'</plist>'
        start_index = data.find(start_marker)
        end_index = data.rfind(end_marker) + len(end_marker)

        # 提取 plist 文件内容
        plist_data = data[start_index:end_index]
    return  plist_data

def export_certificate_info(mobileprovision_path):
    # 提取的 plist 文件
    plist_data = extract_plist_from_mobileprovision(mobileprovision_path)

    # 解析 plist 数据
    mobileprovision = plistlib.loads(plist_data)

    # 获取 DeveloperCertificates 数据
    developer_certificates = mobileprovision['DeveloperCertificates']

    for i, certificate_data in enumerate(developer_certificates):
        # 创建 OpenSSL 证书对象
        certificate: OpenSSL.X509 = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_ASN1, certificate_data)

        public_key: OpenSSL.crypto.PKey = certificate.get_pubkey()

        # 解析PEM格式的公钥
        public_key_pem = OpenSSL.crypto.dump_publickey(OpenSSL.crypto.FILETYPE_PEM, public_key)

        # 导出证书.cer
        with open(f"certificate_{i}.cer", 'wb') as cert_file:
            cert_file.write(OpenSSL.crypto.dump_certificate(OpenSSL.crypto.FILETYPE_PEM, certificate))
        # 导出公共密钥文件.pem
        with open(f"public_key_{i}.pem", 'wb') as cert_file:
            cert_file.write(public_key_pem)


        public_key2 = serialization.load_pem_public_key(public_key_pem.decode().encode(), backend=default_backend())
        # 获取Modulus
        modulus = public_key2.public_numbers().n
        hex_modulus = hex(modulus)[2:].upper()
        hex_modulus = ' '.join(hex_modulus[i:i + 2] for i in range(0, len(hex_modulus), 2))

        # # 导出证书签名的 SHA-1 值
        signature_sha1 = certificate.digest('sha1').decode('utf-8').replace(':', ' ')

        print(f"公开秘钥256字节:{hex_modulus}\n签名SHA1:{signature_sha1}")

if __name__ == '__main__':
    # 调用示例
    mobileprovision_path = 'name.mobileprovision'
    export_certificate_info(mobileprovision_path)

参考