rust -#rustc 1.98.1 (48a229cea 2026-09-01)Á‰m6GÞ­n6ÇèÆ2-64f5f36fb0927694ÁûÊÆÍRLñ.åSÛAúwjL-df1bddb45adbe94bÁ«ª1Úë• ¢›ºXÝÓrŽ*-1ad4f876c768bda9Á±ò‰<å%Z‰>¸64‡ËV`-2d2ab9fb0fe1def5Á»ÄóG Øg{ë(3íi«F×-06449a08aaab5e30Árustc_std_workspace_coreÁ€û{ù`ä"Ei¥€ÞÏ%G-cb0d4d77988d81b5Áó"Æ)ΉÉðÛÕpEÍ—E-3ec41d3a5a80a4a4Á miniz_oxideÁÐ8°ø‚ðbž Lƨ°J-e44eaef1807e5fc0Áadler2Á9lí©yA6P/D$UBŸ-dca52f01a59c33e7Á hashbrownÁ™¸ÈXó®÷ …ùý{e-143c77bb957d9940Árustc_std_workspace_allocÁð…¨À �¶÷Üúò·_z%í-145a318e0772276cÁ std_detectÁK(ƒ0ì*ãÛ8²D?-f99feda5ce9e492aÁrustc_demangleÁµ%jŽeårVŠÕÓ•-cfd0ab54bb33760eÁcfg_ifÁÍ}λ—©ŒÕž§C•×o-360da4ba13154744Á addr2lineÁ‹c²ŽúY\ÈGÞö÷ö--09755979c57b7e64ÁgimliÁ¢±QÄÍ`ª§DÞåù¬y-9a1fede77fbbf2f0ÁobjectÁö‚F λâËvú.zËí-7ff85ea729a864ffÁmemchrÁž˜]²1<õ¶=U�ý�Où-0e3477fb2664a277Á  ÿŽ—jl‹®¾To–K™G-549498e8b2e4d924ÁrustlsÁÀ¾*:´à`-Zh„ã]/-dd34ca9d1487a0ebÁrustls_pki_typesÁ i&à¥}õ1™6¬±‡a’l-a9c4cf58fe1775a8ÁzeroizeÁ€ZbëÊÛâà�W§¥JCw-0ae2e9de1fce3072Á aws_lc_rsÁ4{ (7¯¬(À ²Å%Û-39ce43203c4945d3Á aws_lc_sysÁ+�®°‰Ù3 žKÜà—-10f67b41e8954029ÁwebpkiÁXgÀv dP˜=×áÜôÏD-f6aa7d34e64b5f06Á untrustedÁAðúžu†²‘ó¹Þ*ôF‡-6046503770adb7b5ÁsubtleÁ–€R†�Ð÷BÝû>-d2b64395c76666cbÁlogÁÙ¥|ÿO=ŒÄ<Œ-3e104b0ce6b0ff02Árustls_native_certsÁÑ cöâ®·Xcù“ïgçÁ‚-a20dd7f375a685e2Á openssl_probeÁpü/w‘-½�$ |í-5aeca0b807d90d4cÁCryptoProviderÁt§ÓdbgÁ|�CertificateDerÁtæÓŠ |½ K=É< ÈappleÁ¼ü " Ï ,ÿÈÏ ¼á VerifierÁD¶ÈÏ ¼� androidÁ<îÅ• ¬Ç ÷ D§Å• ¬þ É<ÆÉ<¸ ÷ DñÉ<Ö invalid_certificateÁœÐ É<© ÈÏ ¼² ü¨ " ALLOWED_EKUSÁdñÅɬ¹ §d“Å• ¬ñ• <òåŽdocsrsÁ4“l�Å• ¬œü‰)testsÁ,øÍ$ÓÓ ffi-testingÁ¼ÙüÒverifier_for_dbgÁ„À ÓŠ |§ ‰ verificationÁ othersÁ                      ˜ new_with_extra_rootsÁ>Á new_innerÁ¤  "verify_server_certÁ# "verify_tls12_signatureÁ"verify_tls13_signatureÁ"supported_verify_schemesÁ map_webpki_errorsÁ  *ñ  log_server_certÁBuilderVerifierExtÁ/with_platform_verifierÁ1ÚConfigVerifierExtÁ3Ú5Ú ÷ 7innerÁ 9ñ EkuErrorÁ;  =ñ  @•:8:8:8#8#8#8#8#8#8#8#8%8%8%8%8%8&8&8&8&8&8'8>8>8>8A8A8+8+8+8-8-8/3Ÿg77÷ 8³ t|žP š¤ºŸg;;<Ê bíègW8¨h�Çõ÷±õõ¤gõ�õ/ÑKÑK ConfigBuilderÁÔKƒÕKproviderÁÖK time_providerÁ×KsideÁâÙŸ4š²D��V�V ClientConfigÁžValpn_protocolsÁŸVcheck_selected_alpnÁ V resumptionÁ¡Vmax_fragment_sizeÁ¢Vclient_auth_cert_resolverÁ£V enable_sniÁ¤Vkey_logÁ¥Venable_secret_extractionÁ¦Venable_early_dataÁ§V require_emsÁ¨V‰©VöÖ!ªVversionsÁÖ!«VverifierÁÖ!¬Vcert_decompressorsÁ­Vcert_compressorsÁ®Vcert_compression_cacheÁ¯Vech_modeÁÖ!°Vsend_ticket_requestÁêC1å¦ÔæŒáKáK WantsVerifierÁâKçãKclient_ech_modeÁƒ•is84ö33¿97=;"7?;@;*;,;1ÑK5�VŸg/¤ �Ç÷±¤g�/3ø¾  „K„KK‡Kí ä7ˆKphantomÁä7‰K«ä7ƒ¢3à6ú�ùUùUWebPkiServerVerifierÁúUrootsÁÞûUcrlsÁÞüUrevocation_check_depthÁÞýUunknown_revocation_policyÁÞþUrevocation_expiration_policyÁÞÿU supportedÁÞÿ=º£]ÅÅFÅFÆFGlobalÁ Ä› +ÉÑw„ Ÿg(È Ùg % ›"ÒØ@Ì Í:mÀœÜÄœ¯ÅœóƜǜ€Èœó‘¥_¿´ÒwĤĤŤErrorÁ Ñâó:½ÖàMõ ºÿ €g€gŠ‚gê ûcƒgbufÁûcØ«q¢1È¡Eë!î  ýüÎ$mœ{†Ì$ë!3†"˜$¦  Å™ŸŸ — ¢ó V ~NŸ¢ïÁü‰ 3ó ¤\™ r|¬ 2 »  üÁ �ÀœÜÄœ¯ÅœóƜǜ€Èœó‘¥_¿´ÒwºÛFÜFInappropriateMessageÁÝF expect_typesÁÞFgot_typeÁßFInappropriateHandshakeMessageÁàFÃ&áFØ&âFãFInvalidEncryptedClientHelloÁäFóåFæFInvalidMessageÁçFóèFéFNoCertificatesPresentedÁêFëFUnsupportedNameTypeÁìFíF DecryptErrorÁîFïF EncryptErrorÁðFñFPeerIncompatibleÁòFóóFôFPeerMisbehavedÁ õFóöF÷F AlertReceivedÁ øFóùFúFInvalidCertificateÁ ûFóüFýFInvalidCertRevocationListÁ þFóÿF€GGeneralÁ �Gó‚GƒGFailedToGetCurrentTimeÁ„G…GFailedToGetRandomBytesÁ†G‡GHandshakeNotCompleteÁˆG‰GPeerSentOversizedRecordÁŠG‹GNoApplicationProtocolÁŒG�GBadMaxFragmentSizeÁŽG�GInconsistentKeysÁ�Gó‘G’G³“GóVfÏ¢Û\ý$´è €&\æ „K„KK‡Kí ä7ˆK›ä7‰K«ä7ƒ¢3à6ú�ÑFÑFð ÒF cipher_suitesÁÓF kx_groupsÁÔF!signature_verification_algorithmsÁÕF secure_randomÁÖF key_providerÁ9Ô¨×Ë#Í«¤!|¹ řǙș­É™Ê™àË™óG*¤�R{9 µ%É extra_rootsÁQcrypto_providerÁ�fû%ÁHtúU³KKý—�"K …CÜÜ TrustAnchorÁÞsubjectÁßsubject_public_key_infoÁàname_constraintsÁXJ“Îôš´¤!Z((RawVecÁ+³,_markerÁ©XÕ”ˆó‰Þ1¤!©Õ¥K ÂUK ¾KKø(¬FJèX(¸   ‘P€&\¸3-28^NTZib  ÆQ�P€&ˆ,‘– ¢ © $°  àµ%¨)Ò ¤Ò TÒ  ü  • + $á ,LÝ(ñ 3 å zL%η$L UÈ·$L54RX4ºüÃ(’   3ü�2 I´  T�  dµ  …C…CüˆCž#Ð=‰C¶Ð=ò¹Úàŵ%¤!‰ 7  ’ñ7…u 1ü›' Á  ,þ  »3<…  »3  \Ó  » »3)  Ñ ì" ™ ó"  Sýæê,2R¥æê2S  ÿ`ÿ`V�a¬â`½68ŸœRt»3½ûê2UiLë®3T%�¯Ï5US“2“2 UnsafeCellÁ•2�ñ.ç–\*=°"�ø`ø`ù`Align8Áû`óë` x:B’‚£+}»3‘3TU »3ùLß®!3  Ùa»3TÀ “�”�•�Ï–�—�И�™�Gš�›�Fœ���Ü­Úݱä}LÂ)Lú®R61¥$ …# ù Ú#- 8,þ ù,Ú#- H,ý  ]ù�æÇa?Yù�™"a?Z ïVbA]ý�™"bBZ ]®®«°¿ ”3¯f*²Û�¾#ù�šìa?[ �´a?\�Ã!a?\u ¥g»3 »3 €g€gŠ‚gê ûcƒgž#ûcØ«q¢1È¡ï"Bÿ¹�Ûa@[ \Ÿ> €g€gŠ‚gê ûcƒgž#ûcØ«q¢1È¡ï"ÿ �…a?\j?Y —¤Z[j„!„!…! PhantomDataÁo$z�é - ¾# �¬ a?[ ?Zù�» ýa? §¤Y �· a?Y  ]  §¤§¤ArgumentÁ©¤‚¡f‹0mÖ”49d ,†$ p w żù D^ D^ b »3<®®«°¿ ”3¯f*²Û�óB¥Üù D_ D_ ®®«°¿ ”3¯f*²Û�óAý¦ùL D ‰¥^_ ñù D_ D^ö ù ®$O ù ¯$N á à$  ýÄ5$ˆF‚ Ï 7 Ÿ%   %     ù Æ"å ÿ ‚  ª% üЀ " Ï h-ë !lë » º ¹ I‚+ »…C…CüˆCž#Ð=‰C¶Ð=ò¹ÚàÅ66Ò"7contextÁ8¦Dæ^š€� é¤!((ì1+³,„2©XÕ”ˆó‰ÕF¤!-- RawVecInnerÁ/í 0capÁ1«#,P»›McΤ!ÀÀUniqueÁ¿ µÃ„2µ´]8"»OÿóBƒC€ º›F�GËG¦—¦—§—UsizeNoHighBitÁ¨—ó§  „H·’äèBŽß ¹›F»3þ b dšŠ I`á]` »®®«°¿ ”3¯f*²Û�ÕF-Ê Jaý¥$b`a » ÕF�Õ‹ Kc½Ã‹oe oe¹‚I’$I’$I»3ý°‹+oe Ú‹oeý羌pca¹ýÕ‹ Kbc ÕF ç‹ KcÙ@ “vd º»3ý¹Œ AM! á?ÕF¤!`‚„!„!…!€@o$z�é -ÕFd‚ï­ï­ ManuallyDropÁñ­�¶„Ÿ~ Á$¤!`b ƒ� Ja I`µ d¼ b-÷ » º ¹Û "â "!ø-Þtý#$ $"‚ ÆQá?á?IntoIterÁä?ž#Ð=å?›Ð=æ?ðFÐ=ç?«Ð=è?í Ð=é?’Ð=ö_©ú¥O ÕF¤!$¨#+²¸%#Å% ,â&&#àÕFÑì"'™ó"( gî fê g‚ž:· i´ €h± ‚igù:Î €hiø;= €‚�<hó ‚¨<È f8*i -Ñ$ # "1$ …#(ùÚ#-*(/»+&ù/Ú#-,8/º- qä Œmß ŒnÛ Žq+Ú �n qŸ>© Œo¤ Œp¡ Œp‚ ¥gÕF ÕF—?ï"Bÿ\ �o pò? Œpo Œm —¤no‚ò@ÒŒoÚŒnÑŒ- §¤mÌŒmðq, óA- /†$-.".,�‘r—‘r ‚ óB»3&ƒCa‘si‘s .ÉC3‘* ‰¥rs0‘s8‘r—.ù®$O/ù¯$N0áà$10“‚áD19F Ÿ%*  %1 0/,ùÆ"åF(‚ ª%'ƒ&+’&™$ #L² "¹ !UçK”tE›‰–t…C…CüˆCž#Ð=‰C¶Ð=ò¹ÚàÅÞ1¤!»37—u?—ut‚ÇqÇqÇ»36—u3—u¬¹! t tüì!z 2ü˜"; 3ÕÑL˜v}ÑL˜w¥˜Ž™w ‚.›"  óBµ‹‹œ~ œÙ™žx=ß™žxwý½¤)¡|ýð49¢} ¢�ýσM¹€¹‚ ÁF¤!xE僂 ! UninitializedÁ"#ZeroedÁ{‡u¬Š–¤SÅ¤!-‰„‚¥µ¥µ¤¦µßƒ†§µ¦ƒ†¼ºàË£]�„€<1å “ tÑì"4™ó"5 Š†Ì‰„ÌŠ‚ž:SÌŒRÍ‹PÏŒŠù:oÍ‹Œø;àÍ‚�<‹—‚¨<l‰?1$ …#5ùÚ#-7(1£#8ù1Ú#-981¢#: ”kÙ�gÙ‘dÛ”8dÜ‘ ”Ÿ>5Ù’1Ù“/Ù“‚ý>…?ÏÚ’ “ò?}Ù“åÙ� —¤‘’‚ò@KÙ’TÙ‘LÙ: §¤�HÙ�ç”ù9 óA: 1†$:;;9 Þ•Þ• ‚ óB»30ƒCà Þ–é Þ– ;ÉC´ Þ7 ‰¥•–³ Þ–¼ Þ•Ÿ;ù®$O<ù¯$N=áà$>µ à‚áD>@Ë  Ÿ%7  %> =<9ùÆ"å E5‚  ª%4 è#  ü¾%„?ø2Ø%ß@üØ%ÞAüØ%›BüØ%†CŒ•&DT•&EJ‚E]üËâ› µƒã—ýʃ†ã˜aL„Úå™ ‚»3 :3㘠Ý8ÂUÂU RootCertStoreÁÃUð¹XB �ÄCñ™™EýÁƒ�ã‚ ¬Ý8Ý8ArcInnerÁß8strongÁä7à8Âä7á8dataÁä71%wãÿÃxdÆb˜—A3ƒ Ý&FD‚ ˆ CŠB"3<ì& ò&Cü�'5¦%ÀŒŠ¦BUºŒŠ¦FE È')t{‚%*&-8‚'K(.[)É'� &+¡ "1ü3¨.¸/ü‡ê›F3ÿI30ü- J-2 ”¸$M $M €œ'5­¸&N &N Àœ¸Ä¬©^—¯fœ'MÕš¸& ÊüÀœÜÄœ¯ÅœóƜǜ€Èœó‘¥_¿´ÒwÞgœ'¾#N ³¸&N $M®L)æ *æ  [‘hÜOãQE¿»'Ou¹»'QO‚#'Q Ú»'P 'P€œ'•à»( Àœºœ'P ñ»'PQQQO½ ç 6 =DM$3QL < p w~^ Lÿ®3Tm2Uý×ê<2 RùúûOffÁüýÒ"þÿWarnÁ€�InfoÁ‚ƒq„…TraceÁ—ÝwŽd~ ’ë2R| S•òó_7X�¡™=Xù^“„3_>W‚»3X=7Xmâ�_;Výµw,_<VW•â�_;V‚ ó�_;V  Ç  ‚ .›"‚ .›" ö ù •#‹ ‚ ;#€€� GlobalLoggerÁ Ð’ÒQÅC‚—‚Ðnù áv3â‚ÛÜÝÒ"Þßà‡káâ›kãäqåæ¾k5åEÊꊦn ™$낾# �% 1ÿ „€hîi�( fÖkùf„gö„lôŠl(ò‹k‚»3l+„lðˆjî‰jkìˆ'j‚âmêˆj '0 ‚ .›"‚ .›"1®/0ù•#‹‚Ån‚Ðnùáv3*¬‚©o™$/‚¾#�%)*_ U§œ z%ãÁi£~wõãÁi£z~ óBuÉœ {Eи§v((ì1+³,„2©XÕ”ˆó‰óB¤!ËG›HƒCܬ{  óBýÍå7‹®z{x Üœ {  z•Ñ£³v»3xýå›É ; ­� y Í�žxbœjœ~­„–�3 ëIv ëL˜w ˜vá 2 ÛF 3 å" 3üè! Àœºœ'2 æ" 2“ š ¡ ‚%²¹�€ýɃS¹�>=Ú†¹„ ¹„€€†I†ITryReserveErrorÁ‡I¦‚ ?õµ³tôä�↻‚ r„1&%®„¹}€¯ËGýå…-º‚ýæ…,ºƒýåè3¼†ýåè!¼‡Eñ¹¾ˆ ¾ˆ}ýH{¿‡ ˆ»3 ƒº¾ˆù:¡ä#^À†‡‚»3 —鼇ýØè@¼ƒx†#¼†ú‚ƒ ‘†ºƒýÖ@„Á‚ ’†º‚ ý†¹€›¢�ýÖ4€¢| (óB¤!}‚„!„!…!€@o$z�é -óB Õ5¢}ý²¤>¡v …CóB¤!|‚»3 嵐|=è› y  yx‚»3- y;: &Í‹ÒÌŒ&Ì5 ‰Ök Ì‰–Š Ñ�Ÿ×�5žØŽ‚»3�ÙÑ�ŸÕ�žÖ�ŽžÕ4�‚âm�Õ�'4®= ‚ .›"‚ .›">Ý<=ù•#‹‚Ån‚Ðnùáv37Ú‚©o™$<2‚¾#�%61_ Єã˜�õ„äš ÿ„ä� ä�—ÀÀ¥G¿ µÃ„2µ´]8"»Oÿ¦c®®«°¿ ”3¯f*²Û�¦ceƒ× ê› � ¦c €…ä�]ÝYbúœ ÝYbúœ›µÓYbúš œ¥ èYbúœýÉ\)üD „KÆb¤!š‚„!„!…!€@o$z�é -¦c‚¤! ˆ…äš �…㗼⛠¥&E¼¸&F<È&¢EÁ¬ýžEƒÞÿ£%Ÿ‰b€£®®«°¿ ”3¯f*²Û�Ý8Ý8°bß8Ábä7à8Âä7á8ßbä71%wãÿÃxd÷.Mè'Œ‚¢ £ ¡‚¯ÿ£iL¼¬ƒ¤ALÁ¬ƒ¥ç…¥¢ :ù:M‡Œ†¤¥ »3<ƒ¥ý‰Ï :‡‚ ™»3»3Ô«Õ«Ö«Ï׫ث٫ÐÚ«Û«Ü«Gݫޫ߫Fà«á«â«Üã« šÃíc1Œ¤¤ºÏ ‚»3¿Ï žDÑ=ª¶þ‚ Ä  »¶þŸEã¶þ¡ þ¡ó�͈F „K÷.¤!¡‚„!„!…!€@o$z�é -¡‚‚¤! ÿ¶þ¡ ‡·ýž²¢Ë‚ ‹ DÖFßC!3ð LÕ¬ƒ¤½„¶þŸ þŸž‚ÿÿÿÿÿÿÿ»30þŸCB 󌊨 ЍB€‰VŠV‹V NoRootAnchorsÁŒV�V InvalidCrlÁŽVó;oC¼h¥-ýŒŒ©¼�'�ª\¨'�« �¬�°¥Ž­¢Ž®«Ž® Ý8•ˆ™™¨FŽ‚ ¬Ý8Ý8°bß8Ábä7à8Âä7á8ßbä71%wãÿÃxd•ˆ®3­G3³ ÖŒŠ§ ЧB¯ý-ÜŒ‹A Àœýœ'§ àŒŠ§D¦ µ'B ä·¨³ ¨³A¯ýÅê·©@ Êü‘hý³ �¸¨³2¶'AüØ%ßH@mý“? 7Hü»%ˆ Àœºœ'? Â'?ÍÔ@Ý#.2AŽ®>�¯;�²D�²­ÀÀ¥G¿ µÃ„2µ´]8"»Oÿ牮®«°¿ ”3¯f*²Û�ç‰;•° ² ç‰9�²6¥±4¥±°2¥¯ ±ß�1¥±/§¬ „K•ˆ¤!¯‚„!„!…!€@o$z�é -牂¤!/�¯,Ž­N�°W�«¬„K„KK‡Kí ä7ˆK›ä7‰K«ä7ƒ¢3à6ú��ýÆÿ ¤! ²'�¬Ù�ª ÈJ« ³'�«ü�'(�© ÛFª ´'�ªUùŒŒA Àœýœ'© ‚�Œ© Ѝx¦4B6¨´?¨´A€œ'8ªµAªµ ÀœÞgœ'´'ª@ Êü‘hýµÔªµÝ¨´\A3¶'G G@[‘hè¶ð¸Ï«¶GΫ¸¶‚éiñ«¸Ñ«·Ú«·G€œ'Ó¬ Àœºœ'·Ò«·}¸…¶ÃG×?£ª@‚'®üLçüöÓ^^äëò¬Òü¶³üùð ù ®"ƒ M M ó# ú#ù®"ƒ'"."ù®"ƒ »Â¤«²ý„AK‘ô‹ýò€MŒCÞ1Bý‡!F4Þ1m¢�ýà:Ž>Þ1¤!¥³!ýÀW’Þ1¥»<ýÑ­�U¤!ý <0ý�®ÏýÁDƒœ•Ñ®ýé!Çb·óBý¯®5ý§ p¬ÏóBý™®Lý�·Ä×`¾#œ'Qýá·!$$ý�¸$$$ý캗Ü`ºœ'œ'QåÖ»''ýÑé$”(Éœ'mä»'ýÁóf_ ³²©oÖkù É"ý­Ì»n*ëW�²‚²ƒ²LessÁ„²…²†²‡²ˆ²‰²GreaterÁв%ÑÓ¡yû Ùå…ô_*}ÈÍn++ýŽHB±,Ž#ŒšŒš©™%ÓÍn+ý·�C_-Ù4-ý¹v®_.ÔEç�_.ý¸˜‚*&*ù^Õƒƒ_0¸³½œ™0ý†ç‘ ›kùLÉ­Ç2Ÿ Ò2ùLöå `3³ ALð®3ýè¬ßÏ4 2±;)L¼æ 4ýØ>Œ4ç±;»31LÂæ 4§ ³²©oÖkaŸ7ëW©™Œš9768839Ž#ŒšŒš¼š-8*:ÙZ:';Ô#; 7&/7=¸³=ýé ta §f»3Xù�°Öa??ýþU‡b?Å»3Ù�™a?ý‚˜µb?Ô»3¾#1�µa?ýÖ|ûbBÏ»3Eœ™bBýÐ÷ª  ‹g»3<»3Mý…E ÓÅ!ý†5hˆE¢Z•¶EýÞˆ ¬ ÕDÕF¤!Z"ý¢‰ âGGýЉ ´HGý–Š îIGý¿Š ÅJGýåŠ ŸKGý�Œ tLGý¹4o}GÆ›F½«‰ Gýˆ_~Nì›F͇5}Ný˜U9}HÏ›Fuø‰ Gýì8~Pí›FEÃU}Pýˆ…HH²CÕF¤!]û‰ Gýø]QRHÕF¤!]¿…Rý º;S_¤!]¸^Sý‚Çå‹H„¤!Íî‰ GÎHƤ!ý܉ ,GËVì¤!ÇVÄIÏ›F5 Š GÀXí›F¼XýÚZWIFÕF¤!U§Š Gýœ¸[Z\¤!ÕFU¡[Zýº-Ǭ[ÔóBÕF5Ù¸[k\ÔóBÕF5Ý.¬\e]ÏóBa]ýò#M¬[ÑÕF�à¸[’JÏÕFEÏŠ GšKÏ›FE¦‹ G—aí›F”aý戋KéCÕF¤!-©‹ Gý‘‰àccýýø‡ŒK“ÕFÝ”‹ G'eçÕFóBeÇùŒeý†óŠŒe’óB�ÔùŒeýƒ•øŒgýóBýëóŒgýî °ŒeëóBÕFµèùŒeýÙkšiÚÕFu‰"Œiýµ&¹šißÕF¾#ýà!8Œi·KÏ›FEß‹ G´lí›F±lKéCÕF¤!-â‹ Gnný–´ø ŒKŽÕFmÛ‹ GLÏ›F5šŒ Gqí›Fqý¹\`LGÕF¤!U¡Œ Gýøj•sÙÕFu„]sý‹¹�s^¤!Åû\sù@Æ …“u½•Uú¹uT³²©oÖkùÉ"PwëW©™ŒšêwçxxäyŽ#ŒšŒš¼šÞxÛzÙ zØ{ÔÔ{Ñw&àwÌ}¸³Æ}ÛY'¾Ÿ Ò¸€³ ´€±� 2±;¬�©�ç±;»3¦�J³²©oÖkO'B„ëW©™ŒšÝ„Û……Ú†Ž#ŒšŒš¼šÕ…Ó‡Ù‡ÒˆÔψ̈́&݄ʊ¸³Åб§fÕF<(®ŒŒªŒÅÕF§Œ¤ŒÔÕF¾# Œ��ÏÕFš�˜‹g»3&»31(“Óõ)�’¢Z�’ý¾>K ˜TÄ!ýº;K”™-ìK”[•éCÞ1¤!-êK•W––ý…Lo Î4TÉ"ýŒ�¨˜¯€UÖL˜ýäÿ:˜â3óBUáL˜ýÖ…ešŒ3óBE�€šý�ŠÁ›�3óB¤!�¤†›ý¾•a˜¤5ýµL7˜ý…™Éœ£3óB¤!î*œýÕ™ùžžýø™ÖŸžýí£‰Ÿ�MóB¤!ý„š!žýŠ4Ò¡¼FóB¤!+¡ý²ÁUi ÝwóBE©œžý‘ïÚ °CóB¤!eËœžýýYI¤EóB¤!-àð¤ýº·N¥Z¤!óB-»Z¥È¦\¤!óB}귦ǧÔóBóBç, ¨ÔóBóB¨% ©ÏóB" ©Â§ÑóB¿§O ¦ÏóBEú·¦ý»’‡œ ®óBý²œ+žý‡Þ�‹­ÍóBý””&œ­ý¬*ñƒ®Ç9xî$ƒ®ùPƒâ[¯Á°ùPêä4¯o®ÙóBu¾á‹®ý´œM•®ãóB}éá‹®ý•¡Õ ³CóB¤!eùœžýòI³ŸCóB¤!U𣳴GóB¤!Uü²´ÿµÙóBûµúµ^¤!öµõ·½•ð·ýó‚‘¢ÀF¤!â+¢ý«„ž¹¹íÖ†¹¹ýô窺i¤!ýë…'¹ýº8;«¼™†5ÿ輎¼^¤!åê輌¾½•‡¾ù:àãn^¼�¨�‡é¼ý�>ý„º— ýÎ…E¹ÑÁÇ9aî$ƒÁÌÂÁ°ÇÂ8³²©oÖkùÉ"4ÄëW©™ŒšÏ ÄÍ ÅÅÌ ÆŽ#ŒšŒš¼šÇ ÅÅ ÇÙö ÇÄ ÈÔÁ È¿ Ä&Ï$ļ ʸ³· ʵ ›ð,° ÌŸ Ò̬ ͳ ¨ Í¥ Π2±;  Î� Îç±;»3š Î>³²©oÖkæ,6ÑëW©™ŒšÑÑÏÒÒÎÓŽ#ŒšŒš¼šÉÒÇÔÙøÔÆÕÔÃÕÁÑ&Ñ%Ѿ׸³¹×¥ §f»3Â-¢ ÙÙž ÙÅ»3› Ù˜ ÙÔ»3¾#” Ù‘ ÜÏ»3Ž ÜŒ ‹g»30»3·-‡ Óö,„ ߢZ� ßý¥ç0”ÆÆb„K„KK‡Kí ä7ˆK›ä7‰K«ä7ƒ¢3à6ú�Æb¤!4 &ýÜË1á¢;ÆbmÂç”áýë�¦âé8Æb±,âý±ƒàããùLרÉã• Ýéƒãã• ݘ„ãýµ¨¿ 䇦c¤!eõ„ãý‚©r ççý–ÓŠ瀦c¤!ý•© çý×Ó„ ééýùÖb êéý™×B ëéoéÆŸŸ BoxÁ£ó‹¤ô‹ljô²ßk#¦c¤!ÍãÓ é²íìë¼±íý WE}êÒë¼�× éý±D~ïîë¼E×W}ïçëÏë¼¹× éçñíë¼æñ•네!}®× éýÝ=B•èÕ¤!•¾© çý€>•ôô‰ôƤ!¥ˆ>•ôˆöì¤!†ö�äÆ ¦c¥5‚…ãýÔ”?bø°¦cZøýàX‘bùƦc¥ù”bùýŽXsä½8Æbýä„%ãýú[~ûÃ8Æb¤!ýÙX ûýާúü9÷.¤!Šý½¬Ë ýýýüÚ—ýÄ9÷.¤!=Ѭýý¯‡’bÿС‚¿ÿˆ€Ï¡‚E¤‰b€ý´'CŒ€í¡‚e­‰b€ùL†«àý¥ ­à¬ý ƒ³ `ƒ„ 2±;„„ç±;»3„ý¯Í ïƒåa»3»3ùL±¬%ƒ8þÃ8÷.¤!ý϶1ý)M“ þÊF=ø¶ýý´‹àÇ_ý•ˆœ'!€&•ˆœ'Uÿ¾#c/uÓŒŠŠ¥ïŒŠŠü‰',Œ!€&¨Ã¾#ƒŠm�é8•ˆƒ�iŽŽdŽ• ^ŽwŽ• \ŽY�‡ç‰¤!UŽR’’N’€ç‰¤!J’F””A•”=–”¨”ÆŸŸ ù»£ó‹¤ô‹ljô²ßk#牤!8”ç˜ì¤Åæ˜5•Ò¤Å2”/šî¤Å,š–ϤÅ*”œí¤Å œ¼–„¤!'”$“Õ¤! ’ŸŸ¢ŸÆ¤!Ÿž¡ì¤!œ¡³�Æ ç‰ß�Ž£°ç‰l£¤Æç‰¤ �½8•ˆ ަÃ8•ˆ¤!¦0×`ýœ'0+¨¨)¨¨'Ü`ºœ'œ'0"««!¬Éœ'«¼Ê&´Õ€&\ØŸ0[².|¦Æb:ð4vð4vŸ0v ð4véi^µ%3ÊüÍüÎümÏüóÐüÑü[Òüó}µŒOƒDê^‘h¾#QÀœÜÄœ¯ÅœóƜǜ€Èœó‘¥_¿´Òw¾#œ'Z Æbb‘h(1//CertificateResultÁ0certsÁ1errorsÁÜ€ýÌR|S¤»3ñ »3  »3»3+©ËHñ7])aÖkk¾#/‰¥‰¥ ArgumentsÁ‹¥templateÁûcŒ¥Çûcg‡@#éó 3 »3>óA»3M óAX ¹ÍM ›"›" ÿ™ÿ™LocationÁ�šfilenameÁ‰Z‚š¿‰ZƒšcolÁ‰Z„š _filenameÁ‰ZA…úÜ •¯!åͺ!ëÍÅ!‡NZ"‡NZ" řǙș­É™Ê™àË™óG*¤�R{9 ÕFZ" ‡NZ"éiK&ÕF1'O'ÖkY'¾#ê.ØÌ( ÕF"(¹Í1(óA<(×Í1(ãÍß)åÍê)ëÍõ)œ'c+ëIëIåìI–æ4È ª¬KÄñl+æ,Ökð,¾#Ñ)ØÌ�-®Í¨-¹Í·-óAÂ-×Í·-ãÍd/åÍo/ëÍz/º0ÊüÍüÎümÏüóÐüÑü[Òüó}µŒOƒDê^‘hý0ÀœÜÄœ¯ÅœóƜǜ€Èœó‘¥_¿´Òwýœ'0ÀœÜÄœ¯ÅœóƜǜ€Èœó‘¥_¿´Òwý•ˆ'0îUîUServerCertVerifierBuilderÁïUðÞðU�ÞñU‘ÞòU³ÞóUØÞôUsupported_algsÁÞ¼¶x.ðYí10œº;0ÆbC0².ô)‘hX!ýº$ô/ 2ÉVBéi-á·$œ'%3$‘hE3$éi5Ö»'œ'u4'I4'»3{2ž:†2ø;Ü3 ù:å�¯Ï5âm„4;©™ý‹™(=»35¢™=—¤™¤ PlaceholderÁš¤�¡f›¤ formatterÁ¡fœ¤ _lifetimeÁ¡f�¤ž¤CountÁŸ¤ó¡fÑ&þ<Š$«Æg?Ÿ>t?ò?Ð?…?Ý?ø;mïVbAƒCÑ DÉC4!DýIf$IÈJ®$J¿K/%GÈJÍ$G»3”Œ L×$n»3{ž:†ø;Ü€¤Ö=‚âm¾5ˆ©™;Š»38ŠÒÖgŒŸ>tŒò?ÐŒ¥RÝŒ¿K°ŽƒCÑ ‘ÉC4!‘»3®*”×$–…C…CüˆCž#Ð=‰C¶Ð=ò¹ÚàÅóB¤!u+˜¡X+˜»3º+ž•/ž¬s»3ž¡t“3žÍsÖ+¡ËGâ+¢ £X•ãÁi£ƒC±3§ÀœÜÄœ¯ÅœóƜǜ€Èœó‘¥_¿´ÒwËGðvõ+¹éiE«„¹å1¹à1¹ðvž2¹E2¹»3í1¼»3é1¼ýHå1¾»3{Ìž:†Ìø;ÜÍ¤Ö Ïâm16Õ©™ ×»3×ÒÖgÙŸ>tÙò?ÐÙ…?ÝÙø;ÛƒCÑ ÞÉC4!Þë¼w0ã¦cƒ0ã :éã¥v/ãéÜé ¦cÐ.ú¥‡/ã»3.ý0+ý5,ýó�,ýþ‚ÕŸ‰b€ó�,.€Ѓ‹-ƒ¤Öø…éi-ÓŒŠýï)Š•ˆK+Šœ'Ý*ŠÈJÈJÉJ OtherErrorÁÊJó Î]9š¸2�+�ê�+�„K„KK‡Kí ä7ˆK›ä7‰K«ä7ƒ¢3à6ú�•ˆ¤!b+�¤Åw0Žç‰ƒ0Žß�Â0Ž¡Ž)” ç‰0¥ß�Ö0Žýƒ*¨œ'%3¨‘hE3¨éiQ«œ'u4«I4«»3c"ýHc"ƒCc"ð/Ö  test_rootÁ?&‰0ê  root_storeÁ:�vcertÁ3 Æ 4Žd&‚¾#Ç  addedÁñ ignoredÁ  lvlÁ ²" ‚©oÇM ®Í®ÍÇM �Z""errorÁ1'&¬á²"‚©oÇ1(”ДÐ+Ç1(,¬á²"‚©oÇ·-Õâ®Í8Ç·-9Æ ¸(GŽ,HÑ2Á Ð"ÔÖkÁÐ"ÔÖkÁÐ"ÔÖkýÌ;<?Þ1¤!¾#¾#ýç*©Þ1š¬š¬J›¬_inner_repr_trickÁƒ•#ðÊM^HEǯ%ýHMòŠ ªÕF…Ê‹¬ÕF»3¬ÕF»3ý˜p •§ÕF»3Uݹħ»3F¬Þ1»3MŸ5«óB�ZE§óB»3ýÞœ!•¨óB»3i§óB»3dħ»3pħ»3e�¶¦8»3DŒ4vê4v„6Zð4¤ð4¤š7 ¿8+Ån´6�NZ"‡Nî'Ånœ8ÕFî'Ån!5ˆ‡10²d'0². 2Ÿ0 2Æb 2². 2Ÿ0 2ÕFî'‡Nî'ð4¤². 2Ÿ0 2œº–1›Fô/Æb 2€& 2¤! Ï<¤! ݯŒš çÍn�<Œšý>èáDÑ! ÝóBýÄ–%ŒŒš3�<Œš?�RèáDÑ! ³wóBÅ+ØÙÿ9¤!ÿ9 ¦°éxˆ%ƒ •M雈%ƒ�Yõ+ÀwF9ËG Ȇ ¡ªéaˆ%ƒŒš©�<Œšµý>èáDÑ! c1Æbœ4Ç…‡2 ™»3»3ýƒýÒÑ 9 ™»3»3ýƒý�Ñ 9 ™»3»3ýƒý¯Ð : ™»3»3ýƒýÜÏ :ðƒò3�à “�˜ßê�c1á‰1•ˆX5³¼ÔÖkÊÙi+ ÖkøÖk ÔÖk09ÔÖkGV½+¾ìsÖk{ƒˆÔÖk«´ÔÖkÂÑk,¾ìîÖköþÔÖk Í2Ê2Ñ2Ø2 w0ƒ0«‘0 ‚»3 :ƒ0 Ý8•ˆ Ï„1‚ቃ01®8©8 ¤8 «8  �ß�78  ¡Ž08 +8 '8  "8  ß�8 8 „K•ˆ¤! ‚‹�‚¤!ñ7 ì7 4 4ê�`064 ÈJZ0W0 ÛFR0µ'!#vé8•ˆ‹4oh• ay• ]Y‡ç‰¤!TPJ€ç‰¤!E@93 œ)ƤÅé—) ì¤Å•) ãÒ¤ÅßÛ î¤Å× ») ϤÅÓ¶)í¤Å´)b) „¤!ÌÈÕ¤!ÿB*Ƥ!¸<*ì¤!9*OÆÈÇß�°¬°ç‰§Æç‰£Ÿ½8•ˆœ—Ã8•ˆ¤!” œ'Œ'�Ãÿ•ˆ Š'ÏÞo6ê�n6˜ßw6¤Åw0牃0 :Oß�Ü;¡ŽB’à4;ß�ë;›ew˜ßê�Ø6á‰1•ˆÍ:($Ç‚ Êg‚ ›"&.$Ì>Fï"Q õ[ý#bkœx‚„÷ŒH%΂%×A*4Ë÷<Ë÷DMî Zd     /3‰Ku„KWantsClientCertÁ|‹—VÉdœ�VÕlªÑK«l¹áK÷ Dò7.)üœøà‹ü'&à‹# rustls-platform-verifier [![crates.io version](https://img.shields.io/crates/v/rustls-platform-verifier.svg)](https://crates.io/crates/rustls-platform-verifier) [![crate documentation](https://docs.rs/rustls-platform-verifier/badge.svg)](https://docs.rs/rustls-platform-verifier) ![MSRV](https://img.shields.io/badge/rustc-1.85+-blue.svg) [![crates.io downloads](https://img.shields.io/crates/d/rustls-platform-verifier.svg)](https://crates.io/crates/rustls-platform-verifier) ![CI](https://github.com/1Password/rustls-platform-verifier/workflows/CI/badge.svg) A Rust library to verify the validity of TLS certificates based on the operating system's certificate facilities. On operating systems that don't have these, `webpki` and/or `rustls-native-certs` is used instead. This crate is advantageous over `rustls-native-certs` on its own for a few reasons: - Improved correctness and security, as the OSes [CA constraints](https://support.apple.com/en-us/HT212865) will be taken into account. - Better integration with OS certificate stores and enterprise CA deployments. - Revocation support via verifying validity via OCSP and CRLs. - Less I/O and memory overhead because all the platform CAs don't need to be loaded and parsed. This library supports the following platforms and flows: | OS | Certificate Store | Verification Method | Revocation Support | |----------------|-----------------------------------------------|--------------------------------------|--------------------| | Windows | Windows platform certificate store | Windows API certificate verification | Yes | | macOS (10.14+) | macOS platform roots and keychain certificate | macOS `Security.framework` | Yes | | iOS | iOS platform roots and keychain certificates | iOS `Security.framework` | Yes | | Android | Android System Trust Store | Android Trust Manager | Sometimes[^1] | | Linux | System CA bundle, or user-provided certs[^3] | webpki | No[^2] | | WASM | webpki roots | webpki | No[^2] | [^1]: On Android, revocation checking requires API version >= 24 (e.g. at least Android 7.0, August 2016). When available, revocation checking is only performed for the end-entity certificate. If a stapled OCSP response for the end-entity cert isn't provided, and the certificate omits both a OCSP responder URL and CRL distribution point to fetch revocation information from, revocation checking may fail. [^2]: The fall-back webpki verifier configured for Linux/WASM does not support providing CRLs for revocation checking. If you require revocation checking on these platforms, prefer constructing your own `WebPkiServerVerifier`, providing necessary CRLs. See the Rustls [`ServerCertVerifierBuilder`] docs for more information. [^3]: On Linux the [rustls-native-certs] and [openssl-probe] crates are used to try and discover the system CA bundle. Users may wish to augment these certificates with [webpki-roots] using [`Verifier::new_with_extra_roots`] in case a system CA bundle is unavailable. [`ServerCertVerifierBuilder`]: https://docs.rs/rustls/latest/rustls/client/struct.ServerCertVerifierBuilder.html [`Verifier::new_with_extra_roots`]: https://docs.rs/rustls-platform-verifier/latest/rustls_platform_verifier/struct.Verifier.html#method.new_with_extra_roots [rustls-native-certs]: https://github.com/rustls/rustls-native-certs [openssl-probe]: https://github.com/alexcrichton/openssl-probe [webpki-roots]: https://github.com/rustls/webpki-roots ## Deployment Considerations When choosing to use `rustls-platform-verifier` or another trust store option, these differences are important to consider. They are primarily about root certificate availability: | Backend | Updates | Roots used | Supports system-local roots | |-------------------------------------------------|---------------------------------|-------------------------------------------------------------------------------------------------------|------------------------------| | `rustls-platform-verifier` (non-Linux/BSD) | Updated by OS | System store, with full (dis)trust decisions from every source available. | Yes | | `rustls-native-certs` + `webpki` | Updated by OS | System store, with no (dis)trust decisions. All roots are treated equally regardless of their status. | Yes, with exceptions | | `webpki-roots` + `webpki` | Static, manual updates required | Hardcoded Mozilla CA roots, limited support for constrained roots. | No | **In general**: It is the opinion of the `rustls` and `rustls-platform-verifier` teams that this is the best default available for client-side libraries and applications making connections to TLS servers when running on common operating systems. This is because it gets both live trust information (new roots, explicit markers, and auto-managed CRLs) and better matches the common expectation of apps running on that platform (to use proxies, for example). Otherwise, it becomes your maintenance burden to ship updates right away in order to handle increasing numbers of positive and negative trust events in the WebPKI/certificate ecosystem, or risk availability and security concerns. #### Linux/BSD As of the time of writing, `rustls-platform-verifier` on these OSes only loads the trust stores from the OS once upon startup. This is the same behavior as `rustls-native-certs`, but the abstraction allows better behavior on the other platforms without extra work for downstreams. #### Other Alternatively, there is a clear answer to use static `webpki-roots` in your application instead if you are deploying containerized applications frequently, where root store changes will make it to production faster and any possibly used trust root is static by definition. Even though platform verifiers are sometimes implemented in memory-unsafe languages, it is very unlikely that Rust apps using this library will become a point of weakness. This is due to either using a smaller set of servers or just being less exposed then other critical functions of the operating system, default web browser, etc. But if your activity is identical or close to one of the following examples that process large amounts of untrusted input, a 100% Rust option like `webpki` is a more secure option: - Seeing how many TLS servers `rustls` with a specific configuration can connect to. - Harvesting data from various untrusted TLS endpoints exposed on the internet. - Extracting info from a known-evil endpoint. - Scanning all TLS certificates on the open internet. `rustls-platform-verifier` is widely deployed by several applications that use the `rustls` stack, such as 1Password, Bitwarden, Signal, and `rustup`, on a wide set of OSes. This means that it has received lots of exposure to edge cases and has real-world experience/expertise invested into it to ensure optimal compatibility and security. ## Installation and setup On most platforms, no setup should be required beyond adding the dependency via `cargo`: ```toml rustls-platform-verifier = "0.5" ``` To get a rustls `ClientConfig` configured to use the platform verifier use: ```rust use rustls::ClientConfig; use rustls_platform_verifier::ConfigVerifierExt; let config = ClientConfig::with_platform_verifier(); ``` This crate will use the [rustls process-default crypto provider](https://docs.rs/rustls/latest/rustls/crypto/struct.CryptoProvider.html#using-the-per-process-default-cryptoprovider). To construct a `ClientConfig` with a different `CryptoProvider`, use: ```rust use rustls::ClientConfig; use rustls_platform_verifier::BuilderVerifierExt; let arc_crypto_provider = std::sync::Arc::new(rustls::crypto::ring::default_provider()); let config = ClientConfig::builder_with_provider(arc_crypto_provider) .with_safe_default_protocol_versions() .unwrap() .with_platform_verifier() .unwrap() .with_no_client_auth(); ``` ### Android Some manual setup is required, outside of `cargo`, to use this crate on Android. In order to use Android's certificate verifier, the crate needs to call into the JVM. A small Kotlin component must be included in your app's build to support `rustls-platform-verifier`. If distributing a library, that component will need to be bundled into your release jar [as it is not yet available on Maven](https://github.com/rustls/rustls-platform-verifier/issues/115). #### Gradle Setup `rustls-platform-verifier` bundles the required native components in the crate, but the project must be setup to locate them automatically and correctly. These steps assume you are using `.gradle` Groovy files because they're the most common, but if you are using Kotlin scripts (`.gradle.kts`) for configuration instead, an example snippet is included towards the end of this section. Inside of your project's `build.gradle` file, add the following code and Maven repository definition. If applicable, this should only be the one "app" sub-project that will actually be using this crate at runtime. With multiple projects running this, your Gradle configuration performance may degrade.
App Snippets `$PATH_TO_DEPENDENT_CRATE` is the relative path to the Cargo manifest (`Cargo.toml`) of any crate in your workspace that depends on `rustls-platform-verifier` from the location of your `build.gradle` file: ```groovy import groovy.json.JsonSlurper // ...Your own script code could be here... repositories { // ... Your other repositories could be here... maven { url = findRustlsPlatformVerifierProject() metadataSources.artifact() } } String findRustlsPlatformVerifierProject() { def dependencyText = providers.exec { it.workingDir = new File("../") commandLine("cargo", "metadata", "--format-version", "1", "--filter-platform", "aarch64-linux-android", "--manifest-path", "$PATH_TO_DEPENDENT_CRATE/Cargo.toml") }.standardOutput.asText.get() def dependencyJson = new JsonSlurper().parseText(dependencyText) def manifestPath = file(dependencyJson.packages.find { it.name == "rustls-platform-verifier-android" }.manifest_path) return new File(manifestPath.parentFile, "maven").path } ``` Then, wherever you declare your dependencies, add the following: ```groovy implementation "rustls:rustls-platform-verifier:latest.release" ```
Library Snippets ```groovy import groovy.json.JsonSlurper // ...Your own script code could be here... File findRustlsPlatformVerifierClasses() { def dependencyText = providers.exec { it.workingDir = new File("../") commandLine("cargo", "metadata", "--format-version", "1") }.standardOutput.asText.get() def dependencyJson = new JsonSlurper().parseText(dependencyText) def manifestFile = file(dependencyJson.packages.find { it.name == "rustls-platform-verifier-android" }.manifest_path) return new File(manifestFile.parentFile, "classes.jar") } ``` Then, wherever you declare your dependencies, add the following: ```groovy implementation files(findRustlsPlatformVerifierClasses()) ```
Cargo automatically handles finding the downloaded crate in the correct location for your project. It also handles updating the version when new releases of `rustls-platform-verifier` are published. If you only use published releases, no extra maintenance should be required. These script snippets can be tweaked as best suits your project, but the `cargo metadata` invocation must be included so that the Android implementation part can be located on-disk. ##### Kotlin and Gradle
Kotlin script App example `build.gradle.kts`: ```kotlin import kotlinx.serialization.decodeFromString import kotlinx.serialization.json.Json import kotlinx.serialization.json.JsonObject import kotlinx.serialization.json.jsonArray import kotlinx.serialization.json.jsonObject import kotlinx.serialization.json.jsonPrimitive buildscript { dependencies { classpath(libs.kotlinx.serialization.json) } } repositories { rustlsPlatformVerifier() } fun RepositoryHandler.rustlsPlatformVerifier(): MavenArtifactRepository { @Suppress("UnstableApiUsage") val manifestPath = let { val dependencyJson = providers.exec { workingDir = File(project.rootDir, "../") commandLine("cargo", "metadata", "--format-version", "1", "--filter-platform", "aarch64-linux-android", "--manifest-path", "$PATH_TO_DEPENDENT_CRATE/Cargo.toml") }.standardOutput.asText val path = Json.decodeFromString(dependencyJson.get()) .getValue("packages") .jsonArray .first { element -> element.jsonObject.getValue("name").jsonPrimitive.content == "rustls-platform-verifier-android" }.jsonObject.getValue("manifest_path").jsonPrimitive.content File(path) } return maven { url = uri(File(manifestPath.parentFile, "maven").path) metadataSources.artifact() } } dependencies { // `rustls-platform-verifier` is a Rust crate, but it also has a Kotlin component. implementation(libs.rustls.platform.verifier) } ``` `libs.version.toml`: ```toml # We always use the latest release because `cargo` keeps it in sync with the associated Rust crate's version. rustls-platform-verifier = { group = "rustls", name = "rustls-platform-verifier", version = "latest.release" } ```
Kotlin script Library example `build.gradle.kts`: ```kotlin import kotlinx.serialization.decodeFromString import kotlinx.serialization.json.Json import kotlinx.serialization.json.JsonObject import kotlinx.serialization.json.jsonArray import kotlinx.serialization.json.jsonObject import kotlinx.serialization.json.jsonPrimitive buildscript { dependencies { classpath(libs.kotlinx.serialization.json) } } fun findRustlsPlatformVerifierClasses(): File { val dependencyJson = providers.exec { workingDir = File(project.rootDir, "../") commandLine("cargo", "metadata", "--format-version", "1") }.standardOutput.asText val path = Json.decodeFromString(dependencyJson.get()) .getValue("packages") .jsonArray .first { element -> element.jsonObject.getValue("name").jsonPrimitive.content == "rustls-platform-verifier-android" }.jsonObject.getValue("manifest_path").jsonPrimitive.content val manifestFile = File(path) return File(manifestFile.parentFile, "classes.jar") } dependencies { implementation(files(findRustlsPlatformVerifierClasses())) } ```
#### Proguard If your Android application makes use of Proguard for optimizations, its important to make sure that the Android verifier component isn't optimized out because it looks like dead code. Proguard is unable to see any JNI usage, so your rules must manually opt into keeping it. The following rule can do this for you: ```text -keep, includedescriptorclasses class org.rustls.platformverifier.** { *; } ``` #### Crate initialization In order for the crate to call into the JVM, it needs handles from Android. These are provided either the `init_external` or `init_hosted` function. These give `rustls-platform-verifier` the resources it needs to make calls into the Android certificate verifier. As an example, if your Rust Android component which the "native" Android part of your app calls at startup has an initialization, like this: ```rust ,ignore #[export_name = "Java_com_orgname_android_rust_init"] extern "C" fn java_init( env: JNIEnv, _class: JClass, context: JObject, ) -> jboolean { // ... initialize your app's other parts here. } ``` In the simplest case, you should to insert a call to `rustls_platform_verifier::android::init_hosted()` here, before any networking has a chance to run. This only needs to be called once and the verifier will be valid for the lifetime of your app's process. ```rust ,ignore extern "C" fn java_init( env: JNIEnv, _class: JClass, context: JObject, ) -> jboolean { // ... initialize your app's other parts here. // Then, initialize the certificate verifier for future use. rustls_platform_verifier::android::init_hosted(&env, context); } ``` In more advanced cases, such as where your code already stores long-lived handles into the Android environment, you can alternatively use `init_external`. This function takes a `&'static` reference to something that implements the `android::Runtime` trait, which the crate then uses to obtain the access when required to the JVM. ## Credits Made with �� by the [1Password](https://1password.com/) and `rustls` teams. Portions of the Android and Windows verifier implementations were adapted and referenced from Chromium's previous verifier implementations as well. #### License Licensed under either of Apache License, Version 2.0 or MIT license at your option.
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in this crate by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. Á /3‰�FK‘F„K¼øƒF—VÉ‚F�VÕ�FÑK«€FáK÷ F7.) G GGtjG4ú¼ƒñFáFäFÔF×FÇFÊF„ÊdÎ -;<÷ DÐ7)T»Ì$V¶½´\ôUÅ• ¬}¼|ÈÏ ¼�ÌœüLlüCw4¿ (7q,Ÿg  q¢g  K$„K  HandshakeSignatureValidÁ¼G²K ServerCertVerifiedÁ”`¼K ServerCertVerifierÁ”t¤ Ó¤�ùU  pki_typesÁL¿•3 ð täÑF CertificateErrorÁ„ôÊI DigitallySignedStructÁ¬†ÊK TlsErrorÁD¦ÛF ÝÝT°ÈJ ÝÝÉJ SignatureSchemeÁ|ÀñS §|à - |©t�´.jmLO.1ü�$'Œ·4뫆 êìÆÈ,�³¡£oq´Ùdlãºü­Jü÷FC Creates a new verifier whose certificate validation is provided byÁüÂ=: WebPKI, using root certificates provided by the platform.Á´².Ê&Bÿ ‰0|¸üÁ ½ü¸Fì‹üƒ MJ WebPKI, using root certificates provided by the platform and augmented byÁüÕ )& the provided extra root certificates.Á¤È €&².Ê&Bÿ¤þÆ€&üó <ŽP€&üø 7�P€&ŸŸ — ¢ó V ~NŸ¢ïÁü… ) €&ð/¬‰0™moü©LÅ €&řǙș­É™Ê™àË™óG*¤�R{9 ½�².Ê&Bÿ¤  ‘�üå<¢�üê7²�ü÷)û%ð/%d‡àÓI‰06d/1‰'�!�!�!!�Ãüò'$º#%&'¥¦§¨#&'%ü�(­” (EFGHIJKL Eº FŸŸ — ¢ó V ~NŸ¢ïÁG H ŸŸ — ¢ó V ~NŸ¢ïÁI JÑÓÔDnsNameÁÕóÖ× IpAddressÁØó/­+£õK L£XææçUnixTimeÁèó ÞÓJñ­N�ÞÀœÜÄœ¯ÅœóƜǜ€Èœó‘¥_¿´Òw¼K¼K½K£ˆ¾KóŒ yFÅÙ3Û”œ'Bÿ" ¼(" #$½( end_entityÁTË( intermediatesÁlÿ( server_nameÁ\¸) ocsp_responseÁlå)nowÁƒ*²-#�$�$�$$#$œ'œ'Uÿ¾#ü¬.Ç´¯.MNOPQ Mº N£X OŸŸ — ¢ó V ~NŸ¢ïÁP QÊKÊKЉËKschemeÁÌKsigÁŒ (ôŸéÌb²ÀœÜÄœ¯ÅœóƜǜ€Èœó‘¥_¿´Òw²K²K³Kú‡´KóŒ ÞC'C�ù݇œ'Bÿ" Ï." %$Ð.© <Þ.Îà$ö.dssÁ¤/ü¿0Ç´Â0RSTUV Rº S£X TŸŸ — ¢ó V ~NŸ¢ïÁU VÆš‡›Bÿ" â0" &$ã0© <ñ0Îà$‰1»›·1üÒ2:ÄÕ2W Wº…C…CüˆCž#Ð=‰C¶Ð=ò¹ÚàÅñSòSóSRSA_PKCS1_SHA1ÁôSõSECDSA_SHA1_LegacyÁöS÷SRSA_PKCS1_SHA256ÁøSùSECDSA_NISTP256_SHA256ÁúSûSRSA_PKCS1_SHA384ÁüSýSECDSA_NISTP384_SHA384ÁþSÿSRSA_PKCS1_SHA512Á€T�TECDSA_NISTP521_SHA512Á‚TƒTRSA_PSS_SHA256Á„T…TRSA_PSS_SHA384Á †T‡TRSA_PSS_SHA512Á ˆT‰TED25519Á ŠT‹TED448Á ŒT�T ML_DSA_44Á ŽT�T ML_DSA_65Á�T‘T ML_DSA_87Á’T“TUnknownÁ”Tó·UWÒÍIª™¤!Bÿ" î2" '$ï2üÆ3/ŒÉ3 œ'œ'Bÿ (errÁÛ3„ÈÌ$Û¶½´áôÚÅ• ¬‚¼�ÈÏ ¼¢Ì¡üÑlüÈw[ü÷#õ+¥g+ü¡B¤]^_ ]õ ^€g€gŠ‚gê ûcƒgž#ûcØ«q¢1È¡_ï"Bÿ* ¨* +$©œ ¯ü©#õüÚ G|Ý  `a `ŸŸ — ¢ó V ~NŸ¢ïÁa¾#Bÿ ú  - _end_entityÁ\í ´ä•Väó üŸ SP Extension trait to help configure [`ClientConfig`]s with the platform verifier.Á”ý //ÿÆüó ê/®¨®¨!000üåvü– =: Configures the `ClientConfig` with the platform verifier.ÁØ �\à  ```rustÁìð  use rustls::ClientConfig;Áü’ 52 use rustls_platform_verifier::BuilderVerifierExt;ÁüÌ (% let config = ClientConfig::builder()Áüù ! .with_platform_verifier()ÁŒŸ .unwrap()Áüµ .with_no_client_auth();Á<Ù ```Á´è¶¨ÀœÜÄœ¯ÅœóƜǜ€Èœó‘¥_¿´ÒwÑKÑKÕÔKƒÕKöÖK‰×K¡âÙŸ4š²D�¿—V—V¼ø˜Vç×!™Vû×!šVÌ×!yC9b¥¡Pœ'Bÿ// 0¶¨$ˆüßFË202ü¬u´¯Ë…¬Bÿ11 2$ÏܱüàPM Extension trait to help build a [`ClientConfig`] with the platform verifier.ÁŒ»33®¨ü±�3®¨®¨!444üíCüÓYV Build a [`ClientConfig`] with the platform verifier and the default `CryptoProvider`.Á±�\¹ǨìÉÛ¨üë41 use rustls_platform_verifier::ConfigVerifierExt;Áü¤85 let config = ClientConfig::with_platform_verifier();Á<á઴ðÀœÜÄœ¯ÅœóƜǜ€Èœó‘¥_¿´Òw¿œ'Bÿ33 4¶¨ü´'¿646üâB´åÁ²Bÿ55 6œÐüòLI A TLS certificate verifier that uses the system's root store and WebPKI.ÁDÛºt|žP š8ü¾ ,¾ 77ýz º: g:zzBCD Bº C€g€gŠ‚gê ûcƒgž#ûcØ«q¢1È¡Dï"Bÿ9È9 :zœzÔÚDìõbíègW8¨h<.(;;õ2`"õ> g>M`P`XYZ Xõ Y€g€gŠ‚gê ûcƒgž#ûcØ«q¢1È¡Zï"Bÿ=$Ç= >ç`œî`Z`#õl`#õAù±Aˆ`‹`[\ [õ \õBÿ@%Î@ AÞ`î å`½‚Âz‚‚ ×(‚ò(‚ Ž)‚ª)‚ Å)‚TÑ)‚ ô)‚)‚ ç.‚ ü.‚—/‚ ©/‚w‚ ú0‚ �1‚ª1‚ ¼1‚â ‚;‚A‚b‚¿‚Ä‚¸ ‚ ²‚Ë‚+ ‚� ‚KŒÓ(https://docs.rs/rustls-platform-verifierÁcrates.io downloadsÁCA constraintsÁÉ&rustls process-default crypto providerÁFhttps://docs.rs/rustls/latest/rustls/crypto/struct.CryptoProvider.htmlÁ#as it is not yet available on MavenÁ-https://github.com/rustls/rustls-native-certsÁ openssl-probeÁŒÓ-https://github.com/alexcrichton/openssl-probeÁcrate documentationÁκûºÉ�V]https://docs.rs/rustls-platform-verifier/latest/rustls_platform_verifier/struct.Verifier.htmlÁ«»Ö»rustls-native-certsÁɼû¼÷ ŒÓhttps://1password.com/Á1https://crates.io/crates/rustls-platform-verifierÁŽκVerifier::new_with_extra_rootsÁ󽫻Qhttps://docs.rs/rustls/latest/rustls/client/struct.ServerCertVerifierBuilder.htmlÁá¾ɼ÷  1PasswordÁ�¿crates.io versionÁ«¿Ž&https://github.com/rustls/webpki-rootsÁí¿ó½(https://support.apple.com/en-us/HT212865ÁœÀá¾÷ 7=https://github.com/rustls/rustls-platform-verifier/issues/115ÁƒÁ�¿—Á«¿ webpki-rootsÁ¹Áí¿“»ðÁœÀ¡¼²ÂƒÁ—Á“½ŒÃ¹Áûº“»ðÁÉÖ»¡¼²Âû¼“½ŒÃ/3…ù öÌí÷±¯²ŠP³¯ÿ ¦£¬©€#…#ˆ#‹#Î!Ñ!Ö!ÔPŽQ—PŽPÄQýÆþÆÈǵì6Verifierinnerÿÿ<À9 platform CA root certificates were ignored due to errors<&#Error loading CA root certificate: À&.No CA certificates were loaded from the system.ÿÿ0Loaded À% CA root certificates from the system0.rustls_platform_verifier::verification::others.EkuErrorˆÅ—Å£ÅÂÅÅňƵÆêƉÇÀÇõÇõùì|x䨅ï!ýž�íœ0 ŠöŸúkRI ÜóâZy©üÁ1¶È_a;ð(�ûžÔrõõƒéh<ד¥h£ïS'mˆ¦Ø1±ÑùóZZz-äÐ|ãPæb65I~ì“ åÕvq¦�Vݺb¾Ñ·É~‰è'k–Fž”�»ª“ƒ {ôDŸPž÷*ÖWÿ7Ôaܙ Hµ#cÛýÏÿU—Óà‡nj×® .žd šÓ‡Fæ¼°(o䌣ÝsV=yéÚè®´Ò °,™°Uzxf†ÔôÿÐЀΤ·||i˜l5åó‡e!'`PÔjö@7�íc;ö¼.�Hñeí¡Š ô '»öëBmt� k >@XxãN(ÚÂÈDýãÝE ^v”°#\±ÓÖ ó*×9KG ¦rÏž(™ÐÉ‘)NAל�Oí.HQ4Ò6�uë6O'i`ƒÌ8_Zœ .ðO亙åÍÊ)™d’xtÖÖ3ê[C‚ÆåVx½†, ÒcVˆÁ+äý_wXíÀf–”n“W ‡X_ÔTþ™Óİ£€°ä"|€y5†µ¡?è[Ÿãà!Gó¹e©~™‚w6Lh2ý,µ®ƒÿ!ñøÏúmx€ðÆ#«¾Xz=`®0�=�ôóˆÎñKNú¼^Øâ¢HW;M‘‹ÇÐVí�WJw9®½û_¡Ü;áxò;Y¯öľ¨Þï“}Ð%MS/§ó;gëâS äëéÉÔ:¥�§ãµ‡@áDrÖiâÌt_ýä 6Ý~»ÓÒ†*øØRXô$ÜÂâ„2p¬ïê_M‹©Fh]ä€y™ ±äEdzó¶*þ72oâ™<\Oúi‘:\8KѪ ‚ÊÍÞøO°µeò ØŽVè** Un<±}â-A§/´ä8»“jà &L å™À„ÜG7¡ÈveØuž§=v�a± ø(†Húƒ-kÇÍBn54æK—CW�j¢ÛÃw"ú% �ýÐiÓá�3ôõ´+Ée'PÞ²_º*ÒÓwרÓ}×EݪÂc̨̮|0Ã3Ã:Ã>ÃDÃJÃPÃWÃwÃqÅwÅ}ŀņŌŔśŢŦūůŵŹŽÅÃÅÉÅáŹÆÈæÈ/ÉhÉÛË8ÌÊÍ›Î8ÑuÑÉÑäьҞÒ.Ó5Óê Ó�ÖªÖçÖ�×0ÙJÙ~ÙÿÙÚ1ÚÖÚ+ÛFÛêÛüÛܧÂ_ÃÄÃÞÓƒ×ÕÅ=ÉÕјÒßӜք×<ÙùÙ$ÚÛ9ÛøÛ Ü    (¦Â]ÃÂÃ’ÆkÇ4È€ÉPÌâͳÎPÑüѶҘÓ~ÕÂÖG×½ØbÙÚÙÚHÚÞÚÛ]Û/Ü©|'Ã-Ã0Ã6Ã:ÃAÃGÃMÃSÃsÃnÅtÅzÅ}ŃʼnÅ�ŗŞŢũŭűŷŻſÅÅÅÜÅ³Æ ÈÈÕÈâÈ*ÉbÉ×Ë2ÌÄÍ–Î3ÑqÑÄÑßчҙÒ*Ó1ÓåÓ‹Ö¥ÖãÖŠ×+ÙEÙzÙúÙÚ.ÚÒÚÛ(ÛCÛçÛùÛÜuÜ{Ü�܇Ü�ܔܛܢܩܷܾܰÜÄÜËÜÒÜÙÜàÜæÜíÜôÜûÜÝÝÝÝÝÝ$Ý*Ý1Ý8Ý>Ý*Ã3Ã>ÃDÃJÃPÃYþÃqÅwŀņŌŔśŦūůŵŹŽÅÃÅzÆSÇ ÈÈ×ÈhÉ8ÌÊÍ›Î8ÑÁÑäÑžÒ.Ó”ÓfÕªÖC×¥ØJÙÖÙÿÙ1ÚÚÚÛFÛÜxÜ~܄܊ܑܘܟܦܭܴܻÜÁÜÈÜÏÜÖÜÝÜãÜêÜñÜøÜÿÜÝ ÝÝÝÝ!Ý'Ý.Ý5Ý;ÝBÝÑţƌÇÈžÈßÈ#É9ÉnËÌ™ÍmÎ$Ñ`ÑÑÑpÒ”ÒÓ«ÓxÖ˜ÖÔÖZ×Ù8ÙrÙáÙ Ú Ú½ÚæÚ"Û5ÛÒÛôÛÜ`ÜËÅ›ÆwÇ È‰ÈÙÈúÈ3ÉbËïË�ÍaÎÑZÑËÑdÒŽÒÓ™ÓpÖ’ÖÌÖH×Ù2ÙjÙÛÙÚÚ°ÚàÚÛ/ÛÅÛîÛÜSÜÓŧÆôǽÈ'É;ÉrËÌ�ÍqÎ(ÑbÑÓÑtÒ–ÒÓ|ÖšÖØÖ#Ù:ÙvÙãÙÚ"ÚÁÚèÚ&Û7ÛÖÛöÛÜdÜ“ÆlÇ6È�ÉQÌãÍ´ÎRÑýѸÒÕÃÖ¾ØcÙÛÙIÚàÚÛ^Û0Ü“ÆmÇ7È�ÉQÌãÍ´ÎRÑýѸҀÕÃÖ¿ØcÙIÚ^Û0Ü~ÆWÇ ÈæÈlÉÛË<ÌÎÍŸÎ<ÑèÑ¢ÒjÕ®Ö©ØNÙ4ÚÛIÛÜf ³ ½ Ç w5 p š ¥ ÈáÈÁÓf×8Ãv×òz‹{6{uðz‰{ü{7|uñzŠ{ý{«ÆûÇ¿ÈvË¡ÍuÎ,ÑfÑxÒÓ„ÖÜÖ+ÙzÙÅÚÚÛhÜÂÓgפÂWüÃÉÅ1ÉÉьҒÓ�ÖA×0ÙÔÙÚØÚ-ÛìÛþÛòÙ÷ÚåÙêÚô÷þ -:>BFJNRVZ^bfjnrvz~… ãóúþ   < Y x � ” ˜ Ÿ £ ¹ ½ Ö ó ÷ þ   ! ( / ; ? F U Y ] d h l s y  … ‹ ‘ — � £ © ¯ µ » Á Ç Í Ó Ù ß å ë ñ ÷ ý     ! ' - ôÙùÚØÅÙÅÚÅAÉFÉKÉPÉÖÑàÓ�Ö…×=Ù%Ú:Û Ü|||||| | |||||þ{||FÝ"âÛÅUÉÛјÒáÓ¡Ö†×AÙ*Ú?ÛøÛÜ2+6#%&'Å9ɤ!+'.) +ØŽ #$0* ר †Á"&É(¹, ¨Ø®%‚‚ ¶'‚úûèõùì|x䨙Ý3Ìh¾(É„¿…ÿ‚]´œõùì|x䨼æûš^ƒ -ü¬F‚õùì|x䨭0L¬«'`"$crate::__private_api::format_argsÁùÚ#-Åõ‘] fmt_internalsÁfmt_arguments_from_strÁžœõùì|xä¨=ÓDÊ5½ $crate::__logÁ ù ¦»•Œ  õùì|xä¨ÐdsQH0 3‚ï÷ÿ÷õùì|xä¨eAà‰·øù¦»_  õùì|xä¨Uÿ'-(ýq,È}©Ø core_intrinsicsÁfmt_helpers_for_deriveÁ¢g¡gõùì|xä¨DþŒ$¸&Þ �-‚ï÷ÿ÷õùì|xä¨ÍŻȲ™ÿ¾$crate::__log_loggerÁ ù Ê*ͧv õùì|xä¨Lk[@XxãN(Ú".�Hñeí¡ŠÂÈDýãÝE #/§ó;gëâSEDrÖiâÌt_Húi‘:\8KÑQøO°µeò ØS<±}â-AU7¡ÈveØužYý_wXíÀ2§=v�a± øZôóˆÎñKNú>䌣ÝsV=yžÔrõõƒœ0 ŠöŸúDŸPž÷*ÖWƒÿ!ñøÏúm;Ò†*øØRXJ¢ÛÃw"ú%^á�3ôõ´+É`¤·||i˜l€°ä"|€y6ÿ4|ÿ5;rÿÿW#ÿÿÿÿr'NoÿMvzTi,O)I7ÿÿ>/ÿH/ÿXpD45!7ÿÿOÿÿÿrQ5H ÿaÿÿ]gNiD 3%ÿÿÿ-iq$^mE)/hl O |ÿÿ}ÿ<ÿA+6,d6<ÿÿÿ4|ÿ5;rÿÿd/root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/rustls-platform-verifier-0.7.0/src/lib.rsÁY/root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/rustls-platform-verifier-0.7.0Ád/root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/rustls-platform-verifier-0.7.0/src/lib.rsÁ 1àÒÿA}]ˆŸÐߺtõBZ��\''$'S 9= 553+ :2 <DV##*;BTB":-&$ NIOGCQ^"9= H*I#'$Îöî­!S."<Y@&2.9@KR.S.%5>A.2G\V! 9þ‡3Œr“)õ¯Ä-ev}_j/root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/rustls-platform-verifier-0.7.0/src/../README.mdÁY/root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/rustls-platform-verifier-0.7.0Áj/root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/rustls-platform-verifier-0.7.0/src/../README.mdÁ ‹õà¢GéÀr;ùWókrà‹à‹ñˆw;ŠTrcTˆO?`9khi[m^m wr#qžE?7�3ÝÝÝÝݪµ›µ»^ µ\¬¡¶UP.6¯¦Y!L15ý2YF+ ]Y®f}‹z¨†  ¤* ,4 2#-*(ª"Ez;A @  $ ,+*(B"Ez<A : �‡Š, - .'-,-03J".6® K" pI?#W2no  1 .'-,-030*2BGlE"8? ”’LRiLID63nQC3ACWX\? }g JAPPGä†ç† ’$Þá4ªü=•?úlãW  í.x86_64-unknown-linux-gnuÁ z–ÆMÓÄ9'õ†Ú·AÛrustls_platform_verifierÁ-9481411cb67ce396Áõùì|x䍸§¹ Å ü Õª!b�44œœ8¨ !BBB9B59B54ÆAœbÃBbb„bÄÄBB„B„B„BÆB„A„‚4Bh„B„B„BÆ4Ah‚<