ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Neo私钥到地址

2019-06-27 12:00:37  阅读:286  来源: 互联网

标签:Neo 公钥 私钥 字节 曲线 地址 平面


基础名词

Neo是个区块链工程,地址,公钥,私钥,地址脚本,base58,sha256,ripemd160,ECCsa,secp256k1,secp25r1这些词都是区块链技术相关的,或是新东西或者有应用到

通过学习后,记录下自己的理解,如果是新接触的话,需要找基础的区块链入门资料学习.

参考资料https://www.cnblogs.com/crazylights/p/8166690.html

ECCurve类文档https://docs.microsoft.com/zh-cn/dotnet/api/system.security.cryptography.eccurve?view=netcore-2.2

Neo区块链

一个区块链开源项目,git:https://github.com/neo-project 区块链的应用之一是数字加密货币.

私钥

私钥是一个大整数,换成二进制是一个256位的数.私钥类似于银行账户,失去私钥等于失去了资产.私钥非常重要!

例:用十六进制表示的私钥 0d005d28cf3d62ec461770746ba42d4a30a638c73c6fbfa90fb3359dc7f72e6b

这个数是有限大的,取值范围由位数和椭圆曲线有关.取256位的话,肯定不会大于2^256-1.也和使用的椭圆曲线有关,但没研究.

公钥

公钥通过私钥计算而来,NEO的计算办法叫ECCsa,使用的是secp256r1曲线,固定的起始G点,经过私钥次数的相加而得到.简单公式描述为 公钥=私钥*G

例: 022b03a16c8d16226618a7327226b4a073daef9ae259d7d884afce47353b51ee29

ecc加密算法有关的知识很多,如果要搞清楚,不太容易.尤其在数学基础很弱的情况下更困难.此次学习也没有懂,了解一些词如下:

私钥到公钥算法相关知识

算法基于被证明过的数学理论,从一条在射影平面上的ecc椭圆曲线上的点开始,不停的做加法,做够n次时,得到的点的坐标是公钥.这个点位于曲线上,n次值就是私钥

射影平面

射影平面上,两条平行线相交于无穷远点.与中学时学的平面几何(欧氏几何)不同,这个平面是另一门几何,它们基于的公理不完全一样.例如,平行线不相交这点就不同

射影平面上,所有直线都有一个无穷远点,任何两条直线都有1个交点.如果两行直线平行,那么它们的交点是无穷远点.如果不平行,则它们有各自的无穷远点

一个射影平面上有且只有一条无穷远直线,平面上所有的无穷远点都在此条直线上.

射影平面是一个有限平面,并且是单面的,从平面上一点出发,可以走到平面上任何一点,不存在平面的另一面.这点,可以参考默比乌斯带特点

或者想象球面,不同于长方体有6个面,要走完6个面,必须跨过面与面之间的边界,球只有一个面,不存在从一面到另一面要跨过边界的情况.

ecc曲线加法

ecc椭圆曲线位于射影平面上,有一些数学计算规则.这个规则就是ecc加密用到的算法之一.对比下图,算法大至逻辑如下:

加法定义:曲线上一点与另一点之和,等于这两点所在直线与曲线的交点的X轴对称点.如果这个点是同一点,那么和等于该点所在切线与曲线交点的X轴对称点.

例如图上G点,它的和就是2G,2G正是G点切线与曲线交点G的X轴对称点.继续做加法,从2G点开始得到4G...

做N次加法之后,得到一个点Q,这个点就是公钥,而N就是私钥.

算法特点

采用这种算法计算有个特点,G是固定的,私钥(N)是个随机大整数,公钥(Q)是一个坐标(X,Y).那么,给定N时,通过将G相加N次,就得到了公钥Q.

那么反过来,给定Q时,却很难计算出N,也就是说,从G点开始,不知道是相加了多少次而得到Q的.那么,有私钥好计算公钥,而反过来则不行.

如果将ecc曲线加法换成简单的加法,也能得出相似的结论.例如2+2+2=6,一眼看出,是2相加3次得到的.那么公钥是6,私钥是3,基点是2

那么,2+2+.?.+2=2744584774030027284458040387221349021599708342405734667783110002634902555648 这个人工算要很久,要靠计算机算.

如果以现有计算能力,破解一个密码要很久,比如几百年.那么这个加密手段肯定是有效的,因为人已经死了几个世纪了,你却还不能破解密码.

地址脚本

脚本是一段程序代码,地址脚本也是程序代码.由公钥计算得到地址脚本.

例如这个地址脚本: cc8e9da86d4c81663d52b5baf9d1c2a2d935013f 计算方法如下

公钥的形式

上文讲述曲线时提到,公钥是一个坐标,是一个椭圆曲线上的点,它有X,Y两个值.十六进制表示格式如:04XY,看起来有些误解.它是04开头接着X坐标和Y坐标的十六进制值

X,Y都是一个32字节的数,那么整个O4XY一共是65个字节.这种表示形式是非压缩的.压缩的形式如下

022b03a16c8d16226618a7327226b4a073daef9ae259d7d884afce47353b51ee29 这是个33字节的数据,开始的02表示Y为偶数,如果Y是奇数,那么是03开头.后面是X值

选用压缩形式表示公钥,因为短.由于椭圆曲线的特点,只需要知道X坐标和Y坐标的奇偶性,就能推算出Y坐标.所以能这样干.至于这特点,并未深入研究,所以没懂.

压缩公钥算出地址脚本

在公钥前面加0x21,后面加oxac,然后做一次sha256,再做一次ripemd160,最后得到20字节的数据,就是地址脚本

21022b03a16c8d16226618a7327226b4a073daef9ae259d7d884afce47353b51ee29ac 0x21=33,而压缩公钥的长度是33字节.

地址

地址由地址脚本计算得到,计算办法如下:

将地址脚本,前面加17变成21个字节,然后将其做两次sha256,取得到的数据前4字节,加到这21个字节后面 简单的讲,地址是地址脚本加了摘要,可以验证.

17cc8e9da86d4c81663d52b5baf9d1c2a2d935013f1234abcd 类似这样,然后用base58编码成如下形式

AXdWU5vYe3Ja9n778RpgJrrCUjAsfQgT1r

区块链的数字账户,通过此地址发生交易.类似于银行账号,转账时需要双方的银行卡号.有了对方地址,就能向对方转加密货币.

小结

转换过程: 私钥 ==> 公钥 ==> 地址脚本 ==> 地址

账户相关这些都源于私钥.WIF是一种私钥形式,由私钥到WIF的计算如下:

私钥前面加0x80后面加0x01,一共34字节,将这34字节做两次SHA256,取结果前4字节,放到34个字节后面,变成38字节.然后base58编码得到WIF.和地址类似,能验证

080d005d28cf3d62ec461770746ba42d4a30a638c73c6fbfa90fb3359dc7f72e6b011234abcd

写代码时,需要用到的一些库:

摘要相关: System.Security.Cryptography命名空间下, SHA256 , RIPEMD160(这个在.netcore上还没有,framework上有)

ecc曲线相关: System.Security.Cryptography命名空间下 ECCurve ECDsa ECParameters

大整数: System.Numerics命名空间下 BigInteger

base58,这个没有库,但是比较简单,可以自己实现.算法类同于将2进制转为16进制.58编码就是将2进制转为58进制

其它

Neo ECC曲线参数

            NeoSecp256r1 = new ECCurve
            {
                // 选择曲线 y^2 = x^ + ax + b
                CurveType = ECCurve.ECCurveType.PrimeShortWeierstrass,

                A = hex2ByteArray("FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC"),

                B = hex2ByteArray("5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B"),

                // 所谓"阶",没搞明白
                Prime = hex2ByteArray("FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF"),

                // 私钥必须小于n n对应是Order这个属性
                Order = hex2ByteArray("FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551"),

                Cofactor = hex2ByteArray("01"),

                // 加法起点G
                G=new ECPoint
                {
                    X=hex2ByteArray("6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296"),
                    Y=hex2ByteArray("4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5")
                }
            }
        

ECCurve

用c#的这个类,可以得到一对私钥和公钥.如下

            // secp2561曲线,相关参数是neo特定的
            var secp256r1 = NeoSecp256r1;

            ECDsa sa = ECDsa.Create();

            // 随机生成密钥对,私钥和公钥
            sa.GenerateKey(secp256r1);

            // 导出的对象里包含私钥和公钥
            ECParameters ecpE = sa.ExportParameters(true);

            // 如果不异常,则生成成功
            ecpE.Validate();

            // 私钥
            ecpE.D

            // 公钥
            ecpE.Q
        

在这个类中,没有找到给定私钥求公钥的方法.NEO源码中有ECC加密的代码,有这样的方法,G*私钥=公钥,可以实现.

标签:Neo,公钥,私钥,字节,曲线,地址,平面
来源: https://www.cnblogs.com/mirrortom/p/11096200.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有