前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >请收藏!这可能是目前最安全的数据加密传输解决方案

请收藏!这可能是目前最安全的数据加密传输解决方案

作者头像
zls365
发布2021-09-02 15:43:15
2.1K0
发布2021-09-02 15:43:15
举报
文章被收录于专栏:CSharp编程大全CSharp编程大全

问题

为了安全性起见,客户要求客户端必须将数据加密后才能传给服务端。

起先,准备使用非对称加密(RSA)方式,但是发现它对原始文本长度有限制。

而对称加密(AES)没有长度限制,但是使用固定密钥存在暴露的风险。

有没有两全其美的办法呢?

思路

密钥肯定每个用户不同,而要验证用户则必须登录。

因此,唯一可以安全获取密钥的时机,只能是在登录时。

而为了保证用户名密码传输安全,可以使用RSA公钥加密后传输,所有客户端使用同一公钥也没问题。

登录成功后,服务端将生成token和AES密钥返回给客户端。但是,返回的AES密钥是经过加密的,而加密密钥则是“用户名+密码”。

这样保证了,只有刚才成功登录的客户端才能解密出AES密钥。

以后的传输,全部使用AES加密,服务端可以根据token从缓存获取AES密钥解密。

整体流程如下图:

服务端实现

下面是示例服务端的实现代码:

代码语言:javascript
复制
[HttpPost("Login")]
public LoginOutput Login(LoginInput input)
{
    var userName = RsaHelper.Decrypt(input.UserName, privateKey);
    var password = RsaHelper.Decrypt(input.Password, privateKey);
    (byte[] tmpKey, byte[] tmpIV) = AesHelper.CreateKeyIV(userName + password, password + userName);

    var token = Guid.NewGuid().ToString("N"); 
    (byte[] key, byte[] iv) = AesHelper.CreateKeyIV();
    _cache.Add(token, (key, iv));
    return new LoginOutput
    {
        Token = token,
        Key = AesHelper.Encrypt(Convert.ToBase64String(key), tmpKey, tmpIV),
        IV = AesHelper.Encrypt(Convert.ToBase64String(iv), tmpKey, tmpIV)
    };
}

[HttpPost("TestMethod")]
public string TestMethod([FromQuery]string token, [FromBody]string cipherText)
{
    (byte[] key, byte[] iv) = _cache[token];
    return AesHelper.Decrypt(cipherText, key, iv);
}

Login用于验证用户密码并返回token和AES密钥.

TestMethod用于演示接收客户端数据如何解密,为了演示方便,直接在URL传递token。

客户端实现

使用xunit测试项目演示客户端操作,代码如下:

代码语言:javascript
复制
[Fact]
public async void Test1()
{
    //登录获得AES密钥
    var response = await _httpClient.PostAsync( "/Demo/Login",
        JsonContent.Create(new WebApplication1.LoginInput{ 
            UserName = RsaHelper.Encrypt(userName, publicKey),
            Password = RsaHelper.Encrypt(password, publicKey)
        }));
    var loginResult = await response.Content.ReadFromJsonAsync<WebApplication1.LoginOutput>();

    (byte[] tmpKey, byte[] tmpIV) = AesHelper.CreateKeyIV(userName + password, password + userName);

    byte[] key =Convert.FromBase64String(AesHelper.Decrypt(loginResult.Key, tmpKey, tmpIV));
    byte[] iv = Convert.FromBase64String(AesHelper.Decrypt(loginResult.IV, tmpKey, tmpIV));

    //使用AES密钥加密
    var cipherText = AesHelper.Encrypt(PlainText, key, iv);
    _output.WriteLine(cipherText);
    response = await _httpClient.PostAsync("/Demo/TestMethod?token=" + loginResult.Token,
        JsonContent.Create(cipherText));

    var decryptResult = await response.Content.ReadAsStringAsync();

    _output.WriteLine(decryptResult);
    Assert.Equal(PlainText, decryptResult);
}

将大量数据(千字文)加密后传给服务。

可以看到,返回了正确的原始数据:

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-08-23,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 CSharp编程大全 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 问题
  • 思路
  • 服务端实现
  • 客户端实现
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档