コード例 #1
0
        //http://blog.differentpla.net/blog/2013/03/18/using-bouncy-castle-from-net
        public void CreateCertTest()
        {
            const string subject = "test";
            // ReSharper disable once UnusedVariable
            //const string password = "******";
            //// ReSharper disable once UnusedVariable
            //const int strength = 1024;

            var certService = new CertificateService {
                RandomPasswordSize = 4
            };

            using (var certificate = certService.CreateCert(subject))
            {
                var publicKeyProvider  = (RSACryptoServiceProvider)certificate.PublicKey.Key;
                var privateKeyProvider = (RSACryptoServiceProvider)certificate.PrivateKey;

                var rsaService         = RsaService.Create(certificate);
                var exportedCertBytes  = certificate.Export(X509ContentType.Pfx);
                var exportedCertBytes2 = certificate.Export(X509ContentType.Cert);

                var exportedCertBytesReparsed  = new X509Certificate2(exportedCertBytes);
                var exportedCertBytes2Reparsed = new X509Certificate2(exportedCertBytes2);

                Assert.IsNotNull(exportedCertBytesReparsed);
                Assert.IsNotNull(exportedCertBytes2Reparsed);
                Assert.AreEqual(publicKeyProvider.ToXmlString(false), privateKeyProvider.ToXmlString(false));
                Assert.AreEqual(rsaService.PrivateKey, privateKeyProvider.ToXmlString(true));
                Assert.AreEqual(rsaService.PublicKey, privateKeyProvider.ToXmlString(false));
            }
        }
コード例 #2
0
        public void DigitalSignatureTest()
        {
            var aesService = new AesService();

            (byte[] aesKey, byte[] aesIv) = aesService.CreateKey();

            const string messageData = "this is a test message";

            var messageBytes = Encoding.UTF8.GetBytes(messageData);
            var sender       = RsaService.Create();
            var receiver     = RsaService.Create();
            var hasher       = new Sha256BitHasher();


            var hashedMessageBytes = hasher.CreateHash(messageBytes);

            var digitalSignature = sender.EncryptPrivate(hashedMessageBytes);
            var cryptoBytes      = aesService.Encrypt(messageBytes, aesKey, aesIv);

            var hashMessageBytesFromSignature = receiver.DecryptPublic(digitalSignature, sender.PublicKey);
            var plainMessageBytes             = aesService.Decrypt(cryptoBytes, aesKey, aesIv);
            var hashedPlainMessageBytes       = hasher.CreateHash(plainMessageBytes);

            Assert.IsTrue(hashMessageBytesFromSignature.SequenceEqual(hashedPlainMessageBytes));
        }
コード例 #3
0
        public void KeyDeliveryTest()
        {
            //const string plainText = "this is the test plain data";
            var aesService = new AesService();

            (byte[] aesKey, byte[] aesIv) = aesService.CreateKey();
            var combinedBytes = aesKey.Concat(aesIv).ToArray();
            var client        = RsaService.Create();
            var server        = RsaService.Create();

            //send client aes encryption data from client to server
            var cryptoBytes           = client.Encrypt(combinedBytes, server.PublicKey);
            var receivedClientAesData = server.Decrypt(cryptoBytes);
            var receivedClientAesKey  = receivedClientAesData.Take(32).ToArray();
            var receivedClientAesIv   = receivedClientAesData.Reverse().Take(16).Reverse().ToArray();

            Assert.IsTrue(aesKey.SequenceEqual(receivedClientAesKey));
            Assert.IsTrue(aesIv.SequenceEqual(receivedClientAesIv));

            //send client aes encrypted message using received key and iv
            const string responseToClientMessage          = "I got your key thanks";
            var          responseToClientBytes            = Encoding.UTF8.GetBytes(responseToClientMessage);
            var          responseToClientBytesCryptoBytes = aesService.Encrypt(responseToClientBytes, receivedClientAesKey, receivedClientAesIv);

            //client decrypts server's response message
            var messageToClientBytes = aesService.Decrypt(responseToClientBytesCryptoBytes, aesKey, aesIv);
            var messageToClientText  = Encoding.UTF8.GetString(messageToClientBytes);

            Assert.IsTrue(responseToClientBytes.SequenceEqual(messageToClientBytes));
            Assert.AreEqual(responseToClientMessage, messageToClientText);
        }
コード例 #4
0
 public UserController(UserService userService, IMemoryCache memoryCache, ILogger <UserController> logger, RsaService rsaService, RsaServerKeys rsaServerKeys)
 {
     _userService   = userService;
     _memoryCache   = memoryCache;
     _logger        = logger;
     _rsaService    = rsaService;
     _rsaServerKeys = rsaServerKeys;
 }
コード例 #5
0
        public MainWindow()
        {
            InitializeComponent();
            _httpClient = new HttpClient
            {
                BaseAddress = new Uri(CommonEnvironment.HostServer)
            };

            _rsaService = new RsaService();
        }
コード例 #6
0
 public RsaController(RsaServerKeys rsaServerKeys,
                      IMemoryCache memoryCache,
                      RsaService rsaService,
                      ILogger <RsaController> logger)
 {
     _rsaServerKeys = rsaServerKeys;
     _memoryCache   = memoryCache;
     _rsaService    = rsaService;
     _logger        = logger;
 }
コード例 #7
0
        /// <summary>
        /// Create a default RSA public key
        /// </summary>
        /// <param name="receiver">The target receiver</param>
        /// <param name="isSender">Is </param>
        /// <returns>CipherKey object</returns>
        /// <remarks>This method will be used when cannot get receiver's public key from KMS</remarks>
        public async Task <CipherKey> CreateDefaultAsymmetricKey(KeyTypeEnum keyType, bool isIncludePrivateKey = true)
        {
            switch (keyType)
            {
            case KeyTypeEnum.RSA:
                using (var rsa = new RsaService())
                {
                    return(await rsa.CreateKeyAsync());
                }

            default:
                throw new NotImplementedException();
            }
        }
コード例 #8
0
        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);

            services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
            .AddCookie();
            services.AddScoped <UserService>();
            services.AddMemoryCache();
            services.AddSwaggerGen(opt =>
            {
                opt.SwaggerDoc("v1", new Info {
                    Title = "Документация API", Version = "v1"
                });

                opt.DescribeAllEnumsAsStrings();
            });
            var rsaKeys    = RsaService.GetKeyPair();
            var serverKeys = new RsaServerKeys(rsaKeys.PublicKey, rsaKeys.PrivateKey);

            services.AddRsaService();
            services.AddSingleton(serverKeys);
        }
コード例 #9
0
        /// <summary>
        /// 获取AES回执
        /// </summary>
        /// <returns></returns>
        private async Task <ApplyAESEncryptKeyResponse> GetDefaultAesKey(bool getnew = false)
        {
            var result = await _cacheManager.GetCache(AppConsts.Cache_AesKeyModal).GetOrDefaultAsync("AesKeyResult");

            if (result == null || getnew)
            {
                UserLoginSoapClient client = new UserLoginSoapClient(UserLoginSoapClient.EndpointConfiguration.UserLoginSoap);

                RSAParameters publicKey = RsaService.GetRsaPublicKey();

                ApplyAESEncryptKeyResponse AesResult = await client.ApplyAESEncryptKeyAsync(new ApplyAESEncryptKeyRequest { DeviceCode = deviceCode, Modulus = Convert.ToBase64String(publicKey.Modulus), Exponent = Convert.ToBase64String(publicKey.Exponent) });

                await _cacheManager.GetCache(AppConsts.Cache_AesKeyModal).SetAsync("AesKeyResult", AesResult);

                return(AesResult);
            }
            else
            {
                ApplyAESEncryptKeyResponse AesResult = (ApplyAESEncryptKeyResponse)result;
                return(AesResult);
            }
        }
コード例 #10
0
        public AsymmetricControllerFixture()
        {
            var svc = new RsaService();

            controller = new AsymmetricController(svc);
        }
コード例 #11
0
        /// <summary>
        /// Send the request
        /// </summary>
        /// <param name="request">Request</param>
        /// <param name="cancellationToken">Cancellation token</param>
        /// <returns>HttpResponseMessage</returns>
        protected override async Task <HttpResponseMessage> SendAsync(
            HttpRequestMessage request,
            CancellationToken cancellationToken)
        {
            #region Get receiver-name and retry-times from Http Header

            // Retry Times
            request.Headers.TryGetValues(CustomHttpHeaderFactory.RetryTimes, out IEnumerable <string> retryTimesValues);
            int retryTimes = 0;
            int.TryParse(retryTimesValues.FirstOrDefault(), out retryTimes);

            // RequestCacheId
            request.Headers.TryGetValues(CustomHttpHeaderFactory.RequestCacheId, out IEnumerable <string> requestCacheIdValues);
            var requestCacheId = requestCacheIdValues.FirstOrDefault();
            #endregion

            #region Encrypt the Http Request (Only in the first time)

            if (retryTimes.Equals(0))
            {
                this.logger.LogDebug($"Start encrypting request...");
                using (var rsa = new RsaService())
                {
                    #region Get public key
                    var publicKey = await this.keyManager.GetPublicKeyAsync(KeyTypeEnum.RSA);

                    #endregion

                    #region Get original payload

                    // Load payload
                    string content = await request.Content.ReadAsStringAsync();

                    // Remove escapted character, eq. "\"xxxxx\"" => "xxxxx"
                    var jsonPayload = JsonConvert.DeserializeObject <string>(content);
                    #endregion

                    #region Save the original payload before encrypted

                    var cacheKey = requestCacheId;
                    this.memoryCache.Set(cacheKey, jsonPayload, DateTimeOffset.Now.AddSeconds(CacheRequestTimeout));

                    this.logger.LogDebug($"Successfully caching original request to memory cache: {cacheKey}.");

                    #endregion

                    #region Encrypt

                    // Encrypt
                    string encryptedPayload = await rsa.EncryptAsync(publicKey, jsonPayload);

                    // Replace the original content with the encrypted one
                    var newContent = new System.Net.Http.StringContent($"\"{encryptedPayload}\"", Encoding.UTF8, "application/json");
                    ////newContent.Headers.ContentType.CharSet = string.Empty;
                    request.Content = newContent;

                    this.logger.LogDebug($"Successfully encrypting request.");
                    #endregion
                }
            }
            #endregion

            // base.SendAsync calls the inner handler
            var response = await base.SendAsync(request, cancellationToken);

            return(response);
        }
コード例 #12
0
        public async Task MakeSessionAsync(string acessToken, string refreshToken = null)
        {
            var rsa = new RsaService();
            var aes = new AesCrypt();

            var rsaPair = rsa.GenerateKeys();

            var strongKeyRequest = new
            {
                publicKey = rsaPair.publicKey
            };

            var authRequest = new AuthRequest(acessToken);

            string strongKeyJsonRequest    = JsonConvert.SerializeObject(strongKeyRequest);
            var    strongKeyRequestMessage = authRequest.BuildRequestMessage(ConfigurationManager.AppSettings.Get("devUrl") + Urls.GetStrongKeyUrl, HttpMethod.Post, strongKeyJsonRequest);

            var strongKeyResponseMessage = await authRequest.httpClient.SendAsync(strongKeyRequestMessage);

            if (strongKeyResponseMessage.StatusCode == HttpStatusCode.NotFound)
            {
                var firstSessionRequestModel = new CreateMessangerSessionRequest()
                {
                    PublicKey = rsaPair.publicKey
                };

                string jsonRequest = JsonConvert.SerializeObject(firstSessionRequestModel);

                var firstSessionResponse = await authRequest.GetStringFromHttpResultAsync(ConfigurationManager.AppSettings.Get("devUrl") + Urls.CreateFirstSessionUrl, HttpMethod.Post, jsonRequest);

                var response = JsonConvert.DeserializeObject <CreateFirstMessangerSessionResponse>(firstSessionResponse);

                string decryptedAesKey = rsa.Decrypt(rsaPair.privateKey, response.CryptedAes);

                byte[] decryptedAesKeyBuffer = decryptedAesKey.FromUrlSafeBase64();

                await userProvider.CreateStrongKeyAsync(UserId, decryptedAesKeyBuffer);

                string newToken = await tokenService.MakeAuthTokenAsync(UserId, true);

                authRequest = new AuthRequest(newToken);

                rsaPair = rsa.GenerateKeys();

                string cryptedPublicKey    = aes.Crypt(decryptedAesKeyBuffer.ToUrlSafeBase64(), rsaPair.publicKey);
                var    sessionRequestModel = new CreateMessangerSessionRequest()
                {
                    PublicKey = cryptedPublicKey
                };

                jsonRequest = JsonConvert.SerializeObject(sessionRequestModel);

                var httpRequest     = authRequest.BuildRequestMessage(ConfigurationManager.AppSettings.Get("devUrl") + Urls.CreateSessionUrl, HttpMethod.Post, jsonRequest);
                var sessionResponse = await authRequest.httpClient.SendAsync(httpRequest);

                sessionResponse.EnsureSuccessStatusCode();

                var    session = JsonConvert.DeserializeObject <CreateMessangerSessionResponse>(await sessionResponse.Content.ReadAsStringAsync());
                string decryptedServerPublicKey = aes.Decrypt(decryptedAesKey, session.ServerPublicKey);
                string decryptedSessionId       = aes.Decrypt(decryptedAesKey, session.SessionId);

                await userProvider.CreateSessionAsync(new Session()
                {
                    ClientPrivateKey = rsaPair.privateKey,
                    ServerPublicKey  = decryptedServerPublicKey,
                    ClientPublicKey  = rsaPair.publicKey,
                    UserId           = UserId,
                    SessionId        = decryptedSessionId
                });
            }
            else if (!string.IsNullOrEmpty(refreshToken) && strongKeyResponseMessage.StatusCode == HttpStatusCode.OK)
            {
                var strongKeyResponse = JsonConvert.DeserializeObject <GetStrongKeyResponse>(
                    await strongKeyResponseMessage.Content.ReadAsStringAsync()
                    );

                var decryptedStrongKey = rsa.Decrypt(rsaPair.privateKey, strongKeyResponse.StrongKey);
                await userProvider.CreateStrongKeyAsync(UserId, decryptedStrongKey.FromUrlSafeBase64());

                rsaPair = rsa.GenerateKeys();
                var cryptedPublicKey = aes.Crypt(decryptedStrongKey, rsaPair.publicKey);

                var sessionRequest = new CreateMessangerSessionRequest()
                {
                    PublicKey = cryptedPublicKey
                };

                string jsonSessionRequest = JsonConvert.SerializeObject(sessionRequest);
                var    sessionResponse    = await authRequest.MakeRequestAsync <CreateMessangerSessionResponse>(ConfigurationManager.AppSettings.Get("devUrl") + Urls.CreateSessionUrl, HttpMethod.Post, jsonSessionRequest);

                string decryptedPublicKey = aes.Decrypt(decryptedStrongKey, sessionResponse.ServerPublicKey);
                string decryptedSessionId = aes.Decrypt(decryptedStrongKey, sessionResponse.SessionId);

                await userProvider.CreateSessionAsync(new Session()
                {
                    ClientPrivateKey = rsaPair.privateKey,
                    ClientPublicKey  = rsaPair.publicKey,
                    ServerPublicKey  = decryptedPublicKey,
                    UserId           = UserId,
                    SessionId        = decryptedSessionId
                });
            }
        }
コード例 #13
0
 public SportsController(RsaService rsaService, IUrlHelper urlHelper)
 {
     _rsaService = rsaService;
     _urlHelper  = urlHelper;
 }
コード例 #14
0
        /// <summary>
        /// OnActionExecutionAsync
        /// </summary>
        /// <param name="context">ActionExecutingContext</param>
        /// <param name="next">ActionExecutionDelegate</param>
        private async Task <bool> OnBeforeActionAsync(ResourceExecutingContext context)
        {
            var  request = context.HttpContext.Request;
            var  err     = string.Empty;
            bool isForwardRequestToApiAction = true;

            // Get request's custom headers
            var retryTimes     = int.Parse(this.GetHeaderSingleValue(request.Headers, CustomHttpHeaderFactory.RetryTimes) ?? "0");
            var requestCacheId = this.GetHeaderSingleValue(request.Headers, CustomHttpHeaderFactory.RequestCacheId);

            // Validate the Receiver value from header
            if (this.ValidateRequiredHeaders(requestCacheId, ref err))
            {
                var encryptedPayload = string.Empty;

                #region Reading body from Http request

                this.logger.LogDebug($"{nameof(DecryptRequestFilter)}: start reading encrypted content from Http request...");
                var initialBody = request.Body;
                try
                {
                    request.EnableBuffering();  // Use request.EnableRewind() instead before ASP.NET Core 3
                    using (var reader = new StreamReader(request.Body))
                    {
                        var content = await reader.ReadToEndAsync();

                        // Remove escapted character, eq. "\"xxxxx\"" => "xxxxx"
                        encryptedPayload = JsonConvert.DeserializeObject <string>(content);
                    }
                }
                catch (Exception ex)
                {
                    string loadBodyErr = $"{nameof(DecryptRequestFilter)}: cannot read request body!";
                    this.logger.LogError(ex, loadBodyErr);
                    isForwardRequestToApiAction = false;
                }
                finally
                {
                    // (Optional) Render the original body, since it was flushed by StreamReader,
                    // so that API action will be able to read body as well
                    request.Body = initialBody;
                }

                this.logger.LogDebug($"{nameof(DecryptRequestFilter)}: end reading encrypted content from Http request.");
                #endregion

                #region Decrypt the encrypted content

                this.logger.LogDebug($"{nameof(DecryptRequestFilter)}: start decrypting content from Http request...");
                if (string.IsNullOrEmpty(encryptedPayload))
                {
                    isForwardRequestToApiAction = false;
                }
                else
                {
                    using (var rsa = new RsaService())
                    {
                        try
                        {
                            #region Get public key
                            var privateKey = await this.keyManager.GetPrivateKeyAsync(KeyTypeEnum.RSA);

                            // To test retry policy...
                            ////var privateKey = string.Empty;
                            ////if (retryTimes > 0)
                            ////   privateKey = await this.keyManager.GetPrivateKeyAsync(KeyTypeEnum.RSA);
                            ////else
                            ////   privateKey = (await this.keyManager.CreateDefaultAsymmetricKey(KeyTypeEnum.RSA, isIncludePrivateKey: true)).PrivateKey; // Set a incorrect private key to decrypt
                            #endregion

                            #region Decrypt and refactor to add escape charater for "\"

                            // Get decrypted string
                            var decryptedPayload = await rsa.DecryptAsync(privateKey, encryptedPayload);

                            // Add escape charater for "\"
                            var escaptedDecryptedPayload = decryptedPayload.Replace("\"", "\\\"");
                            escaptedDecryptedPayload = $"\"{escaptedDecryptedPayload}\"";
                            #endregion

                            #region Convert the decrypted payload to byte array and bind to HttpRequest's body

                            byte[] byteContent = Encoding.UTF8.GetBytes(escaptedDecryptedPayload);
                            request.EnableBuffering(); // Use request.EnableRewind() instead before ASP.NET Core 3
                            request.Body.Position = 0;
                            using (var reader = new StreamReader(request.Body))
                            {
                                request.Body = new MemoryStream(byteContent);
                                request.Headers.Remove("content-type");
                                request.Headers.Add("content-type", "application/json");
                            }
                            #endregion
                        }
                        catch (Exception ex) when(ex is FormatException || ex is CryptographicException)
                        {
                            /*
                             * FormatException occurs when the private key is incorrect RSA key
                             * CryptographicException occuers when the data is incorrect encrypted
                             */

                            var publicKey = await this.keyManager.GetPublicKeyAsync(KeyTypeEnum.RSA);

                            this.logger.LogWarning(ex, $"Cannot decrypt with private key!");
                            context.Result = new EmptyResult();
                            context.HttpContext.Response.StatusCode = StatusCodes.Status422UnprocessableEntity;
                            context.HttpContext.Response.Headers.Add(CustomHttpHeaderFactory.RequestCacheId, requestCacheId);
                            context.HttpContext.Response.Headers.Add(CustomHttpHeaderFactory.PublicKey, publicKey);

                            isForwardRequestToApiAction = false;
                        }
                        catch (Exception ex)
                        {
                            this.logger.LogError(ex, ex.Message);
                            context.Result = new EmptyResult();
                            context.HttpContext.Response.StatusCode = StatusCodes.Status500InternalServerError;
                            isForwardRequestToApiAction             = false;
                        }
                    }
                }

                this.logger.LogDebug($"{nameof(DecryptRequestFilter)}: end decrypting content from Http request.");
                #endregion
            }

            if (!string.IsNullOrEmpty(err))
            {
                isForwardRequestToApiAction = false;
                await context.HttpContext.Response.WriteAsync(err);
            }

            return(isForwardRequestToApiAction);
        }
コード例 #15
0
        /// <summary>
        /// Create Retry policy hander instance
        /// </summary>
        /// <returns>PolicyBuilder of HttpResponseMessage</returns>
        public async Task <Polly.Retry.AsyncRetryPolicy <HttpResponseMessage> > CreateAsync(int maxRetryTimes = DefaultMaxRetryTimes)
        {
            var retryPolicy = Policy.HandleResult <HttpResponseMessage>(r => r.StatusCode.Equals(HttpStatusCode.UnprocessableEntity))
                              .RetryAsync(maxRetryTimes, async(exception, retryCount) =>
            {
                this.logger.LogWarning($"The encrypted data was rejected, update public key and will retry {retryCount}/{maxRetryTimes}(times/total)...");

                var request  = exception.Result.RequestMessage;
                var response = exception.Result;

                // Public key
                response.Headers.TryGetValues(CustomHttpHeaderFactory.PublicKey, out IEnumerable <string> publicKeyValues);
                var correctPublicKey = publicKeyValues.FirstOrDefault();

                // RequestICached
                response.Headers.TryGetValues(CustomHttpHeaderFactory.RequestCacheId, out IEnumerable <string> requestCacheIdValues);
                var requestCacheId = requestCacheIdValues.FirstOrDefault();

                if (string.IsNullOrEmpty(correctPublicKey))
                {
                    this.logger.LogWarning($"The response does not have required header: \"{CustomHttpHeaderFactory.PublicKey}\". Stop retrying the request!");
                    throw new OperationCanceledException();
                }
                else if (string.IsNullOrEmpty(requestCacheId))
                {
                    this.logger.LogWarning($"The response does not have required header: \"{CustomHttpHeaderFactory.RequestCacheId}\" on response. Stop retrying the request!");
                    throw new OperationCanceledException();
                }
                else
                {
                    #region Get the original request
                    var cacheKey = requestCacheId;
                    this.memoryCache.TryGetValue(cacheKey, out string jsonPayload);
                    if (string.IsNullOrEmpty(jsonPayload))
                    {
                        this.logger.LogWarning($"Lost the original request in MemoryCache (Key: {cacheKey}). Stop retrying the request!");
                        throw new OperationCanceledException();
                    }

                    #endregion

                    #region Encrypt the original request by the new public key

                    using (var rsa = new RsaService())
                    {
                        string encryptedPayload = await rsa.EncryptAsync(correctPublicKey, jsonPayload);

                        // Replace the original content with the encrypted one
                        var newContent  = new System.Net.Http.StringContent($"\"{encryptedPayload}\"", Encoding.UTF8, "application/json");
                        request.Content = newContent;

                        this.logger.LogDebug($"Successfully encrypting request.");
                    }
                    #endregion

                    #region Retry times incremental
                    request.Headers.Remove(CustomHttpHeaderFactory.RetryTimes);
                    request.Headers.Add(CustomHttpHeaderFactory.RetryTimes, retryCount.ToString());
                    #endregion

                    #region Update the correct public key with KeyManager

                    var key       = (await this.keyManager.GetKeyAsync(KeyTypeEnum.RSA));
                    key.PublicKey = correctPublicKey;

                    await this.keyManager.SaveKeyAsync(key);
                    this.logger.LogWarning($"Updated the correct public key. Now start retrying sending request.");
                    #endregion
                }
            });

            return(await Task.FromResult(retryPolicy));
        }