summary refs log tree commit diff
path: root/crypto/src/crmf
diff options
context:
space:
mode:
authorDavid Hook <dgh@bouncycastle.org>2019-01-15 11:01:18 +1100
committerDavid Hook <dgh@bouncycastle.org>2019-01-15 11:01:18 +1100
commitf25f7bed6807096d9a67d31f547398c1f6f213e4 (patch)
treee05afc98f495985870a7b4edbf8ab45f63a75e68 /crypto/src/crmf
parentadded alg constructor (diff)
downloadBouncyCastle.NET-ed25519-f25f7bed6807096d9a67d31f547398c1f6f213e4.tar.xz
first cut on Pkcs8
Diffstat (limited to 'crypto/src/crmf')
-rw-r--r--crypto/src/crmf/EncryptedValueBuilder.cs163
-rw-r--r--crypto/src/crmf/IEncryptedValuePadder.cs29
2 files changed, 192 insertions, 0 deletions
diff --git a/crypto/src/crmf/EncryptedValueBuilder.cs b/crypto/src/crmf/EncryptedValueBuilder.cs
new file mode 100644
index 000000000..f9279bd53
--- /dev/null
+++ b/crypto/src/crmf/EncryptedValueBuilder.cs
@@ -0,0 +1,163 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Text;
+using Org.BouncyCastle.Asn1.Nist;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Crmf;
+using System.IO;
+using Org.BouncyCastle.Pkcs;
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.X509;
+using Org.BouncyCastle.Utilities.IO;
+
+namespace Org.BouncyCastle.Crmf
+{
+    public class EncryptedValueBuilder
+    {
+        private IKeyWrapper wrapper;
+        private ICipherBuilderWithKey encryptor;
+        private EncryptedValuePadder padder;
+
+        /**
+         * Create a builder that makes EncryptedValue structures.
+         *
+         * @param wrapper a wrapper for key used to encrypt the actual data contained in the EncryptedValue.
+         * @param encryptor  an output encryptor to encrypt the actual data contained in the EncryptedValue. 
+         */
+        public EncryptedValueBuilder(IKeyWrapper wrapper, ICipherBuilderWithKey encryptor) : this(wrapper, encryptor, null)
+        {
+        }
+
+        /**
+         * Create a builder that makes EncryptedValue structures with fixed length blocks padded using the passed in padder.
+         *
+         * @param wrapper a wrapper for key used to encrypt the actual data contained in the EncryptedValue.
+         * @param encryptor  an output encryptor to encrypt the actual data contained in the EncryptedValue.
+         * @param padder a padder to ensure that the EncryptedValue created will always be a constant length.
+         */
+        public EncryptedValueBuilder(IKeyWrapper wrapper, ICipherBuilderWithKey encryptor, EncryptedValuePadder padder)
+        {
+            this.wrapper = wrapper;
+            this.encryptor = encryptor;
+            this.padder = padder;
+        }
+
+        /**
+         * Build an EncryptedValue structure containing the passed in pass phrase.
+         *
+         * @param revocationPassphrase  a revocation pass phrase.
+         * @return an EncryptedValue containing the encrypted pass phrase.
+         * @throws CrmfException on a failure to encrypt the data, or wrap the symmetric key for this value.
+         */
+        public EncryptedValue Build(char[] revocationPassphrase)
+        {
+            return encryptData(padData(Strings.ToUtf8ByteArray(revocationPassphrase)));
+        }
+
+        /**
+         * Build an EncryptedValue structure containing the certificate contained in
+         * the passed in holder.
+         *
+         * @param holder  a holder containing a certificate.
+         * @return an EncryptedValue containing the encrypted certificate.
+         * @throws CrmfException on a failure to encrypt the data, or wrap the symmetric key for this value.
+         */
+        public EncryptedValue Build(X509Certificate holder)
+        {
+            try
+            {
+                return encryptData(padData(holder.GetEncoded()));
+            }
+            catch (IOException e)
+            {
+                throw new CrmfException("cannot encode certificate: " + e.Message, e);
+            }
+        }
+
+        /**
+         * Build an EncryptedValue structure containing the private key contained in
+         * the passed info structure.
+         *
+         * @param privateKeyInfo  a PKCS#8 private key info structure.
+         * @return an EncryptedValue containing an EncryptedPrivateKeyInfo structure.
+         * @throws CrmfException on a failure to encrypt the data, or wrap the symmetric key for this value.
+         */
+        public EncryptedValue Build(PrivateKeyInfo privateKeyInfo)
+        {
+            Pkcs8EncryptedPrivateKeyInfoBuilder encInfoBldr = new Pkcs8EncryptedPrivateKeyInfoBuilder(privateKeyInfo);
+
+            AlgorithmIdentifier intendedAlg = privateKeyInfo.PrivateKeyAlgorithm;
+            AlgorithmIdentifier symmAlg = (AlgorithmIdentifier)encryptor.AlgorithmDetails;
+            DerBitString encSymmKey;
+
+            try
+            {
+                Pkcs8EncryptedPrivateKeyInfo encInfo = encInfoBldr.Build(encryptor);
+
+                encSymmKey = new DerBitString(wrapper.Wrap(((KeyParameter)encryptor.Key).GetKey()).Collect());
+
+                AlgorithmIdentifier keyAlg = (AlgorithmIdentifier)wrapper.AlgorithmDetails;
+                Asn1OctetString valueHint = null;
+
+                return new EncryptedValue(intendedAlg, symmAlg, encSymmKey, keyAlg, valueHint, new DerBitString(encInfo.GetEncryptedData()));
+            }
+            catch (Exception e)
+            {
+                throw new CrmfException("cannot wrap key: " + e.Message, e);
+            }
+        }
+
+        private EncryptedValue encryptData(byte[] data)
+        {
+            MemoryOutputStream bOut = new MemoryOutputStream();
+
+            Stream eOut = encryptor.BuildCipher(bOut).Stream;
+
+            try
+            {
+                eOut.Write(data, 0, data.Length);
+
+                eOut.Close();
+            }
+            catch (IOException e)
+            {
+                throw new CrmfException("cannot process data: " + e.Message, e);
+            }
+
+            AlgorithmIdentifier intendedAlg = null;
+            AlgorithmIdentifier symmAlg = (AlgorithmIdentifier)encryptor.AlgorithmDetails;
+            DerBitString encSymmKey;
+
+            try
+            {
+                encSymmKey = new DerBitString(wrapper.Wrap(((KeyParameter)encryptor.Key).GetKey()).Collect());
+            }
+            catch (Exception e)
+            {
+                throw new CrmfException("cannot wrap key: " + e.Message, e);
+            }
+
+            AlgorithmIdentifier keyAlg = (AlgorithmIdentifier)wrapper.AlgorithmDetails;
+            Asn1OctetString valueHint = null;
+            DerBitString encValue = new DerBitString(bOut.ToArray());
+
+            return new EncryptedValue(intendedAlg, symmAlg, encSymmKey, keyAlg, valueHint, encValue);
+        }
+
+        private byte[] padData(byte[] data)
+        {
+            if (padder != null)
+            {
+                return padder.GetPaddedData(data);
+            }
+
+            return data;
+        }
+    }
+}
diff --git a/crypto/src/crmf/IEncryptedValuePadder.cs b/crypto/src/crmf/IEncryptedValuePadder.cs
new file mode 100644
index 000000000..b620186dc
--- /dev/null
+++ b/crypto/src/crmf/IEncryptedValuePadder.cs
@@ -0,0 +1,29 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Org.BouncyCastle.Crmf
+{
+    /**
+     * An encrypted value padder is used to make sure that prior to a value been
+     * encrypted the data is padded to a standard length.
+     */
+    public interface EncryptedValuePadder
+    {
+        /**
+         * Return a byte array of padded data.
+         *
+         * @param data the data to be padded.
+         * @return a padded byte array containing data.
+         */
+        byte[] GetPaddedData(byte[] data);
+
+        /**
+         * Return a byte array of with padding removed.
+         *
+         * @param paddedData the data to be padded.
+         * @return an array containing the original unpadded data.
+         */
+        byte[] GetUnpaddedData(byte[] paddedData);
+    }
+}