package Ġnet . cord a . core . internal Ċ Ċ import Ġnet . cord a . core . identity . C ord a X 5 0 0 Name Ċ import Ġnet . cord a . core . identity . Party Ċ import Ġnet . cord a . testing . core . AL ICE _ NAME Ċ import Ġnet . cord a . testing . core . BO B _ NAME Ċ import Ġorg . assertj . core . api . Assertions . assertThat Ċ import Ġorg . junit . After Ċ import Ġorg . junit . After Class Ċ import Ġorg . junit . BeforeClass Ċ import Ġorg . junit . Test Ċ import Ġjava . io . FileInputStream Ċ import Ġjava . nio . file . Files Ċ import Ġjava . nio . file . Path Ċ import Ġjava . nio . file . Paths Ċ import Ġjava . util . jar . Jar InputStream Ċ import Ġkotlin . test . assertEquals Ċ import Ġkotlin . test . assert Fails With Ċ Ċ class ĠJar Signature Collector Test Ġ{ ĊĠĠĠ Ġcompanion Ġobject Ġ{ ĊĠĠĠĠĠĠĠ Ġprivate Ġval Ġdir Ġ= ĠFiles . create Temp Directory ( Jar Signature Collector Test :: class . simple Name ) ĊĠĠĠĠĠĠĠ Ġprivate Ġval Ġbin Ġ= ĠPaths . get ( System . getProperty (" java . home ")). let Ġ{ Ġif Ġ( it . endsWith (" jre ")) Ġit . parent Ġelse Ġit Ġ} Ġ/ Ġ" bin " ĊĠĠĠĠĠĠĠ Ġprivate Ġval Ġsh red der Ġ= Ġ( dir Ġ/ Ġ"_ sh red der "). to File () Ġ// ĠNo Ġneed Ġto Ġdelete Ġafter Ġeach Ġtest . ĊĊĠĠĠĠĠĠĠ Ġfun Ġexecute ( var arg Ġcommand : ĠString ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠassertEquals ( 0 , ĠProcess Builder () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. inherit IO () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. redirect Output ( sh red der ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. directory ( dir . to File ()) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. command (( bin Ġ/ Ġcommand [ 0 ]). toString (), Ġ* command . slice Array ( 1 Ġuntil Ġcommand . size )) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. start () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. waitFor ()) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġprivate Ġconst Ġval ĠFIL ENAME Ġ= Ġ" attachment . jar " ĊĠĠĠĠĠĠĠ Ġprivate Ġconst Ġval ĠA LIC E Ġ= Ġ" alice " ĊĠĠĠĠĠĠĠ Ġprivate Ġconst Ġval ĠA LIC E _ PASS Ġ= Ġ" alice pass " ĊĠĠĠĠĠĠĠ Ġprivate Ġconst Ġval ĠB OB Ġ= Ġ" bob " ĊĠĠĠĠĠĠĠ Ġprivate Ġconst Ġval ĠB OB _ PASS Ġ= Ġ" bob pass " ĊĊĠĠĠĠĠĠĠ Ġprivate Ġfun Ġgenerate Key ( alias : ĠString , Ġpassword : ĠString , Ġname : ĠC ord a X 5 0 0 Name ) Ġ= ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġexecute (" key tool ", Ġ"- gen key ", Ġ"- keystore ", Ġ"_ test store ", Ġ"- store pass ", Ġ" store pass ", Ġ"- key alg ", Ġ" RSA ", Ġ"- alias ", Ġalias , Ġ"- key pass ", Ġpassword , Ġ"- d name ", Ġname . toString ()) ĊĊĠĠĠĠĠĠĠ Ġ@ BeforeClass ĊĠĠĠĠĠĠĠ Ġ@ Jvm Static ĊĠĠĠĠĠĠĠ Ġfun Ġbefore Class () Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġgenerate Key ( AL ICE , ĠA LIC E _ PASS , ĠA LIC E _ NAME ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġgenerate Key ( BO B , ĠB OB _ PASS , ĠB OB _ NAME ) ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġ( dir Ġ/ Ġ"_ sign able 1 "). write Lines ( listOf (" sign able 1 ")) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ( dir Ġ/ Ġ"_ sign able 2 "). write Lines ( listOf (" sign able 2 ")) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ( dir Ġ/ Ġ"_ sign able 3 "). write Lines ( listOf (" sign able 3 ")) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġ@ After Class ĊĠĠĠĠĠĠĠ Ġ@ Jvm Static ĊĠĠĠĠĠĠĠ Ġfun Ġafter Class () Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġdir . delete Re cursively () ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġval ĠList < Party >. names Ġget () Ġ= Ġmap Ġ{ Ġit . name Ġ} ĊĊĠĠĠ Ġ@ After ĊĠĠĠ Ġfun ĠtearDown () Ġ{ ĊĠĠĠĠĠĠĠ Ġdir . list Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġit . filter Ġ{ Ġ! it . fileName . toString (). startsWith ("_ ") Ġ}. forEach ( Path :: delete Re cursively ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ ĠassertThat ( dir . list ()). has Size ( 5 ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ Test ĊĠĠĠ Ġfun Ġ` empty Ġjar Ġhas Ġno Ġsign ers `() Ġ{ ĊĠĠĠĠĠĠĠ Ġ( dir Ġ/ Ġ" META - INF "). create Directory () Ġ// ĠAt Ġleast Ġone Ġarg Ġis Ġrequired , Ġand Ġjar Ġcv f Ġconvenient ly Ġignores Ġthis . ĊĠĠĠĠĠĠĠ Ġcreate Jar (" META - INF ") ĊĠĠĠĠĠĠĠ ĠassertEquals ( emptyList (), Ġget Jar Sign ers ()) ĊĊĠĠĠĠĠĠĠ Ġsign As Alice () ĊĠĠĠĠĠĠĠ ĠassertEquals ( emptyList (), Ġget Jar Sign ers ()) Ġ// ĠThere Ġneeds Ġto Ġhave Ġbeen Ġa Ġfile Ġfor ĠA LIC E Ġto Ġsign . ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ Test ĊĠĠĠ Ġfun Ġ` unsigned Ġjar Ġhas Ġno Ġsign ers `() Ġ{ ĊĠĠĠĠĠĠĠ Ġcreate Jar ("_ sign able 1 ") ĊĠĠĠĠĠĠĠ ĠassertEquals ( emptyList (), Ġget Jar Sign ers ()) ĊĊĠĠĠĠĠĠĠ Ġupdate Jar ("_ sign able 2 ") ĊĠĠĠĠĠĠĠ ĠassertEquals ( emptyList (), Ġget Jar Sign ers ()) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ Test ĊĠĠĠ Ġfun Ġ` one Ġsigner `() Ġ{ ĊĠĠĠĠĠĠĠ Ġcreate Jar ("_ sign able 1 ", Ġ"_ sign able 2 ") ĊĠĠĠĠĠĠĠ Ġsign As Alice () ĊĠĠĠĠĠĠĠ ĠassertEquals ( listOf ( AL ICE _ NAME ), Ġget Jar Sign ers (). names ) Ġ// ĠWe Ġonly Ġreused ĠA LIC E 's Ġdistingu ished Ġname , Ġso Ġthe Ġkeys Ġwill Ġbe Ġdifferent . ĊĊĠĠĠĠĠĠĠ Ġ( dir Ġ/ Ġ" my - dir "). create Directory () ĊĠĠĠĠĠĠĠ Ġupdate Jar (" my - dir ") ĊĠĠĠĠĠĠĠ ĠassertEquals ( listOf ( AL ICE _ NAME ), Ġget Jar Sign ers (). names ) Ġ// ĠUnsigned Ġdirectory Ġis Ġir relevant . ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ Test ĊĠĠĠ Ġfun Ġ` two Ġsign ers `() Ġ{ ĊĠĠĠĠĠĠĠ Ġcreate Jar ("_ sign able 1 ", Ġ"_ sign able 2 ") ĊĠĠĠĠĠĠĠ Ġsign As Alice () ĊĠĠĠĠĠĠĠ Ġsign As Bob () ĊĊĠĠĠĠĠĠĠ ĠassertEquals ( listOf ( AL ICE _ NAME , ĠB OB _ NAME ), Ġget Jar Sign ers (). names ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ Test ĊĠĠĠ Ġfun Ġ` all Ġfiles Ġmust Ġbe Ġsigned Ġby Ġthe Ġsame Ġset Ġof Ġsign ers `() Ġ{ ĊĠĠĠĠĠĠĠ Ġcreate Jar ("_ sign able 1 ") ĊĠĠĠĠĠĠĠ Ġsign As Alice () ĊĠĠĠĠĠĠĠ ĠassertEquals ( listOf ( AL ICE _ NAME ), Ġget Jar Sign ers (). names ) ĊĊĠĠĠĠĠĠĠ Ġupdate Jar ("_ sign able 2 ") ĊĠĠĠĠĠĠĠ Ġsign As Bob () ĊĠĠĠĠĠĠĠ Ġassert Fails With < Invalid Jar Sign ers Exception >( ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ""" ĊĠĠĠĠĠĠĠĠĠĠĠ ĠMis match Ġbetween Ġsign ers Ġ[ O = Alice ĠCorp , ĠL = Mad rid , ĠC = ES , ĠO = Bob ĠPl c , ĠL = R ome , ĠC = IT ] Ġfor Ġfile Ġ_ sign able 1 ĊĠĠĠĠĠĠĠĠĠĠĠ Ġand Ġsign ers Ġ[ O = Bob ĠPl c , ĠL = R ome , ĠC = IT ] Ġfor Ġfile Ġ_ sign able 2 . ĊĠĠĠĠĠĠĠĠĠĠĠ ĠSee Ġhttps :// docs . cord a . net / design / data - model - upgrade s / signature - constraints . html Ġfor Ġdetails Ġof Ġthe ĊĠĠĠĠĠĠĠĠĠĠĠ Ġconstraints Ġapplied Ġto Ġattachment Ġsignatures . ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ""" . trim Indent (). replace ('\ n ', Ġ' Ġ') ĊĠĠĠĠĠĠĠ Ġ) Ġ{ Ġget Jar Sign ers () Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ Test ĊĠĠĠ Ġfun Ġ` bad Ġsignature Ġis Ġcaught Ġeven Ġif Ġthe Ġparty Ġwould Ġnot Ġqual ify Ġas Ġa Ġsigner `() Ġ{ ĊĠĠĠĠĠĠĠ Ġ( dir Ġ/ Ġ" volatile "). write Lines ( listOf (" volatile ")) ĊĠĠĠĠĠĠĠ Ġcreate Jar (" volatile ") ĊĠĠĠĠĠĠĠ Ġsign As Alice () ĊĠĠĠĠĠĠĠ ĠassertEquals ( listOf ( AL ICE _ NAME ), Ġget Jar Sign ers (). names ) ĊĊĠĠĠĠĠĠĠ Ġ( dir Ġ/ Ġ" volatile "). write Lines ( listOf (" garbage ")) ĊĠĠĠĠĠĠĠ Ġupdate Jar (" volatile ", Ġ"_ sign able 1 ") Ġ// ĠA LIC E 's Ġsignature Ġon Ġvolatile Ġis Ġnow Ġbad . ĊĠĠĠĠĠĠĠ Ġsign As Bob () ĊĠĠĠĠĠĠĠ Ġ// ĠThe ĠJDK Ġdoesn 't Ġcare Ġthat ĠB OB Ġhas Ġcorrectly Ġsigned Ġthe Ġwhole Ġthing , Ġit Ġwon 't Ġlet Ġus Ġprocess Ġthe Ġentry Ġwith ĠA LIC E 's Ġbad Ġsignature : ĊĠĠĠĠĠĠĠ Ġassert Fails With < Security Exception > Ġ{ Ġget Jar Sign ers () Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ// region ĠHelper Ġfunctions ĊĠĠĠ Ġprivate Ġfun Ġcreate Jar ( var arg Ġcontents : ĠString ) Ġ= ĊĠĠĠĠĠĠĠĠĠĠĠ Ġexecute (*( array Of (" jar ", Ġ" cv f ", ĠFIL ENAME ) Ġ+ Ġcontents )) ĊĊĠĠĠ Ġprivate Ġfun Ġupdate Jar ( var arg Ġcontents : ĠString ) Ġ= ĊĠĠĠĠĠĠĠĠĠĠĠ Ġexecute (*( array Of (" jar ", Ġ" uv f ", ĠFIL ENAME ) Ġ+ Ġcontents )) ĊĊĠĠĠ Ġprivate Ġfun Ġsign Jar ( alias : ĠString , Ġpassword : ĠString ) Ġ= ĊĠĠĠĠĠĠĠĠĠĠĠ Ġexecute (" jar signer ", Ġ"- keystore ", Ġ"_ test store ", Ġ"- store pass ", Ġ" store pass ", Ġ"- key pass ", Ġpassword , ĠFIL ENAME , Ġalias ) ĊĊĠĠĠ Ġprivate Ġfun Ġsign As Alice () Ġ= Ġsign Jar ( AL ICE , ĠA LIC E _ PASS ) ĊĠĠĠ Ġprivate Ġfun Ġsign As Bob () Ġ= Ġsign Jar ( BO B , ĠB OB _ PASS ) ĊĊĠĠĠ Ġprivate Ġfun Ġget Jar Sign ers () Ġ= ĊĠĠĠĠĠĠĠĠĠĠĠ ĠJar InputStream ( FileInputStream (( dir Ġ/ ĠFIL ENAME ). to File ())). use ( Jar Signature Collector :: collect Signing Part ies ) ĊĠĠĠ Ġ// endregion Ċ Ċ } Ċ