summary refs log tree commit diff
path: root/Crypto/src/x509/SubjectPublicKeyInfoFactory.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Crypto/src/x509/SubjectPublicKeyInfoFactory.cs')
-rw-r--r--Crypto/src/x509/SubjectPublicKeyInfoFactory.cs187
1 files changed, 187 insertions, 0 deletions
diff --git a/Crypto/src/x509/SubjectPublicKeyInfoFactory.cs b/Crypto/src/x509/SubjectPublicKeyInfoFactory.cs
new file mode 100644
index 000000000..54ca78090
--- /dev/null
+++ b/Crypto/src/x509/SubjectPublicKeyInfoFactory.cs
@@ -0,0 +1,187 @@
+using System;
+using System.IO;
+using System.Collections;
+using System.Text;
+
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.CryptoPro;
+using Org.BouncyCastle.Asn1.Oiw;
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Asn1.X9;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Math.EC;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.X509
+{
+    /// <summary>
+    /// A factory to produce Public Key Info Objects.
+    /// </summary>
+    public sealed class SubjectPublicKeyInfoFactory
+    {
+        private SubjectPublicKeyInfoFactory()
+        {
+        }
+
+		/// <summary>
+        /// Create a Subject Public Key Info object for a given public key.
+        /// </summary>
+        /// <param name="key">One of ElGammalPublicKeyParameters, DSAPublicKeyParameter, DHPublicKeyParameters, RsaKeyParameters or ECPublicKeyParameters</param>
+        /// <returns>A subject public key info object.</returns>
+        /// <exception cref="Exception">Throw exception if object provided is not one of the above.</exception>
+        public static SubjectPublicKeyInfo CreateSubjectPublicKeyInfo(
+			AsymmetricKeyParameter key)
+        {
+			if (key == null)
+				throw new ArgumentNullException("key");
+            if (key.IsPrivate)
+                throw new ArgumentException("Private key passed - public key expected.", "key");
+
+			if (key is ElGamalPublicKeyParameters)
+            {
+				ElGamalPublicKeyParameters _key = (ElGamalPublicKeyParameters)key;
+				ElGamalParameters kp = _key.Parameters;
+
+				SubjectPublicKeyInfo info = new SubjectPublicKeyInfo(
+					new AlgorithmIdentifier(
+						OiwObjectIdentifiers.ElGamalAlgorithm,
+						new ElGamalParameter(kp.P, kp.G).ToAsn1Object()),
+						new DerInteger(_key.Y));
+
+				return info;
+            }
+
+			if (key is DsaPublicKeyParameters)
+            {
+                DsaPublicKeyParameters _key = (DsaPublicKeyParameters) key;
+				DsaParameters kp = _key.Parameters;
+				Asn1Encodable ae = kp == null
+					?	null
+					:	new DsaParameter(kp.P, kp.Q, kp.G).ToAsn1Object();
+
+				return new SubjectPublicKeyInfo(
+                    new AlgorithmIdentifier(X9ObjectIdentifiers.IdDsa, ae),
+					new DerInteger(_key.Y));
+            }
+
+			if (key is DHPublicKeyParameters)
+            {
+                DHPublicKeyParameters _key = (DHPublicKeyParameters) key;
+				DHParameters kp = _key.Parameters;
+
+				SubjectPublicKeyInfo info = new SubjectPublicKeyInfo(
+                    new AlgorithmIdentifier(
+						_key.AlgorithmOid,
+						new DHParameter(kp.P, kp.G, kp.L).ToAsn1Object()),
+						new DerInteger(_key.Y));
+
+				return info;
+            } // End of DH
+
+            if (key is RsaKeyParameters)
+            {
+                RsaKeyParameters _key = (RsaKeyParameters) key;
+
+				SubjectPublicKeyInfo info = new SubjectPublicKeyInfo(
+					new AlgorithmIdentifier(PkcsObjectIdentifiers.RsaEncryption, DerNull.Instance),
+					new RsaPublicKeyStructure(_key.Modulus, _key.Exponent).ToAsn1Object());
+
+				return info;
+            } // End of RSA.
+
+			if (key is ECPublicKeyParameters)
+            {
+                ECPublicKeyParameters _key = (ECPublicKeyParameters) key;
+
+				if (_key.AlgorithmName == "ECGOST3410")
+				{
+					if (_key.PublicKeyParamSet == null)
+						throw Platform.CreateNotImplementedException("Not a CryptoPro parameter set");
+
+					ECPoint q = _key.Q;
+					BigInteger bX = q.X.ToBigInteger();
+					BigInteger bY = q.Y.ToBigInteger();
+
+					byte[] encKey = new byte[64];
+					ExtractBytes(encKey, 0, bX);
+					ExtractBytes(encKey, 32, bY);
+
+					Gost3410PublicKeyAlgParameters gostParams = new Gost3410PublicKeyAlgParameters(
+						_key.PublicKeyParamSet, CryptoProObjectIdentifiers.GostR3411x94CryptoProParamSet);
+
+					AlgorithmIdentifier algID = new AlgorithmIdentifier(
+						CryptoProObjectIdentifiers.GostR3410x2001,
+						gostParams.ToAsn1Object());
+
+					return new SubjectPublicKeyInfo(algID, new DerOctetString(encKey));
+				}
+				else
+				{
+					X962Parameters x962;
+					if (_key.PublicKeyParamSet == null)
+					{
+						ECDomainParameters kp = _key.Parameters;
+						X9ECParameters ecP = new X9ECParameters(kp.Curve, kp.G, kp.N, kp.H, kp.GetSeed());
+
+						x962 = new X962Parameters(ecP);
+					}
+					else
+					{
+						x962 = new X962Parameters(_key.PublicKeyParamSet);
+					}
+
+					Asn1OctetString p = (Asn1OctetString)(new X9ECPoint(_key.Q).ToAsn1Object());
+
+					AlgorithmIdentifier algID = new AlgorithmIdentifier(
+						X9ObjectIdentifiers.IdECPublicKey, x962.ToAsn1Object());
+
+					return new SubjectPublicKeyInfo(algID, p.GetOctets());
+				}
+			} // End of EC
+
+			if (key is Gost3410PublicKeyParameters)
+			{
+				Gost3410PublicKeyParameters _key = (Gost3410PublicKeyParameters) key;
+
+				if (_key.PublicKeyParamSet == null)
+					throw Platform.CreateNotImplementedException("Not a CryptoPro parameter set");
+
+				byte[] keyEnc = _key.Y.ToByteArrayUnsigned();
+				byte[] keyBytes = new byte[keyEnc.Length];
+
+				for (int i = 0; i != keyBytes.Length; i++)
+				{
+					keyBytes[i] = keyEnc[keyEnc.Length - 1 - i]; // must be little endian
+				}
+
+				Gost3410PublicKeyAlgParameters algParams = new Gost3410PublicKeyAlgParameters(
+					_key.PublicKeyParamSet, CryptoProObjectIdentifiers.GostR3411x94CryptoProParamSet);
+
+				AlgorithmIdentifier algID = new AlgorithmIdentifier(
+					CryptoProObjectIdentifiers.GostR3410x94,
+					algParams.ToAsn1Object());
+
+				return new SubjectPublicKeyInfo(algID, new DerOctetString(keyBytes));
+			}
+
+			throw new ArgumentException("Class provided no convertible: " + key.GetType().FullName);
+		}
+
+		private static void ExtractBytes(
+			byte[]		encKey,
+			int			offset,
+			BigInteger	bI)
+		{
+			byte[] val = bI.ToByteArray();
+			int n = (bI.BitLength + 7) / 8;
+
+			for (int i = 0; i < n; ++i)
+			{
+				encKey[offset + i] = val[val.Length - 1 - i];
+			}
+		}
+	}
+}