温故知新,.Net Core遇见Digital Signature(MD5/RSA/SM),微服务签名机制设计

什么是数字签名(Digital Signature)

数字签名(Digital Signature)是只有信息的发送者才能产生的别人无法伪造的一段数字串,这段数字串同时也是对信息的发送者发送信息真实性的一个有效证明。

image

在一封信中,文末的签名是为了表示这封信是签名者写的。计算机中,数字签名也是相同的含义:证明消息是某个特定的人,而不是随随便便一个人发送的(有效性);除此之外,数字签名还能证明消息没有被篡改(完整性)。

什么是MD5

消息摘要算法版本5(Message Digest Algorithm 5)它是一种Hash算法。作用是为了信息安全。再具体点,MD5值就是一串128bit的数据。MD5的核心是通过算法把任意长度的原始数据映射成128bit的数据。这一点跟CRC类似,都是把一串数据经过处理,得到另一个固定长度的数据。

什么是RSA

RSA公钥加密算法是美国计算机学家RonRivest、AdiShamir和LeonardAdleman于1977年提出,是最早的公钥加密算法之一,在全球范围被广泛使用。随着密码技术和计算机技术的发展,目前1024位RSA算法已经被证实存在被破解的风险,美国NIST(国家标准技术研究院)在2010年要求全面禁用1024位RSA算法,升级到2048位RSA算法。此外,斯诺登事件爆发后,其泄露出的机密文档显示,RSA算法中可能存在NSA的预置后门,对RSA算法的安全性产生巨大影响。

RSA是Rivest-Shamir-Adleman算法的缩写。它是目前最常用的公钥加密算法。RSA公钥密码系统的原理是:根据数论,找到两个大素数比较简单,但是分解其乘积因式非常困难,因此该乘积可以公开用作加密密钥。

RSA算法安全性:RSA的安全性依赖于大数分解,但是否等同于大数分解一直未能得到理论上的证明,也并没有从理论上证明破译。RSA的难度与大数分解难度等价。因为没有证明破解RSA就一定需要做大数分解。RSA算法的安全强度随着其密钥长度的增加而增加。但是,密钥越长,加密和解密所花费的时间就越长。因此,有必要综合考虑受保护信息的敏感性,攻击者破解的成本以及系统所需的响应时间,尤其是在商业信息领域。

RSA运算速度:由于所有计算都是大数,因此无论是通过软件还是硬件来实现,RSA最快的情况都比DES慢几倍。速度一直是RSA的缺陷。通常只用于少量数据加密。RSA的速度比相同安全级别的相应对称加密算法慢大约1000倍。

什么是SM

SM2算法由国家密码管理局于2010年12月17日发布,是我国自主设计的公钥密码算法,基于更加安全先进的椭圆曲线密码机制,在国际标准的ECC椭圆曲线密码理论基础上进行自主研发设计,具备ECC算法的性能特点并实现优化改进。

生成随机MD5密钥

/// <summary>
/// 生成随机MD5密钥
/// </summary>
private string CreateAppSecret()
{
    #region CreateAppSecret

    var str = Guid.NewGuid().ToString();
    MD5 md5 = MD5.Create();//实例化一个md5对像
    // 加密后是一个字节类型的数组,这里要注意编码UTF8/Unicode等的选择 
    byte[] s = md5.ComputeHash(Encoding.UTF8.GetBytes(str));
    StringBuilder stringBuilder = new StringBuilder();
    // 通过使用循环,将字节类型的数组转换为字符串,此字符串是常规字符格式化所得
    for (int i = 0; i < s.Length; i++)
    {
        stringBuilder.Append(s[i].ToString("x2"));
    }
    return stringBuilder.ToString();

    #endregion
}

生成.Net/Java版RSA密钥

/// <summary>
/// 生成.Net/Java版RSA密钥
/// </summary>
private (string, string) CreateRSASecret(string seedKey, bool isFormat = true, bool isJava = false)
{
    #region CreateRSASecret

    var generator = new RsaKeyPairGenerator();
    var seed = Encoding.UTF8.GetBytes(seedKey);
    var secureRandom = new SecureRandom();
    secureRandom.SetSeed(seed);

    generator.Init(new KeyGenerationParameters(secureRandom, 2048));
    var pair = generator.GenerateKeyPair();

    string privateKey;
    if (isJava)
    {
        var privateKeyInfo = PrivateKeyInfoFactory.CreatePrivateKeyInfo(pair.Private);
        byte[] serializedPrivateBytes = privateKeyInfo.ToAsn1Object().GetEncoded();
        privateKey = Convert.ToBase64String(serializedPrivateBytes);
        Console.WriteLine("Private Key:" + privateKey);
    }
    else
    {
        var twPrivate = new StringWriter();
        PemWriter pwPrivate = new PemWriter(twPrivate);
        pwPrivate.WriteObject(pair.Private);
        pwPrivate.Writer.Flush();
        privateKey = twPrivate.ToString();
        Console.WriteLine("Private Key:" + privateKey);
    }

    var twPublic = new StringWriter();
    PemWriter pwPublic = new PemWriter(twPublic);
    pwPublic.WriteObject(pair.Public);
    pwPublic.Writer.Flush();
    var publicKey = twPublic.ToString();
    Console.WriteLine("Public Key:" + publicKey);

    if (isFormat)
    {
        privateKey = privateKey?.Replace("-----BEGIN RSA PRIVATE KEY-----", "")?.Replace("-----END RSA PRIVATE KEY-----", "")?.Replace("\r\n", "");
        publicKey = publicKey?.Replace("-----BEGIN PUBLIC KEY-----", "")?.Replace("-----END PUBLIC KEY-----", "")?.Replace("\r\n", "");
    }

    return (publicKey, privateKey);

    #endregion
}

参考

posted @ 2021-05-20 23:24  TaylorShi  阅读(352)  评论(0编辑  收藏  举报