コード例 #1
0
        /// <summary>
        /// Creates an RSA PKCS#1 v1.5 or PSS signature of a hash algorithm for the stream.
        /// </summary>
        private static byte[] Rsa_Sign(
            ArraySegment <byte> dataToSign,
            X509Certificate2 signingCertificate,
            HashAlgorithmName algorithm,
            RSASignaturePadding padding)
        {
            RSA rsa = null;

            try
            {
                // extract the private key.
                rsa = signingCertificate.GetRSAPrivateKey();
                if (rsa == null)
                {
                    throw ServiceResultException.Create(StatusCodes.BadSecurityChecksFailed, "No private key for certificate.");
                }

                // create the signature.
                return(rsa.SignData(dataToSign.Array, dataToSign.Offset, dataToSign.Count, algorithm, padding));
            }
            finally
            {
                RsaUtils.RSADispose(rsa);
            }
        }
コード例 #2
0
    /// <summary>
    /// Get private key parameters from a X509Cerificate2.
    /// The private key must be exportable.
    /// </summary>
    private static RsaPrivateCrtKeyParameters GetPrivateKeyParameter(X509Certificate2 certificate)
    {
        RSA rsa = null;

        try
        {
            // try to get signing/private key from certificate passed in
            rsa = certificate.GetRSAPrivateKey();
            RSAParameters rsaParams = rsa.ExportParameters(true);
            RsaPrivateCrtKeyParameters keyParams = new RsaPrivateCrtKeyParameters(
                new BigInteger(1, rsaParams.Modulus),
                new BigInteger(1, rsaParams.Exponent),
                new BigInteger(1, rsaParams.D),
                new BigInteger(1, rsaParams.P),
                new BigInteger(1, rsaParams.Q),
                new BigInteger(1, rsaParams.DP),
                new BigInteger(1, rsaParams.DQ),
                new BigInteger(1, rsaParams.InverseQ));
            return(keyParams);
        }
        finally
        {
            RsaUtils.RSADispose(rsa);
        }
    }
コード例 #3
0
        /// <summary>
        /// Encrypts the message using RSA PKCS#1 v1.5 encryption.
        /// </summary>
        private ArraySegment <byte> Rsa_Encrypt(
            ArraySegment <byte> dataToEncrypt,
            ArraySegment <byte> headerToCopy,
            X509Certificate2 encryptingCertificate,
            bool useOaep)
        {
            RSA rsa = null;

            try
            {
                // get the encrypting key.
                rsa = encryptingCertificate.GetRSAPublicKey();
                if (rsa == null)
                {
                    throw ServiceResultException.Create(StatusCodes.BadSecurityChecksFailed, "No public key for certificate.");
                }

                int inputBlockSize  = RsaUtils.GetPlainTextBlockSize(rsa, useOaep);
                int outputBlockSize = RsaUtils.GetCipherTextBlockSize(rsa, useOaep);

                // verify the input data is the correct block size.
                if (dataToEncrypt.Count % inputBlockSize != 0)
                {
                    Utils.Trace("Message is not an integral multiple of the block size. Length = {0}, BlockSize = {1}.", dataToEncrypt.Count, inputBlockSize);
                }

                byte[] encryptedBuffer = BufferManager.TakeBuffer(SendBufferSize, "Rsa_Encrypt");
                Array.Copy(headerToCopy.Array, headerToCopy.Offset, encryptedBuffer, 0, headerToCopy.Count);

                using (MemoryStream ostrm = new MemoryStream(
                           encryptedBuffer,
                           headerToCopy.Count,
                           encryptedBuffer.Length - headerToCopy.Count))
                {
                    // encrypt body.
                    byte[] input = new byte[inputBlockSize];

                    for (int ii = dataToEncrypt.Offset; ii < dataToEncrypt.Offset + dataToEncrypt.Count; ii += inputBlockSize)
                    {
                        Array.Copy(dataToEncrypt.Array, ii, input, 0, input.Length);
                        if (useOaep == true)
                        {
                            byte[] cipherText = rsa.Encrypt(input, RSAEncryptionPadding.OaepSHA1);
                            ostrm.Write(cipherText, 0, cipherText.Length);
                        }
                        else
                        {
                            byte[] cipherText = rsa.Encrypt(input, RSAEncryptionPadding.Pkcs1);
                            ostrm.Write(cipherText, 0, cipherText.Length);
                        }
                    }
                }
                // return buffer
                return(new ArraySegment <byte>(encryptedBuffer, 0, (dataToEncrypt.Count / inputBlockSize) * outputBlockSize + headerToCopy.Count));
            }
            finally
            {
                RsaUtils.RSADispose(rsa);
            }
        }
コード例 #4
0
        /// <summary>
        /// Get public key parameters from a X509Certificate2
        /// </summary>
        internal static RsaKeyParameters GetPublicKeyParameter(X509Certificate2 certificate)
        {
            RSA rsa = null;

            try
            {
                rsa = certificate.GetRSAPublicKey();
                return(GetPublicKeyParameter(rsa));
            }
            finally
            {
                RsaUtils.RSADispose(rsa);
            }
        }
コード例 #5
0
        /// <summary>
        /// Get private key parameters from a X509Certificate2.
        /// The private key must be exportable.
        /// </summary>
        internal static RsaPrivateCrtKeyParameters GetPrivateKeyParameter(X509Certificate2 certificate)
        {
            RSA rsa = null;

            try
            {
                // try to get signing/private key from certificate passed in
                rsa = certificate.GetRSAPrivateKey();
                return(GetPrivateKeyParameter(rsa));
            }
            finally
            {
                RsaUtils.RSADispose(rsa);
            }
        }
コード例 #6
0
    /// <summary>
    /// Verify RSA key pair of two certificates.
    /// </summary>
    public static bool VerifyRSAKeyPair(
        X509Certificate2 certWithPublicKey,
        X509Certificate2 certWithPrivateKey,
        bool throwOnError = false)
    {
        bool result        = false;
        RSA  rsaPrivateKey = null;
        RSA  rsaPublicKey  = null;

        try
        {
            // verify the public and private key match
            rsaPrivateKey = certWithPrivateKey.GetRSAPrivateKey();
            rsaPublicKey  = certWithPublicKey.GetRSAPublicKey();
            X509KeyUsageFlags keyUsage = GetKeyUsage(certWithPublicKey);
            if ((keyUsage & X509KeyUsageFlags.DataEncipherment) != 0)
            {
                result = VerifyRSAKeyPairCrypt(rsaPublicKey, rsaPrivateKey);
            }
            else if ((keyUsage & X509KeyUsageFlags.DigitalSignature) != 0)
            {
                result = VerifyRSAKeyPairSign(rsaPublicKey, rsaPrivateKey);
            }
            else
            {
                throw new CryptographicException("Don't know how to verify the public/private key pair.");
            }
        }
        catch (Exception e)
        {
            if (throwOnError)
            {
                throw e;
            }
        }
        finally
        {
            RsaUtils.RSADispose(rsaPrivateKey);
            RsaUtils.RSADispose(rsaPublicKey);
            if (!result && throwOnError)
            {
                throw new CryptographicException("The public/private key pair in the certficates do not match.");
            }
        }
        return(result);
    }
コード例 #7
0
    /// <summary>
    /// Get public key parameters from a X509Certificate2
    /// </summary>
    private static RsaKeyParameters GetPublicKeyParameter(X509Certificate2 certificate)
    {
        RSA rsa = null;

        try
        {
            rsa = certificate.GetRSAPublicKey();
            RSAParameters rsaParams = rsa.ExportParameters(false);
            return(new RsaKeyParameters(
                       false,
                       new BigInteger(1, rsaParams.Modulus),
                       new BigInteger(1, rsaParams.Exponent)));
        }
        finally
        {
            RsaUtils.RSADispose(rsa);
        }
    }
コード例 #8
0
        /// <summary>
        /// Verifies an RSA PKCS#1 v1.5 or PSS signature of a hash algorithm for the stream.
        /// </summary>
        private static bool Rsa_Verify(
            ArraySegment <byte> dataToVerify,
            byte[] signature,
            X509Certificate2 signingCertificate,
            HashAlgorithmName algorithm,
            RSASignaturePadding padding)
        {
            RSA rsa = null;

            try
            {
                // extract the public key.
                rsa = signingCertificate.GetRSAPublicKey();
                if (rsa == null)
                {
                    throw ServiceResultException.Create(StatusCodes.BadSecurityChecksFailed, "No public key for certificate.");
                }

                // verify signature.
                if (!rsa.VerifyData(dataToVerify.Array, dataToVerify.Offset, dataToVerify.Count, signature, algorithm, padding))
                {
                    string messageType     = new UTF8Encoding().GetString(dataToVerify.Array, dataToVerify.Offset, 4);
                    int    messageLength   = BitConverter.ToInt32(dataToVerify.Array, dataToVerify.Offset + 4);
                    string actualSignature = Utils.ToHexString(signature);

                    Utils.Trace(
                        "Could not validate signature.\r\nCertificate={0}, MessageType={1}, Length={2}\r\nActualSignature={3}",
                        signingCertificate.Subject,
                        messageType,
                        messageLength,
                        actualSignature);

                    return(false);
                }
                return(true);
            }
            finally
            {
                RsaUtils.RSADispose(rsa);
            }
        }
 /// <summary>
 /// Validates the cert and extracts the token from the cert.
 /// </summary>
 private static string CheckForToken(X509Certificate2 cert, string name)
 {
     if ((cert.SubjectName.Decode(X500DistinguishedNameFlags.None | X500DistinguishedNameFlags.DoNotUseQuotes).Equals("CN=" + name, StringComparison.OrdinalIgnoreCase)) &&
         (DateTime.Now < cert.NotAfter))
     {
         RSA rsa = cert.GetRSAPrivateKey();
         if (rsa != null)
         {
             foreach (System.Security.Cryptography.X509Certificates.X509Extension extension in cert.Extensions)
             {
                 // check for instruction code extension
                 if ((extension.Oid.Value == "2.5.29.23") && (extension.RawData.Length >= 4))
                 {
                     byte[] bytes = new byte[extension.RawData.Length - 4];
                     Array.Copy(extension.RawData, 4, bytes, 0, bytes.Length);
                     byte[] token = rsa.Decrypt(bytes, RSAEncryptionPadding.OaepSHA1);
                     return(Encoding.ASCII.GetString(token));
                 }
             }
             RsaUtils.RSADispose(rsa);
         }
     }
     return(null);
 }
        /// <summary>
        /// Creates a cert with the connectionstring (token) and stores it in the given cert store.
        /// </summary>
        public async static Task WriteAsync(string name, string connectionString, string storeType, string storePath)
        {
            if (string.IsNullOrEmpty(connectionString))
            {
                throw new ArgumentException("Token not found in X509Store and no new token provided!");
            }

            SecureRandom            random = new SecureRandom();
            KeyGenerationParameters keyGenerationParameters = new KeyGenerationParameters(random, 2048);
            RsaKeyPairGenerator     keyPairGenerator        = new RsaKeyPairGenerator();

            keyPairGenerator.Init(keyGenerationParameters);
            AsymmetricCipherKeyPair keys = keyPairGenerator.GenerateKeyPair();

            ArrayList nameOids = new ArrayList();

            nameOids.Add(X509Name.CN);
            ArrayList nameValues = new ArrayList();

            nameValues.Add(name);
            X509Name subjectDN = new X509Name(nameOids, nameValues);
            X509Name issuerDN  = subjectDN;

            X509V3CertificateGenerator cg = new X509V3CertificateGenerator();

            cg.SetSerialNumber(BigIntegers.CreateRandomInRange(BigInteger.One, BigInteger.ValueOf(Int64.MaxValue), random));
            cg.SetIssuerDN(issuerDN);
            cg.SetSubjectDN(subjectDN);
            cg.SetNotBefore(DateTime.Now);
            cg.SetNotAfter(DateTime.Now.AddMonths(12));
            cg.SetPublicKey(keys.Public);
            cg.AddExtension(X509Extensions.KeyUsage, true, new KeyUsage(KeyUsage.DataEncipherment));

            // encrypt the token with the public key so only the owner of the assoc. private key can decrypt it and
            // "hide" it in the instruction code cert extension
            RSA              rsa       = RSA.Create();
            RSAParameters    rsaParams = new RSAParameters();
            RsaKeyParameters keyParams = (RsaKeyParameters)keys.Public;

            rsaParams.Modulus = new byte[keyParams.Modulus.ToByteArrayUnsigned().Length];
            keyParams.Modulus.ToByteArrayUnsigned().CopyTo(rsaParams.Modulus, 0);

            rsaParams.Exponent = new byte[keyParams.Exponent.ToByteArrayUnsigned().Length];
            keyParams.Exponent.ToByteArrayUnsigned().CopyTo(rsaParams.Exponent, 0);

            rsa.ImportParameters(rsaParams);
            if (rsa != null)
            {
                byte[] bytes = rsa.Encrypt(Encoding.ASCII.GetBytes(connectionString), RSAEncryptionPadding.OaepSHA1);
                if (bytes != null)
                {
                    cg.AddExtension(X509Extensions.InstructionCode, false, bytes);
                }
                else
                {
                    RsaUtils.RSADispose(rsa);
                    throw new CryptographicException("Can not encrypt IoTHub security token using generated public key!");
                }
            }
            RsaUtils.RSADispose(rsa);

            // sign the cert with the private key
            ISignatureFactory signatureFactory = new Asn1SignatureFactory("SHA256WITHRSA", keys.Private, random);

            Org.BouncyCastle.X509.X509Certificate x509 = cg.Generate(signatureFactory);

            // create a PKCS12 store for the cert and its private key
            X509Certificate2 certificate = null;

            using (MemoryStream pfxData = new MemoryStream())
            {
                Pkcs12StoreBuilder builder = new Pkcs12StoreBuilder();
                builder.SetUseDerEncoding(true);
                Pkcs12Store            pkcsStore = builder.Build();
                X509CertificateEntry[] chain     = new X509CertificateEntry[1];
                string passcode = Guid.NewGuid().ToString();
                chain[0] = new X509CertificateEntry(x509);
                pkcsStore.SetKeyEntry(name, new AsymmetricKeyEntry(keys.Private), chain);
                pkcsStore.Save(pfxData, passcode.ToCharArray(), random);

                // create X509Certificate2 object from PKCS12 file
                certificate = CertificateFactory.CreateCertificateFromPKCS12(pfxData.ToArray(), passcode);

                // handle each store type differently
                switch (storeType)
                {
                case CertificateStoreType.Directory:
                {
                    // Add to DirectoryStore
                    using (DirectoryCertificateStore store = new DirectoryCertificateStore())
                    {
                        store.Open(storePath);
                        X509CertificateCollection certificates = await store.Enumerate();

                        // remove any existing cert with our name from the store
                        foreach (X509Certificate2 cert in certificates)
                        {
                            if (cert.SubjectName.Decode(X500DistinguishedNameFlags.None | X500DistinguishedNameFlags.DoNotUseQuotes).Equals("CN=" + name, StringComparison.OrdinalIgnoreCase))
                            {
                                await store.Delete(cert.Thumbprint);
                            }
                        }

                        // add new one
                        await store.Add(certificate);
                    }
                    break;
                }

                case CertificateStoreType.X509Store:
                {
                    // Add to X509Store
                    using (X509Store store = new X509Store(storePath, StoreLocation.CurrentUser))
                    {
                        store.Open(OpenFlags.ReadWrite);

                        // remove any existing cert with our name from the store
                        foreach (X509Certificate2 cert in store.Certificates)
                        {
                            if (cert.SubjectName.Decode(X500DistinguishedNameFlags.None | X500DistinguishedNameFlags.DoNotUseQuotes).Equals("CN=" + name, StringComparison.OrdinalIgnoreCase))
                            {
                                store.Remove(cert);
                            }
                        }

                        // add new cert to store
                        try
                        {
                            store.Add(certificate);
                        }
                        catch (Exception e)
                        {
                            throw new Exception($"Not able to add cert to the requested store type '{storeType}' (exception message: '{e.Message}'.");
                        }
                    }
                    break;
                }

                default:
                {
                    throw new Exception($"The requested store type '{storeType}' is not supported. Please change.");
                }
                }
                return;
            }
        }