如何使用 .NET Core 安全地加/解密文件

前言

由于客户网络安全限制,连接到互联网的设备不能访问内网。

需要先从客户端应用中导出数据到文件,再将文件复制到U盘,最后通过内网机器上传数据。

如何保证,在复制、传输过程中,文件的安全性?

思路

首先想到的是对文件进行加密。但是文件本身可能非常大,因此只能采取对称加密(AES)。

如果将对称加密的密钥存储在客户端的应用里,可能导致密钥泄露。

最好是每次加密都使用不同的AES密钥。

现在的关键是,如何将这个随机AES密钥传输给解密方?

根据我们在《请收藏!这可能是目前最安全的数据加密传输解决方案》中的思路,我们可以采用RSA公钥加密AES密钥,并将其作为文件的一部分发给解密方。

加密文件将由以下几个部分组成:

  • 256字节RSA加密后的AES密钥

  • 16字节初始化向量

  • AES加密的文件数据

解密方首先读取并使用RSA私钥解密出AES密钥,再用AES密钥解密出实际的文件数据。

实现

理清了思路,让我们来看一下实现。

首先是加密代码:

(byte[] aesKey, byte[] aesIV) = AesHelper.Create();

using (var origFileStream = File.OpenRead("原始文件"))
{
    using (var encryptFileStream = File.Create("加密文件"))
    { 
        await encryptFileStream.WriteAsync(RSAHelper.Encrypt(aesKey));
        await encryptFileStream.WriteAsync(aesIV);

        using (var cryptoStream = AesHelper.CreateWriteStream(encryptFileStream, aesKey, aesIV))
        {
            await origFileStream.CopyToAsync(cryptoStream);
        }
    }
}

然后是解密代码:

using (var decryptFileStream = File.OpenRead("解密文件"))
{
    using (var encryptFileStream = File.OpenRead("加密文件"))
    {
        var aesKeyData = new byte[256];
        await encryptFileStream.ReadAsync(aesKeyData, 0, aesKeyData.Length);
        var aesKey = RSAHelper.Decrypt(aesKeyData);

        var aesIVData = new byte[16];
        await encryptFileStream.ReadAsync(aesIVData, 0, aesIVData.Length);
        var aesIV = aesIVData;

        using (var cryptoStream = AesHelper.CreateReadStream(encryptFileStream, aesKey, aesIV))
        {
            await cryptoStream.CopyToAsync(decryptFileStream);
        }
    }
}

结论

通过使用RSA+AES,同时保证了密钥和数据的安全性。

如果你也碰到了类似需求,不妨试试本文的实现方案。

技术群:添加小编微信并备注进群

小编微信:mm1552923   

公众号:dotNet编程大全      

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
.NET Core 中,可以使用 RabbitMQ、Azure Service Bus、Kafka 等消息队列作为 EventBus/EventQueue 的实现。以下是一个使用 RabbitMQ 的示例: 1. 安装 RabbitMQ 可以通过官网下载 RabbitMQ 安装包进行安装。 2. 安装 RabbitMQ.Client 在 .NET Core 项目中,可以通过 NuGet 安装 RabbitMQ.Client 包。 3. 配置 RabbitMQ 连接信息 在 appsettings.json 文件中,添加 RabbitMQ 连接信息: ``` { "RabbitMQ": { "HostName": "localhost", "UserName": "guest", "Password": "guest", "Port": 5672 } } ``` 4. 创建 EventBus/EventQueue 可以通过继承 IEventBus 接口来实现 EventBus,或者通过使用 RabbitMQ 的 API 创建 EventQueue。 以下是一个使用 RabbitMQ 的示例: ``` public class RabbitMQEventBus : IEventBus { private readonly IRabbitMQPersistentConnection _persistentConnection; private readonly ILogger<RabbitMQEventBus> _logger; private readonly IEventBusSubscriptionsManager _subsManager; private readonly string _exchangeName = "event_bus_exchange"; public RabbitMQEventBus(IRabbitMQPersistentConnection persistentConnection, ILogger<RabbitMQEventBus> logger, IEventBusSubscriptionsManager subsManager) { _persistentConnection = persistentConnection ?? throw new ArgumentNullException(nameof(persistentConnection)); _logger = logger ?? throw new ArgumentNullException(nameof(logger)); _subsManager = subsManager ?? new InMemoryEventBusSubscriptionsManager(); } public void Publish(IntegrationEvent @event) { if (!_persistentConnection.IsConnected) { _persistentConnection.TryConnect(); } using (var channel = _persistentConnection.CreateModel()) { var eventName = @event.GetType().Name; var message = JsonConvert.SerializeObject(@event); var body = Encoding.UTF8.GetBytes(message); channel.ExchangeDeclare(exchange: _exchangeName, type: "direct"); var properties = channel.CreateBasicProperties(); properties.Persistent = true; channel.BasicPublish(exchange: _exchangeName, routingKey: eventName, basicProperties: properties, body: body); } } public void Subscribe<T, TH>() where T : IntegrationEvent where TH : IIntegrationEventHandler<T> { var eventName = typeof(T).Name; _logger.LogInformation($"Subscribing to event {eventName}"); _subsManager.AddSubscription<T, TH>(); } public void Unsubscribe<T, TH>() where T : IntegrationEvent where TH : IIntegrationEventHandler<T> { var eventName = typeof(T).Name; _logger.LogInformation($"Unsubscribing from event {eventName}"); _subsManager.RemoveSubscription<T, TH>(); } } ``` 5. 注册 EventBus/EventQueue 可以通过依赖注入的方式注册 EventBus/EventQueue。以下是一个使用 RabbitMQ 的示例: ``` services.AddSingleton<IRabbitMQPersistentConnection>(sp => { var logger = sp.GetRequiredService<ILogger<DefaultRabbitMQPersistentConnection>>(); var factory = new ConnectionFactory() { HostName = Configuration["RabbitMQ:HostName"], UserName = Configuration["RabbitMQ:UserName"], Password = Configuration["RabbitMQ:Password"], Port = int.Parse(Configuration["RabbitMQ:Port"]) }; return new DefaultRabbitMQPersistentConnection(factory, logger); }); services.AddSingleton<IEventBusSubscriptionsManager, InMemoryEventBusSubscriptionsManager>(); services.AddSingleton<IEventBus, RabbitMQEventBus>(); ``` 6. 发布/订阅事件 可以通过 IEventBus 接口的 Publish 和 Subscribe 方法来发布/订阅事件。以下是一个使用 RabbitMQ 的示例: ``` _eventBus.Subscribe<TestIntegrationEvent, TestIntegrationEventHandler>(); _eventBus.Publish(new TestIntegrationEvent() { Message = "Hello, world!" }); ``` 其中 TestIntegrationEvent 是一个继承自 IntegrationEvent 的事件类,TestIntegrationEventHandler 是一个实现了 IIntegrationEventHandler<TestIntegrationEvent> 接口的事件处理程序类。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值