Defines functions to implement RSA cryptography.
예제 #1
0
        /// <summary>
        /// Signs the data using the SecurityPolicyUri and returns the signature.
        /// </summary>
        public static SignatureData Sign(X509Certificate2 certificate, string securityPolicyUri, byte[] dataToSign)
        {
            SignatureData signatureData = new SignatureData();

            // check if nothing to do.
            if (dataToSign == null)
            {
                return(signatureData);
            }

            // nothing more to do if no encryption.
            if (String.IsNullOrEmpty(securityPolicyUri))
            {
                return(signatureData);
            }

            // sign data.
            switch (securityPolicyUri)
            {
            case SecurityPolicies.Basic256:
            case SecurityPolicies.Basic128Rsa15:
            {
                signatureData.Algorithm = SecurityAlgorithms.RsaSha1;
                signatureData.Signature = RsaUtils.RsaPkcs15Sha1_Sign(new ArraySegment <byte>(dataToSign), certificate);
                break;
            }

            case SecurityPolicies.None:
            {
                signatureData.Algorithm = null;
                signatureData.Signature = null;
                break;
            }

            default:
            {
                throw ServiceResultException.Create(
                          StatusCodes.BadSecurityPolicyRejected,
                          "Unsupported security policy: {0}",
                          securityPolicyUri);
            }
            }

            return(signatureData);
        }
        /// <summary>
        /// Decrypts the data using RSA encryption.
        /// </summary>
        internal static byte[] Decrypt(
            ArraySegment <byte> dataToDecrypt,
            X509Certificate2 encryptingCertificate,
            Padding padding)
        {
            RSA rsa = null;

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

                int plainTextSize = dataToDecrypt.Count / GetCipherTextBlockSize(rsa, padding);
                plainTextSize *= GetPlainTextBlockSize(encryptingCertificate, padding);

                byte[] buffer = new byte[plainTextSize];
                ArraySegment <byte> plainText = Decrypt(dataToDecrypt, rsa, padding, new ArraySegment <byte>(buffer));
                System.Diagnostics.Debug.Assert(plainText.Count == buffer.Length);

                // decode length.
                int length = 0;

                length += (((int)plainText.Array[plainText.Offset + 0]));
                length += (((int)plainText.Array[plainText.Offset + 1]) << 8);
                length += (((int)plainText.Array[plainText.Offset + 2]) << 16);
                length += (((int)plainText.Array[plainText.Offset + 3]) << 24);

                if (length > (plainText.Count - plainText.Offset - 4))
                {
                    throw ServiceResultException.Create(StatusCodes.BadEndOfStream, "Could not decrypt data. Invalid total length.");
                }

                byte[] decryptedData = new byte[length];
                Array.Copy(plainText.Array, plainText.Offset + 4, decryptedData, 0, length);

                return(decryptedData);
            }
            finally
            {
                RsaUtils.RSADispose(rsa);
            }
        }
예제 #3
0
        /// <summary>
        /// Returns the length of a RSA PKCS#1 v1.5 signature of a digest.
        /// </summary>
        internal static int GetSignatureLength(X509Certificate2 signingCertificate)
        {
            RSA rsa = null;

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

                return(rsa.KeySize / 8);
            }
            finally
            {
                RsaUtils.RSADispose(rsa);
            }
        }
예제 #4
0
        /// <summary>
        /// Encrypts the data using RSA encryption.
        /// </summary>
        internal static byte[] Encrypt(
            byte[] dataToEncrypt,
            X509Certificate2 encryptingCertificate,
            Padding padding)
        {
            RSA rsa = null;

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

                int plaintextBlockSize = GetPlainTextBlockSize(rsa, padding);
                int blockCount         = ((dataToEncrypt.Length + 4) / plaintextBlockSize) + 1;
                int plainTextSize      = blockCount * plaintextBlockSize;
                int cipherTextSize     = blockCount * GetCipherTextBlockSize(rsa, padding);

                byte[] plainText = new byte[plainTextSize];

                // encode length.
                plainText[0] = (byte)((0x000000FF & dataToEncrypt.Length));
                plainText[1] = (byte)((0x0000FF00 & dataToEncrypt.Length) >> 8);
                plainText[2] = (byte)((0x00FF0000 & dataToEncrypt.Length) >> 16);
                plainText[3] = (byte)((0xFF000000 & dataToEncrypt.Length) >> 24);

                // copy data.
                Array.Copy(dataToEncrypt, 0, plainText, 4, dataToEncrypt.Length);

                byte[] buffer = new byte[cipherTextSize];
                ArraySegment <byte> cipherText = Encrypt(new ArraySegment <byte>(plainText), rsa, padding, new ArraySegment <byte>(buffer));
                System.Diagnostics.Debug.Assert(cipherText.Count == buffer.Length);

                return(buffer);
            }
            finally
            {
                RsaUtils.RSADispose(rsa);
            }
        }
예제 #5
0
        /// <summary>
        /// Computes an RSA/SHA256 PKCS#1 v1.5 signature.
        /// </summary>
        public static byte[] RsaPkcs15Sha256_Sign(
            ArraySegment <byte> dataToSign,
            X509Certificate2 signingCertificate)
        {
            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, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1));
            }
            finally
            {
                RsaUtils.RSADispose(rsa);
            }
        }
예제 #6
0
        /// <summary>
        /// Verifies an RSA/SHA1 PKCS#1 v1.5 signature.
        /// </summary>
        public static bool RsaPkcs15Sha1_Verify(
            ArraySegment <byte> dataToVerify,
            byte[] signature,
            X509Certificate2 signingCertificate)
        {
            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.
                return(rsa.VerifyData(dataToVerify.Array, dataToVerify.Offset, dataToVerify.Count, signature, HashAlgorithmName.SHA1, RSASignaturePadding.Pkcs1));
            }
            finally
            {
                RsaUtils.RSADispose(rsa);
            }
        }
예제 #7
0
        /// <summary>
        /// Verifies the signature using the SecurityPolicyUri and return true if valid.
        /// </summary>
        public static bool Verify(X509Certificate2 certificate, string securityPolicyUri, byte[] dataToVerify, SignatureData signature)
        {
            // check if nothing to do.
            if (signature == null)
            {
                return(true);
            }

            // nothing more to do if no encryption.
            if (String.IsNullOrEmpty(securityPolicyUri))
            {
                return(true);
            }

            // decrypt data.
            switch (securityPolicyUri)
            {
            case SecurityPolicies.Basic256:
            case SecurityPolicies.Basic128Rsa15:
            {
                if (signature.Algorithm == SecurityAlgorithms.RsaSha1)
                {
                    return(RsaUtils.Rsa_Verify(new ArraySegment <byte>(dataToVerify), signature.Signature, certificate, HashAlgorithmName.SHA1, RSASignaturePadding.Pkcs1));
                }
                throw ServiceResultException.Create(
                          StatusCodes.BadSecurityChecksFailed,
                          "Unexpected signature algorithm for Basic256/Basic128Rsa15: {0}\n" +
                          "Expected signature algorithm: {1}",
                          signature.Algorithm,
                          SecurityAlgorithms.RsaSha1);
            }

            case SecurityPolicies.Aes128_Sha256_RsaOaep:
            case SecurityPolicies.Basic256Sha256:
            {
                if (signature.Algorithm == SecurityAlgorithms.RsaSha256)
                {
                    return(RsaUtils.Rsa_Verify(new ArraySegment <byte>(dataToVerify), signature.Signature, certificate, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1));
                }
                throw ServiceResultException.Create(
                          StatusCodes.BadSecurityChecksFailed,
                          "Unexpected signature algorithm for Basic256Sha256/Aes128_Sha256_RsaOaep: {0}\n" +
                          "Expected signature algorithm: {1}",
                          signature.Algorithm,
                          SecurityAlgorithms.RsaSha256);
            }

            case SecurityPolicies.Aes256_Sha256_RsaPss:
            {
                if (signature.Algorithm == SecurityAlgorithms.RsaPssSha256)
                {
                    return(RsaUtils.Rsa_Verify(new ArraySegment <byte>(dataToVerify), signature.Signature, certificate, HashAlgorithmName.SHA256, RSASignaturePadding.Pss));
                }
                throw ServiceResultException.Create(
                          StatusCodes.BadSecurityChecksFailed,
                          "Unexpected signature algorithm for Aes256_Sha256_RsaPss: {0}\n" +
                          "Expected signature algorithm : {1}",
                          signature.Algorithm,
                          SecurityAlgorithms.RsaPssSha256);
            }

            // always accept signatures if security is not used.
            case SecurityPolicies.None:
            {
                return(true);
            }

            default:
            {
                throw ServiceResultException.Create(
                          StatusCodes.BadSecurityPolicyRejected,
                          "Unsupported security policy: {0}",
                          securityPolicyUri);
            }
            }

            throw ServiceResultException.Create(
                      StatusCodes.BadSecurityChecksFailed,
                      "Unexpected security policy Uri: {0}",
                      securityPolicyUri);
        }
예제 #8
0
        /// <summary>
        /// Decrypts the CipherText using the SecurityPolicyUri and returns the PlainTetx.
        /// </summary>
        public static byte[] Decrypt(X509Certificate2 certificate, string securityPolicyUri, EncryptedData dataToDecrypt)
        {
            // check if nothing to do.
            if (dataToDecrypt == null)
            {
                return(null);
            }

            // nothing more to do if no encryption.
            if (String.IsNullOrEmpty(securityPolicyUri))
            {
                return(dataToDecrypt.Data);
            }

            // decrypt data.
            switch (securityPolicyUri)
            {
            case SecurityPolicies.Basic256:
            case SecurityPolicies.Basic256Sha256:
            case SecurityPolicies.Aes128_Sha256_RsaOaep:
            {
                if (dataToDecrypt.Algorithm == SecurityAlgorithms.RsaOaep)
                {
                    return(RsaUtils.Decrypt(new ArraySegment <byte>(dataToDecrypt.Data), certificate, RsaUtils.Padding.OaepSHA1));
                }
                break;
            }

            case SecurityPolicies.Basic128Rsa15:
            {
                if (dataToDecrypt.Algorithm == SecurityAlgorithms.Rsa15)
                {
                    return(RsaUtils.Decrypt(new ArraySegment <byte>(dataToDecrypt.Data), certificate, RsaUtils.Padding.Pkcs1));
                }
                break;
            }

            case SecurityPolicies.Aes256_Sha256_RsaPss:
            {
                if (dataToDecrypt.Algorithm == SecurityAlgorithms.RsaOaepSha256)
                {
                    return(RsaUtils.Decrypt(new ArraySegment <byte>(dataToDecrypt.Data), certificate, RsaUtils.Padding.OaepSHA256));
                }
                break;
            }

            case SecurityPolicies.None:
            {
                if (String.IsNullOrEmpty(dataToDecrypt.Algorithm))
                {
                    return(dataToDecrypt.Data);
                }
                break;
            }

            default:
            {
                throw ServiceResultException.Create(
                          StatusCodes.BadSecurityPolicyRejected,
                          "Unsupported security policy: {0}",
                          securityPolicyUri);
            }
            }

            throw ServiceResultException.Create(
                      StatusCodes.BadIdentityTokenInvalid,
                      "Unexpected encryption algorithm : {0}",
                      dataToDecrypt.Algorithm);
        }
예제 #9
0
        /// <summary>
        /// Encrypts the text using the SecurityPolicyUri and returns the result.
        /// </summary>
        public static EncryptedData Encrypt(X509Certificate2 certificate, string securityPolicyUri, byte[] plainText)
        {
            EncryptedData encryptedData = new EncryptedData();

            encryptedData.Algorithm = null;
            encryptedData.Data      = plainText;

            // check if nothing to do.
            if (plainText == null)
            {
                return(encryptedData);
            }

            // nothing more to do if no encryption.
            if (String.IsNullOrEmpty(securityPolicyUri))
            {
                return(encryptedData);
            }

            // encrypt data.
            switch (securityPolicyUri)
            {
            case SecurityPolicies.Basic256:
            case SecurityPolicies.Basic256Sha256:
            case SecurityPolicies.Aes128_Sha256_RsaOaep:
            {
                encryptedData.Algorithm = SecurityAlgorithms.RsaOaep;
                encryptedData.Data      = RsaUtils.Encrypt(plainText, certificate, RsaUtils.Padding.OaepSHA1);
                break;
            }

            case SecurityPolicies.Basic128Rsa15:
            {
                encryptedData.Algorithm = SecurityAlgorithms.Rsa15;
                encryptedData.Data      = RsaUtils.Encrypt(plainText, certificate, RsaUtils.Padding.Pkcs1);
                break;
            }

            case SecurityPolicies.Aes256_Sha256_RsaPss:
            {
                encryptedData.Algorithm = SecurityAlgorithms.RsaOaepSha256;
                encryptedData.Data      = RsaUtils.Encrypt(plainText, certificate, RsaUtils.Padding.OaepSHA256);
                break;
            }

            case SecurityPolicies.None:
            {
                break;
            }

            default:
            {
                throw ServiceResultException.Create(
                          StatusCodes.BadSecurityPolicyRejected,
                          "Unsupported security policy: {0}",
                          securityPolicyUri);
            }
            }

            return(encryptedData);
        }
        /// <summary>
        /// Loads the private key from a PFX file in the certificate store.
        /// </summary>
        public X509Certificate2 LoadPrivateKey(string thumbprint, string subjectName, string password)
        {
            if (m_certificateSubdir == null || !m_certificateSubdir.Exists)
            {
                return(null);
            }

            if (string.IsNullOrEmpty(thumbprint) && string.IsNullOrEmpty(subjectName))
            {
                return(null);
            }

            foreach (FileInfo file in m_certificateSubdir.GetFiles("*.der"))
            {
                try
                {
                    X509Certificate2 certificate = new X509Certificate2(file.FullName);

                    if (!String.IsNullOrEmpty(thumbprint))
                    {
                        if (!string.Equals(certificate.Thumbprint, thumbprint, StringComparison.CurrentCultureIgnoreCase))
                        {
                            continue;
                        }
                    }

                    if (!String.IsNullOrEmpty(subjectName))
                    {
                        if (!Utils.CompareDistinguishedName(subjectName, certificate.Subject))
                        {
                            if (subjectName.Contains("=") || !certificate.Subject.Contains("CN=" + subjectName))
                            {
                                continue;
                            }
                        }
                    }

                    string fileRoot = file.Name.Substring(0, file.Name.Length - file.Extension.Length);

                    StringBuilder filePath = new StringBuilder();
                    filePath.Append(m_privateKeySubdir.FullName);
                    filePath.Append(Path.DirectorySeparatorChar);
                    filePath.Append(fileRoot);

                    FileInfo privateKeyFile = new FileInfo(filePath.ToString() + ".pfx");
                    RSA      rsa            = null;

                    try
                    {
                        certificate = new X509Certificate2(
                            privateKeyFile.FullName,
                            (password == null) ? String.Empty : password,
                            X509KeyStorageFlags.Exportable | X509KeyStorageFlags.UserKeySet);
                        rsa = certificate.GetRSAPrivateKey();
                    }
                    catch (Exception)
                    {
                        certificate = new X509Certificate2(
                            privateKeyFile.FullName,
                            (password == null) ? String.Empty : password,
                            X509KeyStorageFlags.Exportable | X509KeyStorageFlags.MachineKeySet);
                        rsa = certificate.GetRSAPrivateKey();
                    }
                    if (rsa != null)
                    {
                        int    inputBlockSize = RsaUtils.GetPlainTextBlockSize(rsa, true);
                        byte[] bytes1         = rsa.Encrypt(new byte[inputBlockSize], RSAEncryptionPadding.OaepSHA1);
                        byte[] bytes2         = rsa.Decrypt(bytes1, RSAEncryptionPadding.OaepSHA1);
                        if (bytes2 != null)
                        {
                            // Utils.Trace(1, "RSA: {0}", certificate.Thumbprint);
                            return(certificate);
                        }
                    }
                }
                catch (Exception e)
                {
                    Utils.Trace(e, "Could not load private key for certificate " + subjectName);
                }
            }

            return(null);
        }