From 1b3d1da8297daa62a68de3cc9c9ab7fcaf02cd6a Mon Sep 17 00:00:00 2001 From: hugeBlack Date: Thu, 20 Nov 2025 22:41:11 +0800 Subject: [PATCH] put p12 cert into sidestore's bundle when installing. machine_id is added to DevelopmentCertificate since it is needed for sidestore to decrypt the p12 cert. --- isideload/src/certificate.rs | 37 ++++++++++++++++++++++++++---- isideload/src/developer_session.rs | 7 ++++++ isideload/src/sideload.rs | 18 +++++++++++++++ 3 files changed, 58 insertions(+), 4 deletions(-) diff --git a/isideload/src/certificate.rs b/isideload/src/certificate.rs index c8c6094..59f8f44 100644 --- a/isideload/src/certificate.rs +++ b/isideload/src/certificate.rs @@ -3,6 +3,7 @@ use hex; use openssl::{ hash::MessageDigest, + pkcs12::Pkcs12, pkey::{PKey, Private}, rsa::Rsa, x509::{X509, X509Name, X509ReqBuilder}, @@ -23,6 +24,7 @@ pub struct CertificateIdentity { pub key_file: PathBuf, pub cert_file: PathBuf, pub machine_name: String, + pub machine_id: String, } impl CertificateIdentity { @@ -67,14 +69,15 @@ impl CertificateIdentity { key_file, cert_file, machine_name, + machine_id: "".to_owned(), }; - if let Ok(cert) = cert_identity + if let Ok((cert, machine_id)) = cert_identity .find_matching_certificate(dev_session, team) .await { cert_identity.certificate = Some(cert.clone()); - + cert_identity.machine_id = machine_id; let cert_pem = cert.to_pem().map_err(|e| { Error::Certificate(format!("Failed to encode certificate to PEM: {}", e)) })?; @@ -93,7 +96,7 @@ impl CertificateIdentity { &self, dev_session: &DeveloperSession, team: &DeveloperTeam, - ) -> Result { + ) -> Result<(X509, String), Error> { let certificates = dev_session .list_all_development_certs(DeveloperDeviceType::Ios, team) .await @@ -113,7 +116,7 @@ impl CertificateIdentity { && let Ok(cert_public_key_der) = cert_public_key.public_key_to_der() && cert_public_key_der == our_public_key { - return Ok(x509_cert); + return Ok((x509_cert, cert.machine_id.clone())); } } Err(Error::Certificate( @@ -203,6 +206,7 @@ impl CertificateIdentity { fs::write(&self.cert_file, cert_pem).map_err(Error::Filesystem)?; self.certificate = Some(certificate); + self.machine_id = apple_cert.machine_id.clone(); Ok(()) } @@ -241,4 +245,29 @@ impl CertificateIdentity { Ok(num.trim_start_matches("0").to_string()) } + + pub fn to_pkcs12(&self, password: &str) -> Result, Error> { + let cert = match &self.certificate { + Some(c) => c, + None => { + return Err(Error::Certificate( + "No certificate available to create PKCS#12".to_string(), + )); + } + }; + + let mut pkcs12_builder = Pkcs12::builder(); + pkcs12_builder.pkey(&self.private_key); + pkcs12_builder.cert(cert); + pkcs12_builder.name("certificate"); + let pkcs12 = pkcs12_builder + .build2(password) + .map_err(|e| Error::Certificate(format!("Failed to create PKCS#12 bundle: {}", e)))?; + + let der_bytes = pkcs12 + .to_der() + .map_err(|e| Error::Certificate(format!("Failed to encode PKCS#12 to DER: {}", e)))?; + + Ok(der_bytes) + } } diff --git a/isideload/src/developer_session.rs b/isideload/src/developer_session.rs index f32de23..732c885 100644 --- a/isideload/src/developer_session.rs +++ b/isideload/src/developer_session.rs @@ -257,6 +257,11 @@ impl DeveloperSession { .and_then(|v| v.as_string()) .unwrap_or("") .to_string(); + let machine_id = dict + .get("machineId") + .and_then(|v| v.as_string()) + .ok_or(Error::Parse("machineId".to_string()))? + .to_string(); let cert_content = dict .get("certContent") .and_then(|v| v.as_data()) @@ -268,6 +273,7 @@ impl DeveloperSession { certificate_id, serial_number, machine_name, + machine_id, cert_content, }); } @@ -685,6 +691,7 @@ pub struct DevelopmentCertificate { pub certificate_id: String, pub serial_number: String, pub machine_name: String, + pub machine_id: String, pub cert_content: Vec, } diff --git a/isideload/src/sideload.rs b/isideload/src/sideload.rs index 90203fc..88fe89e 100644 --- a/isideload/src/sideload.rs +++ b/isideload/src/sideload.rs @@ -259,6 +259,24 @@ pub async fn sideload_app( "ALTAppGroups".to_string(), plist::Value::Array(vec![plist::Value::String(group_identifier.clone())]), ); + + app.bundle.app_info.insert( + "ALTCertificateID".to_string(), + plist::Value::String(cert.get_serial_number().unwrap()), + ); + + match cert.to_pkcs12(&cert.machine_id) { + Ok(p12_bytes) => { + let alt_cert_path = app.bundle.bundle_dir.join("ALTCertificate.p12"); + if alt_cert_path.exists() { + std::fs::remove_file(&alt_cert_path).map_err(Error::Filesystem)?; + } + + let mut file = std::fs::File::create(&alt_cert_path).map_err(Error::Filesystem)?; + file.write_all(&p12_bytes).map_err(Error::Filesystem)?; + } + Err(e) => return error_and_return(logger, e), + } } let app_groups = match dev_session