手机根证书格式说明
证书格式概述
手机根证书采用JSON格式存储,包含ECC和RSA两种加密算法的证书链。每个证书链包含根证书、中间证书和叶子证书,以及对应的私钥。所有证书和密钥均采用DER格式,并以Base64编码存储。证书链最多支持两个中间证书,按照顺序命名为intermediate0和intermediate1。
JSON结构
{
"ecc_key": "xxxx", // ECC私钥,DER格式,Base64编码
"ecc_cert_leaf": "xxxx", // ECC叶子证书,DER格式,Base64编码
"ecc_cert_intermediate0": "xxxx", // ECC第一个中间证书,DER格式,Base64编码
"ecc_cert_intermediate1": "xxxx", // ECC第二个中间证书(可选),DER格式,Base64编码
"ecc_cert_root": "xxxx", // ECC根证书,DER格式,Base64编码
"rsa_key": "xxxx", // RSA私钥,DER格式,Base64编码
"rsa_cert_leaf": "xxxx", // RSA叶子证书,DER格式,Base64编码
"rsa_cert_intermediate0": "xxxx", // RSA第一个中间证书,DER格式,Base64编码
"rsa_cert_intermediate1": "xxxx", // RSA第二个中间证书(可选),DER格式,Base64编码
"rsa_cert_root": "xxxx" // RSA根证书,DER格式,Base64编码
}
字段说明
ECC证书链
ecc_key
: ECC私钥,DER格式,Base64编码ecc_cert_leaf
: ECC叶子证书,DER格式,Base64编码ecc_cert_intermediate0
: ECC第一个中间证书,DER格式,Base64编码ecc_cert_intermediate1
: ECC第二个中间证书(可选),DER格式,Base64编码ecc_cert_root
: ECC根证书,DER格式,Base64编码
RSA证书链
rsa_key
: RSA私钥,DER格式,Base64编码rsa_cert_leaf
: RSA叶子证书,DER格式,Base64编码rsa_cert_intermediate0
: RSA第一个中间证书,DER格式,Base64编码rsa_cert_intermediate1
: RSA第二个中间证书(可选),DER格式,Base64编码rsa_cert_root
: RSA根证书,DER格式,Base64编码
注意事项
- 所有证书和密钥均采用DER格式,并以Base64编码存储
- 证书链必须完整,包含根证书、中间证书和叶子证书
- 私钥必须与对应的证书匹配
- 中间证书最多支持两个,按照顺序命名为intermediate0和intermediate1
转换工具
可以使用Python脚本将keybox.xml格式转换为上述JSON格式。转换脚本会:
- 解析keybox.xml文件中的PEM格式证书和密钥
- 将PEM格式转换为DER格式
- 对DER格式数据进行Base64编码
- 生成最终的JSON格式输出
转换脚本需要以下Python库:
# coding=utf-8
import sys
import json
import hashlib
from cryptography.hazmat.backends import default_backend
from cryptography.x509 import load_pem_x509_certificate
from cryptography.hazmat.primitives import serialization
import base64
import xml.etree.ElementTree as ET
def pem_cert_to_der_cert_base64(pem_cert):
try:
# Try to load as a certificate first
pub_key = load_pem_x509_certificate(pem_cert.encode(), default_backend())
der_certificate = pub_key.public_bytes(
encoding=serialization.Encoding.DER
)
except ValueError:
# If not a certificate, try to load as a private key
priv_key = serialization.load_pem_private_key(pem_cert.encode(), password=None, backend=default_backend())
der_certificate = priv_key.private_bytes(
encoding=serialization.Encoding.DER,
format=serialization.PrivateFormat.TraditionalOpenSSL,
encryption_algorithm=serialization.NoEncryption()
)
return base64.b64encode(der_certificate).decode('utf-8')
def generate_new_der_attest_key(root_pem_attest_key):
root_attest_key = root_pem_attest_key
new_attest_key = {}
ecc_key = root_attest_key["ecc_key"]
ecc_cert_leaf = root_attest_key["ecc_cert_leaf"]
new_attest_key["ecc_key"] = pem_cert_to_der_cert_base64(ecc_key)
new_attest_key["ecc_cert_leaf"] = pem_cert_to_der_cert_base64(ecc_cert_leaf)
new_attest_key["ecc_cert_root"] = pem_cert_to_der_cert_base64(root_attest_key["ecc_cert_root"])
rsa_key = root_attest_key["rsa_key"]
rsa_cert_leaf = root_attest_key["rsa_cert_leaf"]
new_attest_key["rsa_key"] = pem_cert_to_der_cert_base64(rsa_key)
new_attest_key["rsa_cert_leaf"] = pem_cert_to_der_cert_base64(rsa_cert_leaf)
new_attest_key["rsa_cert_root"] = pem_cert_to_der_cert_base64(root_attest_key["rsa_cert_root"])
atkeys = root_attest_key.keys()
for atkey in atkeys:
if atkey.startswith("ecc_cert_intermediate") or atkey.startswith("rsa_cert_intermediate"):
new_attest_key[atkey] = pem_cert_to_der_cert_base64(root_attest_key[atkey])
return new_attest_key
def generate_key_batch(root_pem_attest_key, root_attest_key_md5, batch_size):
batch_keys = []
for _ in range(batch_size):
new_der_attest_key = generate_new_der_attest_key(root_pem_attest_key)
der_attest_key_str = json.dumps(new_der_attest_key)
key_md5 = hashlib.md5(der_attest_key_str.encode('utf-8')).hexdigest()
batch_keys.append((root_attest_key_md5, key_md5, der_attest_key_str))
return batch_keys
def parse_xml_keybox(file_path):
tree = ET.parse(file_path)
attest_keys = {}
for keybox in tree.getroot().findall("Keybox"):
attest_key = {}
_DeviceID = keybox.get("DeviceID")
keys = keybox.findall("Key")
if len(keys) != 2:
print(f"wrong key {_DeviceID}")
continue
for _key in keys:
_key_algorithm = _key.get("algorithm")
_key_type = "ecc"
if _key_algorithm == "ecdsa":
_key_type = "ecc"
elif _key_algorithm == "rsa":
_key_type = "rsa"
else:
print(f"wrong key algorithm{_key_algorithm} for {_DeviceID}")
_pem_privkey = _key.find("PrivateKey").text
_num_certs = int(_key.find("CertificateChain").find("NumberOfCertificates").text)
if _num_certs < 2:
print(f"wrong cert {_DeviceID}")
break
_certs = _key.find("CertificateChain").findall("Certificate")
_leaf_pem_cert = _certs[0].text
_root_pem_cert = _certs[-1].text
attest_key[_key_type + "_key"] = _pem_privkey
attest_key[_key_type + "_cert_leaf"] = _leaf_pem_cert
attest_key[_key_type + "_cert_root"] = _root_pem_cert
intermediate_idx = 0
for intermediate_cert in _certs[1:-1]:
# print(intermediate_cert.text)
attest_key[_key_type + "_cert_intermediate" + str(intermediate_idx)] = intermediate_cert.text
intermediate_idx += 1
attest_keys[hashlib.md5(json.dumps(attest_key).encode('utf-8')).hexdigest()] = attest_key
return attest_keys
if __name__ == '__main__':
root_attest_keys = parse_xml_keybox("keybox.xml")
for root_pem_attest_key in root_attest_keys.values():
new_der_attest_key = generate_new_der_attest_key(root_pem_attest_key)
print(json.dumps(new_der_attest_key, indent=4))
break