Exemplo n.º 1
0
        /// <summary>
        /// Initiates a conversation between two endpoints. The initiator is
        /// the endpoint which estbalished the connection (not the one which
        /// was listening.)
        /// <para>
        /// The distinction of "Initiator" is only relevant for connection
        /// handshake (initiator writes first, listener writes last.)
        /// </para>
        /// </summary>
        /// <param name="rsa"></param>
        /// <remarks>
        /// connection negotiation starts with the client(initiater) not the server(listener).
        ///
        /// 1. initiator sends pubkey, in the clear
        /// 2. listener sends pubkey, in the clear
        /// 3. initiator sends aes key, encrypted with listener pubkey
        /// 4. listener sends aes key, encrypted with initiator pubkey
        /// 5.
        ///
        /// upon success communication continues over unidirectional,
        /// encrypted channels.
        /// </remarks>
        private async Task InitiateConversation(RSA rsa)
        {
            if (_worker != null)
            {
                throw new InvalidOperationException("Conversation already initiated.");
            }

            // TODO: should hold write-lock until success/fail
            // TODO: separate "initiator-handshake" from "worker loop" -- do this for both "initiator-handshake" as well as "listener-handshake"

            // initial streams are "in the clear"
            _outputStream = _tcpClient.GetStream();
            _inputStream  = _tcpClient.GetStream();

            // send pubkey (in the clear)
            var rsaParameters = rsa.ExportParameters(false);
            var pubkey        = JsonConvert.SerializeObject(new
            {
                E = rsaParameters.Exponent,
                M = rsaParameters.Modulus
            });
            var pubkeyBytes = Encoding.UTF8.GetBytes(pubkey);

            await WriteMessage(pubkeyBytes);

            // expect pubkey (in the clear)
            var remoteRsaExpectedSize = await ReadMessageLength();

            var remoteRsaData = await ReadMessagePayload(
                _inputStream,
                remoteRsaExpectedSize,
                _cancellationTokenSource.Token);

            var remoteRsaJson       = Encoding.UTF8.GetString(remoteRsaData);
            var remoteRsaParameters = JsonConvert.DeserializeObject <dynamic>(
                remoteRsaJson);

            var remoteRSA = RSA.Create();

            remoteRSA.ImportParameters(
                new RSAParameters
            {
                Exponent = Convert.FromBase64String(
                    Convert.ToString(remoteRsaParameters.E)),
                Modulus = Convert.FromBase64String(
                    Convert.ToString(remoteRsaParameters.M)),
            });

            var thumbprint = _crypt.GetThumbprint(remoteRSA);

            Peer.Thumbprint = thumbprint;

            /*
             * // check thumbprint against whitelist, if not in whitelist then
             * // force a disconnect
             * if (_whitelist.TryGetAlias(thumbprint, out string alias))
             * {
             *  Peer.Alias = alias;
             *  _onStatusChange($"Connected to {Peer}".Log());
             * }
             * else
             * {
             *  Peer.Alias = Peer.Thumbprint;
             *  _onStatusChange($@"Rejecting {Peer}, thumbprint is not authorized.
             * You can use the `/WHITELIST <thumbprint>` and `/BAN <thumbprint>` commands to authorized/deauthorize.".Log());
             *  return;
             * }
             */

            // send our AES key (encrypted with remote pubkey)
            var aes     = Aes.Create();
            var aesKey  = aes.Key;
            var aesIV   = aes.IV;
            var aesJson = JsonConvert.SerializeObject(new
            {
                K = Convert.ToBase64String(aes.Key),
                V = Convert.ToBase64String(aes.IV)
            });
            var aesJsonBytes = Encoding.UTF8.GetBytes(aesJson);

            aesJsonBytes = remoteRSA.Encrypt(aesJsonBytes, RSAEncryptionPadding.Pkcs1);
            await WriteMessage(aesJsonBytes, true); // NOTE: flush block must come encrypted

            // expect remote AES key (encrypted with our pubkey)
            var remoteAesExpectedSize = await ReadMessageLength();

            var remoteAesBytes = await ReadMessagePayload(
                _inputStream,
                remoteAesExpectedSize,
                _cancellationTokenSource.Token);

            remoteAesBytes = rsa.Decrypt(remoteAesBytes, RSAEncryptionPadding.Pkcs1);
            var remoteAesJson       = Encoding.UTF8.GetString(remoteAesBytes);
            var remoteAesParameters = JsonConvert.DeserializeObject <dynamic>(remoteAesJson);
            var remoteAes           = Aes.Create();

            remoteAes.Key = Convert.FromBase64String(
                Convert.ToString(remoteAesParameters.K));
            remoteAes.IV = Convert.FromBase64String(
                Convert.ToString(remoteAesParameters.V));

            // continue communication using aes keys (rsa keys can be discarded)
            _inputStream = new CryptoStream(_inputStream, aes.CreateDecryptor(), CryptoStreamMode.Read);
            var encryptor = remoteAes.CreateEncryptor();

            //_idealFlushBlockCount = ((encryptor.InputBlockSize / 4) + 1);
            _outputStream = new CryptoStream(_outputStream, encryptor, CryptoStreamMode.Write);

            await WriteFlushBlock();

            _worker = EnterConversationLoop();
        }
        private async Task <bool> InvokeCryptographyEndpointAsync()
        {
            // Metadata requests must be made via GET.
            // See http://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfigurationRequest
            if (!HttpMethods.IsGet(Request.Method))
            {
                Logger.LogError("The cryptography request was rejected because an invalid " +
                                "HTTP method was specified: {Method}.", Request.Method);

                return(await SendCryptographyResponseAsync(new OpenIdConnectResponse
                {
                    Error = OpenIdConnectConstants.Errors.InvalidRequest,
                    ErrorDescription = "The specified HTTP method is not valid."
                }));
            }

            var request = new OpenIdConnectRequest(Request.Query);

            // Note: set the message type before invoking the ExtractCryptographyRequest event.
            request.SetProperty(OpenIdConnectConstants.Properties.MessageType,
                                OpenIdConnectConstants.MessageTypes.CryptographyRequest);

            // Store the cryptography request in the ASP.NET context.
            Context.SetOpenIdConnectRequest(request);

            var @event = new ExtractCryptographyRequestContext(Context, Scheme, Options, request);
            await Provider.ExtractCryptographyRequest(@event);

            if (@event.Result != null)
            {
                if (@event.Result.Handled)
                {
                    Logger.LogDebug("The cryptography request was handled in user code.");

                    return(true);
                }

                else if (@event.Result.Skipped)
                {
                    Logger.LogDebug("The default cryptography request handling was skipped from user code.");

                    return(false);
                }
            }

            else if (@event.IsRejected)
            {
                Logger.LogError("The cryptography request was rejected with the following error: {Error} ; {Description}",
                                /* Error: */ @event.Error ?? OpenIdConnectConstants.Errors.InvalidRequest,
                                /* Description: */ @event.ErrorDescription);

                return(await SendCryptographyResponseAsync(new OpenIdConnectResponse
                {
                    Error = @event.Error ?? OpenIdConnectConstants.Errors.InvalidRequest,
                    ErrorDescription = @event.ErrorDescription,
                    ErrorUri = @event.ErrorUri
                }));
            }

            Logger.LogInformation("The cryptography request was successfully extracted " +
                                  "from the HTTP request: {Request}.", request);

            var context = new ValidateCryptographyRequestContext(Context, Scheme, Options, request);
            await Provider.ValidateCryptographyRequest(context);

            if (context.Result != null)
            {
                if (context.Result.Handled)
                {
                    Logger.LogDebug("The cryptography request was handled in user code.");

                    return(true);
                }

                else if (context.Result.Skipped)
                {
                    Logger.LogDebug("The default cryptography request handling was skipped from user code.");

                    return(false);
                }
            }

            else if (context.IsRejected)
            {
                Logger.LogError("The cryptography request was rejected with the following error: {Error} ; {Description}",
                                /* Error: */ context.Error ?? OpenIdConnectConstants.Errors.InvalidRequest,
                                /* Description: */ context.ErrorDescription);

                return(await SendCryptographyResponseAsync(new OpenIdConnectResponse
                {
                    Error = context.Error ?? OpenIdConnectConstants.Errors.InvalidRequest,
                    ErrorDescription = context.ErrorDescription,
                    ErrorUri = context.ErrorUri
                }));
            }

            var notification = new HandleCryptographyRequestContext(Context, Scheme, Options, request);

            foreach (var credentials in Options.SigningCredentials)
            {
                // If the signing key is not an asymmetric key, ignore it.
                if (!(credentials.Key is AsymmetricSecurityKey))
                {
                    Logger.LogDebug("A non-asymmetric signing key of type '{Type}' was excluded " +
                                    "from the key set.", credentials.Key.GetType().FullName);

                    continue;
                }

#if SUPPORTS_ECDSA
                if (!credentials.Key.IsSupportedAlgorithm(SecurityAlgorithms.RsaSha256) &&
                    !credentials.Key.IsSupportedAlgorithm(SecurityAlgorithms.EcdsaSha256) &&
                    !credentials.Key.IsSupportedAlgorithm(SecurityAlgorithms.EcdsaSha384) &&
                    !credentials.Key.IsSupportedAlgorithm(SecurityAlgorithms.EcdsaSha512))
                {
                    Logger.LogInformation("An unsupported signing key of type '{Type}' was ignored and excluded " +
                                          "from the key set. Only RSA and ECDSA asymmetric security keys can be " +
                                          "exposed via the JWKS endpoint.", credentials.Key.GetType().Name);

                    continue;
                }
#else
                if (!credentials.Key.IsSupportedAlgorithm(SecurityAlgorithms.RsaSha256))
                {
                    Logger.LogInformation("An unsupported signing key of type '{Type}' was ignored and excluded " +
                                          "from the key set. Only RSA asymmetric security keys can be exposed " +
                                          "via the JWKS endpoint.", credentials.Key.GetType().Name);

                    continue;
                }
#endif

                var key = new JsonWebKey
                {
                    Use = JsonWebKeyUseNames.Sig,

                    // Resolve the JWA identifier from the algorithm specified in the credentials.
                    Alg = OpenIdConnectServerHelpers.GetJwtAlgorithm(credentials.Algorithm),

                    // Use the key identifier specified in the signing credentials.
                    Kid = credentials.Kid,
                };

                if (credentials.Key.IsSupportedAlgorithm(SecurityAlgorithms.RsaSha256))
                {
                    RSA algorithm = null;

                    // Note: IdentityModel 5 doesn't expose a method allowing to retrieve the underlying algorithm
                    // from a generic asymmetric security key. To work around this limitation, try to cast
                    // the security key to the built-in IdentityModel types to extract the required RSA instance.
                    // See https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/issues/395
                    if (credentials.Key is X509SecurityKey x509SecurityKey)
                    {
                        algorithm = x509SecurityKey.PublicKey as RSA;
                    }

                    else if (credentials.Key is RsaSecurityKey rsaSecurityKey)
                    {
                        algorithm = rsaSecurityKey.Rsa;

                        // If no RSA instance can be found, create one using
                        // the RSA parameters attached to the security key.
                        if (algorithm == null)
                        {
                            var rsa = RSA.Create();
                            rsa.ImportParameters(rsaSecurityKey.Parameters);
                            algorithm = rsa;
                        }
                    }

                    // Skip the key if an algorithm instance cannot be extracted.
                    if (algorithm == null)
                    {
                        Logger.LogWarning("A signing key was ignored because it was unable " +
                                          "to provide the requested algorithm instance.");

                        continue;
                    }

                    // Export the RSA public key to create a new JSON Web Key
                    // exposing the exponent and the modulus parameters.
                    var parameters = algorithm.ExportParameters(includePrivateParameters: false);

                    Debug.Assert(parameters.Exponent != null &&
                                 parameters.Modulus != null,
                                 "RSA.ExportParameters() shouldn't return null parameters.");

                    key.Kty = JsonWebAlgorithmsKeyTypes.RSA;

                    // Note: both E and N must be base64url-encoded.
                    // See https://tools.ietf.org/html/rfc7518#section-6.3.1.1
                    key.E = Base64UrlEncoder.Encode(parameters.Exponent);
                    key.N = Base64UrlEncoder.Encode(parameters.Modulus);
                }

#if SUPPORTS_ECDSA
                else if (credentials.Key.IsSupportedAlgorithm(SecurityAlgorithms.EcdsaSha256) ||
                         credentials.Key.IsSupportedAlgorithm(SecurityAlgorithms.EcdsaSha384) ||
                         credentials.Key.IsSupportedAlgorithm(SecurityAlgorithms.EcdsaSha512))
                {
                    ECDsa algorithm = null;

                    if (credentials.Key is X509SecurityKey x509SecurityKey)
                    {
                        algorithm = x509SecurityKey.PublicKey as ECDsa;
                    }

                    else if (credentials.Key is ECDsaSecurityKey ecdsaSecurityKey)
                    {
                        algorithm = ecdsaSecurityKey.ECDsa;
                    }

                    // Skip the key if an algorithm instance cannot be extracted.
                    if (algorithm == null)
                    {
                        Logger.LogWarning("A signing key was ignored because it was unable " +
                                          "to provide the requested algorithm instance.");

                        continue;
                    }

                    // Export the ECDsa public key to create a new JSON Web Key
                    // exposing the coordinates of the point on the curve.
                    var parameters = algorithm.ExportParameters(includePrivateParameters: false);

                    Debug.Assert(parameters.Q.X != null &&
                                 parameters.Q.Y != null,
                                 "ECDsa.ExportParameters() shouldn't return null coordinates.");

                    key.Kty = JsonWebAlgorithmsKeyTypes.EllipticCurve;
                    key.Crv = OpenIdConnectServerHelpers.GetJwtAlgorithmCurve(parameters.Curve);

                    // Note: both X and Y must be base64url-encoded.
                    // See https://tools.ietf.org/html/rfc7518#section-6.2.1.2
                    key.X = Base64UrlEncoder.Encode(parameters.Q.X);
                    key.Y = Base64UrlEncoder.Encode(parameters.Q.Y);
                }
#endif

                // If the signing key is embedded in a X.509 certificate, set
                // the x5t and x5c parameters using the certificate details.
                var certificate = (credentials.Key as X509SecurityKey)?.Certificate;
                if (certificate != null)
                {
                    // x5t must be base64url-encoded.
                    // See https://tools.ietf.org/html/rfc7517#section-4.8
                    key.X5t = Base64UrlEncoder.Encode(certificate.GetCertHash());

                    // Unlike E or N, the certificates contained in x5c
                    // must be base64-encoded and not base64url-encoded.
                    // See https://tools.ietf.org/html/rfc7517#section-4.7
                    key.X5c.Add(Convert.ToBase64String(certificate.RawData));
                }

                notification.Keys.Add(key);
            }

            await Provider.HandleCryptographyRequest(notification);

            if (notification.Result != null)
            {
                if (notification.Result.Handled)
                {
                    Logger.LogDebug("The cryptography request was handled in user code.");

                    return(true);
                }

                else if (notification.Result.Skipped)
                {
                    Logger.LogDebug("The default cryptography request handling was skipped from user code.");

                    return(false);
                }
            }

            else if (notification.IsRejected)
            {
                Logger.LogError("The cryptography request was rejected with the following error: {Error} ; {Description}",
                                /* Error: */ notification.Error ?? OpenIdConnectConstants.Errors.InvalidRequest,
                                /* Description: */ notification.ErrorDescription);

                return(await SendCryptographyResponseAsync(new OpenIdConnectResponse
                {
                    Error = notification.Error ?? OpenIdConnectConstants.Errors.InvalidRequest,
                    ErrorDescription = notification.ErrorDescription,
                    ErrorUri = notification.ErrorUri
                }));
            }

            var keys = new JArray();

            foreach (var key in notification.Keys)
            {
                var item = new JObject();

                // Ensure a key type has been provided.
                // See https://tools.ietf.org/html/rfc7517#section-4.1
                if (string.IsNullOrEmpty(key.Kty))
                {
                    Logger.LogError("A JSON Web Key was excluded from the key set because " +
                                    "it didn't contain the mandatory 'kid' parameter.");

                    continue;
                }

                // Create a dictionary associating the
                // JsonWebKey components with their values.
                var parameters = new Dictionary <string, string>
                {
                    [JsonWebKeyParameterNames.Kid] = key.Kid,
                    [JsonWebKeyParameterNames.Use] = key.Use,
                    [JsonWebKeyParameterNames.Kty] = key.Kty,
                    [JsonWebKeyParameterNames.Alg] = key.Alg,
                    [JsonWebKeyParameterNames.Crv] = key.Crv,
                    [JsonWebKeyParameterNames.E]   = key.E,
                    [JsonWebKeyParameterNames.N]   = key.N,
                    [JsonWebKeyParameterNames.X]   = key.X,
                    [JsonWebKeyParameterNames.Y]   = key.Y,
                    [JsonWebKeyParameterNames.X5t] = key.X5t,
                    [JsonWebKeyParameterNames.X5u] = key.X5u
                };

                foreach (var parameter in parameters)
                {
                    if (!string.IsNullOrEmpty(parameter.Value))
                    {
                        item.Add(parameter.Key, parameter.Value);
                    }
                }

                if (key.KeyOps.Count != 0)
                {
                    item.Add(JsonWebKeyParameterNames.KeyOps, new JArray(key.KeyOps));
                }

                if (key.X5c.Count != 0)
                {
                    item.Add(JsonWebKeyParameterNames.X5c, new JArray(key.X5c));
                }

                keys.Add(item);
            }

            // Note: AddParameter() is used here to ensure the mandatory "keys" node
            // is returned to the caller, even if the key set doesn't expose any key.
            // See https://tools.ietf.org/html/rfc7517#section-5 for more information.
            var response = new OpenIdConnectResponse();
            response.AddParameter(OpenIdConnectConstants.Parameters.Keys, keys);

            return(await SendCryptographyResponseAsync(response));
        }
Exemplo n.º 3
0
            private async ValueTask <X509Certificate2> LoadCertificateFromPemFileAsync(bool async, string clientCertificatePath, CancellationToken cancellationToken)
            {
                if (!(Certificate is null))
                {
                    return(Certificate);
                }

                string certficateText;

                try
                {
                    if (!async)
                    {
                        certficateText = File.ReadAllText(clientCertificatePath);
                    }
                    else
                    {
                        cancellationToken.ThrowIfCancellationRequested();

                        using (StreamReader sr = new StreamReader(clientCertificatePath))
                        {
                            certficateText = await sr.ReadToEndAsync().ConfigureAwait(false);
                        }
                    }

                    Regex certificateRegex = new Regex("(-+BEGIN CERTIFICATE-+)(\n\r?|\r\n?)([A-Za-z0-9+/\n\r]+=*)(\n\r?|\r\n?)(-+END CERTIFICATE-+)", RegexOptions.CultureInvariant, TimeSpan.FromSeconds(5));
                    Regex privateKeyRegex  = new Regex("(-+BEGIN PRIVATE KEY-+)(\n\r?|\r\n?)([A-Za-z0-9+/\n\r]+=*)(\n\r?|\r\n?)(-+END PRIVATE KEY-+)", RegexOptions.CultureInvariant, TimeSpan.FromSeconds(5));

                    Match certificateMatch = certificateRegex.Match(certficateText);
                    Match privateKeyMatch  = privateKeyRegex.Match(certficateText);

                    if (!certificateMatch.Success)
                    {
                        throw new InvalidDataException("Could not find certificate in PEM file");
                    }

                    if (!privateKeyMatch.Success)
                    {
                        throw new InvalidDataException("Could not find private key in PEM file");
                    }

                    // ImportPkcs8PrivateKey was added in .NET Core 3.0, it is only present on Core.  If we can't find this method, we have a lightweight decoder we can use.
                    MethodInfo importPkcs8PrivateKeyMethodInfo = typeof(RSA).GetMethod("ImportPkcs8PrivateKey", BindingFlags.Instance | BindingFlags.Public, null, new Type[] { typeof(ReadOnlySpan <byte>), typeof(int).MakeByRefType() }, null);

                    // CopyWithPrivateKey is present in .NET Core 2.0+ and .NET 4.7.2+.
                    MethodInfo copyWithPrivateKeyMethodInfo = typeof(RSACertificateExtensions).GetMethod("CopyWithPrivateKey", BindingFlags.Static | BindingFlags.Public, null, new Type[] { typeof(X509Certificate2), typeof(RSA) }, null);

                    if (copyWithPrivateKeyMethodInfo == null)
                    {
                        throw new PlatformNotSupportedException("The current platform does not support reading a private key from a PEM file");
                    }

                    RSA privateKey;

                    if (importPkcs8PrivateKeyMethodInfo != null)
                    {
                        privateKey = RSA.Create();

                        // Because ImportPkcs8PrivateKey takes a ReadOnlySpan<byte> as an argument, we can not call it directly via MethodInfo.Invoke (since all the arguments to the function
                        // have to be passed to MethodInfo.Invoke in an object array, and you can't put a byref type like ReadOnlySpan<T> in an array. So we create a delegate with the
                        // correct signature bound to the privateKey we want to import into and invoke that.
                        ImportPkcs8PrivateKeyDelegate importPrivateKey = (ImportPkcs8PrivateKeyDelegate)importPkcs8PrivateKeyMethodInfo.CreateDelegate(typeof(ImportPkcs8PrivateKeyDelegate), privateKey);
                        importPrivateKey(Convert.FromBase64String(privateKeyMatch.Groups[3].Value), out int _);
                    }
                    else
                    {
                        privateKey = LightweightPkcs8Decoder.DecodeRSAPkcs8(Convert.FromBase64String(privateKeyMatch.Groups[3].Value));
                    }

                    X509Certificate2 certWithoutPrivateKey = new X509Certificate2(Convert.FromBase64String(certificateMatch.Groups[3].Value));
                    Certificate = (X509Certificate2)copyWithPrivateKeyMethodInfo.Invoke(null, new object[] { certWithoutPrivateKey, privateKey });

                    // On desktop NetFX it appears the PrivateKey property is not initialized after calling CopyWithPrivateKey
                    // this leads to an issue when using the MSAL ConfidentialClient which uses the PrivateKey property to get the
                    // signing key vs. the extension method GetRsaPrivateKey which we were previously using when signing the claim ourselves.
                    // Because of this we need to set PrivateKey to the instance we created to deserialize the private key
                    if (Certificate.PrivateKey == null)
                    {
                        Certificate.PrivateKey = privateKey;
                    }

                    return(Certificate);
                }
                catch (Exception e) when(!(e is OperationCanceledException))
                {
                    throw new CredentialUnavailableException("Could not load certificate file", e);
                }
            }
Exemplo n.º 4
0
 public static void CreateWithKeysize_InvalidKeySize(int keySizeInBits)
 {
     Assert.Throws <CryptographicException>(() => RSA.Create(keySizeInBits));
 }
Exemplo n.º 5
0
 private Encryption()
 {
     _rsa = RSA.Create();
 }
Exemplo n.º 6
0
        private static string RSAEncrypt(string sourceString)
        {
            RSA rsa = RSA.Create();

            throw new NotImplementedException();
        }
Exemplo n.º 7
0
        public RSA CreateRsaProviderFromPublicKey(string publicKeyString)
        {
            // encoded OID sequence for  PKCS #1 rsaEncryption szOID_RSA_RSA = "1.2.840.113549.1.1.1"
            byte[] seqOid = { 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00 };
            byte[] seq    = new byte[15];

            var x509Key = System.Convert.FromBase64String(publicKeyString);

            // ---------  Set up stream to read the asn.1 encoded SubjectPublicKeyInfo blob  ------
            using (MemoryStream mem = new MemoryStream(x509Key))
            {
                using (BinaryReader binr = new BinaryReader(mem))  //wrap Memory Stream with BinaryReader for easy reading
                {
                    byte   bt       = 0;
                    ushort twobytes = 0;

                    twobytes = binr.ReadUInt16();
                    if (twobytes == 0x8130) //data read as little endian order (actual data order for Sequence is 30 81)
                    {
                        binr.ReadByte();    //advance 1 byte
                    }
                    else if (twobytes == 0x8230)
                    {
                        binr.ReadInt16();   //advance 2 bytes
                    }
                    else
                    {
                        return(null);
                    }

                    seq = binr.ReadBytes(15);            //read the Sequence OID
                    if (!CompareBytearrays(seq, seqOid)) //make sure Sequence for OID is correct
                    {
                        return(null);
                    }

                    twobytes = binr.ReadUInt16();
                    if (twobytes == 0x8103) //data read as little endian order (actual data order for Bit String is 03 81)
                    {
                        binr.ReadByte();    //advance 1 byte
                    }
                    else if (twobytes == 0x8203)
                    {
                        binr.ReadInt16();   //advance 2 bytes
                    }
                    else
                    {
                        return(null);
                    }

                    bt = binr.ReadByte();
                    if (bt != 0x00)     //expect null byte next
                    {
                        return(null);
                    }

                    twobytes = binr.ReadUInt16();
                    if (twobytes == 0x8130) //data read as little endian order (actual data order for Sequence is 30 81)
                    {
                        binr.ReadByte();    //advance 1 byte
                    }
                    else if (twobytes == 0x8230)
                    {
                        binr.ReadInt16();   //advance 2 bytes
                    }
                    else
                    {
                        return(null);
                    }

                    twobytes = binr.ReadUInt16();
                    byte lowbyte  = 0x00;
                    byte highbyte = 0x00;

                    if (twobytes == 0x8102)        //data read as little endian order (actual data order for Integer is 02 81)
                    {
                        lowbyte = binr.ReadByte(); // read next bytes which is bytes in modulus
                    }
                    else if (twobytes == 0x8202)
                    {
                        highbyte = binr.ReadByte(); //advance 2 bytes
                        lowbyte  = binr.ReadByte();
                    }
                    else
                    {
                        return(null);
                    }
                    byte[] modint  = { lowbyte, highbyte, 0x00, 0x00 };  //reverse byte order since asn.1 key uses big endian order
                    int    modsize = BitConverter.ToInt32(modint, 0);

                    int firstbyte = binr.PeekChar();
                    if (firstbyte == 0x00)
                    {                    //if first byte (highest order) of modulus is zero, don't include it
                        binr.ReadByte(); //skip this null byte
                        modsize -= 1;    //reduce modulus buffer size by 1
                    }

                    byte[] modulus = binr.ReadBytes(modsize); //read the modulus bytes

                    if (binr.ReadByte() != 0x02)              //expect an Integer for the exponent data
                    {
                        return(null);
                    }
                    int    expbytes = (int)binr.ReadByte();     // should only need one byte for actual exponent data (for all useful values)
                    byte[] exponent = binr.ReadBytes(expbytes);

                    // ------- create RSACryptoServiceProvider instance and initialize with public key -----
                    var           rsa        = RSA.Create();
                    RSAParameters rsaKeyInfo = new RSAParameters
                    {
                        Modulus  = modulus,
                        Exponent = exponent
                    };
                    rsa.ImportParameters(rsaKeyInfo);

                    return(rsa);
                }
            }
        }
Exemplo n.º 8
0
        private async Task AuthenticateSha256Async(byte[] packet, string scramble, byte sequenceNumber)
        {
            // See https://mariadb.com/kb/en/caching_sha2_password-authentication-plugin/
            // Success authentication.
            if (packet[0] == 0x01 && packet[1] == 0x03)
            {
                return;
            }

            // Send clear password if ssl is used.
            var writer = new PacketWriter(sequenceNumber);

            if (_options.UseSsl)
            {
                writer.WriteNullTerminatedString(_options.Password);
                await _channel.WriteBytesAsync(writer.CreatePacket());

                packet = await _channel.ReadPacketSlowAsync();

                ThrowIfErrorPacket(packet, "Sending caching_sha2_password clear password error.");
                return;
            }

            // Request public key.
            writer = new PacketWriter(sequenceNumber);
            writer.WriteByte(0x02);
            await _channel.WriteBytesAsync(writer.CreatePacket());

            packet = await _channel.ReadPacketSlowAsync();

            sequenceNumber += 2;
            ThrowIfErrorPacket(packet, "Requesting caching_sha2_password public key.");

            // Extract public key.
            var publicKeyString = Encoding.UTF8.GetString(new ReadOnlySequence <byte>(packet, 1, packet.Length - 1).ToArray());

            publicKeyString = publicKeyString
                              .Replace("-----BEGIN PUBLIC KEY-----", "")
                              .Replace("-----END PUBLIC KEY-----", "")
                              .Replace("\n", "");
            byte[] publicKey = Convert.FromBase64String(publicKeyString);

            // Password must be null terminated. Not documented in MariaDB.
            var password          = Encoding.UTF8.GetBytes(_options.Password += '\0');
            var encryptedPassword = AuthenticateCommand.Xor(password, Encoding.UTF8.GetBytes(scramble));

            using (var rsa = RSA.Create())
            {
#if NETSTANDARD2_1
                rsa.ImportSubjectPublicKeyInfo(publicKey, out _);
#else
                rsa.ImportParameters(CertificateImporter.DecodePublicKey(publicKey));
#endif
                var encryptedBody = rsa.Encrypt(encryptedPassword, RSAEncryptionPadding.OaepSHA1);

                writer = new PacketWriter(sequenceNumber);
                writer.WriteByteArray(encryptedBody);
                await _channel.WriteBytesAsync(writer.CreatePacket());

                packet = await _channel.ReadPacketSlowAsync();

                ThrowIfErrorPacket(packet, "Authentication error.");
            }
        }
Exemplo n.º 9
0
        internal static async Task <AssertionVerificationResult> MakeAssertionResponse(COSE.KeyType kty, COSE.Algorithm alg, COSE.EllipticCurve crv = COSE.EllipticCurve.P256, CredentialPublicKey cpk = null, ushort signCount = 0, ECDsa ecdsa = null, RSA rsa = null, byte[] expandedPrivateKey = null)
        {
            const string rp = "fido2.azurewebsites.net";

            byte[] rpId         = Encoding.UTF8.GetBytes(rp);
            var    rpIdHash     = SHA256.Create().ComputeHash(rpId);
            var    flags        = AuthenticatorFlags.AT | AuthenticatorFlags.ED | AuthenticatorFlags.UP | AuthenticatorFlags.UV;
            var    aaguid       = new Guid("F1D0F1D0-F1D0-F1D0-F1D0-F1D0F1D0F1D0");
            var    credentialID = new byte[] { 0xf1, 0xd0, 0xf1, 0xd0, 0xf1, 0xd0, 0xf1, 0xd0, 0xf1, 0xd0, 0xf1, 0xd0, 0xf1, 0xd0, 0xf1, 0xd0, };

            if (cpk == null)
            {
                switch (kty)
                {
                case COSE.KeyType.EC2:
                {
                    if (ecdsa == null)
                    {
                        ecdsa = MakeECDsa(alg, crv);
                    }
                    var ecparams = ecdsa.ExportParameters(true);
                    cpk = MakeCredentialPublicKey(kty, alg, crv, ecparams.Q.X, ecparams.Q.Y);
                    break;
                }

                case COSE.KeyType.RSA:
                {
                    if (rsa == null)
                    {
                        rsa = RSA.Create();
                    }
                    var rsaparams = rsa.ExportParameters(true);
                    cpk = MakeCredentialPublicKey(kty, alg, rsaparams.Modulus, rsaparams.Exponent);
                    break;
                }

                case COSE.KeyType.OKP:
                {
                    byte[] publicKey = null;
                    if (expandedPrivateKey == null)
                    {
                        MakeEdDSA(out var privateKeySeed, out publicKey, out expandedPrivateKey);
                    }

                    cpk = MakeCredentialPublicKey(kty, alg, COSE.EllipticCurve.Ed25519, publicKey);
                    break;
                }
                    throw new ArgumentOutOfRangeException(nameof(kty), $"Missing or unknown kty {kty}");
                }
            }
            var acd      = new AttestedCredentialData(aaguid, credentialID, cpk);
            var extBytes = CBORObject.NewMap().Add("testing", true).EncodeToBytes();
            var exts     = new Extensions(extBytes);

            var ad       = new AuthenticatorData(rpIdHash, flags, (uint)(signCount + 1), acd, exts);
            var authData = ad.ToByteArray();

            var challenge = new byte[128];
            var rng       = RandomNumberGenerator.Create();

            rng.GetBytes(challenge);

            var clientData = new
            {
                Type      = "webauthn.get",
                Challenge = challenge,
                Origin    = rp,
            };
            var clientDataJson = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(clientData));

            var sha = SHA256.Create();
            var hashedClientDataJson = sha.ComputeHash(clientDataJson);

            byte[] data = new byte[authData.Length + hashedClientDataJson.Length];
            Buffer.BlockCopy(authData, 0, data, 0, authData.Length);
            Buffer.BlockCopy(hashedClientDataJson, 0, data, authData.Length, hashedClientDataJson.Length);
            byte[] signature = SignData(kty, alg, data, ecdsa, rsa, expandedPrivateKey);

            var userHandle = new byte[16];

            rng.GetBytes(userHandle);

            var assertion = new AuthenticatorAssertionRawResponse.AssertionResponse()
            {
                AuthenticatorData = authData,
                Signature         = signature,
                ClientDataJson    = clientDataJson,
                UserHandle        = userHandle,
            };

            var lib = new Fido2(new Fido2Configuration()
            {
                ServerDomain = rp,
                ServerName   = rp,
                Origin       = rp,
            });
            var existingCredentials = new List <PublicKeyCredentialDescriptor>();
            var cred = new PublicKeyCredentialDescriptor
            {
                Type = PublicKeyCredentialType.PublicKey,
                Id   = new byte[] { 0xf1, 0xd0 }
            };

            existingCredentials.Add(cred);

            var options = lib.GetAssertionOptions(existingCredentials, null, null);

            options.Challenge = challenge;
            var response = new AuthenticatorAssertionRawResponse()
            {
                Response = assertion,
                Type     = PublicKeyCredentialType.PublicKey,
                Id       = new byte[] { 0xf1, 0xd0 },
                RawId    = new byte[] { 0xf1, 0xd0 },
            };
            IsUserHandleOwnerOfCredentialIdAsync callback = (args) =>
            {
                return(Task.FromResult(true));
            };

            return(await lib.MakeAssertionAsync(response, options, cpk.GetBytes(), signCount, callback));
        }
Exemplo n.º 10
0
        public void RoundtripSample1()
        {
            using (StringWriter sw = new StringWriter())
            {
                // Encryption
                {
                    XmlDocument doc = new XmlDocument();
                    doc.PreserveWhitespace = true;
                    doc.LoadXml("<root>  <child>sample</child>   </root>");

                    XmlElement body = doc.DocumentElement;

                    using (Aes aes = Aes.Create())
                    {
                        aes.Mode    = CipherMode.CBC;
                        aes.KeySize = 256;
                        aes.IV      = Convert.FromBase64String("pBUM5P03rZ6AE4ZK5EyBrw==");
                        // [SuppressMessage("Microsoft.Security", "CS002:SecretInNextLine", Justification="Unit test key.")]
                        aes.Key     = Convert.FromBase64String("o/ilseZu+keLBBWGGPlUHweqxIPc4gzZEFWr2nBt640=");
                        aes.Padding = PaddingMode.Zeros;

                        EncryptedXml  exml      = new EncryptedXml();
                        byte[]        encrypted = exml.EncryptData(body, aes, false);
                        EncryptedData edata     = new EncryptedData();
                        edata.Type             = EncryptedXml.XmlEncElementUrl;
                        edata.EncryptionMethod = new EncryptionMethod(EncryptedXml.XmlEncAES256Url);
                        EncryptedKey ekey = new EncryptedKey();
                        // omit key encryption, here for testing
                        byte[] encKeyBytes = aes.Key;
                        ekey.CipherData       = new CipherData(encKeyBytes);
                        ekey.EncryptionMethod = new EncryptionMethod(EncryptedXml.XmlEncRSA15Url);
                        DataReference dr = new DataReference();
                        dr.Uri = "_0";
                        ekey.AddReference(dr);
                        edata.KeyInfo.AddClause(new KeyInfoEncryptedKey(ekey));
                        ekey.KeyInfo.AddClause(new RSAKeyValue(RSA.Create()));
                        edata.CipherData.CipherValue = encrypted;
                        EncryptedXml.ReplaceElement(doc.DocumentElement, edata, false);
                        doc.Save(new XmlTextWriter(sw));
                    }
                }

                // Decryption
                {
                    using (Aes aes = Aes.Create())
                    {
                        aes.Mode    = CipherMode.CBC;
                        aes.KeySize = 256;
                        // [SuppressMessage("Microsoft.Security", "CS002:SecretInNextLine", Justification="Unit test key.")]
                        aes.Key     = Convert.FromBase64String("o/ilseZu+keLBBWGGPlUHweqxIPc4gzZEFWr2nBt640=");
                        aes.Padding = PaddingMode.Zeros;

                        XmlDocument doc = new XmlDocument();
                        doc.PreserveWhitespace = true;
                        doc.LoadXml(sw.ToString());
                        EncryptedXml  encxml = new EncryptedXml(doc);
                        EncryptedData edata  = new EncryptedData();
                        edata.LoadXml(doc.DocumentElement);
                        encxml.ReplaceData(doc.DocumentElement, encxml.DecryptData(edata, aes));
                    }
                }
            }
        }
Exemplo n.º 11
0
        public static void Load(IServiceCollection services, IConfiguration configuration)
        {
            AuthenticationSettings authenticationSettings = new AuthenticationSettings();

            configuration.Bind(nameof(authenticationSettings), authenticationSettings);
            services.AddSingleton(authenticationSettings);

            services
            .AddAuthentication(o =>
            {
                o.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                o.DefaultScheme             = JwtBearerDefaults.AuthenticationScheme;
                o.DefaultChallengeScheme    = JwtBearerDefaults.AuthenticationScheme;
            })
            .AddJwtBearer(o =>
            {
                o.RequireHttpsMetadata = false;
                o.Authority            = authenticationSettings.KeycloakSettings.Authority;
                o.Audience             = authenticationSettings.KeycloakSettings.Audience;

                RSA publicRsa = RSA.Create();
                publicRsa.FromXmlString(
                    File.ReadAllText(
                        Path.Combine(Directory.GetCurrentDirectory(), "Cert", authenticationSettings.PublicKey))
                    );

                RsaSecurityKey signingKey = new RsaSecurityKey(publicRsa);
                o.SaveToken = true;
                o.TokenValidationParameters = new TokenValidationParameters
                {
                    IssuerSigningKey         = signingKey,
                    ValidateIssuerSigningKey = true,

                    ValidIssuer    = authenticationSettings.KeycloakSettings.Issuer,
                    ValidateIssuer = true,

                    ValidAudience    = authenticationSettings.KeycloakSettings.Audience,
                    ValidateAudience = true
                };

                o.Events = new JwtBearerEvents
                {
                    OnMessageReceived = context =>
                    {
                        var accessToken = context.Request.Query["access_token"];

                        var path = context.HttpContext.Request.Path;
                        if (!string.IsNullOrEmpty(accessToken) && path.StartsWithSegments("/v1/notify"))
                        {
                            context.Token = accessToken;
                        }
                        return(Task.CompletedTask);
                    }
                };
            });

            services.AddCors();
            services.AddAuthorization(opt =>
            {
                opt.AddPolicy("Authenticated", p => p.RequireAssertion(require => require.User.Identity.IsAuthenticated));
                opt.AddPolicy("Anonymous", p => p.RequireAssertion(o => true));
            });

            services.AddScoped <ICurrentSessionUser>(c =>
            {
                var context = c.GetRequiredService <IHttpContextAccessor>().HttpContext;

                if (context != null && context.User.Identity.IsAuthenticated)
                {
                    ClaimsIdentity identity = (ClaimsIdentity)context.User.Identity;

                    string claimsSchemaPrefix = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims";

                    return(new CurrentSessionUser
                    {
                        Id = identity.Claims.FirstOrDefault(c => c.Type == $"{claimsSchemaPrefix}/nameidentifier")?.Value,
                        GivenName = identity.Claims.FirstOrDefault(c => c.Type == $"{claimsSchemaPrefix}/givenname")?.Value,
                        SurName = identity.Claims.FirstOrDefault(c => c.Type == $"{claimsSchemaPrefix}/surname")?.Value,
                        EmailAddress = identity.Claims.FirstOrDefault(c => c.Type == $"{claimsSchemaPrefix}/emailaddress")?.Value
                    });
                }

                return(null);
            });
        }
Exemplo n.º 12
0
        private static RSA CreateRsaFromPublicKey(string publicKey)
        {
            if (publicKey == null)
            {
                throw new ArgumentNullException(nameof(publicKey));
            }
            publicKey = publicKey.SafeToString().Replace("-----BEGIN PUBLIC KEY-----", "")
                        .Replace("-----END PUBLIC KEY-----", "").Trim().Replace("\r", "").Replace("\n", "");

            byte[] SeqOID = { 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00 };
            byte[] x509key;
            byte[] seq = new byte[15];
            int    x509size;

            x509key  = Convert.FromBase64String(publicKey);
            x509size = x509key.Length;

            using (var mem = new MemoryStream(x509key))
            {
                using (var binr = new BinaryReader(mem))
                {
                    byte   bt       = 0;
                    ushort twobytes = 0;

                    twobytes = binr.ReadUInt16();
                    if (twobytes == 0x8130)
                    {
                        binr.ReadByte();
                    }
                    else if (twobytes == 0x8230)
                    {
                        binr.ReadInt16();
                    }
                    else
                    {
                        return(null);
                    }

                    seq = binr.ReadBytes(15);
                    if (!CompareBytearrays(seq, SeqOID))
                    {
                        return(null);
                    }

                    twobytes = binr.ReadUInt16();
                    if (twobytes == 0x8103)
                    {
                        binr.ReadByte();
                    }
                    else if (twobytes == 0x8203)
                    {
                        binr.ReadInt16();
                    }
                    else
                    {
                        return(null);
                    }

                    bt = binr.ReadByte();
                    if (bt != 0x00)
                    {
                        return(null);
                    }

                    twobytes = binr.ReadUInt16();
                    if (twobytes == 0x8130)
                    {
                        binr.ReadByte();
                    }
                    else if (twobytes == 0x8230)
                    {
                        binr.ReadInt16();
                    }
                    else
                    {
                        return(null);
                    }

                    twobytes = binr.ReadUInt16();
                    byte lowbyte  = 0x00;
                    byte highbyte = 0x00;

                    if (twobytes == 0x8102)
                    {
                        lowbyte = binr.ReadByte();
                    }
                    else if (twobytes == 0x8202)
                    {
                        highbyte = binr.ReadByte();
                        lowbyte  = binr.ReadByte();
                    }
                    else
                    {
                        return(null);
                    }

                    byte[] modint  = { lowbyte, highbyte, 0x00, 0x00 };
                    int    modsize = BitConverter.ToInt32(modint, 0);

                    int firstbyte = binr.PeekChar();
                    if (firstbyte == 0x00)
                    {
                        binr.ReadByte();
                        modsize -= 1;
                    }

                    byte[] modulus = binr.ReadBytes(modsize);

                    if (binr.ReadByte() != 0x02)
                    {
                        return(null);
                    }
                    int    expbytes = (int)binr.ReadByte();
                    byte[] exponent = binr.ReadBytes(expbytes);

                    var rsa        = RSA.Create();
                    var rsaKeyInfo = new RSAParameters
                    {
                        Modulus  = modulus,
                        Exponent = exponent
                    };
                    rsa.ImportParameters(rsaKeyInfo);
                    return(rsa);
                }
            }
        }
Exemplo n.º 13
0
        /// <summary>
        /// Generates a self signed certificate.
        /// </summary>
        private void GenerateSelfSignedCertificate()
        {
            if (File.Exists(_currentpath + "\\SquadRconCertificate.pfx"))
            {
                try
                {
                    var certificate = new X509Certificate2(File.ReadAllBytes(_currentpath + "\\SquadRconCertificate.pfx"), CertificatePassword);
                }
                catch (CryptographicException ex)
                {
                    var data = (ex.HResult & 0xFFFF);
                    if (data == 0x56)
                    {
                        Logger.LogError("[Certificate] Certificate password incorrect.");
                        return;
                    }
                    Logger.LogError("[Certificate] Existing Certificate has issues. Please refer to: https://docs.microsoft.com/en-us/windows/win32/debug/system-error-codes--0-499-?redirectedfrom=MSDN");
                    Logger.LogError("Error Code: " + data);
                    Logger.LogError("Error: " + ex);
                    return;
                }
                Certificate = new X509Certificate2(_currentpath + "\\SquadRconCertificate.pfx", CertificatePassword);
                Logger.Log("[Certificate] Existing Certificate successfully loaded!");
                return;
            }
            Logger.Log("[Certificate] Generating self signed SSL Certificate...");

            if (File.Exists(_currentpath + "\\SquadRconCertificate.pfx"))
            {
                File.Delete(_currentpath + "\\SquadRconCertificate.pfx");
            }

            SubjectAlternativeNameBuilder sanBuilder = new SubjectAlternativeNameBuilder();

            sanBuilder.AddIpAddress(IPAddress.Loopback);
            sanBuilder.AddIpAddress(IPAddress.IPv6Loopback);
            sanBuilder.AddDnsName("localhost");
            sanBuilder.AddDnsName(Environment.MachineName);

            foreach (var x in IpsAndDomains.Split(','))
            {
                if (string.IsNullOrEmpty(x))
                {
                    continue;
                }

                if (IPCheck.Match(x.Trim()).Success)
                {
                    sanBuilder.AddIpAddress(IPAddress.Parse(x));
                }
                else
                {
                    sanBuilder.AddDnsName(x.Trim());
                }
            }

            X500DistinguishedName distinguishedName = new X500DistinguishedName($"CN=SquadRconServer");

            using (RSA rsa = RSA.Create(2048))
            {
                var request = new CertificateRequest(distinguishedName, rsa, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);

                request.CertificateExtensions.Add(
                    new X509KeyUsageExtension(X509KeyUsageFlags.DataEncipherment | X509KeyUsageFlags.KeyEncipherment | X509KeyUsageFlags.DigitalSignature, false));


                request.CertificateExtensions.Add(
                    new X509EnhancedKeyUsageExtension(
                        new OidCollection {
                    new Oid("1.3.6.1.5.5.7.3.1")
                }, false));

                request.CertificateExtensions.Add(sanBuilder.Build());

                var certificate = request.CreateSelfSigned(new DateTimeOffset(DateTime.UtcNow.AddDays(-1)), new DateTimeOffset(DateTime.UtcNow.AddDays(3650)));
                certificate.FriendlyName = "SquadRconServer";
                byte[] certbytes = certificate.Export(X509ContentType.Pfx, CertificatePassword);

                Certificate = new X509Certificate2(certbytes,
                                                   CertificatePassword, X509KeyStorageFlags.MachineKeySet);

                // Create PFX (PKCS #12) with private key
                File.WriteAllBytes(_currentpath + "\\SquadRconCertificate.pfx", certbytes);
            }
            Logger.Log("[Certificate] Complete!");
        }
Exemplo n.º 14
0
 public static RsaSshKey Generate(int keyLength)
 {
     using var rsa = RSA.Create(keyLength);
     return(Generate(rsa));
 }
Exemplo n.º 15
0
        internal static (X509Certificate2 certificate, X509Certificate2Collection) GenerateCertificates(string targetName, [CallerMemberName] string?testName = null, bool longChain = false, bool serverCertificate = true)
        {
            const int keySize = 2048;

            if (PlatformDetection.IsWindows && testName != null)
            {
                CleanupCertificates(testName);
            }

            X509Certificate2Collection chain      = new X509Certificate2Collection();
            X509ExtensionCollection    extensions = new X509ExtensionCollection();

            SubjectAlternativeNameBuilder builder = new SubjectAlternativeNameBuilder();

            builder.AddDnsName(targetName);
            extensions.Add(builder.Build());
            extensions.Add(s_eeConstraints);
            extensions.Add(s_eeKeyUsage);
            extensions.Add(serverCertificate ? s_tlsServerEku : s_tlsClientEku);

            CertificateAuthority.BuildPrivatePki(
                PkiOptions.IssuerRevocationViaCrl,
                out RevocationResponder responder,
                out CertificateAuthority root,
                out CertificateAuthority intermediate,
                out X509Certificate2 endEntity,
                subjectName: targetName,
                testName: testName,
                keySize: keySize,
                extensions: extensions);

            if (longChain)
            {
                using (RSA intermedKey2 = RSA.Create(keySize))
                    using (RSA intermedKey3 = RSA.Create(keySize))
                    {
                        X509Certificate2 intermedPub2 = intermediate.CreateSubordinateCA(
                            $"CN=\"A SSL Test CA 2\", O=\"testName\"",
                            intermedKey2);

                        X509Certificate2 intermedCert2 = intermedPub2.CopyWithPrivateKey(intermedKey2);
                        intermedPub2.Dispose();
                        CertificateAuthority intermediateAuthority2 = new CertificateAuthority(intermedCert2, null, null, null);

                        X509Certificate2 intermedPub3 = intermediateAuthority2.CreateSubordinateCA(
                            $"CN=\"A SSL Test CA 3\", O=\"testName\"",
                            intermedKey3);

                        X509Certificate2 intermedCert3 = intermedPub3.CopyWithPrivateKey(intermedKey3);
                        intermedPub3.Dispose();
                        CertificateAuthority intermediateAuthority3 = new CertificateAuthority(intermedCert3, null, null, null);

                        RSA eeKey = (RSA)endEntity.PrivateKey;
                        endEntity = intermediateAuthority3.CreateEndEntity(
                            $"CN=\"A SSL Test\", O=\"testName\"",
                            eeKey,
                            extensions);

                        endEntity = endEntity.CopyWithPrivateKey(eeKey);

                        chain.Add(intermedCert3);
                        chain.Add(intermedCert2);
                    }
            }

            chain.Add(intermediate.CloneIssuerCert());
            chain.Add(root.CloneIssuerCert());

            responder.Dispose();
            root.Dispose();
            intermediate.Dispose();

            if (PlatformDetection.IsWindows)
            {
                endEntity = new X509Certificate2(endEntity.Export(X509ContentType.Pfx));
            }

            return(endEntity, chain);
        }
Exemplo n.º 16
0
 /// <summary>
 /// 创建PEM格式的RSA密钥对,默认填充为【PKCS#8】,默认【密钥长度】为2048
 /// <para>【isPKCS8】为真时返回PKCS#8格式,否则返回PKCS#1格式,默认为【PKCS#8】</para>
 /// </summary>
 /// <param name="isPKCS8">是否为【PKCS#8】填充方式</param>
 /// <param name="size">密钥长度</param>
 /// <returns></returns>
 public (string publicKey, string privateKey) CreatePemKey(bool isPKCS8 = true, RsaSize size = RsaSize.R2048)
 {
     using RSA rsa = RSA.Create();
     rsa.KeySize   = (int)size;
     return(RsaToPEM(rsa, false, isPKCS8), RsaToPEM(rsa, true, isPKCS8));
 }
Exemplo n.º 17
0
        private static RSA DecodeRSAPrivateKey(byte[] privkey)
        {
            byte[] MODULUS, E, D, P, Q, DP, DQ, IQ;

            // ---------  Set up stream to decode the asn.1 encoded RSA private key  ------
            MemoryStream mem      = new MemoryStream(privkey);
            BinaryReader binr     = new BinaryReader(mem); //wrap Memory Stream with BinaryReader for easy reading
            byte         bt       = 0;
            ushort       twobytes = 0;
            int          elems    = 0;

            try
            {
                twobytes = binr.ReadUInt16();
                if (twobytes == 0x8130) //data read as little endian order (actual data order for Sequence is 30 81)
                {
                    binr.ReadByte();    //advance 1 byte
                }
                else if (twobytes == 0x8230)
                {
                    binr.ReadInt16();   //advance 2 bytes
                }
                else
                {
                    return(null);
                }

                twobytes = binr.ReadUInt16();
                if (twobytes != 0x0102) //version number
                {
                    return(null);
                }
                bt = binr.ReadByte();
                if (bt != 0x00)
                {
                    return(null);
                }


                //------  all private key components are Integer sequences ----
                elems   = GetIntegerSize(binr);
                MODULUS = binr.ReadBytes(elems);

                elems = GetIntegerSize(binr);
                E     = binr.ReadBytes(elems);

                elems = GetIntegerSize(binr);
                D     = binr.ReadBytes(elems);

                elems = GetIntegerSize(binr);
                P     = binr.ReadBytes(elems);

                elems = GetIntegerSize(binr);
                Q     = binr.ReadBytes(elems);

                elems = GetIntegerSize(binr);
                DP    = binr.ReadBytes(elems);

                elems = GetIntegerSize(binr);
                DQ    = binr.ReadBytes(elems);

                elems = GetIntegerSize(binr);
                IQ    = binr.ReadBytes(elems);

                // ------- create RSACryptoServiceProvider instance and initialize with public key -----
                RSA           RSA       = RSA.Create();
                RSAParameters RSAparams = new RSAParameters();
                RSAparams.Modulus  = MODULUS;
                RSAparams.Exponent = E;
                RSAparams.D        = D;
                RSAparams.P        = P;
                RSAparams.Q        = Q;
                RSAparams.DP       = DP;
                RSAparams.DQ       = DQ;
                RSAparams.InverseQ = IQ;
                RSA.ImportParameters(RSAparams);
                return(RSA);
            }
            catch (Exception)
            {
                return(null);
            }
            finally { binr.Dispose(); }
        }
Exemplo n.º 18
0
        static async Task Main(string[] args)
        {
            if (args.Length < 2)
            {
                var versionString = Assembly.GetEntryAssembly()
                                    .GetCustomAttribute <AssemblyInformationalVersionAttribute>()
                                    .InformationalVersion
                                    .ToString();

                Console.WriteLine($"coaget v{versionString}");
                Console.WriteLine("-------------");
                Console.WriteLine("\nUsage:");
                Console.WriteLine("  coaget <coalite_server_uri> <user_tag> [action=CLAIM] [priv_key_path=key.pkcs1.prv] [pub_key_path=key.pkcs1.pub] [existing_coalite=None] [mint_payload=payload.b64]");
                return;
            }
            var             coaliteServerUri = args[0];
            var             userTag          = args[1];
            var             coaliteAction    = args.Length > 2 ? Enum.Parse <CoaliteAction>(args[2]) : CoaliteAction.CLAIM;
            var             privateKeyData   = args.Length > 3 ? File.ReadAllText(args[3]) : File.ReadAllText("key.prv");
            var             publicKeyData    = args.Length > 4 ? File.ReadAllText(args[4]) : File.ReadAllText("key.pub").Trim();
            CoaliteResource existingCoalite  = args.Length > 5 ? JToken.Parse(File.ReadAllText(args[5])).ToObject <CoaliteResource>() : null;
            var             mintPayload      = coaliteAction == CoaliteAction.MINT ? (args.Length > 6 ? File.ReadAllText(args[6]) : File.ReadAllText("payload.b64").Trim()) : "";


            RSA rsa = RSA.Create();
            int bytesRead;

            rsa.ImportRSAPrivateKey(Convert.FromBase64String(privateKeyData), out bytesRead);

            var             httpClient      = new HttpClient();
            CoaliteResource coaliteResource = null;

            if (coaliteAction == CoaliteAction.CLAIM)
            {
                // In this case we need to get a new coalite to claim
                var response = await httpClient.GetStringAsync($"{coaliteServerUri}/coalite");//"http://localhost:5000/coalite"

                coaliteResource = JToken.Parse(response).ToObject <CoaliteResource>();
            }
            else
            {
                // In this case we loaded an existing coalite from a file and try to execute an action on it
                if (existingCoalite == null)
                {
                    Console.WriteLine("Error: For actions other than CLAIM, an existing coalite resource file needs to be provided.");
                    return;
                }
                coaliteResource = existingCoalite;
            }

            var request = coaliteResource.CreateActionRequest(rsa, coaliteAction, mintPayload, publicKeyData, userTag);

            var buffer    = Encoding.UTF8.GetBytes(request.GetAsSignablePayload());
            var signature = Convert.FromBase64String(request.Signature);
            var clientRsa = RSA.Create();
            int bytesReadPk;
            var pk = request.SignerPublicKey.Split(' ').OrderByDescending(s => s.Length).FirstOrDefault();

            clientRsa.ImportRSAPublicKey(Convert.FromBase64String(pk), out bytesReadPk);

            // Check integrity of the signature of own request.
            if (!clientRsa.VerifyData(buffer, signature, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1))
            {
                throw new Exception("Could not verify own signature. Something wrong with client keys.");
            }

            var requestStr     = JToken.FromObject(request).ToString(Newtonsoft.Json.Formatting.None);
            var requestContent = new StringContent(requestStr,
                                                   Encoding.UTF8, "application/json");
            var result = await httpClient.PostAsync($"{coaliteServerUri}/coalite/action", requestContent);

            var finalResult = await result.Content.ReadAsStringAsync();

            Console.WriteLine(finalResult);
            result.EnsureSuccessStatusCode();
        }
Exemplo n.º 19
0
        private static RSA DecodeRSAPublicKey(byte[] publickey)
        {
            // encoded OID sequence for  PKCS #1 rsaEncryption szOID_RSA_RSA = "1.2.840.113549.1.1.1"
            byte[] SeqOID = { 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00 };
            byte[] seq    = new byte[15];
            // ---------  Set up stream to read the asn.1 encoded SubjectPublicKeyInfo blob  ------
            MemoryStream mem      = new MemoryStream(publickey);
            BinaryReader binr     = new BinaryReader(mem); //wrap Memory Stream with BinaryReader for easy reading
            byte         bt       = 0;
            ushort       twobytes = 0;

            try
            {
                twobytes = binr.ReadUInt16();
                if (twobytes == 0x8130) //data read as little endian order (actual data order for Sequence is 30 81)
                {
                    binr.ReadByte();    //advance 1 byte
                }
                else if (twobytes == 0x8230)
                {
                    binr.ReadInt16();   //advance 2 bytes
                }
                else
                {
                    return(null);
                }

                seq = binr.ReadBytes(15);            //read the Sequence OID
                if (!CompareBytearrays(seq, SeqOID)) //make sure Sequence for OID is correct
                {
                    return(null);
                }

                twobytes = binr.ReadUInt16();
                if (twobytes == 0x8103) //data read as little endian order (actual data order for Bit String is 03 81)
                {
                    binr.ReadByte();    //advance 1 byte
                }
                else if (twobytes == 0x8203)
                {
                    binr.ReadInt16();   //advance 2 bytes
                }
                else
                {
                    return(null);
                }

                bt = binr.ReadByte();
                if (bt != 0x00)     //expect null byte next
                {
                    return(null);
                }

                twobytes = binr.ReadUInt16();
                if (twobytes == 0x8130) //data read as little endian order (actual data order for Sequence is 30 81)
                {
                    binr.ReadByte();    //advance 1 byte
                }
                else if (twobytes == 0x8230)
                {
                    binr.ReadInt16();   //advance 2 bytes
                }
                else
                {
                    return(null);
                }

                twobytes = binr.ReadUInt16();
                byte lowbyte  = 0x00;
                byte highbyte = 0x00;

                if (twobytes == 0x8102)        //data read as little endian order (actual data order for Integer is 02 81)
                {
                    lowbyte = binr.ReadByte(); // read next bytes which is bytes in modulus
                }
                else if (twobytes == 0x8202)
                {
                    highbyte = binr.ReadByte(); //advance 2 bytes
                    lowbyte  = binr.ReadByte();
                }
                else
                {
                    return(null);
                }
                byte[] modint  = { lowbyte, highbyte, 0x00, 0x00 };  //reverse byte order since asn.1 key uses big endian order
                int    modsize = BitConverter.ToInt32(modint, 0);

                byte firstbyte = binr.ReadByte();
                binr.BaseStream.Seek(-1, SeekOrigin.Current);

                if (firstbyte == 0x00)
                {                    //if first byte (highest order) of modulus is zero, don't include it
                    binr.ReadByte(); //skip this null byte
                    modsize -= 1;    //reduce modulus buffer size by 1
                }

                byte[] modulus = binr.ReadBytes(modsize); //read the modulus bytes

                if (binr.ReadByte() != 0x02)              //expect an Integer for the exponent data
                {
                    return(null);
                }
                int    expbytes = (int)binr.ReadByte();     // should only need one byte for actual exponent data (for all useful values)
                byte[] exponent = binr.ReadBytes(expbytes);

                // ------- create RSACryptoServiceProvider instance and initialize with public key -----
                RSA           RSA        = RSA.Create();
                RSAParameters RSAKeyInfo = new RSAParameters();
                RSAKeyInfo.Modulus  = modulus;
                RSAKeyInfo.Exponent = exponent;
                RSA.ImportParameters(RSAKeyInfo);
                return(RSA);
            }
            catch (Exception)
            {
                return(null);
            }

            finally { binr.Dispose(); }
        }
Exemplo n.º 20
0
        static RSA FromCapiPrivateKeyBlob(byte[] blob, int offset)
        {
            RSAParameters rsap = new RSAParameters();

            try {
                if ((blob [offset] != 0x07) ||                                          // PRIVATEKEYBLOB (0x07)
                    (blob [offset + 1] != 0x02) ||                                      // Version (0x02)
                    (blob [offset + 2] != 0x00) ||                                      // Reserved (word)
                    (blob [offset + 3] != 0x00) ||
                    (ToUInt32LE(blob, offset + 8) != 0x32415352))                       // DWORD magic = RSA2
                {
                    throw new CryptographicException("Invalid blob header");
                }

                // ALGID (CALG_RSA_SIGN, CALG_RSA_KEYX, ...)
                // int algId = ToInt32LE (blob, offset+4);

                // DWORD bitlen
                int bitLen = ToInt32LE(blob, offset + 12);

                // DWORD public exponent
                byte[] exp = new byte [4];
                Buffer.BlockCopy(blob, offset + 16, exp, 0, 4);
                Array.Reverse(exp);
                rsap.Exponent = Trim(exp);

                int pos = offset + 20;
                // BYTE modulus[rsapubkey.bitlen/8];
                int byteLen = (bitLen >> 3);
                rsap.Modulus = new byte [byteLen];
                Buffer.BlockCopy(blob, pos, rsap.Modulus, 0, byteLen);
                Array.Reverse(rsap.Modulus);
                pos += byteLen;

                // BYTE prime1[rsapubkey.bitlen/16];
                int byteHalfLen = (byteLen >> 1);
                rsap.P = new byte [byteHalfLen];
                Buffer.BlockCopy(blob, pos, rsap.P, 0, byteHalfLen);
                Array.Reverse(rsap.P);
                pos += byteHalfLen;

                // BYTE prime2[rsapubkey.bitlen/16];
                rsap.Q = new byte [byteHalfLen];
                Buffer.BlockCopy(blob, pos, rsap.Q, 0, byteHalfLen);
                Array.Reverse(rsap.Q);
                pos += byteHalfLen;

                // BYTE exponent1[rsapubkey.bitlen/16];
                rsap.DP = new byte [byteHalfLen];
                Buffer.BlockCopy(blob, pos, rsap.DP, 0, byteHalfLen);
                Array.Reverse(rsap.DP);
                pos += byteHalfLen;

                // BYTE exponent2[rsapubkey.bitlen/16];
                rsap.DQ = new byte [byteHalfLen];
                Buffer.BlockCopy(blob, pos, rsap.DQ, 0, byteHalfLen);
                Array.Reverse(rsap.DQ);
                pos += byteHalfLen;

                // BYTE coefficient[rsapubkey.bitlen/16];
                rsap.InverseQ = new byte [byteHalfLen];
                Buffer.BlockCopy(blob, pos, rsap.InverseQ, 0, byteHalfLen);
                Array.Reverse(rsap.InverseQ);
                pos += byteHalfLen;

                // ok, this is hackish but CryptoAPI support it so...
                // note: only works because CRT is used by default
                // http://bugzilla.ximian.com/show_bug.cgi?id=57941
                rsap.D = new byte [byteLen];                 // must be allocated
                if (pos + byteLen + offset <= blob.Length)
                {
                    // BYTE privateExponent[rsapubkey.bitlen/8];
                    Buffer.BlockCopy(blob, pos, rsap.D, 0, byteLen);
                    Array.Reverse(rsap.D);
                }
            }
            catch (Exception e) {
                throw new CryptographicException("Invalid blob.", e);
            }

            RSA rsa = null;

            try {
                rsa = RSA.Create();
                rsa.ImportParameters(rsap);
            }
            catch (CryptographicException ce) {
                // this may cause problem when this code is run under
                // the SYSTEM identity on Windows (e.g. ASP.NET). See
                // http://bugzilla.ximian.com/show_bug.cgi?id=77559
                try {
                    CspParameters csp = new CspParameters();
                    csp.Flags = CspProviderFlags.UseMachineKeyStore;
                    rsa       = new RSACryptoServiceProvider(csp);
                    rsa.ImportParameters(rsap);
                }
                catch {
                    // rethrow original, not the later, exception if this fails
                    throw ce;
                }
            }
            return(rsa);
        }
        public ConfigurationManagerL0()
        {
            _agentServer        = new Mock <IAgentServer>();
            _credMgr            = new Mock <ICredentialManager>();
            _promptManager      = new Mock <IPromptManager>();
            _store              = new Mock <IConfigurationStore>();
            _extnMgr            = new Mock <IExtensionManager>();
            _rsaKeyManager      = new Mock <IRSAKeyManager>();
            _machineGroupServer = new Mock <IDeploymentGroupServer>();
            _netFrameworkUtil   = new Mock <INetFrameworkUtil>();

#if OS_WINDOWS
            _serviceControlManager = new Mock <IWindowsServiceControlManager>();
#endif

#if !OS_WINDOWS
            _serviceControlManager = new Mock <ILinuxServiceControlManager>();
#endif

#if !OS_WINDOWS
            string eulaFile = Path.Combine(IOUtil.GetExternalsPath(), Constants.Path.TeeDirectory, "license.html");
            Directory.CreateDirectory(IOUtil.GetExternalsPath());
            Directory.CreateDirectory(Path.Combine(IOUtil.GetExternalsPath(), Constants.Path.TeeDirectory));
            File.WriteAllText(eulaFile, "testeulafile");
#endif

            _capabilitiesManager = new CapabilitiesManager();

            _agentServer.Setup(x => x.ConnectAsync(It.IsAny <VssConnection>())).Returns(Task.FromResult <object>(null));
            _machineGroupServer.Setup(x => x.ConnectAsync(It.IsAny <VssConnection>())).Returns(Task.FromResult <object>(null));
            _machineGroupServer.Setup(
                x =>
                x.UpdateDeploymentMachinesAsync(It.IsAny <string>(), It.IsAny <int>(),
                                                It.IsAny <List <DeploymentMachine> >()));
            _netFrameworkUtil.Setup(x => x.Test(It.IsAny <Version>())).Returns(true);

            _store.Setup(x => x.IsConfigured()).Returns(false);
            _store.Setup(x => x.HasCredentials()).Returns(false);
            _store.Setup(x => x.GetSettings()).Returns(() => _configMgrAgentSettings);

            _store.Setup(x => x.SaveSettings(It.IsAny <AgentSettings>()))
            .Callback((AgentSettings settings) =>
            {
                _configMgrAgentSettings = settings;
            });

            _credMgr.Setup(x => x.GetCredentialProvider(It.IsAny <string>())).Returns(new TestAgentCredential());

#if !OS_WINDOWS
            _serviceControlManager.Setup(x => x.GenerateScripts(It.IsAny <AgentSettings>()));
#endif

            var expectedPools = new List <TaskAgentPool>()
            {
                new TaskAgentPool(_expectedPoolName)
                {
                    Id = _expectedPoolId
                }
            };
            _agentServer.Setup(x => x.GetAgentPoolsAsync(It.IsAny <string>())).Returns(Task.FromResult(expectedPools));

            var expectedAgents = new List <TaskAgent>();
            _agentServer.Setup(x => x.GetAgentsAsync(It.IsAny <int>(), It.IsAny <string>())).Returns(Task.FromResult(expectedAgents));

            var expectedAgent = new TaskAgent(_expectedAgentName);
            expectedAgent.Id            = 1;
            expectedAgent.Authorization = new TaskAgentAuthorization
            {
                ClientId         = Guid.NewGuid(),
                AuthorizationUrl = new Uri("http://localhost:8080/tfs"),
            };
            _agentServer.Setup(x => x.AddAgentAsync(It.IsAny <int>(), It.IsAny <TaskAgent>())).Returns(Task.FromResult(expectedAgent));
            _agentServer.Setup(x => x.UpdateAgentAsync(It.IsAny <int>(), It.IsAny <TaskAgent>())).Returns(Task.FromResult(expectedAgent));

            rsa         = RSA.Create();
            rsa.KeySize = 2048;

            _rsaKeyManager.Setup(x => x.CreateKey()).Returns(rsa);
        }
Exemplo n.º 22
0
        internal static void CreateSelfSignCertificatePfx(
            string fileName,
            string hostname,
            ILogger logger)
        {
            if (string.IsNullOrWhiteSpace(fileName))
            {
                throw new ArgumentNullException("fileName");
            }

            byte[]   sn        = Guid.NewGuid().ToByteArray();
            string   subject   = string.Format("CN={0}", hostname);
            string   issuer    = subject;
            DateTime notBefore = DateTime.Now.AddDays(-2);
            DateTime notAfter  = DateTime.Now.AddYears(10);

            RSA issuerKey = RSA.Create();

            issuerKey.FromXmlString(MonoTestRootAgency);
            RSA subjectKey = RSA.Create();

            // serial number MUST be positive
            if ((sn[0] & 0x80) == 0x80)
            {
                sn[0] -= 0x80;
            }

            issuer    = subject;
            issuerKey = subjectKey;

            X509CertificateBuilder cb = new X509CertificateBuilder(3);

            cb.SerialNumber     = sn;
            cb.IssuerName       = issuer;
            cb.NotBefore        = notBefore;
            cb.NotAfter         = notAfter;
            cb.SubjectName      = subject;
            cb.SubjectPublicKey = subjectKey;

            // signature
            cb.Hash = "SHA256";
            byte[] rawcert = cb.Sign(issuerKey);

            PKCS12 p12 = new PKCS12();


            ArrayList list = new ArrayList();

            // we use a fixed array to avoid endianess issues
            // (in case some tools requires the ID to be 1).
            list.Add(new byte[4] {
                1, 0, 0, 0
            });
            Hashtable attributes = new Hashtable(1);

            attributes.Add(PKCS9.localKeyId, list);

            p12.AddCertificate(new X509Certificate(rawcert), attributes);

            p12.AddPkcs8ShroudedKeyBag(subjectKey, attributes);
            p12.SaveToFile(fileName);
        }
Exemplo n.º 23
0
        public async Task AcceptConversation(RSA rsa)
        {
            // initial streams are "in the clear"
            _outputStream = _tcpClient.GetStream();
            _inputStream  = _tcpClient.GetStream();

            /*
             *
             * connection negotiation starts with the client (initiater) not
             * the server (listener).
             *
             * 1. initiator sends pubkey, in the clear
             * 2. listener sends pubkey, encrypted with initiator pubkey
             * 3. initiator sends aes key, encrypted with listener pubkey
             * 4. listener sends aes key, encrypted with initiator aes key
             *
             * upon success communication continues over unidirectional,
             * encrypted channels.
             *
             */

            // expect pubkey (in the clear)
            var remoteRsaExpectedSize = await ReadMessageLength();

            var remoteRsaData = await ReadMessagePayload(
                _inputStream,
                remoteRsaExpectedSize,
                _cancellationTokenSource.Token);

            var remoteRsaJson       = Encoding.UTF8.GetString(remoteRsaData);
            var remoteRsaParameters = JsonConvert.DeserializeObject <dynamic>(
                remoteRsaJson);

            var remoteRSA = RSA.Create();

            remoteRSA.ImportParameters(
                new RSAParameters
            {
                Exponent = Convert.FromBase64String(
                    Convert.ToString(remoteRsaParameters.E)),
                Modulus = Convert.FromBase64String(
                    Convert.ToString(remoteRsaParameters.M)),
            });

            var thumbprint = _crypt.GetThumbprint(remoteRSA);

            Peer.Thumbprint = thumbprint;

            /*
             * // check client pubkey thumbprint against whitelist, if not in
             * // whitelist then force a disconnect
             * if (_whitelist.TryGetAlias(thumbprint, out string alias))
             * {
             *  Peer.Alias = alias;
             *  _onStatusChange($"Connected to {Peer}".Log());
             * }
             * else
             * {
             *  Peer.Alias = Peer.Thumbprint;
             *  _onStatusChange($@"Rejecting {Peer}, thumbprint is not authorized.
             * You can use the `/WHITELIST <thumbprint>` and `/BAN <thumbprint>` commands to authorized/deauthorize.".Log());
             *  return;
             * }
             */

            // send pubkey (in the clear)
            var rsaParameters = rsa.ExportParameters(false);
            var pubkey        = JsonConvert.SerializeObject(new
            {
                E = rsaParameters.Exponent,
                M = rsaParameters.Modulus,
            });
            {
                var buf = Encoding.UTF8.GetBytes(pubkey);
                await WriteMessage(buf);
            }

            // expect AES key (encrypted with our pubkey)
            var remoteAesExpectedSize = await ReadMessageLength();

            var remoteAesBytes = await ReadMessagePayload(_inputStream, remoteAesExpectedSize, _cancellationTokenSource.Token);

            remoteAesBytes = rsa.Decrypt(remoteAesBytes, RSAEncryptionPadding.Pkcs1);
            var remoteAesJson       = Encoding.UTF8.GetString(remoteAesBytes);
            var remoteAesParameters = JsonConvert.DeserializeObject <dynamic>(remoteAesJson);

            var remoteAes = Aes.Create();

            remoteAes.Key = remoteAesParameters.K;
            remoteAes.IV  = remoteAesParameters.V;

            // send our AES key (encrypted with remote pubkey)
            Aes aes     = Aes.Create();
            var aesJson = JsonConvert.SerializeObject(new
            {
                K = aes.Key,
                V = aes.IV
            });
            var aesBytes = Encoding.UTF8.GetBytes(aesJson);

            aesBytes = remoteRSA.Encrypt(aesBytes, RSAEncryptionPadding.Pkcs1);
            await WriteMessage(aesBytes, true); // NOTE: the flush block must come encrypted

            // continue communication using aes keys (rsa keys can be discarded)
            _inputStream = new CryptoStream(_inputStream, aes.CreateDecryptor(), CryptoStreamMode.Read);
            var encryptor = remoteAes.CreateEncryptor();

            // _idealFlushBlockCount = ((encryptor.InputBlockSize / 4) + 1);
            _outputStream = new CryptoStream(_outputStream, encryptor, CryptoStreamMode.Write);

            await WriteFlushBlock();

            _worker = EnterConversationLoop();
        }
        /// <summary>
        /// Adds a new ephemeral key used to sign the tokens issued by the OpenID Connect server:
        /// the key is discarded when the application shuts down and tokens signed using this key
        /// are automatically invalidated. This method should only be used during development.
        /// On production, using a X.509 certificate stored in the machine store is recommended.
        /// </summary>
        /// <param name="credentials">The signing credentials.</param>
        /// <param name="algorithm">The algorithm associated with the signing key.</param>
        /// <returns>The signing credentials.</returns>
        public static IList <SigningCredentials> AddEphemeralKey(
            [NotNull] this IList <SigningCredentials> credentials, [NotNull] string algorithm)
        {
            if (credentials == null)
            {
                throw new ArgumentNullException(nameof(credentials));
            }

            if (string.IsNullOrEmpty(algorithm))
            {
                throw new ArgumentException("The algorithm cannot be null or empty.", nameof(algorithm));
            }

            switch (algorithm)
            {
            case SecurityAlgorithms.RsaSha256Signature:
            case SecurityAlgorithms.RsaSha384Signature:
            case SecurityAlgorithms.RsaSha512Signature: {
                // Note: a 1024-bit key might be returned by RSA.Create() on .NET Desktop/Mono,
                // where RSACryptoServiceProvider is still the default implementation and
                // where custom implementations can be registered via CryptoConfig.
                // To ensure the key size is always acceptable, replace it if necessary.
                var rsa = RSA.Create();

                if (rsa.KeySize < 2048)
                {
                    rsa.KeySize = 2048;
                }

#if NET451
                // Note: RSACng cannot be used as it's not available on Mono.
                if (rsa.KeySize < 2048 && rsa is RSACryptoServiceProvider)
                {
                    rsa.Dispose();
                    rsa = new RSACryptoServiceProvider(2048);
                }
#endif

                if (rsa.KeySize < 2048)
                {
                    throw new InvalidOperationException("The ephemeral key generation failed.");
                }

                // Note: the RSA instance cannot be flowed as-is due to a bug in IdentityModel that disposes
                // the underlying algorithm when it can be cast to RSACryptoServiceProvider. To work around
                // this bug, the RSA public/private parameters are manually exported and re-imported when needed.
                SecurityKey key;
#if NET451
                if (rsa is RSACryptoServiceProvider)
                {
                    var parameters = rsa.ExportParameters(includePrivateParameters: true);
                    key       = new RsaSecurityKey(parameters);
                    key.KeyId = key.GetKeyIdentifier();

                    // Dispose the algorithm instance.
                    rsa.Dispose();
                }

                else
                {
#endif
                key       = new RsaSecurityKey(rsa);
                key.KeyId = key.GetKeyIdentifier();
#if NET451
            }
#endif

                credentials.Add(new SigningCredentials(key, algorithm));

                return(credentials);
            }

#if SUPPORTS_ECDSA
            case SecurityAlgorithms.EcdsaSha256Signature: {
                // Generate a new ECDSA key using the P-256 curve.
                var ecdsa = ECDsa.Create(ECCurve.NamedCurves.nistP256);

                var key = new ECDsaSecurityKey(ecdsa);
                key.KeyId = key.GetKeyIdentifier();

                credentials.Add(new SigningCredentials(key, algorithm));

                return(credentials);
            }

            case SecurityAlgorithms.EcdsaSha384Signature: {
                // Generate a new ECDSA key using the P-384 curve.
                var ecdsa = ECDsa.Create(ECCurve.NamedCurves.nistP384);

                var key = new ECDsaSecurityKey(ecdsa);
                key.KeyId = key.GetKeyIdentifier();

                credentials.Add(new SigningCredentials(key, algorithm));

                return(credentials);
            }

            case SecurityAlgorithms.EcdsaSha512Signature: {
                // Generate a new ECDSA key using the P-521 curve.
                var ecdsa = ECDsa.Create(ECCurve.NamedCurves.nistP521);

                var key = new ECDsaSecurityKey(ecdsa);
                key.KeyId = key.GetKeyIdentifier();

                credentials.Add(new SigningCredentials(key, algorithm));

                return(credentials);
            }
#endif

            default:
                throw new InvalidOperationException("The specified algorithm is not supported.");
            }
        }
Exemplo n.º 25
0
 public RSAService(AiurKeyPair keypair)
 {
     _privateKey = keypair.PrivateKey;
     _publicKey  = keypair.PublicKey;
     _rsa        = RSA.Create();
 }