package Ġid . walt . services . keystore Ċ Ċ import Ġid . walt . crypto .* Ċ import Ġmu . Kotlin Logging Ċ import Ġjava . io . File Ċ import Ġjava . io . File OutputStream Ċ import Ġjava . nio . file . Files Ċ import Ġjava . nio . file . Paths Ċ import Ġjava . security . Key Factory Ċ import Ġjava . security . PrivateKey Ċ import Ġjava . security . PublicKey Ċ import Ġjava . security . spec . PKCS 8 Encoded KeySpec Ċ import Ġjava . security . spec . X 5 0 9 Encoded KeySpec Ċ Ċ open Ġclass ĠFileSystem KeyStore Service Ġ: ĠKey Store Service () Ġ{ ĊĊĠĠĠ Ġprivate Ġval Ġlog Ġ= ĠKotlin Logging . logger Ġ{} ĊĊĠĠĠ Ġ// TODO : Ġget Ġkey Ġformat Ġfrom Ġconfig ĊĠĠĠ Ġprivate Ġval ĠKEY _ FORMAT Ġ= ĠKey Format . PEM ĊĊĠĠĠ Ġinit Ġ{ ĊĠĠĠĠĠĠĠ ĠFile ( KEY _ DIR _ PATH ). mkdir s () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġoverride Ġfun Ġlist Keys (): ĠList < Key > Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġkeys Ġ= ĠArrayList < Key >() ĊĠĠĠĠĠĠĠ ĠFiles . walk ( Paths . get ( KEY _ DIR _ PATH )) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. filter Ġ{ ĠFiles . is Regular File ( it ) Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. filter Ġ{ Ġit . toString (). endsWith (". meta ") Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. forEach Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġkey Id Ġ= Ġit . fileName . toString (). substring Before (".") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġload ( key Id ). let Ġ{ Ġkey Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġkeys . add ( key ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġreturn Ġkeys ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġoverride Ġfun Ġload ( alias : ĠString , Ġkey Type : ĠKey Type ): ĠKey Ġ{ ĊĠĠĠĠĠĠĠ Ġlog . debug Ġ{ Ġ" Loading Ġkey Ġ\" ${ alias }\" ." Ġ} ĊĊĠĠĠĠĠĠĠ Ġval Ġkey Id Ġ= Ġget KeyId ( alias ) Ġ?: Ġalias ĊĊĠĠĠĠĠĠĠ Ġval ĠmetaData Ġ= ĠString ( load Key File ( key Id , Ġ" meta ")) ĊĠĠĠĠĠĠĠ Ġval Ġalgorithm Ġ= ĠmetaData . substring Before ( delimiter Ġ= Ġ"; ") ĊĠĠĠĠĠĠĠ Ġval Ġprovider Ġ= ĠmetaData . substring After ( delimiter Ġ= Ġ"; ") ĊĠĠĠĠĠĠĠ Ġval Ġpublic Part Ġ= ĠFile ("$ KEY _ DIR _ PATH /$ key Id . enc - pubkey "). read Text () ĊĠĠĠĠĠĠĠ Ġval Ġprivate Part Ġ= ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( key Type Ġ== ĠKey Type . PRIVATE ) ĠFile ("$ KEY _ DIR _ PATH /$ key Id . enc - priv key "). read Text () Ġelse Ġnull ĊĊĠĠĠĠĠĠĠ Ġreturn Ġbuild Key ( key Id , Ġalgorithm , Ġprovider , Ġpublic Part , Ġprivate Part , ĠKEY _ FORMAT ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġoverride Ġfun Ġadd Alias ( key Id : ĠKey Id , Ġalias : ĠString ) Ġ{ ĊĠĠĠĠĠĠĠ ĠFile ("${ KEY _ DIR _ PATH }/ Alias -$ alias "). write Text ( key Id . id ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġoverride Ġfun Ġstore ( key : ĠKey ) Ġ{ ĊĠĠĠĠĠĠĠ Ġadd Alias ( key . key Id , Ġkey . key Id . id ) ĊĠĠĠĠĠĠĠ Ġstore Key MetaData ( key ) ĊĠĠĠĠĠĠĠ Ġstore PublicKey ( key ) ĊĠĠĠĠĠĠĠ Ġstore PrivateKey When Existing ( key ) Ċ Ċ // ĠĠĠĠĠĠĠ Ġsave Enc PublicKey ( key . key Id . id , Ġkey . key Pair !!. public ) Ċ // ĠĠĠĠĠĠĠ Ġsave Enc PrivateKey ( key . key Id . id , Ġkey . key Pair !!. private ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġoverride Ġfun Ġget KeyId ( alias : ĠString ) Ġ= Ġrun Catch ing Ġ{ ĠFile ("${ KEY _ DIR _ PATH }/ Alias -$ alias "). read Text () Ġ}. get OrNull () ĊĊĠĠĠ Ġoverride Ġfun Ġdelete ( alias : ĠString ) Ġ{ ĊĠĠĠĠĠĠĠ Ġdelete Key File ( alias , Ġ" enc - pubkey ") ĊĠĠĠĠĠĠĠ Ġdelete Key File ( alias , Ġ" enc - priv key ") ĊĠĠĠĠĠĠĠ Ġdelete Key File ( alias , Ġ" raw - pubkey ") ĊĠĠĠĠĠĠĠ Ġdelete Key File ( alias , Ġ" raw - priv key ") ĊĠĠĠĠĠĠĠ Ġdelete Key File ( alias , Ġ" meta ") ĊĠĠĠĠĠĠĠ Ġdelete Key Alias ( alias ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġstore PublicKey ( key : ĠKey ) Ġ= ĊĠĠĠĠĠĠĠ Ġsave Key Data ( ĊĠĠĠĠĠĠĠĠĠĠĠ Ġkey , Ġ" enc - pubkey ", ĊĠĠĠĠĠĠĠĠĠĠĠ Ġwhen Ġ( KEY _ FORMAT ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠKey Format . PEM Ġ-> Ġkey . get PublicKey (). to PEM () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġ-> Ġkey . get PublicKey (). to Base 6 4 () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ}. toByteArray () ĊĠĠĠĠĠĠĠ Ġ) ĊĊĠĠĠ Ġprivate Ġfun Ġstore PrivateKey When Existing ( key : ĠKey ) Ġ{ ĊĠĠĠĠĠĠĠ Ġif Ġ( key . key Pair Ġ!= Ġnull Ġ&& Ġkey . key Pair !!. private Ġ!= Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġsave Key Data ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġkey , Ġ" enc - priv key ", Ġwhen Ġ( KEY _ FORMAT ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠKey Format . PEM Ġ-> Ġkey . key Pair !!. private . to PEM () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġ-> Ġkey . key Pair !!. private . to Base 6 4 () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ}. toByteArray () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġstore Key MetaData ( key : ĠKey ) Ġ{ ĊĠĠĠĠĠĠĠ Ġsave Key Data ( key , Ġ" meta ", Ġ( key . algorithm . name Ġ+ Ġ";" Ġ+ Ġkey . crypto Provider . name ). toByteArray ()) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġsave Key Data ( key : ĠKey , Ġsuffix : ĠString , Ġdata : ĠByteArray ): ĠUnit Ġ= ĊĠĠĠĠĠĠĠ ĠFileOutputStream ("${ KEY _ DIR _ PATH }/${ key . key Id . id }. $ suffix "). use Ġ{ Ġit . write ( data ) Ġ} ĊĊĊĠĠĠ Ġ// TODO Ġconsider Ġdeprecated Ġmethods Ġbelow ĊĊ Ċ // ĠĠĠ Ġoverride Ġfun Ġsave KeyPair ( keys : ĠKeys ) Ġ{ Ċ // ĠĠĠĠĠĠĠ Ġadd Alias ( keys . key Id , Ġkeys . key Id ) Ċ // ĠĠĠĠĠĠĠ Ġstore Key MetaData ( keys ) Ċ // Ċ // ĠĠĠĠĠĠĠ Ġif Ġ( keys . is Byte Key ()) Ġ{ Ċ // ĠĠĠĠĠĠĠĠĠĠĠ Ġsave Raw PublicKey ( keys . key Id , Ġkeys . pair . public ) Ċ // ĠĠĠĠĠĠĠĠĠĠĠ Ġsave Raw PrivateKey ( keys . key Id , Ġkeys . pair . private ) Ċ // ĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ Ċ // ĠĠĠĠĠĠĠĠĠĠĠ Ġsave Enc PublicKey ( keys . key Id , Ġkeys . pair . public ) Ċ // ĠĠĠĠĠĠĠĠĠĠĠ Ġsave Enc PrivateKey ( keys . key Id , Ġkeys . pair . private ) Ċ // ĠĠĠĠĠĠĠ Ġ} Ċ // ĠĠĠ Ġ} Ċ Ċ // ĠĠĠ Ġoverride Ġfun Ġload ( key Id : ĠString ): ĠKey Ġ{ Ċ // ĠĠĠĠĠĠĠ Ġval ĠmetaData Ġ= ĠString ( load Key File ( key Id , Ġ" meta ")) Ċ // ĠĠĠĠĠĠĠ Ġval Ġalgorithm Ġ= ĠKey Algorithm . valueOf ( metaData . substring Before ( delimiter Ġ= Ġ"; ")) Ċ // ĠĠĠĠĠĠĠ Ġval Ġprovider Ġ= ĠCrypto Provider . valueOf ( metaData . substring After ( delimiter Ġ= Ġ"; ")) Ċ // Ċ // Ċ // ĠĠĠĠĠĠĠ Ġ// ĠKey Factory . getInstance (" RSA ", Ġ" BC ") Ċ // ĠĠĠĠĠĠĠ Ġ// ĠKey Factory . getInstance (" ECD SA ", Ġ" BC ") Ċ // Ċ // ĠĠĠĠĠĠĠ Ġif Ġ( Crypto Provider . SUN . equals ( provider )) Ġ{ Ċ // ĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġkey Factory Ġ= ĠKey Factory . getInstance ( algorithm . name , Ġprovider . name ) Ċ // Ċ // ĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( key File Exists ( key Id , Ġ" enc - pubkey ") Ġ&& Ġkey File Exists ( key Id , Ġ" enc - priv key ")) Ġ{ Ċ // ĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreturn ĠKey ( Ċ // ĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠKey Id ( key Id ), Ġalgorithm , Ġprovider , Ċ // ĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠKey Pair ( load Enc PublicKey ( key Id , Ġkey Factory ), Ġload Enc PrivateKey ( key Id , Ġkey Factory )) Ċ // ĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) Ċ // ĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ċ //// ĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ Ċ //// ĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( key File Exists ( key Id , Ġ" raw - pubkey ") Ġ&& Ġkey File Exists ( key Id , Ġ" raw - priv key ")) Ġ{ Ċ //// ĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġkey Pair Ġ= ĠKey Pair ( Ċ //// ĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠByte PublicKey ( load Raw PublicKey ( key Id ), Ġalgorithm . name ), Ċ //// ĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠByte PrivateKey ( load Raw PrivateKey ( key Id ), Ġalgorithm . name ) Ċ //// ĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) Ċ //// ĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreturn ĠKey ( KeyId ( key Id ), Ġalgorithm , Ġprovider , Ġkey Pair ) Ċ //// ĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ċ // ĠĠĠĠĠĠĠ Ġ} Ċ // ĠĠĠĠĠĠĠ Ġthrow ĠException (" Could Ġnot Ġload Ġkey : Ġ$ key Id ") Ċ // ĠĠĠ Ġ} ĊĊ Ċ // ĠĠ Ġfun Ġload KeyPair ( key Id : ĠString ): ĠKey ? Ġ{ Ċ // ĠĠĠĠĠĠĠ Ġval ĠmetaData Ġ= ĠString ( load Key File ( key Id , Ġ" meta ")) Ċ // ĠĠĠĠĠĠĠ Ġval Ġalgorithm Ġ= ĠmetaData . substring Before ( delimiter Ġ= Ġ"; ") Ċ // ĠĠĠĠĠĠĠ Ġval Ġprovider Ġ= ĠmetaData . substring After ( delimiter Ġ= Ġ"; ") Ċ // ĠĠĠĠĠĠĠ Ġval Ġpublic Part Ġ= ĠFile ("$ KEY _ DIR _ PATH /$ key Id . enc - pubkey "). read Text () Ċ // ĠĠĠĠĠĠĠ Ġval Ġprivate Part Ġ= ĠFile ("$ KEY _ DIR _ PATH /$ key Id . enc - priv key "). read Text () Ċ // Ċ // ĠĠĠĠĠĠĠ Ġreturn Ġbuild Key ( key Id , Ġalgorithm , provider , Ġpublic Part , Ġprivate Part Ġ) Ċ // Ċ // ĠĠĠĠĠĠĠ Ġ// ĠKey Factory . getInstance (" RSA ", Ġ" BC ") Ċ // ĠĠĠĠĠĠĠ Ġ// ĠKey Factory . getInstance (" ECD SA ", Ġ" BC ") Ċ // Ċ //// ĠĠĠĠĠĠĠ Ġif Ġ( provider Ġ== Ġ" BC ") Ġ{ Ċ //// ĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġkey Factory Ġ= ĠKey Factory . getInstance ( algorithm , Ġprovider ) Ċ //// Ċ //// ĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( key File Exists ( key Id , Ġ" enc - pubkey ") Ġ&& Ġkey File Exists ( key Id , Ġ" enc - priv key ")) Ġ{ Ċ //// ĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreturn ĠKeys ( Ċ //// ĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġkey Id , Ċ //// ĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠKey Pair ( load Enc PublicKey ( key Id , Ġkey Factory ), Ġload Enc PrivateKey ( key Id , Ġkey Factory )), Ċ //// ĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġprovider Ċ //// ĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) Ċ //// ĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ċ //// ĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ Ċ //// ĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( key File Exists ( key Id , Ġ" raw - pubkey ") Ġ&& Ġkey File Exists ( key Id , Ġ" raw - priv key ")) Ġ{ Ċ //// ĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġkey Pair Ġ= ĠKey Pair ( Ċ //// ĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠByte PublicKey ( load Raw PublicKey ( key Id ), Ġalgorithm ), Ċ //// ĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠByte PrivateKey ( load Raw PrivateKey ( key Id ), Ġalgorithm ) Ċ //// ĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) Ċ //// ĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreturn ĠKeys ( key Id , Ġkey Pair , Ġprovider ) Ċ //// ĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ċ //// ĠĠĠĠĠĠĠ Ġ} Ċ //// ĠĠĠĠĠĠĠ Ġreturn Ġnull Ċ // ĠĠĠ Ġ}> ĊĊĠĠĠ Ġprivate Ġfun Ġsave Key File ( key Id : ĠString , Ġsuffix : ĠString , Ġdata : ĠByteArray ): ĠUnit Ġ= ĊĠĠĠĠĠĠĠ ĠFileOutputStream ("${ KEY _ DIR _ PATH }/ $ key Id .$ suffix "). use Ġ{ Ġit . write ( data ) Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġsave Enc PublicKey ( key Id : ĠString , Ġencoded PublicKey : ĠPublicKey ) Ġ= ĊĠĠĠĠĠĠĠ Ġsave Key File ( key Id , Ġ" enc - pubkey ", ĠX 5 0 9 Encoded KeySpec ( encoded PublicKey . encoded ). encoded ) ĊĊĠĠĠ Ġprivate Ġfun Ġsave Enc PrivateKey ( key Id : ĠString , Ġencoded PrivateKey : ĠPrivate Key ) Ġ= ĊĠĠĠĠĠĠĠ Ġsave Key File ( key Id , Ġ" enc - priv key ", ĠPKCS 8 Encoded KeySpec ( encoded PrivateKey . encoded ). encoded ) ĊĊĠĠĠ Ġprivate Ġfun Ġsave Raw PublicKey ( key Id : ĠString , Ġraw PublicKey : ĠPublicKey ) Ġ= ĊĠĠĠĠĠĠĠ Ġsave Key File ( key Id , Ġ" raw - pubkey ", Ġraw PublicKey . encoded ) ĊĊĠĠĠ Ġprivate Ġfun Ġsave Raw PrivateKey ( key Id : ĠString , Ġraw PrivateKey : ĠPrivate Key ) Ġ= ĊĠĠĠĠĠĠĠ Ġsave Key File ( key Id , Ġ" raw - priv key ", Ġraw PrivateKey . encoded ) ĊĊĊĠĠĠ Ġprivate Ġfun Ġload Key File ( key Id : ĠString , Ġsuffix : ĠString ): ĠByteArray Ġ= ĊĠĠĠĠĠĠĠ ĠFile ("${ KEY _ DIR _ PATH }/ $ key Id .$ suffix "). read Bytes () ĊĊĠĠĠ Ġprivate Ġfun Ġdelete Key File ( key Id : ĠString , Ġsuffix : ĠString ) Ġ= ĠFile ("${ KEY _ DIR _ PATH }/ $ key Id .$ suffix "). delete () ĊĊĠĠĠ Ġprivate Ġfun Ġdelete Key Alias ( alias : ĠString ) Ġ= ĠFile ("${ KEY _ DIR _ PATH }/ Alias -$ alias "). delete () ĊĊĠĠĠ Ġfun Ġget KeyId List () Ġ= ĠFile ( KEY _ DIR _ PATH ). list Files () !!. map Ġ{ Ġit . name Without Extension Ġ}. distinct () ĊĊĠĠĠ Ġprivate Ġfun Ġkey File Exists ( key Id : ĠString , Ġsuffix : ĠString ) Ġ= ĠFile ("${ KEY _ DIR _ PATH }/ $ key Id .$ suffix "). exists () ĊĊĠĠĠ Ġprivate Ġfun Ġload Raw PublicKey ( key Id : ĠString ): ĠByteArray Ġ= Ġload Key File ( key Id , Ġ" raw - pubkey ") ĊĊĠĠĠ Ġprivate Ġfun Ġload Raw PrivateKey ( key Id : ĠString ): ĠByteArray Ġ= Ġload Key File ( key Id , Ġ" raw - priv key ") ĊĊĠĠĠ Ġprivate Ġfun Ġload Enc PublicKey ( key Id : ĠString , Ġkey Factory : ĠKey Factory ): ĠPublicKey Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn Ġkey Factory . generate Public ( ĊĠĠĠĠĠĠĠĠĠĠĠ ĠX 5 0 9 Encoded KeySpec ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġload Key File ( key Id , Ġ" enc - pubkey ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠ Ġ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġload Enc PrivateKey ( key Id : ĠString , Ġkey Factory : ĠKey Factory ): ĠPrivate Key Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn Ġkey Factory . generate Private ( ĊĠĠĠĠĠĠĠĠĠĠĠ ĠPKCS 8 Encoded KeySpec ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġload Key File ( key Id , Ġ" enc - priv key ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠ Ġ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġcompanion Ġobject Ġ{ ĊĠĠĠĠĠĠĠ Ġ// TODO : Ġget Ġpath Ġfrom Ġconfig ĊĠĠĠĠĠĠĠ Ġprivate Ġconst Ġval ĠKEY _ DIR _ PATH Ġ= Ġ" data / key " ĊĠĠĠ Ġ} Ċ } Ċ