Python社区  »  区块链

区块链椭圆加密及使用

愚人云端 • 1 周前 • 16 次点击  
阅读 10

区块链椭圆加密及使用

相关文章:

  1. [区块链] 密码学——椭圆曲线密码算法(ECC)
  2. 椭圆曲线算法:入门
  3. ECC椭圆曲线详解(有具体实例)
  4. 谁能最简单的详解椭圆曲线算法,secp256k1 是如何生成公钥和私钥的?

加密算法

对称加密

概念:即加密,解密的密钥相同。

优点:是加解密效率高(速度快,空间占用小),加密强度高。

缺点:是参与多方都需要持有密钥,一旦有人泄露则安全性被破坏;另外如何在不安全通道下分发密钥也是个问题。

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

非对称加密

概念:加密密钥和解密密钥是不同的,分别称为公钥和私钥。公钥一般是公开的,人人可获取的,私钥一般是个人自己持有,不能被他人获取。

优点:是公私钥分开,不安全通道也可以使用。 缺点:是加解密速度慢,一般比对称加解密算法慢2到3个数量级;同时加密强度相比对称加密要差。 非对称加密算法的安全性往往需要基于数学问题来保障,目前主要有基于大数质因子分解、离散对数、椭圆曲线等几种思路。

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

混合机密机制

既先用计算复杂度高的非对称机密协商一个临时的加密密钥(会话密钥,一般相对内容来说要短得多),然后双方再通过对称加密对传递的大量数据进行加解密处理。 典型的场景是现在大家常用的HTTPS机制。

即:先用较短的非对称加密确认权限,再用对称加密对传递的大量数据进行加解密。

区块链椭圆曲线加密(Elliptic Curve Crytosystems,ECC)简介

导入

假设这个世界上所有的人都会乘法,却没有人会除法。 有一天张三挑出了两个数字,123,456。 由于张三会乘法,于是乎张三计算出了:

123 * 456 = 56088
复制代码

于是张三告诉你:

123 * ??? =56088
复制代码

你是个天资卓绝的人,但是没办法,上天不允许你会除法,因此你没法知道张三说的???是什么。
当然了,别人也不知道,因为张三没有告诉其他人???是啥。
有一天,你打算告诉张三一个秘密,67。但是你又不想别人知道。于是聪明绝顶的你随手选了一个数字222。

计算出:

123 * 222 = 27306
复制代码
56088 * 222 + 67 = 12451603
复制代码

然后你对张三说:

123 * ??? = 27306
复制代码
56088 * ??? + x = 12451603
复制代码

当然,你聪明绝顶,张三聪明秃顶,于是张三一寻思:

123 * ??? * 456 = 56088 * ???
复制代码

这上下一减,

x = 12451603 - 27306 * 456 = 67
复制代码

哎妈呀,这x就这么被传递过来了。如果我们把上面的过程写成数学公式的话,

G * k = K   (G,K公开,k保密)
c1 = G * Mc2 = K * M + x (M随机选取,x为要加密的数字,M和x都保密)
x = c2 - c1 * k  
  = K * M + x - G * M * k  = G * M * k + x - G * M * k (消除左右两侧的G * M * k) 
  = x
复制代码

总结:

所以我们想要实现加密容易,校验容易,但解密很难, 其实就是要找到一组运算加,减,乘很简单,除却很难,这个事情并不容易。 因为加,减,乘就可以实现加密和校验,但除我们希望他很难,难到几乎无法得到解。 而这个符合这个条件的运算之一,就是:椭圆曲线方程,其加减乘除是指上的加减乘除,域的概念是从我们的有理数,实数的运算中抽象出来的,严格的定义请参考近世代数方面的数。简单的说,域中的元素同有理数一样,有自己得加法、乘法、除法、单位元(1),零元(0),并满足交换率、分配率。

椭圆曲线方程

包括ECC、ECDH或者ECDSA。ECC是Elliptic Curve Cryptography的缩写,就是椭圆加密算法,ECDH和ECDSA是ECC的不同实现。

椭圆加密算法的应用范围很广,主要的三个技术 TLS、PGP以及SSH都在使用它,更别提比特币以及其他加密数字货币了。

椭圆曲线方程:(可以暂时简单的理解为描述了特定点的集合的公式

y² = x³ + ax + b

椭圆曲线几何学上的加法

任意取椭圆曲线上两点P、Q(若P、Q两点重合,则作P点的切线),作直线交于椭圆曲线的另一点R',过R'做y轴的平行线交于R,定义P+Q=R。这样,加法的和也在椭圆曲线上,并同样具备加法的交换律、结合律。

image

椭圆曲线上的加密/解密

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

考虑如下等式: K=kG [其中 K,G为Ep(a,b)上的点,k为小于n(n是点G的阶)的整数] 不难发现,给定k和G,根据加法法则,计算K很容易;但给定K和G,求k就相对困难了。   这就是椭圆曲线加密算法采用的难题。

  我们把点G称为基点(base point),

  k(k<n,n为基点g的阶)称为私有密钥(privte key),

  k称为公开密钥(public="" key)。<="" p="">

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

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(r<n)。 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间传送的明文信息。

总结:

设私钥、公钥分别为k、K,即K = kG,其中G为G点。

公钥加密: 选择随机数r,将消息M生成密文C,该密文是一个点对,即: C = {rG, M+rK},其中K为公钥

私钥解密: M + rK - k(rG) = M + r(kG) - k(rG) = M 其中k、K分别为私钥、公钥。

椭圆曲线签名与验证签名

椭圆曲线签名算法,即ECDSA。 设私钥、公钥分别为k、K,即K = kG,其中G为G点。

私钥签名: 1、选择随机数r,计算点rG(x, y)。 2、根据随机数r、消息M的哈希h、私钥k,计算s = (h + kx)/r。 3、将消息M、和签名{rG, s}发给接收方。

公钥验证签名: 1、接收方收到消息M、以及签名{rG=(x,y), s}。 2、根据消息求哈希h。 3、使用发送方公钥K计算:hG/s + xK/s,并与rG比较,如相等即验签成功。

原理如下: hG/s + xK/s = hG/s + x(kG)/s = (h+xk)G/s = r(h+xk)G / (h+kx) = rG

比特币私钥、公钥、钱包地址的来历和关系

比特币系统选用的secp256k1

比特币钱包地址示例:1QCXRuoxWo5Bya9NxHaVBArBQYhatHJrU7

那这个钱包地址是如何生成的?

从比特币私钥得到我们日常转账所用的比特币钱包地址总共需要9个步骤,中间用到了SHA256加密、RIPEMD160加密和BASE58编码。

1. 生成随机私钥

私钥是一个随机数,随机选取一个32字节的数,这个数的范围大小是介于1 ~ 0xFFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFE BAAE DCE6 AF48 A03B BFD2 5E8C D036 4141之间的一个数,为了方便后面的计算,我们随机生成一个合法的私钥:

8F72F6B29E6E225A36B68DFE333C7CE5E55D83249D3D2CD6332671FA445C4DD3
复制代码

2. 椭圆曲线算公钥

生成了私钥之后,我们使用椭圆曲线加密算法(ECDSA-secp256k1)计算私钥所对应的非压缩公钥,生成的公钥共65字节, 其中一个字节是0x04,其中32个字节是X坐标,另外32个字节是Y坐标:

公钥P.X:06CCAE7536386DA2C5ADD428B099C7658814CA837F94FADE365D0EC6B1519385
复制代码
公钥P.Y:FF83EC5F2C0C8F016A32134589F7B9E97ACBFEFD2EF12A91FA622B38A1449EEB
复制代码

3.计算公钥的SHA-256哈希值

将上述公钥地址拼合,得到标准地址:

0406CCAE7536386DA2C5ADD428B099C7658814CA837F94FADE365D0EC6B1519385FF83EC5F2C0C8F016A32134589F7B9E97ACBFEFD2EF12A91FA622B38A1449EEB
复制代码

对齐进行SHA-256哈希计算,得到结果:

2572e5f4a8e77ddf5bb35b9e61c61f66455a4a24bcfd6cb190a8e8ff48fc097d
复制代码

4.计算 RIPEMD-160哈希值

取上一步结果,进行RIPEMD-160计算,得到结果:

0b14f003d63ab31aef5fedde2b504699547dd1f6
复制代码

5.加入地址版本号(比特币主网版本号“0x00”)

取上一步结果,在前面加上16进制的00,即:

000b14f003d63ab31aef5fedde2b504699547dd1f6
复制代码

6.计算 SHA-256 哈希值

取上一步结果,进行SHA-256计算,可得:




    
ddc2270f93cc84cc6869dd373f3c340bbf5cb9a8f5559297cc9e5d947aab2536
复制代码

然后,对以上结果再次计算 SHA-256 哈希值,得到:

869ac57b83ccf75ca9da8895823562fffb611e3c297d9c2d4612aeeb32850078
复制代码

7.取上一步结果的前4个字节(8位十六进制)

869ac57b
复制代码

8.把这4个字节加在步骤5的结果后面

作为校验位,将这4个字节加载第五步的结果后面,这就是比特币地址的16进制形态了:

869ac57b000b14f003d63ab31aef5fedde2b504699547dd1f6
复制代码

9.用Base58编码变换一下地址

对上一步的结果进行Base58编码,得到:

1QCXRuoxWo5Bya9NxHaVBArBQYhatHJrU7
复制代码

这就是我们经常看到的传统意义上的比特币钱包地址了。

Delos区块链使用的椭圆加密

delos区块链上使用了两种不同的椭圆加密实现,都是go语言编写

  • ed25519 gitlab.zhonganonline.com/ann/ann-module/lib/ed25519

  • secp256k1 github.com/btcsuite/btcd/btcec

delos链生成私钥

privkey crypto.PrivKeyEd25519
复制代码

delos/api项目中调用的是以太坊的delos/eth/crypto的ECDSA椭圆加密方法生成私钥和地址

生成account私钥和地址

result.Privkey = ethcmn.Bytes2Hex(crypto.FromECDSA(privkey))
result.Address = ethcmn.Bytes2Hex(crypto.FromECDSAPubCompressed(&privkey.PublicKey))
复制代码

Breadwallet-android使用的椭圆加密

Breadwallet-android使用的是secp256k1,都是c语言编写

在app/src/main/secp/secp256k1下

生成私钥

app\src\main\jni\breadwallet-core\Java\root\com\breadwallet\core\BRCoreKey.java
复制代码
private static native long createJniCoreKey ();
复制代码

调用的是 jni c库

/*
 * Class:     com_breadwallet_core_BRCoreKey
 * Method:    createJniCoreKey
 * Signature: ()J
 */
JNIEXPORT jlong JNICALL
Java_com_breadwallet_core_BRCoreKey_createJniCoreKey
        (JNIEnv *env, jclass thisClass) {
    BRKey *key = (BRKey *) calloc (1, sizeof(BRKey));
    return (jlong) key;
}
复制代码

生成公钥

可用助记词或序列

src\main\jni\breadwallet-core\Java\root\com\breadwallet\core\BRCoreMasterPubKey.java
复制代码
private static native long createJniCoreMasterPubKeyFromPhrase (byte[] phrase);

private static native long createJniCoreMasterPubKeyFromSerialization(byte[] pubKey);
复制代码

调用的是 jni c库

/*
 * Class:     com_breadwallet_core_BRCoreMasterPubKey
 * Method:    createJniCoreMasterPubKeyFromPubKey
 * Signature: ([B)J
 */
JNIEXPORT jlong JNICALL
Java_com_breadwallet_core_BRCoreMasterPubKey_createJniCoreMasterPubKeyFromSerialization
        (JNIEnv *env, jclass thisClass,
         jbyteArray serialization) {
    jsize serializationLength = (*env)->GetArrayLength (env, serialization);
    jbyte *serializationBytes = (*env)->GetByteArrayElements (env, serialization, 0);
    assert (serializationLength == sizeof(BRMasterPubKey));

    BRMasterPubKey *key = (BRMasterPubKey *) calloc (1, sizeof (BRMasterPubKey));
    memcpy(key, serializationBytes, sizeof(BRMasterPubKey));

    return (jlong) key;
}
复制代码
Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/37621
 
16 次点击  
分享到微博