1212using Keyfactor . PKI . Extensions ;
1313using Keyfactor . PKI . PEM ;
1414using Keyfactor . PKI . PrivateKeys ;
15+ using Keyfactor . PKI . X509 ;
1516using Microsoft . Extensions . Logging ;
1617using Newtonsoft . Json ;
1718using Org . BouncyCastle . Asn1 . X9 ;
2324using Org . BouncyCastle . X509 ;
2425using System ;
2526using System . Collections . Generic ;
27+ using System . DirectoryServices . Protocols ;
2628using System . IO ;
2729using System . Linq ;
2830using System . Security . Cryptography ;
2931using System . Text ;
32+ using static Keyfactor . PKI . PEM . PemUtilities ;
3033
3134namespace Keyfactor . Extensions . Orchestrator . RemoteFile . PEM
3235{
@@ -50,7 +53,7 @@ private enum PrivateKeyTypeEnum
5053
5154 private ILogger logger ;
5255
53- public PEMCertificateStoreSerializer ( string storeProperties )
56+ public PEMCertificateStoreSerializer ( string storeProperties )
5457 {
5558 logger = LogHandler . GetClassLogger ( this . GetType ( ) ) ;
5659 LoadCustomProperties ( storeProperties ) ;
@@ -59,7 +62,7 @@ public PEMCertificateStoreSerializer(string storeProperties)
5962 public Pkcs12Store DeserializeRemoteCertificateStore ( byte [ ] storeContentBytes , string storePath , string storePassword , IRemoteHandler remoteHandler , bool isInventory )
6063 {
6164 logger . MethodEntry ( LogLevel . Debug ) ;
62-
65+
6366 Pkcs12StoreBuilder storeBuilder = new Pkcs12StoreBuilder ( ) ;
6467 Pkcs12Store store = storeBuilder . Build ( ) ;
6568
@@ -68,7 +71,7 @@ public Pkcs12Store DeserializeRemoteCertificateStore(byte[] storeContentBytes, s
6871
6972 if ( IsTrustStore || ( isInventory && IgnorePrivateKeyOnInventory ) )
7073 {
71- foreach ( X509CertificateEntry certificate in certificates )
74+ foreach ( X509CertificateEntry certificate in certificates )
7275 {
7376 store . SetCertificateEntry ( certificate . Certificate . Thumbprint ( ) , certificate ) ;
7477 }
@@ -122,7 +125,7 @@ public List<SerializedStoreInfo> SerializeRemoteCertificateStore(Pkcs12Store cer
122125
123126 if ( ! string . IsNullOrEmpty ( storePassword ) && privateKeyType != PrivateKeyTypeEnum . PKCS8 )
124127 throw new RemoteFileException ( "Error retrieving private key. Certificate store password cannot have a non empty value if the private key is in PKCS#1 format (BEGIN [RSA|EC] PRIVATE KEY)" ) ;
125-
128+
126129 bool keyEntryProcessed = false ;
127130 foreach ( string alias in certificateStore . Aliases )
128131 {
@@ -140,10 +143,27 @@ public List<SerializedStoreInfo> SerializeRemoteCertificateStore(Pkcs12Store cer
140143 AsymmetricKeyParameter privateKey = certificateStore . GetKey ( alias ) . Key ;
141144 PrivateKeyConverter keyConverter = PrivateKeyConverterFactory . FromBCPrivateKeyAndCert ( privateKey , endCertificate ) ;
142145
143- keyString = CryptographicObjectFormatter . PEM . Format ( keyConverter , storePassword ) ;
144- pemString = string . IsNullOrEmpty ( SeparatePrivateKeyFilePath )
145- ? CryptographicObjectFormatter . PEM . Format ( endCertificate , keyConverter , storePassword , false )
146- : CryptographicObjectFormatter . PEM . Format ( endCertificate , false ) ;
146+ pemString = CryptographicObjectFormatter . PEM . Format ( endCertificate , false ) ;
147+
148+ if ( privateKeyType == PrivateKeyTypeEnum . PKCS8 )
149+ {
150+ if ( string . IsNullOrEmpty ( storePassword ) )
151+ keyString = PemUtilities . DERToPEM ( keyConverter . ToPkcs8BlobUnencrypted ( ) , PemObjectType . PrivateKey ) ;
152+ else
153+ keyString = CryptographicObjectFormatter . PEM . Format ( keyConverter , storePassword ) ;
154+ }
155+ else
156+ {
157+ TextWriter textWriter = new StringWriter ( ) ;
158+ PemWriter pemWriter = new PemWriter ( textWriter ) ;
159+ pemWriter . WriteObject ( privateKey ) ;
160+ pemWriter . Writer . Flush ( ) ;
161+
162+ keyString = textWriter . ToString ( ) ;
163+ }
164+
165+ if ( string . IsNullOrEmpty ( SeparatePrivateKeyFilePath ) )
166+ pemString += keyString ;
147167
148168 if ( ! IncludesChain )
149169 {
@@ -180,7 +200,7 @@ private void LoadCustomProperties(string storeProperties)
180200 IncludesChain = properties . IncludesChain == null || string . IsNullOrEmpty ( properties . IncludesChain . Value ) ? false : bool . Parse ( properties . IncludesChain . Value ) ;
181201 SeparatePrivateKeyFilePath = properties . SeparatePrivateKeyFilePath == null || string . IsNullOrEmpty ( properties . SeparatePrivateKeyFilePath . Value ) ? String . Empty : properties . SeparatePrivateKeyFilePath . Value ;
182202 IgnorePrivateKeyOnInventory = properties . IgnorePrivateKeyOnInventory == null || string . IsNullOrEmpty ( properties . IgnorePrivateKeyOnInventory . Value ) ? false : bool . Parse ( properties . IgnorePrivateKeyOnInventory . Value ) ;
183-
203+
184204 logger . LogDebug ( "Custom Properties have been loaded:" ) ;
185205 logger . LogDebug ( $ "IsTrustStore: { IsTrustStore } , IncludesChain: { IncludesChain } , SeparatePrivateKeyFilePath: { SeparatePrivateKeyFilePath } , IgnorePrivateKeyOnInventory: { IgnorePrivateKeyOnInventory } ") ;
186206
@@ -195,7 +215,7 @@ private X509CertificateEntry[] GetCertificates(string certificates)
195215
196216 try
197217 {
198- IEnumerable < string > pemCertificates = PemUtilities . SplitCollection ( certificates ) ;
218+ IEnumerable < string > pemCertificates = PemUtilities . SplitCollection ( RemovePrivateKey ( certificates ) ) ;
199219 certificateEntries . AddRange ( pemCertificates . Select ( cert =>
200220 new X509CertificateEntry ( new X509Certificate ( CryptographicObjectFormatter . DER . Format ( cert ) ) ) )
201221 ) ;
@@ -262,7 +282,7 @@ private AsymmetricKeyEntry GetPrivateKey(string storeContents, string storePassw
262282
263283 logger . MethodExit ( LogLevel . Debug ) ;
264284
265- return keyEntry ;
285+ return keyEntry ;
266286 }
267287
268288 private PrivateKeyTypeEnum GetPrivateKeyType ( string storeContents , out string privateKeyBegDelim )
@@ -325,5 +345,29 @@ private AsymmetricKeyParameter ToBCPrivateKey(ECDiffieHellman ecdh)
325345 throw new RemoteFileException ( "Error converting to BouncyCastle private key - Invalid parameter." ) ;
326346 }
327347 }
348+
349+ private string RemovePrivateKey ( string pemString )
350+ {
351+ List < string > delimiters = new List < string > ( ) ;
352+
353+ foreach ( string delim in PrivateKeyDelimetersPkcs8 )
354+ delimiters . Add ( delim ) ;
355+ foreach ( string delim in PrivateKeyDelimetersRSA )
356+ delimiters . Add ( delim ) ;
357+ foreach ( string delim in PrivateKeyDelimetersEC )
358+ delimiters . Add ( delim ) ;
359+
360+ foreach ( string delim in delimiters )
361+ {
362+ string delimEnd = delim . Replace ( "BEGIN" , "END" ) ;
363+ int certStart = pemString . IndexOf ( delim ) ;
364+ if ( certStart == - 1 )
365+ continue ;
366+ int certLength = pemString . IndexOf ( delimEnd ) + delimEnd . Length - certStart ;
367+ pemString = pemString . Remove ( certStart , certLength ) ;
368+ }
369+
370+ return pemString . Trim ( ) ;
371+ }
328372 }
329373}
0 commit comments