Export P12 certificates for use with SideStore, AltStore, and LiveContainer
Impactor can generate and export P12 (PKCS#12) certificates that contain your Apple Developer signing identity. These certificates are used by apps like SideStore, AltStore, and LiveContainer for automatic app refresh and signing.
// From plume_utils/src/signer.rs:118bundle.set_info_plist_key("ALTCertificateID", &**serial_number)?;fs::write(bundle.bundle_dir().join("ALTCertificate.p12"), p12_data).await?;
The P12 file is written to the app bundle root as ALTCertificate.p12 with the serial number stored in Info.plist.
Impactor retrieves your signing certificate from Apple’s Developer API:
// From plume_core/src/utils/certificate.rs:79let certs = session.qh_list_certs(&team_id).await?.certificates;
2
Key management
Your private key is stored locally in ~/.config/plume/keys/<team_id>/key.pem:
// From plume_core/src/utils/certificate.rs:65let key_path = Self::key_dir(config_path, &team_id)?.join("key.pem");
If no key exists, a new 2048-bit RSA key is generated.
3
P12 creation
The certificate and key are packaged into PKCS#12 format:
// From plume_core/src/utils/certificate.rs:163pub fn create_pkcs12(&self, data: &[Vec<u8>; 2], is_export: bool) -> Option<Vec<u8>> { let cert_der = pem::parse(&data[0]).ok()?.contents().to_vec(); let key_der = pem::parse(&data[1]).ok()?.contents().to_vec(); let cert = p12_keystore::Certificate::from_der(&cert_der).ok()?; let key_chain = p12_keystore::PrivateKeyChain::new(key_der, local_key_id, vec![cert]); let mut keystore = p12_keystore::KeyStore::new(); keystore.add_entry("plume", p12_keystore::KeyStoreEntry::PrivateKeyChain(key_chain));}
4
Password handling
Password is set based on the export type:
// From plume_core/src/utils/certificate.rs:188let password = if is_export { "".to_string() // Empty password for manual export} else { self.machine_id.as_deref().unwrap_or("").to_string() // Machine ID for SideStore};
The P12 local key ID is derived from the private key using SHA-1:
// From plume_core/src/utils/certificate.rs:169let local_key_id = { use sha1::{Digest, Sha1}; let mut hasher = Sha1::new(); hasher.update(&key_der); let hash = hasher.finalize(); hash[..8].to_vec()};
This ensures consistent identification across imports and exports.