/// <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)); }
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); } }
public static void CreateWithKeysize_InvalidKeySize(int keySizeInBits) { Assert.Throws <CryptographicException>(() => RSA.Create(keySizeInBits)); }
private Encryption() { _rsa = RSA.Create(); }
private static string RSAEncrypt(string sourceString) { RSA rsa = RSA.Create(); throw new NotImplementedException(); }
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); } } }
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."); } }
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)); }
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)); } } } }
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); }); }
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); } } }
/// <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!"); }
public static RsaSshKey Generate(int keyLength) { using var rsa = RSA.Create(keyLength); return(Generate(rsa)); }
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); }
/// <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)); }
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(); } }
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(); }
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(); } }
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); }
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); }
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."); } }
public RSAService(AiurKeyPair keypair) { _privateKey = keypair.PrivateKey; _publicKey = keypair.PublicKey; _rsa = RSA.Create(); }