diff --git a/crypto/src/pkcs/Pkcs8EncryptedPrivateKeyInfo.cs b/crypto/src/pkcs/Pkcs8EncryptedPrivateKeyInfo.cs
new file mode 100644
index 000000000..4c4ae83eb
--- /dev/null
+++ b/crypto/src/pkcs/Pkcs8EncryptedPrivateKeyInfo.cs
@@ -0,0 +1,106 @@
+
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Utilities.IO;
+using System;
+using System.IO;
+
+namespace Org.BouncyCastle.Pkcs
+{
+ /// <summary>
+ /// A holding class for a PKCS#8 encrypted private key info object that allows for its decryption.
+ /// </summary>
+ public class Pkcs8EncryptedPrivateKeyInfo
+ {
+ private EncryptedPrivateKeyInfo encryptedPrivateKeyInfo;
+
+ private static EncryptedPrivateKeyInfo parseBytes(byte[] pkcs8Encoding)
+ {
+ try
+ {
+ return EncryptedPrivateKeyInfo.GetInstance(pkcs8Encoding);
+ }
+
+ catch (ArgumentException e)
+ {
+ throw new PkcsIOException("malformed data: " + e.Message, e);
+ }
+ catch (Exception e)
+ {
+ throw new PkcsIOException("malformed data: " + e.Message, e);
+ }
+ }
+
+ /// <summary>
+ /// Base constructor from a PKCS#8 EncryptedPrivateKeyInfo object.
+ /// </summary>
+ /// <param name="encryptedPrivateKeyInfo">A PKCS#8 EncryptedPrivateKeyInfo object.</param>
+ public Pkcs8EncryptedPrivateKeyInfo(EncryptedPrivateKeyInfo encryptedPrivateKeyInfo)
+ {
+ this.encryptedPrivateKeyInfo = encryptedPrivateKeyInfo;
+ }
+
+ /// <summary>
+ /// Base constructor from a BER encoding of a PKCS#8 EncryptedPrivateKeyInfo object.
+ /// </summary>
+ /// <param name="encryptedPrivateKeyInfo">A BER encoding of a PKCS#8 EncryptedPrivateKeyInfo objects.</param>
+ public Pkcs8EncryptedPrivateKeyInfo(byte[] encryptedPrivateKeyInfo) : this(parseBytes(encryptedPrivateKeyInfo))
+ {
+
+ }
+
+ /// <summary>
+ /// Returns the underlying ASN.1 structure inside this object.
+ /// </summary>
+ /// <returns>Return the EncryptedPrivateKeyInfo structure in this object.</returns>
+ public EncryptedPrivateKeyInfo ToAsn1Structure()
+ {
+ return encryptedPrivateKeyInfo;
+ }
+
+ /// <summary>
+ /// Returns a copy of the encrypted data in this structure.
+ /// </summary>
+ /// <returns>Return a copy of the encrypted data in this object.</returns>
+ public byte[] GetEncryptedData()
+ {
+ return encryptedPrivateKeyInfo.GetEncryptedData();
+ }
+
+ /// <summary>
+ /// Return a binary ASN.1 encoding of the EncryptedPrivateKeyInfo structure in this object.
+ /// </summary>
+ /// <returns>A byte array containing the encoded object.</returns>
+ public byte[] GetEncoded()
+ {
+ return encryptedPrivateKeyInfo.GetEncoded();
+ }
+
+ /// <summary>
+ /// Get a decryptor from the passed in provider and decrypt the encrypted private key info, returning the result.
+ /// </summary>
+ /// <param name="inputDecryptorProvider">A provider to query for decryptors for the object.</param>
+ /// <returns>The decrypted private key info structure.</returns>
+ public PrivateKeyInfo DecryptPrivateKeyInfo(IDecryptorBuilderProvider inputDecryptorProvider)
+ {
+ try
+ {
+ ICipherBuilder decryptorBuilder = inputDecryptorProvider.CreateDecryptorBuilder(encryptedPrivateKeyInfo.EncryptionAlgorithm);
+
+ ICipher encIn = decryptorBuilder.BuildCipher(new MemoryInputStream(encryptedPrivateKeyInfo.GetEncryptedData()));
+
+ using (Stream strm = encIn.Stream)
+ {
+ byte[] data = Streams.ReadAll(encIn.Stream);
+
+ return PrivateKeyInfo.GetInstance(data);
+ }
+ }
+ catch (Exception e)
+ {
+ throw new PkcsException("unable to read encrypted data: " + e.Message, e);
+ }
+ }
+ }
+}
diff --git a/crypto/src/pkcs/Pkcs8EncryptedPrivateKeyInfoBuilder.cs b/crypto/src/pkcs/Pkcs8EncryptedPrivateKeyInfoBuilder.cs
new file mode 100644
index 000000000..3b05deea7
--- /dev/null
+++ b/crypto/src/pkcs/Pkcs8EncryptedPrivateKeyInfoBuilder.cs
@@ -0,0 +1,52 @@
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Utilities.IO;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+
+namespace Org.BouncyCastle.Pkcs
+{
+ public class Pkcs8EncryptedPrivateKeyInfoBuilder
+ {
+ private PrivateKeyInfo privateKeyInfo;
+
+ public Pkcs8EncryptedPrivateKeyInfoBuilder(byte[] privateKeyInfo): this(PrivateKeyInfo.GetInstance(privateKeyInfo))
+ {
+ }
+
+ public Pkcs8EncryptedPrivateKeyInfoBuilder(PrivateKeyInfo privateKeyInfo)
+ {
+ this.privateKeyInfo = privateKeyInfo;
+ }
+
+ /// <summary>
+ /// Create the encrypted private key info using the passed in encryptor.
+ /// </summary>
+ /// <param name="encryptor">The encryptor to use.</param>
+ /// <returns>An encrypted private key info containing the original private key info.</returns>
+ public Pkcs8EncryptedPrivateKeyInfo Build(
+ ICipherBuilder encryptor)
+ {
+ try
+ {
+ MemoryStream bOut = new MemoryOutputStream();
+ ICipher cOut = encryptor.BuildCipher(bOut);
+ byte[] keyData = privateKeyInfo.GetEncoded();
+
+ using (var str = cOut.Stream)
+ {
+ str.Write(keyData, 0, keyData.Length);
+ }
+
+ return new Pkcs8EncryptedPrivateKeyInfo(new EncryptedPrivateKeyInfo((AlgorithmIdentifier)encryptor.AlgorithmDetails, bOut.ToArray()));
+ }
+ catch (IOException)
+ {
+ throw new InvalidOperationException("cannot encode privateKeyInfo");
+ }
+ }
+ }
+}
diff --git a/crypto/src/pkcs/PkcsException.cs b/crypto/src/pkcs/PkcsException.cs
new file mode 100644
index 000000000..f82d36724
--- /dev/null
+++ b/crypto/src/pkcs/PkcsException.cs
@@ -0,0 +1,18 @@
+using System;
+
+namespace Org.BouncyCastle.Pkcs
+{
+ /// <summary>
+ /// Base exception for PKCS related issues.
+ /// </summary>
+ public class PkcsException : Exception
+ {
+ public PkcsException(String message) : base(message)
+ {
+ }
+
+ public PkcsException(String message, Exception underlying) : base(message, underlying)
+ {
+ }
+ }
+}
diff --git a/crypto/src/pkcs/PkcsIOException.cs b/crypto/src/pkcs/PkcsIOException.cs
new file mode 100644
index 000000000..19f17a394
--- /dev/null
+++ b/crypto/src/pkcs/PkcsIOException.cs
@@ -0,0 +1,19 @@
+using System;
+using System.IO;
+
+namespace Org.BouncyCastle.Pkcs
+{
+ /// <summary>
+ /// Base exception for parsing related issues in the PKCS namespace.
+ /// </summary>
+ public class PkcsIOException: IOException
+ {
+ public PkcsIOException(String message) : base(message)
+ {
+ }
+
+ public PkcsIOException(String message, Exception underlying) : base(message, underlying)
+ {
+ }
+ }
+}
|