美文网首页大数据区块链大学理财投资
区块链开发——数字加密相关知识 #C01

区块链开发——数字加密相关知识 #C01

作者: 纳兰少 | 来源:发表于2019-03-14 21:08 被阅读31次

    非对称加密

    对称加密指加密和解密使用相同密钥的加密算法。它要求发送方和接收方在安全通信之前,商定一个密钥,泄漏密钥就意味着任何人都可以对他们发送或接收的消息解密。

    每对用户每次使用对称加密算法时,都需要使用其他人不知道的惟一钥匙,这会使得发收信双方所拥有的钥匙数量呈几何级数增长,密钥管理成为用户的负担。同时,对称加密算法能够提供加密和认证却缺乏了签名功能,使得使用范围有所缩小。

    具体算法:AES算法,DES算法,3DES算法,TDEA算法,Blowfish算法,RC5算法,IDEA算法。

    非对称加密指加解密密钥不相关,典型如RSA、EIGamal、椭圆曲线算法。

    椭圆曲线加密

    公开密钥算法总是要基于一个数学上的难题。比如RSA 依据的是:给定两个素数p、q 很容易相乘得到n,而对n进行因式分解却相对困难。那椭圆曲线上有什么难题呢?

    Trapdoor function

    考虑如下等式:

    K=kG  [其中 K,G为Ep(a,b)上的点,k为小于n(n是点G的阶)的整数]  
    

    不难发现,给定k和G,根据加法法则,计算K很容易;但给定K和G,求k就相对困难了。
    这就是椭圆曲线加密算法采用的难题,我们把点G称为基点(base point)。

    现在我们描述一个利用椭圆曲线进行加密通信的过程:

    1. 用户A选定一条椭圆曲线Ep(a,b),并取椭圆曲线上一点,作为基点G。
    2. 用户A选择一个私有密钥k,并生成公开密钥K=kG
    3. 用户A将Ep(a,b)和点K,G传给用户B。
    4. 用户B接到信息后 ,将待传输的明文编码到Ep(a,b)上一点M(编码方法很多,这里不作讨论),并产生一个随机整数r
    5. 用户B计算点C1=M+rK;C2=rG。
    6. 用户B将C1、C2传给用户A。
    7. 用户A接到信息后,计算C1-kC2,结果就是点M。因为
      C1-kC2=M+rK-k(rG)=M+rK-r(kG)=M
      再对点M进行解码就可以得到明文。

    在这个加密通信中,如果有一个偷窥者H,他只能看到Ep(a,b)、K、G、C1、C2,而通过K、G 求k 或通过C2、G求r 都是相对困难的。因此,H无法得到A、B间传送的明文信息。

    公钥与私钥

    公开密钥与私有密钥是一对,如果用公开密钥对数据进行加密,只有用对应的私有密钥才能解密;如果用私有密钥对数据进行加密,那么只有用对应的公开密钥才能解密。
    通过公钥是无法(或极其困难)推算出私钥的。注意这里公钥与私钥都可以用来加密,只是私钥是自己保存,而公钥是公开的。

    比如A发信息给B,就用B的公钥加密信息,然后发给B,B用自己的私钥解密,就可以看到信息内容。

    我们用如下的代码来产生密钥对

    'use strict';
    
    const SHA256 = require("js-sha256");
    var crypto = require('crypto');
    var ed = require('ed25519');
    
    const cipher_algorithm = 'aes192';
    var password = 'this is secret';
    
    // 通过sha256将数据转为哈希值
    var hash = crypto.createHash('sha256').update(password).digest();
    // hash值以16进制显示
    // var hash = crypto.createHash('sha256').update(password).digest('hex');
    // console.log(hash);
    
    var sha = SHA256.create();
    sha.update(password);
    sha.hex();
    // console.log(sha.hex());
    
    // 将哈希值转为密钥对
    var keypair = ed.MakeKeypair(hash);
    

    首先用sha256算法(还有MD5,sha1,sha512等),将随机生成的字符串或者用户设定的密码串,通过crypto模块生成哈希值(也可以直接用js-sha256模块来生成),然后用Ed25519模块直接生成密钥对。生成的keypair中就包含了publicKeyprivateKey

    这里使用Ed25519主要是用户后续的签名操作,因为Ed25519算法相比于NIST系列标准的椭圆曲线,安全性更高,速度更快。

    数字签名

    A把要加密的内容用hash函数生成摘要digest,再用自己的私钥对digest加密,生成数字签名signature。连同加密的内容一起发给B。

    B收到后,对摘要digest(用A的公钥解密)内容(用自己的私钥解密) 都解密,再对内容使用相同hash,看得到的digest是否相同,相同,说明发送的内容没有被修改。

    但是如果这里用B的公钥来加密摘要digest,B收到后用自己的私钥解密,这不是也可以验证内容是否被篡改么?

    如果仅仅从防篡改的角度来讲确实可以,但是这样无法验证这些内容是谁发来的!所以用A的私钥来加密摘要digest,相当于A用自己的私钥给这个摘要digest进行签名,B收到后用A的公钥对digest进行解密还能验证这是不是A发来的内容

    let data = 'where are you';
    console.log('raw data: ' + data);
    // 将数据加密,AES算法是对称加密算法,所以这里都用公钥来进行加解密
    function make_cipher(algorithm, key, buffer) {
        const iv = Buffer.alloc(16, 0); // Initialization vector.
        var cipher = crypto.createCipheriv(algorithm, key.slice(0, 24), iv);
        let encrypted = cipher.update(buffer, 'utf8', 'hex');
        encrypted += cipher.final('hex');
        return encrypted;
    }
    var encrypted_data = make_cipher(cipher_algorithm, keypair.publicKey, data);
    console.log('encrypted data: ' + encrypted_data);
    
    // 用自己的私钥对加密数据进行签名,接收方用我的公钥来进行验证
    var signature = ed.Sign(Buffer.from(encrypted_data, 'utf8'), keypair.privateKey/** 或者直接用keypair*/);
    console.log('signature: ' + signature.toString('hex'));
    var res = ed.Verify(Buffer.from(encrypted_data, 'utf8'), signature, keypair.publicKey);
    console.log('signature verification: ' + res);
    
    // 将数据进行解密
    function make_decipher(algorithm, key, encrypted) {
        const iv = Buffer.alloc(16, 0); // Initialization vector.
        var decipher = crypto.createDecipheriv(algorithm, key.slice(0, 24), iv);
        let decrypted = decipher.update(encrypted, 'hex', 'utf8');
        decrypted += decipher.final('utf8');
        return decrypted;
    }
    
    var raw_msg = make_decipher(cipher_algorithm, keypair.publicKey, encrypted_data);
    console.log('decrypted data: ' + raw_msg);
    

    上述代码用之前生成的密钥对,先对数据进行加密,然后用私钥进行签名,用公钥进行验证,这里使用的是Ed25519算法。
    代码中只使用了密钥对中的公钥来对数据进行加解密,是因为这里主要演示的是签名和验证的过程,所以采用了AES对称加密算法,如果要采用RSA等非对称加密算法可以参考这里

    但是这里有个潜在的问题

    如果B存储的A的公钥被C替换成了C的公钥,那么C就可以冒充A和B进行通信,而B却完全不知道。

    数字证书

    证书中心用自己的私钥对A的公钥和一些相关信息一起加密,形成数字证书
    A在发送内容的同时,在数字签名后再附上数字证书。
    B收到后,先用CA的公钥解密数字证书,得到A真正的公钥,再用A的公钥来验证签名是否是A的签名。

    B可以每次都到CA的网站上(或者什么别的官方途径)获得CA的公钥。

    这么做的目的是为了验证:

    1. 确认该信息确实是A所发;
    2. 确认A发出的信息是完整的。
    • 公钥防泄漏,私钥防篡改、防假冒
      • B收到后,只有用B自己的私钥才能解密内容,别人是无法解密的。防泄漏
      • 再用上述数字证书来验证数字签名是否来自A,发送内容有没有被篡改。防篡改
      • 数字证书一般挂靠在可信任的机构,无法篡改和伪造。

    Merkle Tree

    默克尔树,又叫哈希树,由一个root节点,一组中间节点和一组叶节点组成。
    叶节点包含存储数据或者其哈希值,中间节点和root节点都是其孩子的hash值。

    markle tree.jpg

    应用:

    1. 快速比较数据,两个默克尔树的根节点相同,那么其所代表的数据必然相同
    2. 快速定位修改,比如上面D1数据被修改,可通过root->N4->N1,快速定位到发生改变的D1
    3. 零知识证明,比如要证明某个数据中包含D0,那就构造一个默克尔树,公开root、N4、N1、N0,D0拥有者可以检测到D0存在,但不知道其他内容。(D0拥有者可以看到hash值,但看不到完整的数据内容)(比如用户可以查找自己的money是否在交易所的总备用金中,而不必知道其余用户的money信息;或者p2p下载中,文件切片成小块,下载一个分支后就可以验证该分支的数据是否正确,定位错误数据块重新下载或者继续下载下一个分支数据。)

    相关文章

      网友评论

        本文标题:区块链开发——数字加密相关知识 #C01

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