forked from nattolecats/CertifiedKeyboxOverlayGenerator
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathgenerate.py
More file actions
executable file
·109 lines (90 loc) · 3.67 KB
/
generate.py
File metadata and controls
executable file
·109 lines (90 loc) · 3.67 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
#!/usr/bin/env python3
import os
import sys
import xml.etree.ElementTree as ET
import base64
from cryptography.hazmat.primitives import serialization
def trim(string: str) -> str:
"""Remove espaços e linhas vazias."""
return "\n".join([line.strip() for line in string.strip().splitlines() if line.strip()])
def trim_pem_cert(pem: str) -> str:
"""Remove cabeçalho e rodapé do certificado PEM e junta tudo em uma linha."""
lines = [line.strip() for line in pem.strip().splitlines()]
return ''.join(lines[1:-1]) # remove BEGIN/END
def pem_convert_to_pkcs8_der_base64(pem: str) -> str:
"""Converte chave privada (PEM ou DER em Base64) para PKCS#8 DER codificado em Base64."""
try:
# Tenta carregar como chave PEM
key = serialization.load_pem_private_key(pem.encode("utf-8"), password=None)
except ValueError:
# Se falhar, tenta carregar como DER codificado em Base64
der = base64.b64decode(pem)
key = serialization.load_der_private_key(der, password=None)
der = key.private_bytes(
encoding=serialization.Encoding.DER,
format=serialization.PrivateFormat.PKCS8,
encryption_algorithm=serialization.NoEncryption()
)
return base64.b64encode(der).decode('utf-8')
def get_cert(cert_list, idx):
"""Retorna certificado ou string vazia se não existir."""
return cert_list[idx] if idx < len(cert_list) else ""
def process_key(key_element, key_type):
"""Processa chave privada e cadeia de certificados."""
priv_raw = trim_pem_cert(key_element.find('PrivateKey').text)
priv_base64 = pem_convert_to_pkcs8_der_base64(priv_raw)
certs = []
cert_chain = key_element.find('CertificateChain')
if cert_chain is not None:
for cert in cert_chain.findall('Certificate'):
certs.append(trim_pem_cert(cert.text))
print(f"{key_type} key processed, {len(priv_base64)} bytes, {len(certs)} cert(s) found.")
return priv_base64, certs
def main():
path = 'keybox.xml'
if not os.path.isfile(path):
print("No keybox.xml found.")
sys.exit(1)
tree = ET.parse(path)
root = tree.getroot()
keybox = root.find("Keybox")
if keybox is None:
print("No Keybox element found.")
sys.exit(1)
ec_priv, ec_certs = ("", [""]*3)
rsa_priv, rsa_certs = ("", [""]*3)
# EC key
ec_key = keybox.find('./Key[@algorithm="ecdsa"]')
if ec_key is not None:
ec_priv, ec_certs_list = process_key(ec_key, "EC")
ec_certs = [get_cert(ec_certs_list, i) for i in range(3)]
# RSA key
rsa_key = keybox.find('./Key[@algorithm="rsa"]')
if rsa_key is not None:
rsa_priv, rsa_certs_list = process_key(rsa_key, "RSA")
rsa_certs = [get_cert(rsa_certs_list, i) for i in range(3)]
xml = f'''<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2025 The 2by2 Project
SPDX-License-Identifier: Apache-2.0
-->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<!-- Keybox configuration for device certification -->
<string-array name="config_certifiedKeybox" translatable="false">
<item>EC.PRIV:{ec_priv}</item>
<item>EC.CERT_1:{ec_certs[0]}</item>
<item>EC.CERT_2:{ec_certs[1]}</item>
<item>EC.CERT_3:{ec_certs[2]}</item>
<item>RSA.PRIV:{rsa_priv}</item>
<item>RSA.CERT_1:{rsa_certs[0]}</item>
<item>RSA.CERT_2:{rsa_certs[1]}</item>
<item>RSA.CERT_3:{rsa_certs[2]}</item>
</string-array>
</resources>
'''
os.makedirs("res/values", exist_ok=True)
with open("res/values/strings.xml","w") as o:
o.write(xml)
print("strings.xml generated successfully in res/values/.")
if __name__ == "__main__":
main()