From 0509f0025774931d434ffc7643414ca8de087513 Mon Sep 17 00:00:00 2001 From: nab138 Date: Sat, 7 Feb 2026 09:37:44 -0500 Subject: [PATCH] keep working on cert stuff (broken) --- Cargo.lock | 284 ++++++++++++++++++++------ isideload/Cargo.toml | 5 +- isideload/src/sideload/certificate.rs | 85 ++++++-- isideload/src/util/storage.rs | 14 -- 4 files changed, 300 insertions(+), 88 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4c62fa1..ffdbcbe 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -49,6 +49,45 @@ version = "1.0.100" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" +[[package]] +name = "asn1-rs" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56624a96882bb8c26d61312ae18cb45868e5a9992ea73c58e45c3101e56a1e60" +dependencies = [ + "asn1-rs-derive", + "asn1-rs-impl", + "displaydoc", + "nom", + "num-traits", + "rusticata-macros", + "thiserror 2.0.18", + "time", +] + +[[package]] +name = "asn1-rs-derive" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3109e49b1e4909e9db6515a30c633684d68cdeaa252f215214cb4fa1a5bfee2c" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + +[[package]] +name = "asn1-rs-impl" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b18050c2cd6fe86c3a76584ef5e0baf286d038cda203eb6223df2cc413565f7" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "async-compression" version = "0.4.37" @@ -91,6 +130,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b7b6141e96a8c160799cc2d5adecd5cbbe5054cb8c7c4af53da0f83bb7ad256" dependencies = [ "aws-lc-sys", + "untrusted 0.7.1", "zeroize", ] @@ -335,6 +375,7 @@ dependencies = [ "num-traits", "rand_core 0.10.0", "serdect", + "zeroize", ] [[package]] @@ -358,6 +399,17 @@ dependencies = [ "rand_core 0.10.0", ] +[[package]] +name = "crypto-primes" +version = "0.7.0-pre.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "334a79c97c0b7fa536716dc132fd417d0afbf471440a41fc25a5d9f66d8771cd" +dependencies = [ + "crypto-bigint", + "libm", + "rand_core 0.10.0", +] + [[package]] name = "ctr" version = "0.10.0-rc.3" @@ -410,21 +462,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "02c1d73e9668ea6b6a28172aa55f3ebec38507131ce179051c8033b5c6037653" dependencies = [ "const-oid", - "der_derive", - "flagset", "pem-rfc7468", "zeroize", ] [[package]] -name = "der_derive" -version = "0.8.0-rc.6" +name = "der-parser" +version = "10.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be645fee2afe89d293b96c19e4456e6ac69520fc9c6b8a58298550138e361ffe" +checksum = "07da5016415d5a3c4dd39b11ed26f915f52fc4e0dc197d87908bc916e51bc1a6" dependencies = [ - "proc-macro2", - "quote", - "syn", + "asn1-rs", + "displaydoc", + "nom", + "num-bigint", + "num-traits", + "rusticata-macros", ] [[package]] @@ -496,12 +549,6 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" -[[package]] -name = "flagset" -version = "0.4.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7ac824320a75a52197e8f2d787f6a38b6718bb6897a35142d749af3c0e8f4fe" - [[package]] name = "flate2" version = "1.1.9" @@ -1036,11 +1083,12 @@ dependencies = [ "plist", "plist-macro", "rand", + "rcgen", "reqwest", "rootcause", + "rsa", "serde", "serde_json", - "sha1 0.11.0-rc.5", "sha2", "srp", "thiserror 2.0.18", @@ -1048,7 +1096,7 @@ dependencies = [ "tokio-tungstenite", "tracing", "uuid", - "x509-cert", + "x509-parser", ] [[package]] @@ -1142,6 +1190,12 @@ dependencies = [ "pkg-config", ] +[[package]] +name = "libm" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" + [[package]] name = "linux-keyutils" version = "0.2.4" @@ -1195,6 +1249,12 @@ dependencies = [ "tracing-subscriber", ] +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + [[package]] name = "miniz_oxide" version = "0.8.9" @@ -1216,6 +1276,16 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + [[package]] name = "nu-ansi-term" version = "0.50.3" @@ -1225,12 +1295,31 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "num-bigint" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" +dependencies = [ + "num-integer", + "num-traits", +] + [[package]] name = "num-conv" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf97ec579c3c42f953ef76dbf8d55ac91fb219dde70e49aa4a6b7d74e9919050" +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + [[package]] name = "num-traits" version = "0.2.19" @@ -1240,6 +1329,15 @@ dependencies = [ "autocfg", ] +[[package]] +name = "oid-registry" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12f40cff3dde1b6087cc5d5f5d4d65712f34016a03ed60e9c08dcc392736b5b7" +dependencies = [ + "asn1-rs", +] + [[package]] name = "once_cell" version = "1.21.3" @@ -1262,6 +1360,16 @@ dependencies = [ "hmac", ] +[[package]] +name = "pem" +version = "3.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d30c53c26bc5b31a98cd02d20f25a7c8567146caf63ed593a9d87b2775291be" +dependencies = [ + "base64", + "serde_core", +] + [[package]] name = "pem-rfc7468" version = "1.0.0" @@ -1289,6 +1397,26 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "pkcs1" +version = "0.8.0-rc.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "986d2e952779af96ea048f160fd9194e1751b4faea78bcf3ceb456efe008088e" +dependencies = [ + "der", + "spki", +] + +[[package]] +name = "pkcs8" +version = "0.11.0-rc.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b226d2cc389763951db8869584fd800cbbe2962bf454e2edeb5172b31ee99774" +dependencies = [ + "der", + "spki", +] + [[package]] name = "pkg-config" version = "0.3.32" @@ -1485,6 +1613,20 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c8d0fd677905edcbeedbf2edb6494d676f0e98d54d5cf9bda0b061cb8fb8aba" +[[package]] +name = "rcgen" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10b99e0098aa4082912d4c649628623db6aba77335e4f4569ff5083a6448b32e" +dependencies = [ + "aws-lc-rs", + "pem", + "rustls-pki-types", + "time", + "x509-parser", + "yasna", +] + [[package]] name = "reqwest" version = "0.13.1" @@ -1535,7 +1677,7 @@ dependencies = [ "cfg-if", "getrandom 0.2.17", "libc", - "untrusted", + "untrusted 0.9.0", "windows-sys 0.52.0", ] @@ -1561,12 +1703,39 @@ dependencies = [ "triomphe", ] +[[package]] +name = "rsa" +version = "0.10.0-rc.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b342b99544549f37509ed7fd42b0cea04bfd9ce07c16ca56094cf0fbeefbbcd" +dependencies = [ + "const-oid", + "crypto-bigint", + "crypto-primes", + "digest 0.11.0-rc.11", + "pkcs1", + "pkcs8", + "rand_core 0.10.0", + "signature", + "spki", + "zeroize", +] + [[package]] name = "rustc-hash" version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" +[[package]] +name = "rusticata-macros" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "faf0c4a6ece9950b9abdb62b1cfcf2a68b3b67a10ba445b3bb85be2a293d0632" +dependencies = [ + "nom", +] + [[package]] name = "rustls" version = "0.23.36" @@ -1637,7 +1806,7 @@ dependencies = [ "aws-lc-rs", "ring", "rustls-pki-types", - "untrusted", + "untrusted 0.9.0", ] [[package]] @@ -1770,17 +1939,6 @@ dependencies = [ "digest 0.10.7", ] -[[package]] -name = "sha1" -version = "0.11.0-rc.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b167252f3c126be0d8926639c4c4706950f01445900c4b3db0fd7e89fcb750a" -dependencies = [ - "cfg-if", - "cpufeatures", - "digest 0.11.0-rc.11", -] - [[package]] name = "sha2" version = "0.11.0-rc.5" @@ -1807,6 +1965,16 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" +[[package]] +name = "signature" +version = "3.0.0-rc.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f1880df446116126965eeec169136b2e0251dba37c6223bcc819569550edea3" +dependencies = [ + "digest 0.11.0-rc.11", + "rand_core 0.10.0", +] + [[package]] name = "simd-adler32" version = "0.3.8" @@ -2026,27 +2194,6 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" -[[package]] -name = "tls_codec" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0de2e01245e2bb89d6f05801c564fa27624dbd7b1846859876c7dad82e90bf6b" -dependencies = [ - "tls_codec_derive", - "zeroize", -] - -[[package]] -name = "tls_codec_derive" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d2e76690929402faae40aebdda620a2c0e25dd6d3b9afe48867dfd95991f4bd" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "tokio" version = "1.49.0" @@ -2245,7 +2392,7 @@ dependencies = [ "rand", "rustls", "rustls-pki-types", - "sha1 0.10.6", + "sha1", "thiserror 2.0.18", "utf-8", ] @@ -2278,6 +2425,12 @@ dependencies = [ "subtle", ] +[[package]] +name = "untrusted" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" + [[package]] name = "untrusted" version = "0.9.0" @@ -2884,15 +3037,30 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9" [[package]] -name = "x509-cert" -version = "0.3.0-rc.4" +name = "x509-parser" +version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e21aad3a769f25f3d2d0cbf30ea8b50a1d602354bd6ab687fad112821608ba6" +checksum = "d43b0f71ce057da06bc0851b23ee24f3f86190b07203dd8f567d0b706a185202" dependencies = [ - "const-oid", - "der", - "spki", - "tls_codec", + "asn1-rs", + "aws-lc-rs", + "data-encoding", + "der-parser", + "lazy_static", + "nom", + "oid-registry", + "rusticata-macros", + "thiserror 2.0.18", + "time", +] + +[[package]] +name = "yasna" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e17bb3549cc1321ae1296b9cdc2698e2b6cb1992adfa19a8c72e5b7a738f44cd" +dependencies = [ + "time", ] [[package]] diff --git a/isideload/Cargo.toml b/isideload/Cargo.toml index 42c4d52..798caf2 100644 --- a/isideload/Cargo.toml +++ b/isideload/Cargo.toml @@ -32,7 +32,6 @@ futures-util = "0.3.31" serde_json = "1.0.149" base64 = "0.22.1" hex = "0.4.3" -sha1 = "0.11.0-rc.5" sha2 = "0.11.0-rc.5" srp = "0.7.0-rc.1" pbkdf2 = "0.13.0-rc.9" @@ -40,6 +39,8 @@ hmac = "0.13.0-rc.5" cbc = { version = "0.2.0-rc.3", features = ["alloc"] } aes = "0.9.0-rc.4" aes-gcm = "0.11.0-rc.3" +rsa = { version = "0.10.0-rc.15" } tokio = "1.49.0" keyring = { version = "3.6.3", features = ["apple-native", "linux-native-sync-persistent", "windows-native"], optional = true } -x509-cert = "0.3.0-rc.4" +x509-parser = "0.18.1" +rcgen = { version = "0.14.7", default-features = false, features = ["aws_lc_rs", "pem"] } diff --git a/isideload/src/sideload/certificate.rs b/isideload/src/sideload/certificate.rs index 393c631..06bada3 100644 --- a/isideload/src/sideload/certificate.rs +++ b/isideload/src/sideload/certificate.rs @@ -1,4 +1,10 @@ +use rcgen::{CertificateParams, DistinguishedName, DnType, PKCS_RSA_SHA256}; use rootcause::prelude::*; +use rsa::{ + RsaPrivateKey, + pkcs8::{DecodePrivateKey, EncodePublicKey}, +}; +use sha2::{Digest, Sha256}; use tracing::{error, info}; use crate::{ @@ -16,20 +22,27 @@ pub struct CertificateIdentity { impl CertificateIdentity { pub async fn retrieve( machine_name: &str, - developer_session: DeveloperSession, + apple_email: &str, + developer_session: &mut DeveloperSession, team: &DeveloperTeam, storage: &dyn SideloadingStorage, ) -> Result { - let stored = - Self::retrieve_from_storage(machine_name, developer_session, team, storage).await; + let stored = Self::retrieve_from_storage( + machine_name, + apple_email, + developer_session, + team, + storage, + ) + .await; if let Ok(Some(cert)) = stored { return Ok(cert); } if let Err(e) = stored { - error!("Failed to load certificate from storage: {:?}", e); + error!("Failed to load stored certificate: {:?}", e); } else { - info!("No stored certificate found, generating"); + info!("No stored certificate found"); } todo!("generate CSR") @@ -37,26 +50,70 @@ impl CertificateIdentity { async fn retrieve_from_storage( machine_name: &str, - developer_session: DeveloperSession, + apple_email: &str, + developer_session: &mut DeveloperSession, team: &DeveloperTeam, storage: &dyn SideloadingStorage, ) -> Result, Report> { - let cert = storage.retrieve_data("cert")?; - if cert.is_none() { - return Ok(None); - } - let cert = cert.unwrap(); - let private_key = storage.retrieve_data("key")?; + let mut hasher = Sha256::new(); + hasher.update(apple_email.as_bytes()); + let email_hash = hex::encode(hasher.finalize()); + + let private_key = storage.retrieve(&format!("{}/key", email_hash))?; if private_key.is_none() { return Ok(None); } + let private_key = RsaPrivateKey::from_pkcs8_pem(&private_key.unwrap())?; + let public_key_der = private_key.to_public_key().to_public_key_der()?; for cert in developer_session .list_ios_certs(team) .await? .iter() - .filter(|c| c.machine_name.unwrap_or_default() == machine_name) - {} + .filter(|c| { + c.cert_content.is_some() && c.machine_name.as_deref().unwrap_or("") == machine_name + }) + { + let x509_cert = + x509_parser::parse_x509_certificate(cert.cert_content.as_ref().unwrap().as_ref())?; + if x509_cert + .1 + .tbs_certificate + .subject_pki + .subject_public_key + .data + == public_key_der.as_ref() + { + return Ok(Some(Self { + machine_id: cert + .machine_id + .clone() + .unwrap_or_else(|| x509_cert.1.tbs_certificate.subject.to_string()), + machine_name: machine_name.to_string(), + })); + } + } + + Ok(None) + } + + async fn request_certificate( + machine_name: &str, + developer_session: &mut DeveloperSession, + team: &DeveloperTeam, + ) -> Result { + Ok(()) + } + + fn build_csr(private_key: &RsaPrivateKey) -> Result { + let mut params = CertificateParams::new(vec![])?; + let mut dn = DistinguishedName::new(); + dn.push(DnType::CountryName, "US"); + dn.push(DnType::StateOrProvinceName, "STATE"); + dn.push(DnType::LocalityName, "LOCAL"); + dn.push(DnType::OrganizationName, "ORGNIZATION"); + dn.push(DnType::CommonName, "CN"); + params.distinguished_name = dn; Ok(()) } diff --git a/isideload/src/util/storage.rs b/isideload/src/util/storage.rs index 9eccab4..16f7cfd 100644 --- a/isideload/src/util/storage.rs +++ b/isideload/src/util/storage.rs @@ -9,20 +9,6 @@ pub trait SideloadingStorage: Send + Sync { fn delete(&self, key: &str) -> Result<(), Report> { self.store(key, "") } - - fn store_data(&self, key: &str, value: &[u8]) -> Result<(), Report> { - let encoded = BASE64_STANDARD.encode(value); - self.store(key, &encoded) - } - - fn retrieve_data(&self, key: &str) -> Result>, Report> { - if let Some(encoded) = self.retrieve(key)? { - let decoded = BASE64_STANDARD.decode(&encoded)?; - Ok(Some(decoded)) - } else { - Ok(None) - } - } } pub fn new_storage() -> impl SideloadingStorage {