区块链加密算法小探(一)

作者: WallisW | 来源:发表于2018-04-09 23:41 被阅读95次

    前言

    区块链的底层实现离不开各种加密算法,因此对密码学技术的了解将会更有助于对区块链的学习和理解。本系列从密码学原理和具体代码应用两方面来归纳整理下区块链用到的各种密码学算法。这里用到的语言为Python。

    工程领域从来没有黑科技;密码学不是工程。 密码学在信息技术领域的重要地位无需多言。如果没有现代密码学的研究成果,人类社会根本无法进入信息时代。密码学领域十分繁杂,本章将介绍密码学领域中跟区块链相关的一些基础知识,包括 hash 算 法与摘要、加密算法、数字签名和证书、PKI 体系、Merkle 树、同态加密等,以及如何使用 这些技术实现信息的机密性、完整性、认证性和不可抵赖性。

    (1)哈希算法

    定义

    哈希算法将任意长度的二进制值映射为较短的固定长度的二进制值,这个小的二进制值称为哈希值。哈希值是一段数据唯一且极其紧凑的数值表示形式。如果散列一段明文而且哪怕只更改该段落的一个字母,随后的哈希都将产生不同的值。要找到散列为同一个值的两个不同的输入,在计算上是不可能的,所以数据的哈希值可以检验数据的完整性。一般用于快速查找和加密算法。

    一个优秀的hash 算法,将能实现:

    • 正向快速:给定明文和hash 算法,在有限时间和有限资源内能计算出hash 值。
    • 逆向困难:给定(若干)hash 值,在有限时间内很难(基本不可能)逆推出明文。
    • 输入敏感:原始输入信息修改一点信息,产生的hash 值看起来应该都有很大不同。
    • 冲突避免:很难找到两段内容不同的明文,使得它们的hash 值一致(发生冲突)。

    目前流行的哈希算法有MD5、SHA-1 和 SHA-2。

    代码实战

    """
        @author: chaors
    
        @file: Hash.py
    
        @time: 2018/04/09 21:15
    
        @desc: HASH算法
    """
    
    import hashlib
    
    #SHA256
    myhash = hashlib.sha256()  #sha512将是更安全的哈希算法
    myhash.update("1000001".encode("utf-8"))
    
    print(myhash.hexdigest())  #哈希密码的二进制串
    
      #443372db1ff98d9737596b4f83a8381ab6aab60e44e29854b48be88c74cdf1f0
      #2的256次方,这个数字超级大,达到你几乎无可能无法通过哈希算法对不同数据得出同一个序列
      #数据被修改,hash值一定被改变
    
    print(dir(hashlib))  #哈希算法有这么多
    /**
    ['__all__', '__builtin_constructor_cache', '__builtins__', '__cached__', '__doc__', '__file__', '__get_builtin_constructor', '__loader__', '__name__', '__package__', '__spec__', '_hashlib', 'algorithms_available', 'algorithms_guaranteed', 'blake2b', 'blake2s', 'md5', 'new', 'pbkdf2_hmac', 'sha1', 'sha224', 'sha256', 'sha384', 'sha3_224', 'sha3_256', 'sha3_384', 'sha3_512', 'sha512', 'shake_128', 'shake_256']
    */
    

    (2)对称加密

    定义

    根据加解密的密钥是否相同,算法可以分为对称加密(symmetric cryptography,又称公共密 钥加密,common-key cryptography)和非对称加密(asymmetric cryptography,又称公钥加 密,public-key cryptography)。两种模式适用于不同的需求,恰好形成互补,很多时候也可以 组合使用,形成混合加密机制。

    顾名思义,加解密的密钥是相同的。 优点是加解密效率高(速度快,空间占用小),加密强度高。 缺点是参与多方都需要持有密钥,一旦有人泄露则安全性被破坏;另外如何在不安全通道下分发密钥也是个问题

    代表算法包括DES、3DES、AES、IDEA等。

    • DES(Data Encryption Standard):经典的分组加密算法,1977 年由美国联邦信息处理标准(FIPS)所采用FIPS-46-3,将64 位明文加密为64 位的密文,其密钥长度为56位+8位校验。现在已经很容易被暴力破解。

    • AES(Advanced Encryption Standard):美国国家标准研究所(NIST)采用它取代DES成为对称加密实现的标准。AES也是分组算法,分组长度为128、192、256 位三种。AES的优势在于处理速度快,整个过程可以数学化描述,目前尚未有有效的破解手段。

    • ...

    废话少说撸代码

    """
        @author: chaors
    
        @file: AES_DES.py
    
        @time: 2018/04/09 21:29
    
        @desc: 对称加密算法:DES, AES
    """
    
    import pyDes  #DES加密模块
    from Crypto.Cipher import AES  #AES加密模块
    from binascii import b2a_hex, a2b_hex  #二进制转十六进制
    
    pwd = b"\0\0\0\4\0\0\0\0"  #加密密码要求8个字节
    data = "heollo, bitcoin..."
    key = pyDes.des(b"DESCRYPT",  #加密算法
                    pyDes.CBC,  #加密模式
                    pwd,  #加密密码
                    pad=None,
                    padmode=pyDes.PAD_PKCS5)  #加密参数
    newdata = key.encrypt(data)
    
    print("DES encrypt data:", newdata)
    print("DES decrypt data:", key.decrypt(newdata))
    
    class AES_chaors:
        def __init__(self, key):
            self.key = key  #加密密码
            self.model = AES.MODE_ECB  #加密函数,加密文本必须是16的倍数,不足补零
    
        def encrypt(self, text):  #加密
            cryptor = AES.new(self.key, self.model, self.key)  #新建加密算法
            text = text.encode("utf-8")
            length = 16  #密码长度
            count = len(text)  #求长度
            add = length - (count%length)
            text = text + (b"\0"*add)  #填充0
            self.ciphertext = cryptor.encrypt(text)  #加密
    
            return b2a_hex(self.ciphertext).decode("ASCII")  #ASCII转16进制
    
        def decrypt(self, text):  #解密
            cryptor = AES.new(self.key, self.model, self.key)  # 新建解密算法
            lasttext = cryptor.decrypt(a2b_hex(text))  #文本转16进制
    
            return lasttext.rstrip(b'\0').decode("utf-8")
    
    if __name__ == '__main__':
        aes = AES_chaors("chaors love codi".encode("utf-8"))
        print("AES encrypt:", aes.encrypt("hello, bitcoin!!!"))
        print("AES decrypt:", aes.decrypt(aes.encrypt("hello, bitcoin!!!")))
    

    python3使用AES的大坑

    python使用AES加密模块依赖于Crypto库,网上你能找到的大部分导入方式都是:

    from Crypto.Cipher import AES  #AES加密模块
    

    但是这个时候,pycharm通常会报错:

    Crypto库导入错误

    我们知道这个错的意思是,缺少库文件支持。我们习惯性地将光标移动到Crypto处按下“alt+Enter”快捷键安装模块,发现并没有什么卵用。于是,打开pycharm的工具包看有没有,发现只有一个小写的crypto库,看着差不多以为就是他,接着安装。

    安装长得像Crypto的crypto

    运行文件发现仍然报错,我也是python小白,试着将文件里的Crypto改为crypto,发现根本于事无补!!!

    #from Crypto.Cipher import AES  #AES加密模块
    from crypto.Cipher import AES  #!!!于事无补
    

    依然是这个邪门的错误:

       from Crypto.Cipher import AES  #AES加密模块
    ModuleNotFoundError: No module named 'Crypto'
    

    郁闷了一小会,问度娘。搜到的好几个解决方案是让我找到安装的crypto路径,将crypto改为Crypto即可。可是宝宝根本找不到啊,python下安装的所有例如hashlib的路径都没找到(Mac本,谁知道在哪留言告诉小小白我...)

    踏破铁鞋柳暗花明,最终还是找到了解决方案:
    将crypto卸载,在pycharm工具包中安装pycrypto库(一定要先把之前的crypto卸载再安装),或者命令行执行安装:

    pip uninstall crypto
    pip install pycrypto
    

    如此,就解决了Crypto.Cipher在引入时候的报错问题。

    (3)非对称加密(主要RSA)

    定义

    顾名思义,加密密钥和解密密钥是不同的,分别称为公钥和私钥。 公钥一般是公开的,人人可获取的,私钥一般是个人自己持有,不能被他人获取。 优点是公私钥分开,不安全通道也可使用。

    缺点是加解密速度慢,一般比对称加解密算法慢两到三个数量级;同时加密强度相比对称加 密要差。

    代表算法包括:RSA、ElGamal、椭圆曲线(Elliptic Curve Crytosystems,ECC)系列算 法。

    • RSA:经典的公钥算法,1978 年由Ron Rivest、Adi Shamir、Leonard Adleman 共同提出,三人于2002 年获得图灵奖。算法利用了对大数进行质因数分解困难的特性,但目前还没有数学证明两者难度等价,或许存在未知算法在不进行大数分解的前提下解密。
    • ElGamal:由TaherElGamal 设计,利用了模运算下求离散对数困难的特性。
    • 椭圆曲线算法:现代备受关注的算法系列,基于对椭圆曲线上特定点进行特殊乘法逆运 算难以计算的特性。

    RSA算法等已被认为不够安全,一般推荐采用椭圆曲线系列算法。比特币的秘钥对就是使用椭圆曲线密码学(Elliptic Curve Cryptography)生成的。

    RSA的另一个引用

    类似在纸质合同上签名确认合同内容,数字签名用于证实某数字内容的完整性(integrity)和 来源(或不可抵赖,non-repudiation)。
    一个典型的场景是,A 要发给 B 一个文件(一份信息),B 如何获知所得到的文件即为 A 发 出的原始版本?A 先对文件进行摘要,然后用自己的私钥进行加密,将文件和加密串都发给 B。B 收到后文件和加密串,用 A 的公钥来解密加密串,得到原始的数字摘要,跟对文件进行 摘要后的结果进行比对。如果一致,说明该文件确实是 A 发过来的,并且文件内容没有被修改过。

    代码理解

    """
        @author: chaors
    
        @file: RSA.py
    
        @time: 2018/04/09 22:09
    
        @desc: 非堆成加密算法:RSA
    """
    
    import rsa  #RSA加密模块
    
    #生成公钥,私钥秘钥对
    pubkey, privatekey = rsa.newkeys(1024)
    print(pubkey, privatekey)
    
    #秘钥和pem秘钥文件的相互转化
    with open("rsa_pub.pem", "w+") as publicfile:  #公钥写入文件
        publicfile.write(pubkey.save_pkcs1().decode())
    
    with open("rsa_private.pem", "w+") as privatefile:  #私钥写入文件
        privatefile.write(privatekey.save_pkcs1().decode())
    
    with open("rsa_pub.pem", "r") as publicfile:  #从文件中读取公钥
        pubkey = rsa.PublicKey.load_pkcs1(publicfile.read().encode())
    
    with open("rsa_private.pem", "r") as privatefile:  #从文件中读取私钥
        privatekey = rsa.PrivateKey.load_pkcs1(privatefile.read().encode())
    
    msg = "我自横刀向天笑,去留肝胆两昆仑。"  #原始信息
    encryptdata = rsa.encrypt(msg.encode("utf-8"), pubkey)  #加密
    print("RSA encrypt:", encryptdata,
          "\nRSA decrypt:", rsa.decrypt(encryptdata, privatekey).decode("utf-8"))
    
    #数字签名
    sign = rsa.sign(msg.encode(), privatekey, "SHA-1")  #私钥签名
    print(rsa.verify(msg.encode(), sign, pubkey))  #公钥验证
    print(rsa.verify((msg+"0").encode(), sign, pubkey))  #公钥验证
    

    (4)混合加密机制

    前面说到对称加密和非对称加密两种模式适用于不同的需求,恰好形成互补,很多时候也可以 组合使用,形成混合加密机制。

    即先用计算复杂度高的非对称加密协商一个临时的对称加密密钥(会话密钥,一般相对内容 来说要短的多),然后双方再通过对称加密对传递的大量数据进行加解密处理。

    典型的场景是现在大家常用的HTTPS 机制。HTTPS实际上是利用了TransportLayerSecurity/Secure Socket Layer(TLS/SSL)来实现可靠的传输。TLS 为SSL的升级版本,目前广泛应用的为TLS 1.0,对应到SSL3.1 版本。

    建立安全连接的具体步骤如下:

    1. 客户端浏览器发送信息到服务器,包括随机数R1,支持的加密算法类型、协议版本、压缩算法等。注意该过程为明文。

    2. 服务端返回信息,包括随机数R2、选定加密算法类型、协议版本,以及服务器证书。注意该过程为明文。

    3. 浏览器检查带有该网站公钥的证书。该证书需要由第三方CA来签发,浏览器和操作系统会预置权威CA的根证书。如果证书被篡改作假(中间人攻击),很容易通过CA的证书验证出来。

    4. 如果证书没问题,则用证书中公钥加密随机数R3,发送给服务器。此时,只有客户端和服务器都拥有R1、R2 和R3 信息,基于R1、R2 和R3,生成对称的会话密钥(如AES算法)。后续通信都通过对称加密进行保护。

    注:本文必要术语来源于网络,代码出自本人之手。后续会有其他算法的持续更新。。。

    互联网颠覆世界,区块链颠覆互联网!

    ---------------------------------------------------------20180409 23:40

    相关文章

      网友评论

        本文标题:区块链加密算法小探(一)

        本文链接:https://www.haomeiwen.com/subject/dhmwhftx.html