转-签名+验签详细理解

 

纸质时代,当写信,或者使用支票的时候,签上自己的名字,就表示这是自己写的,当别人拿到信的时候,如果认识笔迹,或者银行拿到支票后,进行一系列验证,验证这个支票的真伪,前面的操作就是签名,说明是自己写的,后面的检验,就是验签,确认书写者身份。

信息时代,也有这方面的需要。

要确保信息是某人发送的,不让别个知道里面的内容,而且中间没有被修改,同时信息要完整。(信息安全三要素,有效性(Availability):信息的使用者是合法的,保密性(Confidentiality):信息在传输时不被泄露,有效性(Availability):信息的使用者是合法的)

这个时候,首先想到的就是加密了。

加密有对称加密,和非对称加密 这两种算法

对称加密,使用一个密码来进行加密和解密,比如我约定规则,用明文(3)乘以4,在加1,这样得到(3*4+1)密文13,另外一个人得到13后,用我们相同的约定,在反向推(13-1)/4=3,就得到我的明文,电视里面密码本就是这样的。大家都知道怎么解密的约定

非对称加密,明文,用A加密,用B解密,加密和解密分别使用不同的规则。

目前大部分都是采用非对称加密算法

其中,公匙密码就是非对称加密的算法的一个具体事列,公匙密码又称为非对称密码。拥有公匙密码的人分别拥有加密密匙和解密密匙,通过加密密匙不能得到解密密匙,同时加密密匙是公开的。

李四拥有公匙密码,他想获得张三的银行卡密码66666,就把公匙给了张三,张三用公密加密后,通过网络传给李四,其他人获取到了这个密文后,没有私密解不开,只有李四知道私密,可以解开,这样,就保证了信息的安全性,好像不能保证信息发送人就是张三,这个特性,其他人要是获得了这个公匙,也能给李四发信息。

这个时候,我们进行逆运算,我用私匙加密,用公匙解密,因为只有私匙加密的东西,我才能用对应的公匙进行解开。同时我解密的时候,我就能确认发送人了。(为什么了?)

数字签名(名词):某种密码运算生成一系列符号及代码组成电子密码进行签名,这个来表示是自己签名

数字签名(动词):用私匙来加密,用公匙来解密,就是公共密码的逆运算。

一般开发阶段,我们都是使用到的是其他第三方给我们的东西进行加密和解密,一般会给我们这2个文件

其中后缀为 .cer的通常存放公钥,后缀为.pfx的通常存放私钥(包含公匙和私匙,对方还会给你一个密码,用来解开这个私匙的密码)

NET中提供类 X509Certificate2,命名空间 System.Security.Cryptography中,这个类实列化后就表示一个类

X509Certificate2 c3 = DataCertificate.GetCertificateFromPfxFile("d:\\mycert\\NT999.pfx", "000000");

string keyPublic3 = c3.PublicKey.Key.ToXmlString(false);  // 公钥
 string keyPrivate3 = c3.PrivateKey.ToXmlString(true);  // 私钥     

string check_value = HashAndSignString(uJson, keyPrivate3); // 加密,原文,私匙
 bool bt = VerifySigned(uJson, check_value, keyPublic3);//验签

       /// <summary>
        /// 数字签名
        /// </summary>
        /// <param name="plaintext">原文</param>
        /// <param name="privateKey">私钥</param>
        /// <returns>签名</returns>
        public static string HashAndSignString(string plaintext, string privateKey)
        {
            UnicodeEncoding ByteConverter = new UnicodeEncoding();
            byte[] dataToEncrypt = ByteConverter.GetBytes(plaintext);

            using (RSACryptoServiceProvider RSAalg = new RSACryptoServiceProvider())
            {
                RSAalg.FromXmlString(privateKey);
                //使用SHA1进行摘要算法,生成签名
                byte[] encryptedData = RSAalg.SignData(dataToEncrypt, new SHA1CryptoServiceProvider());
                return Convert.ToBase64String(encryptedData);
            }
        }

 /// <summary>
        /// 验证签名
        /// </summary>
        /// <param name="plaintext">原文</param>
        /// <param name="SignedData">签名</param>
        /// <param name="publicKey">公钥</param>
        /// <returns></returns>
        public static bool VerifySigned(string plaintext, string SignedData, string publicKey)
        {
            using (RSACryptoServiceProvider RSAalg = new RSACryptoServiceProvider())
            {
                RSAalg.FromXmlString(publicKey);
                UnicodeEncoding ByteConverter = new UnicodeEncoding();
                byte[] dataToVerifyBytes = ByteConverter.GetBytes(plaintext);
                byte[] signedDataBytes = Convert.FromBase64String(SignedData);
                return RSAalg.VerifyData(dataToVerifyBytes, new SHA1CryptoServiceProvider(), signedDataBytes);
            }
        }

这就是一套流程。

生成签名
一般来说,不直接对消息进行签名,而是对消息的哈希值进行签名,步骤如下。
 1,   对消息进行哈希计算,得到哈希值
  2,  利用私钥对哈希值进行加密,生成签名
  3,  将签名附加在消息后面,一起发送过去
验证签名
 1,  收到消息后,提取消息中的签名
 2, 用公钥对签名进行解密,得到哈希值1。
 3,  对消息中的正文进行哈希计算,得到哈希值2。
 4,   比较哈希值1和哈希值2,如果相同,则验证成功。

证书

证书实际上就是对公钥进行数字签名,它是对公钥合法性提供证明的技术。
考虑这样一种场景:我们对签名进行验证时,需要用到公钥。如果公钥也是伪造的,那怎么办?如果公钥是假的,验证数字签名那就无从谈起,根本不可能从数字签名确定对方的合法性。
这时候证书就派上用场了。
证书一般包含:公钥(记住证书中是带有公钥的),公钥的数字签名,公钥拥有者的信息
若证书验证成功,这表示该公钥是合法,可信的。
接下来又有问题了:验证证书中的数字签名需要另一个公钥,那么这个公钥的合法性又该如何保证?该问题可以无限循环下去,岂不是到不了头了?这已经是个社会学问题了。我们为什么把钱存进银行?因为我们相信银行,它是一个可信的机构(虽然也有破产的风险)。跟银行一样,我们需要一个可信的机构来颁发证书和提供公钥,只要是它提供的公钥,我们就相信是合法的。

这种机构称为认证机构(Certification Authority, CA)。CA就是能够认定”公钥确实属于此人”,并能生成公钥的数字签名的组织或机构。CA有国际性组织和政府设立的组织,也有通过提供认证服务来盈利的组织。

如何生成证书?
    服务器将公钥A给CA(公钥是服务器的)
    CA用自己的私钥B给公钥A加密,生成数字签名A
    CA把公钥A,数字签名A,附加一些服务器信息整合在一起,生成证书,发回给服务器。


注:私钥B是用于加密公钥A的,私钥B和公钥A并不是配对的。

如何验证证书?
客户端得到证书
    客户端得到证书的公钥B(通过CA或其它途径)
    客户端用公钥B对证书中的数字签名解密,得到哈希值
    客户端对公钥进行哈希值计算
    两个哈希值对比,如果相同,则证书合法。


注:公钥B和上述的私钥B是配对的,分别用于对证书的验证(解密)和生成(加密)。
证书作废


当用户私钥丢失、被盗时,认证机构需要对证书进行作废(revoke)。要作废证书,认证机构需要制作一张证书作废清单(Certificate Revocation List),简称CRL


假设我们有Bob的证书,该证书有合法的认证机构签名,而且在有效期内,但仅凭这些还不能说明该证书一定有效,还需要查询认证机构最新的CRL,并确认该证书是否有效。
使用场景


下面用两个使用场景来帮助大家理解证书的作用。


客户端在发送或接收消息之前,要验证服务器的合法性(这个服务器是真实的服务器,还是伪造者,我们不知道)


场景1


    服务器生成公钥和私钥密码对
    服务器把公钥给CA。CA生成证书,发送给客户端
    客户端验证证书,取得公钥:此刻证明公钥是合法的
    客户端用公钥加密消息,发送给服务器
    服务器用私钥解密消息(消息加密发送,具有保密性)


场景2


    服务器生成公钥和私钥密码对
    服务器生成消息,用私钥对消息进行数字签名
    服务器把公钥给CA。CA生成证书
    服务器将消息,数字签名,证书一起发送给客户端
    客户端验证证书,取得公钥:此刻证明公钥是合法的

    客户端用公钥验证数字签名,检查消息的完整性和服务器的合法性

后续再慢慢写

转载:https://www.jianshu.com/p/9db57e761255

转载:https://segmentfault.com/a/1190000004461428

新手浅谈证书加解密、签名验签

参考:http://blog.csdn.net/weixin_33602978/article/details/71599672

  ASP.net 使用证书认证

参考:http://blog.csdn.net/wsxqaz/article/details/5389883

参考:https://www.cnblogs.com/atongmyuxiaowanzi/p/5329558.html

 原文https://blog.csdn.net/zhenglianghui163/article/details/79068986

猜你喜欢

转载自www.cnblogs.com/ccnewsky/p/9711522.html
今日推荐