use base64::Engine; use rpki::data_model::roa::RoaObject; use rpki::data_model::signed_object::RpkiSignedObject; fn extract_publish_bytes(xml: &str, uri: &str) -> Vec { let needle = format!(""); let start = xml.find(&needle).expect("publish uri present") + needle.len(); let end = xml[start..].find("").expect("publish end") + start; let b64 = xml[start..end].trim(); base64::engine::general_purpose::STANDARD .decode(b64) .expect("decode publish base64") } #[test] fn signed_object_decode_accepts_real_arin_ber_indefinite_roa_from_multi_rir_bundle() { let xml_path = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR")).join( "../../rpki/target/live/20260316-112341-multi-final3/arin/base-payload-archive/v1/captures/arin-base-arin/rrdp/repos/8bd1405242614aed9f13321d266fe3193db0ca842e0cbffda2b3df05481c331b/4a394319-7460-4141-a416-1addb69284ff/snapshot-160090-880434ae2a6f0e5fff224391c65a22ab037e09ac1d3ebad0ceda18558b49b13e.xml", ); assert!(xml_path.is_file(), "xml path missing: {}", xml_path.display()); let xml = std::fs::read_to_string(&xml_path).expect("read snapshot xml"); let uri = "rsync://rpki.arin.net/repository/arin-rpki-ta/5e4a23ea-e80a-403e-b08c-2171da2157d3/2a246947-2d62-4a6c-ba05-87187f0099b2/9ed5ce80-224e-46ab-94f1-1afce8ccf13f/0b13beb5-6bbb-3994-a254-02c5b10175c5.roa"; let der = extract_publish_bytes(&xml, uri); assert_eq!(der.first().copied(), Some(0x30)); assert_eq!(der.get(1).copied(), Some(0x80)); let signed_object = RpkiSignedObject::decode_der(&der).expect("decode BER-indefinite CMS signed object"); assert_eq!(signed_object.signed_data.encap_content_info.econtent_type, "1.2.840.113549.1.9.16.1.24"); let roa = RoaObject::decode_der(&der).expect("decode ROA object from BER-indefinite CMS"); assert!(!roa.roa.ip_addr_blocks.is_empty()); }