heyuan 发布的文章 - 六币之门
首页
视频教程
网站导航
活动日历
关于我们
用户投稿
推荐
新闻动态
搜 索
1
融资周报 | 公开融资事件11起;加密技术公司Toposware完成500万美元融资,Polygon联创参投
112 阅读
2
六币日报 | 九只比特币ETF在6天内积累了9.5万枚BTC;贝莱德决定停止推出XRP现货ETF计划
76 阅读
3
融资周报 | 公开融资事件27起;L1区块链Monad Labs完成2.25亿美元融资,Paradigm领投
74 阅读
4
六币日报 | 美国SEC再次推迟对灰度以太坊期货ETF做出决定;Do Kwon已出黑山监狱等待引渡
72 阅读
5
【ETH钱包开发06】查询某个地址的交易记录
55 阅读
新闻动态
每日快报
一周精选
融资情况
项目投研
自治组织
数字藏品
去中心化应用
去中心化游戏
去中心化社交
去中心化金融
区块链交易所
科普知识
小白入门
用户手册
开发文档
行业报告
技术前沿
登录
搜 索
标签搜索
新闻
日报
元歌Eden
累计撰写
1,087
篇文章
累计收到
0
条评论
首页
栏目
新闻动态
每日快报
一周精选
融资情况
项目投研
自治组织
数字藏品
去中心化应用
去中心化游戏
去中心化社交
去中心化金融
区块链交易所
科普知识
小白入门
用户手册
开发文档
行业报告
技术前沿
页面
视频教程
网站导航
活动日历
关于我们
用户投稿
推荐
新闻动态
用户登录
登录
找到
1087
篇与
heyuan
相关的结果
2023-03-24
[译] 如何区分支付型代币,实用型代币,证券化代币?
掘金
2023年03月24日
6 阅读
0 评论
0 点赞
2023-03-24
关于数字货币钱包的基础密码学
原文链接:zhuanlan.zhihu.com
2023年03月24日
6 阅读
0 评论
0 点赞
2023-03-24
我学习的编程,都给我带来了什么?
前言写这篇文章的主要的原因是什么呢?主要是想到了自己是怎么从一个工科专业然后转行来做到计算机专业,这中间的酸甜苦辣,人间疾苦想分享给大家,以及学习了编程之后我的世界观、价值观的变化,希望能与大家产生共勉。我的编程之路作为一个从农村出来,家住四川,自然就来到天府之都——成都,开始了我的大学生涯,然而当时在那落后的农村,完全没得啥远见,也没有高人指点的,自己又没得啥高瞻远瞩,最终阴差阳错的就选择了个机械电子工程专业。这里并没有说这个专业不好,只是自己学的不好,大学的生活是那么的丰富多彩。这里的丰富多彩是丰富多彩的玩,平时上课选修课必逃,必修课选逃,那么这些时间都拿去干嘛了呢?打游戏、打球、睡觉、出去嗨。提到打游戏必然是当时最火的游戏LOL了,回想起来大学里面的大好时光都荒废在了LOL上面了,真是LOL害人不浅(但是这就是青春嘛,总要挥霍那么些时间,你回头想起来才知道时间的宝贵),所以即使是这样,我也不会后悔上大学。晃眼,时间流逝飞快,大学四年就那么完了,感觉自己是虚度了这四年,什么东西没学到就要参加工作了。最终毕业的时候找了个工作在一个电子厂里面上班,现在回想一下,我才觉得可能这才是我人生过得最颓废,最无知,最惨淡的一段工作经历。为什么这么说呢?可能在电子厂里面上过班的伙伴应该都知道,那种上班的日子是早进晚出,无法看到太阳(夸张了点);早上太阳刚刚升起你就进入工厂,然后就是暗无天日工作,直到加班到8、9点再下班出来,此时太阳已经落山了。在流水线上做着重复没有技术的工作,靠着加班才能多挣点钱,让自己过得好一点。刚开始可能还感觉不到诧异、奇怪,但是这个工作我自己很不开心,没有积极性,没有追求,没有冲劲,因为每天都是做着重复的没有任何的技术含量的工作,没有一点让你有拼搏的劲,学校和自己现在的情况一对比,好像并没有什么和学校不一样的,住的是公司,吃的是食堂,领着固定的工资,周末的和同事约着出去嗨一下,这完全就是和学校的生活复制过来的。沉思了之后,我连自己单独出去租房子的经历都没有过,总感觉自己的人生缺少什么,所以我毫不犹豫有了这个想法之后提出辞职。为什么说我毫不犹豫的辞职呢?因为我连我辞职了要做什么?想做什么?想过上什么样的生活我自己都不清楚,对未来充满了迷茫、疑惑,完全可以说是一条在大海中心一艘船,不知道我应该往哪里划,会遇到的下一个小岛是什么?下一个小岛会不会就是我驻足的地方。就是在这样一种状态下辞职,迎来的是我父母的说词,放着每个月固定的几千块的收入不要,要辞职换工作,而且还没有一点目标。对于农村来讲,每个月固定的几千块的收入,他们还是比较满意的了。但是我父母好在只是说说而已,但是我做什么他们都是比较支持我的。辞职后还是选择了投大学相关专业的工作,毕竟读了4年的专业还是不忍心就丢弃了。但是投了简历之后才发现,既不是应届生而且还没有工作经验,根本没有人要,2个月过去了,依然没有找到。心灰意冷,然后就想着干脆学计算机,因为有朋友在做这一行,收入不错,工作环境又好,当时想的重点是大学还考了全国计算机VB 2级证书,后来还看过些C语言,尽管当时已经忘记完了,但是对程序还是挺感兴趣的,用程序实现某种功能,那种成就感还是很吸引我的,萌芽了这个想法之后,当即是想的自学,当然是失败的;自己买了些书,看了些视频,但是并没有什么效果;于是就多番的打听、了解了之后,最后选择了去培训机构学习,学习的什么呢?因为我一直都觉得写出界面展示出各种炫酷的效果,是非常有趣的事情,Android当时还比较火然后就选择了Android编程学习之路,至此我就走上了我的编程之路。对我来说这相当于一个新的起点,中间的学习过程也是必然辛苦的,可以堪比读高中一样的学习,累但是内心充实着。 可能会有很多人会看不起培训机构出来的,但是我还是要说我就是培训机构出来的,我相信我慢慢的脚踏实地的一步一步的走,终会成功得到认可。从培训出来到现在已经2年多了,先后在三家公司待过,虽然三家公司都是小公司,但是自己的进步和成长还是看的见的。联想到自己的过去,忍不住话就有点多,说的有点长了。也算是自己对以前的一些回顾和感想,请原谅我话多。通过上面的铺垫,我就来说说编程给我带了什么好处?编程带给我的好处?1.思维方式的改变乔布斯说过:「每个人都应该学习编程,因为它教会你思考的方式」我们学习编程,是不一定要成为程序员的。就像每个人都应该学习法律,但不是都要成为律师;就像每个人都应该学习经济学,但不是必须成为经济学家;就像每个人都要学习数学,也不是为了成为数学家。思维改变归结为一条就是:不能够忍受不清晰的表述。不清晰的表述包括:指代或个体不清晰,逻辑/推断不清晰,表达结构不清晰。例如: 比如如果某组员报告进度时说:“他们。。。” 我肯定会想:“他们是谁?” 比如有人发邮件指出“旧版本不支持”,我肯定会想“你是指xxx.x号版本及以前吗?“ 比如有人报告“发生了A事件,我们进行了B操作”我肯定会想“你是说A是你进行B的理由吗?” 比如开会时有人跑题,我肯定会想立刻把他拉回来。跑一次拉一次,跑一次拉一次,直到他不讲话为止。2.专注力和细心度我相信每个程序员的专注力和细心度,那都是被锻炼出来的。你是不是遇到过一个字母大小写原因,然后排错一下午,最后恍然大悟的发现就是一个字母大小写问题。还有很多的这种原本是个很小的问题,但是对于程序员来说都是大问题。写程序是不能得过且过,敷衍了事,马虎行事,避免当一个差不多先生。3.整理信息和融会贯通整理信息和融会贯通应该是我们每个程序猿必备的能力;我相信程序猿都会遇到BUG,都会遇到技术难点。那么这个时候我们是怎么去克服这些困难的呢?可能通常会先百度,然后翻墙Google,或者是去看官方文档等等手段去获取整理信息,然后通过这些信息我们去融会贯通,解决问题、技术难点等等。5.认知的改变说到认知的改变,这个可能有很多的人和我不一样。我之前说过我来自农村,偏僻的地方,什么都比较落后,大学那会儿也是虚度过去,虽然增加了一些知识面,但是还是太为狭窄。学编程前后生活圈,知识圈,交际圈如果用比喻来说的话井底之蛙也不为过。学习编程之前,生活圈估计就是些同学,家人和同事;知识圈指的是我们在上网查询、了解学习新技术或者新的能力方面,以前估计就只是局限在国内;交际圈那么和生活圈就是一模一样没有变化。学习编程之后,可以说是发生了翻天覆地的变化,生活圈、交际圈可能就不局限在了身边这些人,可能通过网上群、博客、或者技术会,一群志同道合的组织的活动等等,这个知识圈最明显了,比如:以前学习的话预计度娘就是你经常找的地方了,度娘没有的估计就只能询问前辈。但是现在国内搜索不到、那就翻墙去国外,总之就是你的获取知识的途径多样化,获取到的内容丰富化。最后说个最明显的改变,那就是对电脑的认知、对电脑世界的认知,科学的获取信息,清楚C/S的原理,我们平常获取的信息从哪儿来,怎么来,知道电脑发生的各种错误等等,还有很多就不一一举例了。6.眼界、知识面眼界和知识面,那必然是我们的互联网的世界了。互联网的世界是丰富多彩的,以前的我可能就是看看电视、打打游戏或者购物等事。学习了编程之后我想我们更多的是了解这个互联网世界的变化,随时关注的是新的技术、国内外的科技界发生的大事,像BAT大公司的变化等等。技术界的大佬都不是单一的,他们的知识面、眼界都是比我们高很多的,因此也会模仿这学习他们,了解房产、理财、股票、区块链、虚拟数字货币等热门的内容,假如换做我没有学习编程的话,可能只有需要的时候才会了解一点。7.奋斗和努力奋斗和努力不分人,不管任何人都是在奋斗和努力着,我这里要说的是行动力和执行力。程序猿是个比较特殊的行业,技术更新叠加快,有着不进则退的特性,只要你停止了学习,你就可能被淘汰,因此不像很多的行业,只要你工作经验丰富,你就能有一席之地,然而程序猿就不行,假如你不学习进步、奋斗努力,你可能几年之后还是个初级码农都是完全有可能的。每个人都攀比之心,我们经常在技术圈交流、请教看到各种大佬的各种牛逼的地方,你会不会有一种我也要成为这样的技术牛人的成就感,同样会迫使你努力奋斗。所以程序猿是一个比其他行业都要努力、奋斗的行业。总结以上只是个人的一点感悟,并不是鼓励每个人都学编程。可能很多人都不会赞同,但是这确确实实是带给我的改变。还有一个改变就是我学习写作公众号,写文章的同时自己也能增长技术,每天进步一点,日积月累,量变引起质变,这就是我编程给我带来的变化;我希望有志同道合的朋友和我一起变化。原创不易,如果觉得写得好,扫码关注一下点个赞,是我最大的动力。关注我,一定会有意想不到的东西等你: 专注分享Android、JAVA干货备注:程序圈LT
2023年03月24日
5 阅读
0 评论
0 点赞
2023-03-24
非对称加密技术- RSA算法数学原理分析
非对称加密技术,在现在网络中,有非常广泛应用。加密技术更是数字货币的基础。所谓非对称,就是指该算法需要一对密钥,使用其中一个(公钥)加密,则需要用另一个(私钥)才能解密。但是对于其原理大部分同学应该都是一知半解,今天就来分析下经典的非对称加密算法 - RSA算法。通过本文的分析,可以更好的理解非对称加密原理,可以让我们更好的使用非对称加密技术。题外话:并博客一直有打算写一系列文章通俗的密码学,昨天给站点上https, 因其中使用了RSA算法,就查了一下,发现现在网上介绍RSA算法的文章都写的太难理解了,反正也准备写密码学,就先写RSA算法吧,下面开始正文。RSA算法原理RSA算法的基于这样的数学事实:两个大质数相乘得到的大数难以被因式分解。如:有很大质数p跟q,很容易算出N,使得 N = p * q,但给出N, 比较难找p q(没有很好的方式, 只有不停的尝试)这其实也是单向函数的概念下面来看看数学演算过程:选取两个大质数p,q,计算N = p q 及 φ ( N ) = φ (p) φ (q) = (p-1) * (q-1) 三个数学概念:质数(prime numbe):又称素数,为在大于1的自然数中,除了1和它本身以外不再有其他因数。互质关系:如果两个正整数,除了1以外,没有其他公因子,我们就称这两个数是互质关系(coprime)。φ(N):叫做欧拉函数,是指任意给定正整数N,在小于等于N的正整数之中,有多少个与N构成互质关系。如果n是质数,则 φ(n)=n-1。如果n可以分解成两个互质的整数之积, φ(n) = φ(p1p2) = φ(p1)φ(p2)。即积的欧拉函数等于各个因子的欧拉函数之积。 选择一个大于1 小于φ(N)的数e,使得 e 和 φ(N)互质 e其实是1和φ(N)之前的一个质数 计算d,使得de=1 mod φ(N) 等价于方程式 ed-1 = k φ(N) 求一组解。 d 称为e的模反元素,e 和 φ(N)互质就肯定存在d。模反元素是指如果两个正整数a和n互质,那么一定可以找到整数b,使得ab被n除的余数是1,则b称为a的模反元素。可根据欧拉定理证明模反元素存在,欧拉定理是指若n,a互质,则:a^φ(n) ≡ 1(mod n) 及 a^φ(n) = a * a^(φ(n) - 1), 可得a的 φ(n)-1 次方,就是a的模反元素。 (N, e)封装成公钥,(N, d)封装成私钥。假设m为明文,加密就是算出密文c:m^e mod N = c (明文m用公钥e加密并和随机数N取余得到密文c)解密则是:c^d mod N = m (密文c用密钥解密并和随机数N取余得到明文m) 私钥解密这个是可以证明的,这里不展开了。 加解密步骤具体还是来看看步骤,举个例子,假设Alice和Bob又要相互通信。Alice 随机取大质数P1=53,P2=59,那N=53*59=3127,φ(N)=3016 取一个e=3,计算出d=2011。 只将N=3127,e=3 作为公钥传给Bob(公钥公开) 假设Bob需要加密的明文m=89,c = 89^3 mod 3127=1394,于是Bob传回c=1394。 (公钥加密过程) Alice使用c^d mod N = 1394^2011 mod 3127,就能得到明文m=89。 (私钥解密过程) 假如攻击者能截取到公钥n=3127,e=3及密文c=1394,是仍然无法不通过d来进行密文解密的。安全性分析那么,有无可能在已知n和e的情况下,推导出d? ed≡1 (mod φ(n))。只有知道e和φ(n),才能算出d。 φ(n)=(p-1)(q-1)。只有知道p和q,才能算出φ(n)。 n=pq。只有将n因数分解,才能算出p和q。复制代码如果n可以被因数分解,d就可以算出,因此RSA安全性建立在N的因式分解上。大整数的因数分解,是一件非常困难的事情。只要密钥长度足够长,用RSA加密的信息实际上是不能被解破的。补充模运算规则模运算加减法:(a + b) mod p = (a mod p + b mod p) mod p(a - b) mod p = (a mod p - b mod p) mod p 模运算乘法:(a b) mod p = (a mod p b mod p) mod p 模运算幂a ^ b mod p = ((a mod p)^b) mod p 深入浅出区块链 - 系统学习区块链,打造最好的区块链技术博客微信号:区块链技术剖析,欢迎订阅 博主辛苦,赞赏下 打赏微信支付本文作者: Tiny熊 本文链接: learnblockchain.cn/2017/11/15/… 版权声明: 本文采用 CC BY-NC-SA 3.0 许可协议。转载请注明出处!
2023年03月24日
6 阅读
0 评论
0 点赞
2023-03-24
创业札记(十)- 不变的事情
最近公司在招聘很多人,这也必然要求我和公司里的每一位管理者有更好的管理能力 在我们面前的是一场硬仗,因为一场战争最终的对手一定是既聪明也努力的!What's not going to change in the next 10 years?这是一个一切都在高速变化的时代,区块链、人工智能、用户下沉、短视频、新零售、... 概念层出不穷。每一个人都在预测未来,对这个世界即将到来的剧变表达自己的观点,我们在这场旷日持久的“风口”上不停地摇摆。什么“未来已来”、“颠覆创新”、“未来简史”更是无时不刻地浸淫在我们耳畔。与大多数年轻一代创业者不同,我是一个慢热、老派、谨慎的人,可能是因为自己是知识分子家庭出身,批评、冷眼、甚至是对一切快速爆发的事物都有天然的抵触心理。在创业这个大的行业里,我很喜欢两个人 Jeff Bezos 和徐新。前两天看相关的文章的时候,我看到了 Jeff Bezos 除了 It's all about long term 之外让我受益匪浅的一段话:I almost never get the question: 'What's not going to change in the next 10 years?' And I submit to you that that second question is actually the more important of the two -- because you can build a business strategy around the things that are stable in time.他说,即使再过 10 年甚至更久,消费者希望可以买到更便宜的东西、希望可以有更多选择、希望可以尽快拿到购买的商品,我们应该把所有的精力专注在这些不变的事情上。以当下最流行的区块链为例,已经非常多的文章在讲区块链是什么,有什么用,然后就有很多类似于“神学”的布道者不停地为这个技术创新添砖加瓦,好像这是一场人类不可规避的大浪潮。但事实却是如何呢?诚然,区块链技术通过分布式数据存储(注意,我这里没有用账本这个词汇)让一个独立存在的系统通过加密技术完成了信任自证。说到此,云里雾里,对区块链技术有概念的人知道在说什么,没明白的人也讲不清楚。但是,这只是一个技术,不变的不是技术,是要解决的问题!区块链解决不了以效率为需求的问题 区块链可以解决那些需要解决分歧的问题 因而, 我们想快速查询不可能用区块链,我们想尽快转帐不可能用区块链,我们想玩即时游戏。至于产生的代币 value-token,它最大的价值也不在 token 本身上而是数字货币可以快速让资产在二级市场上买卖,这本身一个数字货币应用带来的价值,也不是你项目的价值!而什么是最容易产生分歧的问题呢?我们以借钱这个问题为例虽然,我们总希望赶快把钱借到,但这个要求的时间维度是小时或者是天,在这个应用场景下,借钱方如何确保你有能力未来偿还本金和利息就是借贷的基础。这个信任很容易产生分歧,或者说风险很大,例如借款方希望知道你的工作单位、薪资水平、房车证明、历史的借款记录等等。如何解决这么多需要解决信任和分歧的问题,就成了区块链的机会。因而,类似于借贷信息相关的银行、政府监管、生产制造的供应链溯源很快就应用起区块链技术,相关的解决方案提供商也赚的“盆满钵满”,需求应接不暇。未来,可能有区块链之外更好的方法来解决这个问题,但是问题本身是不变的,是永远要去解决的,因而一个持续可以解决借款方还款信任的服务商就是一个可以长期存在并且有价值的商业模式。基于这样很久很久都不变的需求,寻找最佳的解决方案!迭代者为人,递归者为神这句话很常见,那么我先来解释什么是递归和 YCombinator,如果用 Lambda Calculus 的基础表达形式则如下,这就是递归最基础的解释,千变万化都可以解释成 而 或 YCombinator 就是缔造递归的基础,被递归的是一个函数。以 Fibonacci 数列为例:function fib(n) { if (n <= 2) return 1 else return fib(n-1) + fib(n-2) } 复制代码一个无限的数列,其实可以被简化成如此简单的逻辑,这就是递归的力量。为什么说递归者为神是因为递归者永远在抽象,把复杂的世界简化成规则,而也唯有能够如此简化的人才能创造出所有人都需要的东西。例如 Google 把获取信息如此复杂的需求简化成了一个搜索框,可能就是一个伟大的递归吧!虽然,我觉得最伟大的递归是操作系统内核 terminal 下的进程系统。而迭代者呢?其实是劳动生产,在一个抽象规则下增加循环优化的过程,例如上面的数列递归也可以用循环的方式来实现:function fib(n) { let a = 1, b = 1 for (let i = 3; i <= n; i++) { let c = a + b a = b b = c } return b } 复制代码你会发现,所有的递归算法最后都可以转化成利用迭代循环来实现,只是思维的方式不同。而通过递归抽象的方法来寻找本质,其实就是找到了大千世界中一个统一的问题,这也是为什么越是庞大用户量的产品往往界面功能越简单统一,因为所有人都需要解决的需求必定是简洁明确的,我们应该把所有的精力都放在抽象问题的核心上。Keep calm and carry on最后也是最重要的,相信自己,想自己只要足够认真的思考,吸取别人的优质信息,摒除情绪、利益粉饰下的观点。深度思考后必将可以判别其他人的话是否傻逼!有太多人告诉你什么是对、什么是错;每天无尽的信息洪流在左右你的思维;一个人不会因为获取信息的多少而变得更加智慧,只是平添了处理信息的烦恼。这也就是为什么,我不希望浪费时间来纠结,而是把 80% 的时间用在坚定而沉着的思考上。专注不变的问题 专注问题的抽象核心 冷静专注地思考 想明白了,剩下就好好地大干一场吧!
2023年03月24日
5 阅读
0 评论
0 点赞
2023-03-24
开源,免费的EOS, ETH,XLM收款插件
无需搭建比特币/以太坊/EOS全节点(每一个都需要几百G空间) 无手续费,你的程序你做主 所有收到的钱实时自动转移到开发者个人账户,即使被拖库也没钱可盗。 开发者访问本地 http 接口,向用户展示付款方法,用户付款后程序会访问本地回调URLGitHub 地址步骤:1. 创建一个Mixin Messenger账户.访问 mixin.one/messenger 下载对应手机端App。中国大陆用户可以访问 a.app.qq.com/o/simple.js… 下载2. 激活开发者账号登陆 developer.mixin.one ,用App扫码登录这个 教程对于新开发者很有用。Clone, build, rungit clone https://github.com/myrual/mixin-network-snapshot-golang cd mixin-network-snapshot-golang 复制代码编辑一部分配置信息 const ( userid = "3c5fd587-5ac3-4fb6-b294-423ba3473f7d" sessionid = "42848ded-0ffd-45eb-9b46-094d5542ee01" private_key = `-----BEGIN RSA PRIVATE KEY----- MIICXAIBAAKBgQDACTrT4uaB9el9qe0MUOsFrm8kpaDI9PowauMB1Ha25mpfL+5h MFqISLS5z2P89nAsXBg+KyQ2gAVA6rBwW/ZqOc1PKiJhhLBS80nzo3ayfv7OlzNG IxMyqD5izCCtPixnqpuTePoPWq4CNZlxop0VYklsWEfU0U0qqMBgmtqYfQIDAQAB AoGAR8crZed5oTn5fC73m5LjRcxdXqVJ49MtcMuC7jwr41FckRepUkpwjGAgrRMH nJXAd9Q0e4hEkNppHEqciGLXR1dQfZnaM1Gnv7mD3oSgHaH+4qAMnNOCpvwW4Eu3 yp9b1UGj9SvM3D2BrpA+MGf0E/yEJzpRcT956W6SPYYSegECQQDm4uTK+teoxr1Z agJZuCta+IhMzpxIWMob+JN/Huf7OnRcIa9JpXngg4tHOUWmZCDQdqeJMpaQc8SQ 44hba015AkEA1OyJswNIhdmvVp5P1zgREVVRK6JloYwmAtj+Qo4pWJ117LqH4w+b 491r4AeLEGh8VrZ4k6Hp+Cm783S2jTAWJQJARbWdlHdV45xVkQiDuyjy1h2RsXb0 EpfUNcvAZLIlImIMvcBh1x+CA7pTs+Zj1BAJJEee37qJYQXDBGfeRJPKKQJAVG+c x42Ew/eoTZwoIzvLoOkJcFlNHjwaksSER9ZiVQ7URdVOr99vvXQAJG45Wn9k12oy 9LCfvNan/wqIngK0tQJBAL1Wc02seEbMeWyt5jycJEhn6G8F18s9S1v0GXb4U/7/ 6Y87P3TmDLcEuCXkrbZQaCX7jVLu0BkDw8To58TWjh0= -----END RSA PRIVATE KEY-----` ADMIN_MessengerID = ""//this is your mixin messenger id, you can find your id in contact page. ) 复制代码编译 go build mixin_snap.go 复制代码运行 ./mixin_snap 复制代码数据库 同一目录下会生成一个test.db 的sqlite3文件。 如何使用获取数字资产当前价格信息,因此可以计算客户应该付多少数字资产curl -X GET 'http://localhost:8080/assetsprice' 复制代码价格结果如下,其中Full Name是该币种全名,Symbol是在交易所和钱包的缩写符号,USDPrice是当前资产美元价格,BTCPrice同理。[ , , ] 复制代码如果订单价值1美金,那么根据资产价格可以知道客户需要 10 XLM, 或者 0.17 EOS。创建支付请求用POST方法访问 localhost:8080/charges,参数如下POST /chargesAttributes type description currency String Currency code associated with the amount. Only EOS/XLM/ETH is supported currently amount Float64 Positive float customerid String This field is optional and can be used to attach an identifier of your choice to the charge. Must not exceed 64 characters webhookurl String program will visit localhost+webhook when user pay enough currency before charge is expired expiredafter uint the webhook will be expired after xx minutes. User can pay to an expired charge , program keep income record and will transfer asset to admin account 举例: 需要让客户 "client1245" 支付 0.001 ETH, 60分钟内支付完成之后访问用 POST 访问 localhost:9090/123。curl -d '' -H "Content-Type: application/json" 127.0.0.1:8080/charges 复制代码这条指令返回结果{ "Id":3, "Currency":"ETH", "Amount":0.001, "Customerid":"client1245", "Webhookurl":":9090/123", "Expired_after":60, "Paymentmethod":{ "Name":"ETH", "PaymentAddress":"0x130D3e6655f073e33235e567E7A1e1E1f59ddD79", "PaymentAccount":"", "PaymentMemo":"", "Priceinusd":"310.40105841", "Priceinbtc":"0.02374051" }, "Receivedamount":0, "Paidstatus":0} 复制代码客户需要向以太坊地址 0x130D3e6655f073e33235e567E7A1e1E1f59ddD79 支付0.001 ETH来完成支付。如果想收EOS $ curl -d '' -H "Content-Type: application/json" 127.0.0.1:8080/charges 复制代码{ "Id":2, "Currency":"EOS", "Amount":0.001, "Customerid":"client1245", "Webhookurl":":9090/123", "Expired_after":5, "Paymentmethod":{ "Name":"EOS", "PaymentAddress":"", "PaymentAccount":"eoswithmixin", "PaymentMemo":"a01a148f234ea8be0229a4422d21e7f3", "Priceinusd":"4.63264861", "Priceinbtc":"0.00040277" }, "Receivedamount":0, "Paidstatus":0 } 复制代码客户需要向EOS账户 eoswithmixin 支付 0.001 EOS, 并且必须填写支付备注 a01a148f234ea8be0229a4422d21e7f3。如果想收XLMcurl -d '' -H "Content-Type: application/json" 127.0.0.1:8080/charges 复制代码{ "Id":3, "Currency":"XLM", "Amount":0.001, "Customerid":"client1245", "Webhookurl":":9090/123", "Expired_after":5, "Paymentmethod":{ "Name":"XLM", "PaymentAddress":"", "PaymentAccount":"GD77JOIFC622O5HXU446VIKGR5A5HMSTAUKO2FSN5CIVWPHXDBGIAG7Y", "PaymentMemo":"45da67ad857c907a", "Priceinusd":"0.08866487", "Priceinbtc":"0.00000769" }, "Receivedamount":0, "Paidstatus":0 } 复制代码客户需要向Stellar账户 GD77JOIFC622O5HXU446VIKGR5A5HMSTAUKO2FSN5CIVWPHXDBGIAG7Y 支付 0.001 XLM, 并且必须填写支付备注 45da67ad857c907aPayment_method里面有两种类型的支付:比特币/以太坊: PaymentAddress 不是空,PaymentAccount 和 PaymentMemo是空。这种情况下,你只需要给用户展示资产名字 以太坊和PaymentAddress,客户只需要向以太坊地址付款。在这个例子里面,向用户展示资产名称 ETH,以及收款地址 0x365DA43BC7B22CD4334c3f35eD189C8357D4bEd6,以及你期望的以太坊数量。 EOS/行星 : PaymentAddress 是空, PaymentAccount 和 PaymentMemo 都有内容。这种情况下,你需要给用户展示资产名字,收款账户和收款备注,并且严肃的提醒用户同时填写收款账户和收款备注,客户如果忘记填写备注,会导致不能到账,而且无法退款。 Payment_method的记录内容里面有该资产当前的美元价格和比特币价格,开发者可以根据订单的美元价格来计算客户应该支付多少数字货币。 复制代码支持的货币列表Currency 说明 介绍 EOS EOS.io 主网token - XLM Stellar 主网token - BTC 比特币 - UDT Tether USD 基于比特币的USDT,不是ERC20的代币 XRP 锐波币 - LTC 莱特币 - 检查收款状态访问 localhost:8080/charges, 带有参数charge_id例子 curl -X GET 'http://localhost:8080/charges?charge_id=3' 复制代码如果客户还没有支付,结果如下{ "Id":3, "Currency":"ETH", "Amount":0.001, "Customerid":"client1245", "Webhookurl":":9090/123", "Expired_after":60, "Paymentmethod":{ "Name":"ETH", "PaymentAddress":"0x130D3e6655f073e33235e567E7A1e1E1f59ddD79", "PaymentAccount":"", "PaymentMemo":"", "Priceinusd":"310.40105841", "Priceinbtc":"0.02374051" }, "Receivedamount":0, "Paidstatus":0} } 复制代码如果客户已经支付了,那么结果如下{ "Id":3, "Currency":"ETH", "Amount":0.001, "Customerid":"client1245", "Webhookurl":":9090/123", "Expired_after":60, "Paymentmethod":{ "Name":"ETH", "PaymentAddress":"0x130D3e6655f073e33235e567E7A1e1E1f59ddD79", "PaymentAccount":"", "PaymentMemo":"", "Priceinusd":"309.75108846", "Priceinbtc":"0.02369282" }, "Receivedamount":0.002, "Paidstatus":2 } 复制代码支付状态 Paidstatus的解释值 解释 0 还没有支付 1 支付不足 2 支付完毕 3 支付超过需求 payment_records 有支付信息. 其中一个支付信息如下回调URL用户支付完毕后,程序会访问本地+webook url"http://127.0.0.1"+webhookurl 复制代码http 方法为POST,body 参数如下{ "Id":3, "Currency":"ETH", "Amount":0.001, "Customerid":"client1245", "Webhookurl":":9090/123", "Expired_after":60, "Paymentmethod":{ "Name":"ETH", "PaymentAddress":"0x130D3e6655f073e33235e567E7A1e1E1f59ddD79", "PaymentAccount":"", "PaymentMemo":"", "Priceinusd":"309.75108846", "Priceinbtc":"0.02369282" }, "Receivedamount":0.0021, "Paidstatus":2 } 复制代码所有资产都属于开发者自己么?所有资产都会自动被转移到你指定的账户, 免手续费,1秒到账。 在该程序重启,或者意外退出之后,你可以手动发指令要求程序把所有资产都转移到你指定的账户。 例子:curl -X POST -H "Content-Type: application/json" 127.0.0.1:8080/moneygohome 复制代码结果如下total 20 account will send all balance to admin 复制代码支付的确认时间EOS: 3 分钟 Stellar: 2 分钟 Bitcoin/USDT: 60 分钟 Litecoin/Ethererum/DOGE: 120 分钟 什么是确认时间?为什么要关心确认时间?数字货币从用户发起转账请求,到收款方确认这笔付款不能回滚需要一点时间,比特币需要的时间长,其他需要的时间短一点。支持哪些资产理论上Mixin Network支持的都可以接受。现在支持 BTC, USDT, BCH, 以太坊和 ERC20, ETC, EOS 以及EOS上发的token, DASH, Litecoin, Doge, Horizen, MGD, NEM, XRP, XLM, 波场和波场上发的TRC10, Zcash.目前的代码库默认支持的资产现在代码里面默认支持的资产是EOS和恒星,因为他们都可以3分钟完成支付确认。想要支持更多的币,把对应资产的变量放到 default_asset_id_group 里面就可以.const ( BTC_ASSET_ID = "c6d0c728-2624-429b-8e0d-d9d19b6592fa" EOS_ASSET_ID = "6cfe566e-4aad-470b-8c9a-2fd35b49c68d" USDT_ASSET_ID = "815b0b1a-2764-3736-8faa-42d694fa620a" ETC_ASSET_ID = "2204c1ee-0ea2-4add-bb9a-b3719cfff93a" XRP_ASSET_ID = "23dfb5a5-5d7b-48b6-905f-3970e3176e27" XEM_ASSET_ID = "27921032-f73e-434e-955f-43d55672ee31" ETH_ASSET_ID = "43d61dcd-e413-450d-80b8-101d5e903357" DASH_ASSET_ID = "6472e7e3-75fd-48b6-b1dc-28d294ee1476" DOGE_ASSET_ID = "6770a1e5-6086-44d5-b60f-545f9d9e8ffd" LTC_ASSET_ID = "76c802a2-7c88-447f-a93e-c29c9e5dd9c8" SIA_ASSET_ID = "990c4c29-57e9-48f6-9819-7d986ea44985" ZEN_ASSET_ID = "a2c5d22b-62a2-4c13-b3f0-013290dbac60" ZEC_ASSET_ID = "c996abc9-d94e-4494-b1cf-2a3fd3ac5714" BCH_ASSET_ID = "fd11b6e3-0b87-41f1-a41f-f0e9b49e5bf0" XIN_ASSET_ID = "c94ac88f-4671-3976-b60a-09064f1811e8" CNB_ASSET_ID = "965e5c6e-434c-3fa9-b780-c50f43cd955c" XLM_ASSET_ID = "56e63c06-b506-4ec5-885a-4a5ac17b83c1" TRON_ASSET_ID = "25dabac5-056a-48ff-b9f9-f67395dc407c" ........ ) ....... ....... // to support more asset, just add them in the following array default_asset_id_group := []string 复制代码下一步的开发任务:所有的资产可以自动提取到开发者自己的冷钱包,而不是只能转移到Mixin Messenger账户。 可以把收到的资产通过去中心化交易所自动转换成USDT或者比特币。 支持Mixin Messenger用户付款。 可以提供资产对应的美元价格 在commit 8a634e23254e4841c2a9c3114b3eb847d46f55fc 中已经完成。
2023年03月24日
5 阅读
0 评论
0 点赞
2023-03-24
[译] 数字货币钱包详解
原文地址:ethereumbook-wallets 原文作者:ethereumbook 译文出自:掘金翻译计划 本文永久链接:github.com/xitu/gold-m… 译者:XatMassacrE 校对者:leviding 「钱包」这个词语在以太坊中表示的并不是它本来的意思。宏观的讲,钱包主要就是为用户提供用户界面的一个应用。它掌管着用户的金钱,管理着密钥和地址,追踪账户余额以及创建交易和签名。除此之外,一些以太坊钱包还可以与智能合约进行交互,例如代币之类的。而从一个程序员的角度更准确的讲,「钱包」这个词语指的就是存储和管理密钥和地址的系统。每一个「钱包」都有一个密钥管理组件。而对于有些钱包来说,这就是钱包的全部。其他的大部分钱包都是「浏览器」,其实就是基于以太坊的去中心化应用的接口。所以这些各式各样的「钱包」之间并没有什么明确的界限。接下来让我们先看一看钱包关于密钥管理和私钥容器部分的功能。钱包技术总览在这个部分我们会总结用于构建用户友好、安全以及灵活的以太坊钱包所需要的各种技术。关于以太坊有一个最常见的误解就是大部分人认为以太坊钱包包含以太坊和其他代币。而实际上,钱包只包含密钥。以太坊和其他代币都被记录在以太坊的区块链中。用户通过使用他们钱包中的密钥对钱包签名来控制代币。所以从某种意义上讲,以太坊钱包就是一个钥匙串。提示以太坊钱包只包含密钥,而没有以太坊和代币。每一个用户的钱包都包含密钥。钱包就是包含公私钥对的钥匙串。用户使用密钥对交易签名,以此来证明这些以太坊就是属于他们的。而真正的以太坊则存储在区块链上。目前主要有两种类型的钱包,他们的区别就是所包含的密钥之间是否有关联。第一种类型叫做非确定性钱包,它的每一个密钥都是通过一个随机数独立生成的。密钥之间相互没有关联。这种钱包也叫做 JBOK 钱包(来自 "Just a Bunch Of Keys")。第二种钱包叫做确定性钱包,它所有的密钥都来源于一个单独的叫做种子的主密钥。在这个钱包中所有的密钥都相互关联,并且任何拥有原始种子的人都可以将这些密钥再生成一遍。这种确定性钱包会使用很多不同的密钥派生方法。而其中使用最普遍的则是一种类似树形结构的方法,这样的钱包被称为分层确定性或者 HD 钱包。分层确定性钱包是通过一个种子来初始化的。而为了便于使用,种子会被编码成英语单词(或者其他语言的单词),这些单词被称为助记词。下面的章节将会在更高级的层面介绍这些技术。非确定性(随机)钱包在第一个的以太坊钱包(以太坊预售时发布的)中,钱包文件会存储一个单独随机生成的私钥。然而这种钱包之后被确定性钱包取代了,因为这种钱包无法管理、备份以及导入私钥。但是随机密钥的缺点是,如果你生成了很多那么你就要把它们全部拷贝下来。每一个密钥都要备份,否则一旦钱包丢失,那些密钥对应的资产也会丢失。进一步讲,以太坊地址的隐私性会因为相互之间关联的多笔交易和地址的重复使用而大大降低。一个类型-0 的非确定性钱包并不是一个好的选择,尤其是当你为了避免地址的重复使用而不得不管理多个密钥并不断频繁的备份它们时。很多以太坊客户端(包括 go-ethereum 和 geth)都会使用一个钥匙串文件,这是一个 JSON 编码的文件,而且它还包含一个单独的(随机生成的)私钥,为了安全性,这个私钥会通过一个密码进行加密。这个 JSON 文件就像下面这样:{ "address": "001d3f1ef827552ae1114027bd3ecf1f086ba0f9", "crypto": { "cipher": "aes-128-ctr", "ciphertext": "233a9f4d236ed0c13394b504b6da5df02587c8bf1ad8946f6f2b58f055507ece", "cipherparams": { "iv": "d10c6ec5bae81b6cb9144de81037fa15" }, "kdf": "scrypt", "kdfparams": { "dklen": 32, "n": 262144, "p": 1, "r": 8, "salt": "99d37a47c7c9429c66976f643f386a61b78b97f3246adca89abe4245d2788407" }, "mac": "594c8df1c8ee0ded8255a50caf07e8c12061fd859f4b7c76ab704b17c957e842" }, "id": "4fcb2ba4-ccdb-424f-89d5-26cce304bf9c", "version": 3 } 复制代码钥匙串格式使用的是Key Derivation Function (KDF),同时还被成为密码拉伸算法,这个算法可以防止暴力破解、字典攻击以及彩虹表攻击。简单来说就是私钥并不是直接通过密码简单的进行加密的。相反,这个密码是通过不断的重复哈希拉伸过的。这个哈希函数会重复 262144 轮,这个数字就是钥匙串 JSON 文件中的 crypto.kdfparams.n 这个参数指定的。一个攻击者试图通过暴力破解的手段来破解密码的话,那么他需要为每一个可能的密码执行 262144 轮哈希,这样对于一个足够复杂和长度的密码来说被破解几乎是不可能的。这里还有一些软件库可以读取和写入钥匙串格式,例如 JavaScript 的库 keythereum:github.com/ethereumjs/…提示除了一些简单的测试之外,我们是不推荐使用非确定性钱包的。我们推荐使用的是拥有助记词种子备份功能的基于行业标准的HD 钱包。确定性钱包(种子)钱包确定性或者说「种子」钱包是指那些所有的私钥都是通过一个普通的种子使用一个单向哈希函数延伸而来的钱包。这个种子是结合一些其他的数据而随机生成的数字,例如利用一个索引数字或者「链码」(查看HD 钱包(BIP-32/BIP-44)来派生出私钥。在一个确定性钱包中,一个种子就足够恢复出所有派生的密钥,因此只需要在创建的时候做一次备份就可以了。同时,这个种子对于钱包来说也是可以导入导出的,可以让所有用户的密钥在各种不同的钱包之间进行简单的迁移。HD 钱包 (BIP-32/BIP-44)确定性钱包的开发就是为了可以简单的从一个「种子」派生出很多个密钥。而这种确定性钱包最高级的实现就是由比特币的 BIP-32 标准定义的 HD 钱包。HD 钱包包含的密钥来源于一个树形的结构,例如一个父密钥可以派生出一系列子密钥,每一个子密钥又可以派生出一系列孙子密钥,不停的循环往复,没有尽头。这个树形结构的示意图如下:HD 钱包相对于随机的(非确定性的)密钥有两个主要的优势。一,树形结构可以表达额外的组织意义,例如当一个子密钥特定的分支用来接收转入支付而另一个不同的分支可以接收转出支付的改变。密钥的分支也可以在一些共同的设置中被使用,例如可以分配不同的分支给部门、子公司、特定的函数或者不同的账单类别。第二个优势就是用户可以使用 HD 钱包在不利用相关私钥的情况下创建一系列公钥。这样 HD 钱包就可以用来做一个安全的服务或者是一个仅仅用来观察和接收的服务,而钱包本身却没有私钥,所以它也无法花费资金。种子和助记词 (BIP-39)HD 钱包对于管理多个密钥和地址来说是一个很强力的机制。如果再结合一个从一系列英语单词(或者其他语言的单词)中创建种子的标准化方法的话,那么通过钱包进行抄写、导出和导入都变得更加简单易用。这就是大家所熟知的由标准 BIP-39 定义的助记词。今天,很多以太坊钱包(还有其他的数字货币钱包)都在使用这个标准来导入导出种子,并使用共同的助记词来进行备份和恢复。让我们来从实践的角度看一下。下面哪个种子在抄写、纸上记录以及阅读障碍这几个方面更优秀呢?一个 16 进制编码的确定性钱包种子FCCF1AB3329FD5DA3DA9577511F8F137 复制代码一个由 12 个单词组成的助记词的钱包种子wolf juice proud gown wool unfair wall cliff insect more detail hub 复制代码钱包最佳实践随着数字货币钱包技术的逐渐成熟,也慢慢形成了共同的行业标准,使得钱包在交互性、易用性、安全性和灵活性等方面大幅度提高。这些标准同时也使得钱包可以仅仅从一个单独助记词就为各种不同的数字货币派生出不同的密钥。这些共同的标准就是下面这些:基于 BIP-39 的助记词 基于 BIP-32 的 HD 钱包 基于 BIP-43 的多用途 HD 钱包结构 基于 BIP-44 的多货币多账户钱包 这些标准或许会改变,也或许会被未来的开发者废弃,但是现在它们组成的这一组连锁技术俨然已经成为了大多数数字货币的实际上的钱包标准。这些标准已经被大部分的软件和硬件钱包所采用,使得这些钱包之间可以相互通用。一个用户可以从这些钱包中的任意一个导出助记词,然后导入到另一个钱包中,并恢复所以的交易、密钥和地址。很多软件钱包都支持这种标准,例如(按字母 排序)Jaxx, MetaMask, MyEtherWallet (MEW)。硬件钱包则有 Keepkey, Ledger, and Trezor。下面的章节会详细讲解这些技术。提示如果你要实现一个以太坊钱包,他应该是一个 HD 钱包,种子会被编码成助记词以供备份,BIP-32、BIP-39、BIP-43、和 BIP-44 这些标准会在下面的章节中详细说明。助记词 (BIP-39)助记词就是代表一个随机数的单词序列,这个助记词会作为种子派生出一个确定性钱包。这个序列的单词能够再次创建种子、钱包和所有派生出的密钥。一个实现了确定性钱包助记词功能的应用将会向在第一次创建钱包的时候向用户展示一组长度为 12 到 24 的单词序列。这个序列就是钱包的备份,它可以在任何兼容的钱包上实现恢复和重建所有的密钥。助记词可以让用户更简单的备份钱包,因为相比于一组随机数助记词可读性更好,抄写的正确率也更高。提示助记词常常与「大脑钱包」想混淆。但是它们并不是一回事。而其中最主要的区别在于大脑钱包是由用户自己选择的单词组成的,而助记词则是钱包代表用户随机创建的。这个重要的区别使得助记词更加的安全,因为人类随机性的来源少的可怜。助记词编码是在 BIP-39 中定义的。注意 BIP-39 只是助记词编码的一个实现。还有很多不同的标准,比特币钱包 Electrum 就是在 BIP-39 之前使用了一组不同的单词。BIP-39 这个标准是由硬件钱包 Trezor 背后的公司提出来的,而且还兼容 Electrum 的实现。但是,BIP-39 现在已经取得了广泛的行业支持,并且兼容十几个相互操作的实现,所以 BIP-39 应该就是现在的行业标准。并且,BIP-39 可以用来生成支持以太坊的多货币钱包,而 Electrum 的种子并不支持。BIP-39 标准定义了助记词编码和种子的生成过程,也就是接下来的九个步骤。为了表达的更清楚,整个过程分成了两个部分:第一步到第六步在生成助记词,第七步到第九步在助记词到种子。生成助记词助记词是钱包使用 BIP-39 中定义的标准化过程自动生成的。钱包起始于一个熵的源头,然后添加一个校验和并将熵映射到一个单词数组中。创建一个 128 位到 256 位的随机序列(熵) 通过取 SHA256 的前(熵长度除以 32)位来创建这个随机序列的校验和。 将校验和添加到随机序列的末尾。 将序列分成几个 11 位的部分。 从预定义的 2048 个单词字典中将每一个 11 位的值映射到一个单词上面。 助记词编码就是一系列单词。 生成熵并编码成助记词将会展示出熵是如何生成助记词的。助记词编码:熵和单词长度 展示出了熵数据的大小和单词中助记词长度的关系。助记词编码: 熵(entropy)和单词(word)长度 Entropy (bits) Checksum (bits) Entropy + checksum (bits) Mnemonic length (words) 128 4 132 12 160 5 165 15 192 6 198 18 224 7 231 21 256 8 264 24 从助记词到种子助记词代表着长度为 128 到 256 位的熵。这个熵会通过密钥拉伸函数 PBKDF2 生成一个更长的(512 位)种子。这个种子再构建一个确定性钱包并派生出它的密钥。密钥拉伸函数需要两个参数:助记词和盐。盐的目的是为了让暴力破解构建查询表的难度提高。在标准 BIP-39 中,盐还有另外一个目的,那就是密码可以作为一个额外的安全因子来保护种子,这部分会在BIP-39 中的可选密码中详细讲述。第七步到第九步的过程:密钥拉伸函数 PBKDF2 的第一个参数第六步中生成的助记词。 密钥拉伸函数 PBKDF2 的第二个参数就是盐。这个盐由字符串常量 "mnemonic" 和一个额外的用户提供的密码字符串拼接构成。 PBKDF2 使用 HMAC-SHA512 算法进行了 2048 轮哈希运算对助记词和盐进行拉伸,生成一个 512 位的值作为最后的输出。这个 512 位的值就是种子。 [fig_5_7] 展示出了一个助记词是如何生成种子的。提示密钥拉伸函数以及它的 2048 轮哈希从某种程度上讲对于暴力破解助记词和密码是一个有效的保护。会让其以昂贵的代价(在计算资源上)不停的尝试成千上万种密码和助记词的组合,而这些组合的数量则犹如汪洋大海(2512)。下面的表格分别展示了 #mnemonic_128_no_pass、#mnemonic_128_w_pass 和 #mnemonic_256_no_pass 这几个类型的助记词和他们产生的种子(没有密码)的例子。128 位(bit)熵(entropy)的助记词编码(mnemonic code),无密码生成的种子(seed) Entropy input (128 bits) 0c1e24e5917779d297e14d45f14e1a1a Mnemonic (12 words) army van defense carry jealous true garbage claim echo media make crunch Passphrase (none) Seed (512 bits) 5b56c417303faa3fcba7e57400e120a0ca83ec5a4fc9ffba757fbe63fbd77a89a1a3be4c67196f57c39 a88b76373733891bfaba16ed27a813ceed498804c0570 128 位(bit)熵(entropy)的助记词编码(mnemonic code),有密码生成的种子(seed) Entropy input (128 bits) 0c1e24e5917779d297e14d45f14e1a1a Mnemonic (12 words) army van defense carry jealous true garbage claim echo media make crunch Passphrase SuperDuperSecret Seed (512 bits) 3b5df16df2157104cfdd22830162a5e170c0161653e3afe6c88defeefb0818c793dbb28ab3ab091897d0 715861dc8a18358f80b79d49acf64142ae57037d1d54 256 位(bit)熵(entropy)的助记词编码(mnemonic code),无密码生成的种子(seed) Entropy input (256 bits) 2041546864449caff939d32d574753fe684d3c947c3346713dd8423e74abcf8c Mnemonic (24 words) cake apple borrow silk endorse fitness top denial coil riot stay wolf luggage oxygen faint major edit measure invite love trap field dilemma oblige Passphrase (none) Seed (512 bits) 3269bce2674acbd188d4f120072b13b088a0ecf87c6e4cae41657a0bb78f5315b33b3a04356e53d062e5 5f1e0deaa082df8d487381379df848a6ad7e98798404 BIP-39 中的可选密码BIP-39 标准允许用户在生成种子的时候使用可选密码。如果没有使用密码,那么助记词就会被一个由常量字符串 "mnemonic" 组成的盐拉伸,然后由给定的助记词产生一个特定的 512 位种子。如果使用了密码,则拉伸函数在使用同一个助记词的情况下会产生一个不同的种子。实际上,给定一个助记词,每一个可能的密码都会生成不同的种子。并且基本上没有任何「错误」的 密码。所有的密码都是可用的并且所有的密码都可以生成不同种子,这些不同的助记词会形成一组数量巨大的为初始化的钱包。这些可能的钱包数量是如此之大 (2512),以至于实际情况中暴力破解和意外猜对的可能性几乎为零,只要密码拥有足够的复杂度和长度。提示在标准 BIP-39 中不存在「错误的」密码。每个密码都会生成一个钱包,如果不是之前使用的密码的话那就是一个新的钱包。可选密码会产生两个重要的特性:一个需要记忆的第二个因子可以防止助记词的备份被窃取。 选择密码的这些貌似拥有可信拒绝能力或者说是「监禁的钱包」使得那些小额资金的钱包经常将攻击者的注意力从那些「真正的」大额资金钱包中分散出来。 但是,需要注意的一点是使用密码会面临密码丢失的风险。如果钱包的主人缺乏行动能力或者去世了,那么就没人知道密码了,也没人知道种子是什么,那么钱包中储存的所有资金就全部丢失了。 相反,如果钱包的主人在与种子同样的地方备份了密码,那么它就失去了第二个因素的目的。 虽然密码非常有用,但是也应该结合小心的计划备份和恢复的过程来使用,因为要考虑到钱包主人生还的可能性并可以允许他们的家人来恢复数字货币的资产。助记词的工作BIP-39 在很多不同的编程语言中都有实现的库:python-mnemonic参考了 SatoshiLabs 团队在 BIP-39 中提议的 Python 版本Consensys/eth-lightwallet用于节点和浏览器(基于 BIP-39)的轻量级 JS 以太坊钱包npm/bip39比特币 BIP39 的 JavaScript 实现:用于生成确定性密钥的助记词编码还有一个在单独的网页中实现的 BIP-39 生成器,这个网页在测试和实验中非常有用。BIP-39 生成器展示了一个可以生成助记词、种子以及拓展的私钥的单独的网页。网页(iancoleman.github.io/bip39/)可以在浏览器中离线使用(在线当然也可以)。通过种子创建一个 HD 钱包HD 钱包是通过一个根种子来创建的,这个根种子一般是 128、256 或者 512 位的随机数。通常情况下,这个种子是通过一个助记词来生成的。HD 钱包中的每一个密钥都是派生自这个根种子,这样就使得通过这个种子在其他兼容性钱包中重建整个 HD 钱包成为了可能。同时还使得备份、恢复、导出以及导入包含成千上万个密钥的钱包变的非常简单,仅仅通过转移从根种子派生出的助记词就可以了。[[bip32_bip43/44]] ==== 分层确定性钱包 (BIP-32) 和路径 (BIP-43/44)大多数 HD 钱包都遵循 BIP-32 标准,同时 BIP-32 也是确定密钥生成器的实际上的行业标准。详细的说明可以查看下面的链接:github.com/bitcoin/bip…在这里我们不会讨论 BIP-32,我们只需要理解钱包中使用它的部分就可以了。在其他一些软件库中还有很多关于 BIP-32 彼此协作的实现。Consensys/eth-lightwallet用于节点和浏览器(基于 BIP-39)的轻量级 JS 以太坊钱包这里还有一个标准 BIP-32 的网页版的生成器,对于测试和实验都非常有用。bip32.org/提示这个单独的 BIP-32 生成器不是一个 HTTPS 的站点。就是为了告诉你使用这个工具不是安全的。只是用来做测试的。你不应该在生产环境中(真实的资金)使用这个网页生成的密钥。拓展公钥和私钥在 BIP-32 的术语中,一个父密钥可以拓展的生成「儿子」,这个儿子就是拓展密钥。如果它是一个私钥,那么它就是一个拓展私钥,并通过前缀 xprv 来区分:xprv9s21ZrQH143K2JF8RafpqtKiTbsbaxEeUaMnNHsm5o6wCW3z8ySyH4UxFVSfZ8n7ESu7fgir8imbZKLYVBxFPND1pniTZ81vKfd45EHKX73 复制代码一个拓展公钥通过前缀 xpub 来区分:xpub661MyMwAqRbcEnKbXcCqD2GT1di5zQxVqoHPAgHNe8dv5JP8gWmDproS6kFHJnLZd23tWevhdn4urGJ6b264DfTGKr8zjmYDjyDTi9U7iyT 复制代码HD 钱包中一个非常有用的角色就是从父公钥派生出子公钥,不包含私钥。这会给我们提供两种方法来派生子公钥:从子私钥或者直接从父公钥来派生。一个拓展公钥可以在 HD 钱包的结构中派生出所有的公钥(也只能是公钥)。无论什么情况只要部署的服务和应用有一份拓展公钥并且没有私钥,那么这个快捷方式就可以创建非常安全的公钥。这种部署可以生成无穷个公钥和以太坊地址,但是却不能花费任何发送到这些地址的资金。同时,在另外一个更安全的服务器上,拓展私钥可以派生出所有相关的私钥用来给交易签名,并花费资金。利用这种解决方案的一个常见的应用就是在一个 web 服务器上安装一个拓展公钥,来为电子商务应用服务。这个网页服务器可以使用公钥派生函数为每一笔交易(例如客户的购物车)创造出一个全新的以太坊地址。这个网页服务器没有任何私钥所以盗贼也无法窃取。不使用 HD 钱包的情况下,想做到这个程度唯一的方法就是在一个分割的安全服务器上生成上千个以太坊地址然后在电子商务服务器上预加载他们。这个方法低效笨重,并且需要经常的维护以确保电子商务服务器不会泄露密钥。还有一个常见的应用就是冷存储和硬件钱包。在这种场景下,拓展私钥可以存储在硬件钱包中,但是拓展公钥可以放在线上。用户可以按照他们的意愿创建接收的地址,私钥则会离线安全的保存。想花掉里面的资金的话,用户可以在离线签名的以太坊客户端或者支持交易签名的硬件钱包上使用拓展私钥。硬化密钥派生从 xpub 中派生出一个公钥分支的能力时很有用的,但同时也是具有风险的。知道 xpub 并不意味着知道子密钥。然而,因为 xpub 包含链码,所以如果一个子密钥被别人知道或者暴露了的话,那么它就可以和链码一起派生出所有其他的子密钥。一个单独泄露的子密钥和一个父链码一起可以暴露出所有的子私钥。而更糟糕的是,子私钥和父链码一起还可以推断出父私钥。为了避免这个风险,HD 钱包使用了另外一种叫做硬化派生的派生函数,这个函数可以「破坏」父公钥和子链码的联系。这种硬化派生函数是使用父私钥来派生出子链码的,而不是父公钥。这样会在父或子序列中创造出一个「防火墙」,而这个防火墙并不会威胁到父或者子私钥的安全。简单的来说就是,如果不想承受泄露你自己链码风险,并且还想要方便的使用 xpub 来派生出公钥分支,那么你应该通过硬化父辈来派生它,而不是一个正常的父辈。这其中的最佳实践就是,为了防止威胁到主要的密钥,主要密钥的 level-1 子辈总是通过硬化派生来派生。正常派生和硬化派生的指数BIP-32 中的派生函数使用的是一个 32 位整型的指数。为了方便的区分出正常派生函数和硬化派生函数生成的密钥,这个指数分成了两个区间。0 到 231–1 (0x0 to 0x7FFFFFFF) 只用来表示正常的派生。231 到 232–1 (0x80000000 to 0xFFFFFFFF) 只用来表示硬化派生。因此,如果指数小于 231,则子辈是正常的,如果指数大于等于 231,那么子辈就是硬化的。为了让指数的易读性和显示性更好,硬化子辈的指数是从零开始显示的(有一个素数符合)。第一个正常子密钥则显示为 0,这样第一个硬化子辈(指数为 0x80000000)就会显示为 0'。而第二个硬化密钥指数从 0x80000001 开始,并且显示为1',以此类推。当你看到一个 HD 钱包的指数为 i' 时,就意味着 231+i。HD 钱包密钥标识符(路径)一个 HD 钱包中的密钥是通过「路径」命名规则来标识的,对于树的每一个层级都通过斜杠 (/) 这个字符来分隔(查看HD 钱包路径示例)。 从主私钥派生出的私钥都以 "m." 开头。从主公钥派生出的公钥以 "M." 开头。因此主私钥的第一个子私钥就是 m/0。主公钥的第一个子公钥就是 M/0。第一个子辈的第二个孙子就是 m/0/1,以此类推。一个密钥的「祖先」是从右向左读取的,直到派生出它本身的主密钥为止。举个例子,标识符 m/x/y/z 就是 m/x/y 的第 z 个子密钥、m/x 的第 y 个子密钥、m 的第 x 个子密钥。HD 钱包路径示例 HD path Key described m/0 主私钥 m 的第一个(0)儿子私钥 m/0/0 第一个子辈(m/0)的第一个孙子私钥 m/0'/0 第一个硬化子辈 (m/0') 的第一个标准孙子 m/1/0 第二个子辈(m/1)的第一个孙子私钥 M/23/17/0/0 第 24 个子辈的第 18 个孙子辈的第一个曾孙辈的第一个玄孙的公钥 HD 钱包的树形结构指南HD 钱包的树形结构提供了巨大的灵活性。每一个父拓展密钥都可以拥有 40 亿个子辈:20 亿个普通子辈和 20 亿个硬化子辈。每一个子辈都有另外 40 亿个子辈,以此类推。只要你想,这个树形结构就可以一代一代的无限延伸下去。但是这种灵活性又使得对这个无限的树形结构操作变的复杂。尤其是在各种实现之间转移 HD 钱包变的尤为困难,因为这个内部的结构从分支到子分支的可能性是无限的。现在的两种 BIP 都是通过对 HD 钱包的树形结构创建一些标准来解决这些复杂性的。BIP-43 提议将第一个硬化子指数作为可以表示树形结构「用途」的特殊标识符。而 BIP-43 则认为,HD 钱包应该只使用一个树形结构 level-1 的分支,并通过定义它的用途来让指数来标识结构以及剩余数的命名空间。例如,一个 HD 钱包只使用分支 m/i'/,并打算使用它来指明一个特殊的用途,而这个用途就是用指数 "i" 来标识的。再说明一下这个细则,BIP-44 提议的多货币多账户的结构就是 BIP-43 的「用途」数字 44'。所有的 HD 钱包都遵循 BIP-44 结构,这个结构就是实际中使用树形结构一个分支 m/44'/ 所标识的结构。BIP-44 还指明了五个预定义的树层级:m / purpose' / coin_type' / account' / change / address_index复制代码第一个层级 "purpose" 一直等于 44'。第二个层级 "coin_type" 指明了数字货币的类型,对于多货币的 HD 钱包来每一个种货币都在第二层级下有他自己的子树。这里有几个在标准文档中定义的货币,叫作 SLIP0044:github.com/satoshilabs…举个例子:以太坊是 m/44'/60',以太经典是 m/44'/61',比特币是 m/44'/0',所有这些货币的测试网络都是 m/44'/1'。第三个层级是 "account",它允许用户把他们的钱包再分成几个逻辑子账户,用于会计或者组织的目的。举例来说,一个 HD 钱包可以包含两个以太坊「账户」:m/44'/60'/0' 和 m/44'/60'/1'。而每个帐户都是它自己子树的根。因为 BIP-44 一开始是为比特币创造的,所以它包含的 "quirk" 和以太坊一点关系都没有。路径的第四层级是 "change",一个 HD 钱包有两个子树,一个用来创建接收地址,一个用来创建改变地址。而以太坊中只有「接收」地址,并不需要改变地址。注意,由于上个层级使用了硬化派生,所以这个层级就是普通派生。这是为了让这个层级的树可以在非安全环境下导出可以使用的公钥。可用的地址由 HD 钱包派生出来作为第四层级的子辈,然后形成树第五层级的 "address_index"。举例来说就是,以太坊的第三个接收地址在主账户中的支付将会是 M/44'/60'/0'/0/2。BIP-44 HD 钱包的结构示例:BIP-44 HD 钱包结构示例 HD 路径 密钥描述 M/44'/60'/0'/0/2 主以太坊账户的第三个收到的公钥 M/44'/0'/3'/1/14 第四个比特币账户的第 15 个可变地址的公钥 m/44'/2'/0'/0/1 用于签名交易的莱特币主账户的第二个私钥 掘金翻译计划 是一个翻译优质互联网技术文章的社区,文章来源为 掘金 上的英文分享文章。内容覆盖 Android、iOS、前端、后端、区块链、产品、设计、人工智能等领域,想要查看更多优质译文请持续关注 掘金翻译计划、官方微博、知乎专栏。
2023年03月24日
4 阅读
0 评论
0 点赞
2023-03-24
如何基于 ETH 快速发布自己的数字货币
原文链接:mp.weixin.qq.com
2023年03月24日
6 阅读
0 评论
0 点赞
2023-03-24
使用 Python 学习和破解古典密码
之前在研究一些数字货币的时候有一个概念深深的吸引了我,那就是零知识证明,它指的是证明者能够在不向验证者提供任何有用的信息的情况下,使验证者相信某个论断是正确的。通俗的讲就是我有一个 secret_key,但是我不会把这个 secret_key 提供给验证者,而让验证者相信我知道这个 secret_key。很神奇吧,但是我们今天并不是要说零知识证明,而是从密码学最基础的地方说起。对零知识证明感兴趣的同学可以去看看 zkSNARKs in a nutshell。古典密码学虽然在现在看起来非常简单,但是对于构建密码的原理和一些解决问题的方法上仍然值得我们学习。今天我们就使用 Python 来对两个著名的加密算法进行加解密和破解。本文源码在这里获取。凯撒密码(Caesar Cipher)介绍凯撒密码属于替换密码的一种,替换密码就是指用一个别的字母来替换当前的字母。比如我和对方约定一个替换表: l -> h,o -> a,v -> t,然后我发送love给对方,对方按照对照表就知道我发送的其实是hate。凯撒密码使用的是将正常的 26 个英文字母进行移位替换,通常设定 shift 值为 3,相当于 a -> d,b -> e,c -> f...加解密方法(encrypt,decrypt)下面给出加解密实现:import string lowercase = string.ascii_lowercase def substitution(text, key_table): text = text.lower() result = '' for l in text: i = lowercase.find(l) if i < 0: result += l else: result += key_table[i] return result def caesar_cypher_encrypt(text, shift): key_table = lowercase[shift:] + lowercase[:shift] return substitution(text, key_table) def caesar_cypher_decrypt(text, shift): return caesar_cypher_encrypt(text, -shift)复制代码为了看起来比较容易,所以在方法中把密文的空格和标点符号都保留了下来。今天的两个例子都会使用下面这段经典密文(德国在一战期间邀请墨西哥进攻美国的密文,源自齐默尔曼电报事件)进行演示:We intend to begin on the first of February unrestricted submarine warfare. We shall endeavor in spite of this to keep the United States of America neutral. In the event of this not succeeding, we make Mexico a proposal of alliance on the following basis: make war together, make peace together, generous financial support and an understanding on our part that Mexico is to reconquer the lost territory in Texas, New Mexico, and Arizona. The settlement in detail is left to you. You will inform the President of the above most secretly as soon as the outbreak of war with the United States of America is certain and add the suggestion that he should, on his own initiative, invite Japan to immediate adherence and at the same time mediate between Japan and ourselves. Please call the President's attention to the fact that the ruthless employment of our submarines now offers the prospect of compelling England in a few months to make peace.使用caesar_cypher_encrypt(text, shift)我们会得到:zh lqwhqg wr ehjlq rq wkh iluvw ri iheuxdub xquhvwulfwhg vxepdulqh zduiduh. zh vkdoo hqghdyru lq vslwh ri wklv wr nhhs wkh xqlwhg vwdwhv ri dphulfd qhxwudo. lq wkh hyhqw ri wklv qrw vxffhhglqj, zh pdnh phalfr d sursrvdo ri dooldqfh rq wkh iroorzlqj edvlv: pdnh zdu wrjhwkhu, pdnh shdfh wrjhwkhu, jhqhurxv ilqdqfldo vxssruw dqg dq xqghuvwdqglqj rq rxu sduw wkdw phalfr lv wr uhfrqtxhu wkh orvw whuulwrub lq whadv, qhz phalfr, dqg dulcrqd. wkh vhwwohphqw lq ghwdlo lv ohiw wr brx. brx zloo lqirup wkh suhvlghqw ri wkh deryh prvw vhfuhwob dv vrrq dv wkh rxweuhdn ri zdu zlwk wkh xqlwhg vwdwhv ri dphulfd lv fhuwdlq dqg dgg wkh vxjjhvwlrq wkdw kh vkrxog, rq klv rzq lqlwldwlyh, lqylwh mdsdq wr lpphgldwh dgkhuhqfh dqg dw wkh vdph wlph phgldwh ehwzhhq mdsdq dqg rxuvhoyhv. sohdvh fdoo wkh suhvlghqwv dwwhqwlrq wr wkh idfw wkdw wkh uxwkohvv hpsorbphqw ri rxu vxepdulqhv qrz riihuv wkh survshfw ri frpshoolqj hqjodqg lq d ihz prqwkv wr pdnh shdfh.注:英国情报局截获的密文并不是这样使用凯撒密码加密的破解如果当时你截获到这样一份电报你会怎么想?在短暂的一面懵逼之后,显然要想办法破解出正常的意思才行。破解的思路其实也非常简单:因为加密时可以人为设定 shift 值,那么我们就从 0-25 循环来一遍看看哪个是有意义的就行了:def crack_caesar_cypher(text): for i in range(26): key_table = lowercase[-i:] + lowercase[:-i] print(substitution(text, key_table)[:12], '| shift is ', i, )复制代码看看结果:哪一行是有意义的呢?维吉尼亚密码(Vigener cipher)介绍凯撒密码显然无法阻挡人类的智慧,其实正常的替换密码的空间大小为 26!,这个数字非常大,相当于 2 的 88 次方,就是随机替换字母表生成加密表,然后按照加密表进行加密和解密,但是在字频分析下也败下阵来。然后就出现了维吉尼亚密码。维吉尼亚密码的加密方式也非常简单,先设定一个key = 'crypto',然后将key循环排列与原信息按照字母一一对应,然后将字母在字母表中的所在位置进行相加得到一个index,然后将 index 模 26,得到加密后的字母在字母表中的位置。例如:we intend tocr yptocr yp相当于:22 4 8 13 19 4 13 3 19 142 17 24 15 19 14 2 17 24 15上下相加我们就得到:24 21 32 28 38 18 15 20 43 29 再模 26 得到:24 21 6 2 12 18 15 20 17 3然后对应字母表我们得到:yv gcmspu rd加解密方法(encrypt,decrypt)下面给出加解密实现:def insert_letter(text, i, l): return text[:i] + l + text[i:] def get_blank_record(text): text = text.lower() blank_record = [] for i in range(len(text)): l = text[i] item = [] if lowercase.find(l) < 0: item.append(i) item.append(l) blank_record.append(item) return blank_record def restore_blank_record(text, blank_record): for i in blank_record: text = insert_letter(text, i[0], i[1]) return text def get_vigener_key_table(text, key): text = text.lower() trim_text = '' for l in text: if lowercase.find(l) >= 0: trim_text += l total_length = len(trim_text) key_length = len(key) quotient = total_length // key_length reminder = total_length % key_length key_table = quotient * key + key[:reminder] return trim_text, key_table def vigener_cypher_encrypt(text, key, is_encrypt=True): blank_record = get_blank_record(text) trim_text, key_table = get_vigener_key_table(text, key) result = '' for i in range(len(trim_text)): l = trim_text[i] index_lowercase = lowercase.find(l) index_key_table = lowercase.find(key_table[i]) if not is_encrypt: index_key_table = -index_key_table result += lowercase[(index_lowercase + index_key_table) % 26] return restore_blank_record(result, blank_record) def vigener_cypher_decrypt(text, key): return vigener_cypher_encrypt(text, key, False)复制代码使用vigener_cypher_encrypt(text, key)我们会得到:yv gcmspu rd usizl dg hjv dxkgv fd uxptlygr ipichmfktrtw gwskpkwpv upktcic. lx gjrja xbfvykhf ke qebhg fd iawu km zxsr kft nbkkcs lhckch ht cdcgbqc ecjmfcc. gc mvg vttgh qw rwbg pfr hnqevcsbbi, nc btyg dcmbqq r nghdqjya ht ccjxtbev mc mvg wmaecyzlv uouzq: btyg nyg mcivrwxf, orit isctc ihugkftk, ugecghiu wgctbezya lirgmgm opu yc nbfvphmopugcz cp fsg iotk rwth ovvxvc kj rd kseflfnst kft ecuk rtkfkkmgr wp kcmtg, pvu bxlktm, pgr cigohbc. kft lsvkjtfspk gc wsvrga bg nvdi mc afs. nhi yzja bbhfpb mvg gptlwfvli ht vyc pucxv kdlh uvagxhnp yh lcqe yh mvg fsiufgri dy kci uxmv vyc jgwvvb hmovvq dy oovpxvo kj atkhczl pgr cub ias ulevxgvzmc mvck ft lvqljs, hb jzq dpb kegibovztt, bbxzrt corrl ih wodcsbovv ysastvlrx opu yi mvg jybx hkdc bxrkrrt usvnctg xcgyc tbf fsglsnmch. izgrqt vonc rwx dtvqxwspkq pmhgerxhb vf rwx tctr iaov kft kivyjtlg gdnahmovli ht qlp hnporpxgsu eml hthvph mvg gpdldgtr dy qqdntezkee tgunrls bb c wcl fcpkfh mc orit isctc.为了看起来比较容易,所以在方法中把密文的空格和标点符号都保留了下来。上面的密文看起来似乎与凯撒密码差不多,但是这种加密方法在当时很难被破解。破解这种加密特点在于同样的字母加密之后并不会指向同样的密文,比如前3个单词we intent to中的 t,在凯撒密码或者常规的替换密码的下都会对应一个特定的字母,但是在这里我们可以看到intent中的t加密为m,to中的t加密为r。这样的话,字频分析也不起作用了。但是道高一尺魔高一丈,这个号称不能被破解的密码还是迎来了被破解的命运:假设我知道这个 key 的长度为 6。那么我们把密文以 6 个一组进行切割,那么一组中每个字母对应的原字母出现的的频率就是符合字频分析的,所谓的字频分析就是:26 个英文字母在句子中出现的频率。然后我们开始对每组的字频进行统计:group 0 : [, , , , , , ]group 1 : [, , , , , , ]group 2 : [, , , , , , ]group 3 : [, , , , , , ]group 4 : [, , , , , , ]group 5 : [, , , , , , ]根据字母频率表我们发现,字母e出现的频率超过了 12%,所以我们假设每组中至少有一个是字母e对应的密文,然后遍历出现次数超过10次的字母,并对另外两个出现频率最高的的字符数组['t', 'a']进行检测记分,然后得出最可能的的key。下面是代码:def get_trim_text(text): text = text.lower() trim_text = '' for l in text: if lowercase.find(l) >= 0: trim_text += l return trim_text def crack_vigener_cypher(text, key_length): blank_record = get_blank_record(text) trim_text = get_trim_text(text) group = ['' for i in range(key_length)] for i in range(len(trim_text)): l = trim_text[i] for j in range(key_length): if i % key_length == j: group[j] += l key = '' letter_stats_group = [] for j in range(key_length): letter_stats = [] for l in lowercase: lt = count = group[j].count(l) lt[l] = count letter_stats.append(lt) letter_stats = sorted(letter_stats, key=lambda x: list(x.values())[0], reverse=True) letter_stats_group.append(letter_stats) # print('group', j, ':', letter_stats[:8]) # gvctxs score_list = [] for i in range(3): current_letter = list(letter_stats[i].keys())[0] index = lowercase.find(current_letter) key_letter = lowercase[index - lowercase.find('e')] item = [] item.append(key_letter) score = 0 for k in range(3): vl = list(letter_stats[k].keys())[0] for fl in ['t', 'a']: #if i == 1 and (k == 1 or k == 2) and j == 1: if (lowercase.find(key_letter) + lowercase.find(fl)) % 26 == lowercase.find(vl): score += 1 item.append(score) score_list.append(item) score_list = sorted(score_list, key=lambda x: x[1], reverse=True) key += score_list[0][0] plain_text = vigener_cypher_decrypt(trim_text, key) return restore_blank_record(plain_text, blank_record)复制代码然后我们通过运行crack_vigener_cypher(cypher_text, 6)就可以得到明文了。然而这个地方大家可以看到,我默认传了一个参数 6 进去,也就是 key 的长度。但是当我们截获到密文的时候连 key 都不知道,显然也不会知道 key 的长度了。所以如果我们可以确定 key 的长度,那么维吉尼亚密码在我们面前就是纸老虎了。实际上,像凯撒密码一样,从 1 到 25 去试也是可以破解的,但是我们这里使用一个叫做重合指数的方法来帮助缩小范围(虽然实际效果并不好,但是还是要理解一下方法)。重合指数法:由26个字母构成的一段有意义文字中,任取两个元素刚好相同的概率约为0.067,所以如果一段明文是用同一个字母加密的话,这个概率依然不会改变。因此我们可以写个方法来计算重合指数: def get_coincidence_index(text): trim_text = get_trim_text(text) length = len(trim_text) letter_stats = [] for l in lowercase: lt = count = trim_text.count(l) lt[l] = count letter_stats.append(lt) index = 0 for d in letter_stats: v = list(d.values())[0] index += (v/length) ** 2 return index复制代码然后我们假设不同的 key 的长度,对每组密文进行重合指数的计算,然后选出和0.067相比方差较小的一部分长度作为备选:def get_var(data, mean=0.067): if not data: return 0 var_sum = 0 for d in data: var_sum += (d - mean) ** 2 return var_sum / len(data) def get_key_length(text): trim_text = get_trim_text(text) # assume text length less than 26 group = [] for n in range(1, 26): group_str = ['' for i in range(n)] for i in range(len(trim_text)): l = trim_text[i] for j in range(n): if i % n == j: group_str[j] += l group.append(group_str) var_list = [] length = 1 for text in group: data = [] for t in text: index = get_coincidence_index(t) data.append(index) var_list.append([length, get_var(data)]) length += 1 var_list = sorted(var_list, key=lambda x: x[1]) return [v[0] for v in var_list[:12]]复制代码[[16, 2.9408699990533694e-05], [9, 3.8755178005797864e-05], [10, 5.415541187702294e-05], [17, 5.5154370298645345e-05], [19, 6.055960902865477e-05], [13, 8.572621594737114e-05], [8, 8.734954157595401e-05], [14, 9.767402405996375e-05], [3, 0.00010208649957333127], [20, 0.00012009258116435503], [11, 0.0001230940714957638], [6, 0.00014687184215509398]]正确长度在第12个,我也很绝望啊...现在万事具备了,直接遍历备选的 key_length,然后看看解密之后的效果吧。12 行,应该一眼就可以看到答案了吧。本文到此结束,欢迎批评指正。
2023年03月24日
6 阅读
0 评论
0 点赞
2023-03-24
密码学系列之:1Password的加密基础PBKDF2
小知识,大挑战!本文正在参与“程序员必备小知识”创作活动简介1password是一个非常优秀的密码管理软件,有了它你可以轻松对你的密码进行管理,从而不用再考虑密码泄露的问题,据1password官方介绍,它的底层使用的是PBKDF2算法对密码进行加密。那么PBKDF2是何方神圣呢?它有什么优点可以让1password得以青睐呢?一起来看看吧。PBKDF2和PBKDF1PBKDF的全称是Password-Based Key Derivation Function,简单的说,PBKDF就是一个密码衍生的工具。既然有PBKDF2那么就肯定有PBKDF1,那么他们两个的区别是什么呢?PBKDF2是PKCS系列的标准之一,具体来说他是PKCS#5的2.0版本,同样被作为RFC 2898发布。它是PBKDF1的替代品,为什么会替代PBKDF1呢?那是因为PBKDF1只能生成160bits长度的key,在计算机性能快速发展的今天,已经不能够满足我们的加密需要了。所以被PBKDF2替换了。在2017年发布的RFC 8018(PKCS #5 v2.1)中,是建议是用PBKDF2作为密码hashing的标准。PBKDF2和PBKDF1主要是用来防止密码暴力破解的,所以在设计中加入了对算力的自动调整,从而抵御暴力破解的可能性。PBKDF2的工作流程PBKDF2实际上就是将伪散列函数PRF(pseudorandom function)应用到输入的密码、salt中,生成一个散列值,然后将这个散列值作为一个加密key,应用到后续的加密过程中,以此类推,将这个过程重复很多次,从而增加了密码破解的难度,这个过程也被称为是密码加强。我们看一个标准的PBKDF2工作的流程图:从图中可以看到,初始的密码跟salt经过PRF的操作生成了一个key,然后这个key作为下一次加密的输入和密码再次经过PRF操作,生成了后续的key,这样重复很多次,生成的key再做异或操作,生成了最终的T,然后把这些最终生成的T合并,生成最终的密码。根据2000年的建议,一般来说这个遍历次数要达到1000次以上,才算是安全的。当然这个次数也会随着CPU计算能力的加强发生变化。这个次数可以根据安全性的要求自行调整。有了遍历之后,为什么还需要加上salt呢?加上salt是为了防止对密码进行彩虹表攻击。也就是说攻击者不能预选计算好特定密码的hash值,因为不能提前预测,所以安全性得以提高。标准salt的长度推荐是64bits,美国国家标准与技术研究所推荐的salt长度是128 bits。详解PBKDF2的key生成流程上面一小节,我们以一种通俗易懂的方式告诉大家,PBKDF2到底是怎么工作的。一般来说,了解到这一层也就够了,但是如果你想更加深入,了解PBKDF2的key生成的底层原理,那么还请关注这一小节。我们上面介绍了PBKDF2是一个生成衍生key的函数,作为一个函数,那么就有输入和输出,我们先看下PBKDF2的定义:DK = PBKDF2(PRF, Password, Salt, c, dkLen) 复制代码PBKDF2有5个函数,我们看下各个参数代表什么意思:PRF 是一个伪随机散列函数,我们可以根据需要对其进行替换,比如替换成为HMAC函数。 Password 是主密码用来生成衍生key。 Salt是一个bits序列,用来对密码加盐。 c 是循环的次数。 dkLen 是生成的key要求的bits长度。 DK是最后生成的衍生key。 在上一节中,我们可以看到其实最后的衍生key是由好几部分组成的,上图中的每一个T都代表着衍生key的一部分,最后将这些T合并起来就得到了最终的衍生key,其公式如下:DK = T1 + T2 + ⋯ + Tdklen/hlen Ti = F(Password, Salt, c, i) 复制代码上面的F是c次遍历的异或链。其公式如下:F(Password, Salt, c, i) = U1 ^ U2 ^ ⋯ ^ Uc 复制代码其中:U1 = PRF(Password, Salt + INT_32_BE(i)) U2 = PRF(Password, U1) ⋮ Uc = PRF(Password, Uc−1) 复制代码HMAC密码碰撞如果PBKDF2的PRF使用的是HMAC的话,那么将会发送一些很有意思的问题。对于HMAC来说,如果密码的长度大于HMAC可以接受的范围,那么该密码会首先被做一次hash运算,然后hash过后的字符串会被作为HMAC的输入。我们举个例子,如果用户输入的密码是:Password: plnlrtfpijpuhqylxbgqiiyipieyxvfsavzgxbbcfusqkozwpngsyejqlmjsytrmd复制代码经过一次HMAC-SHA1运算之后,得到:SHA1 (hex): 65426b585154667542717027635463617226672a复制代码将其转换成为字符串得到:SHA1 (ASCII): eBkXQTfuBqp'cTcar&g*复制代码所以说,如果使用PBKDF2-HMAC-SHA1的加密方式的话,下面两个密码生成衍生key是一样的。 "plnlrtfpijpuhqylxbgqiiyipieyxvfsavzgxbbcfusqkozwpngsyejqlmjsytrmd" "eBkXQTfuBqp'cTcar&g*" 复制代码PBKDF2的缺点虽然PBKDF2可以通过调节循环遍历的次数来提高密码破解的难度。但是可以为其研制特殊的处理器,只需要很少的RAM就可以对其进行破解。为此bcrypt 和 scrypt 等依赖于大量RAM的加密算法,这样就导致那些廉价的ASIC处理器无用武之地。总结以上就是PBKDF2的简单介绍,想要详细了解更多的朋友,可以参考我的其他关于密码学的文章。本文已收录于 www.flydean.com/41-pbkdf2/最通俗的解读,最深刻的干货,最简洁的教程,众多你不知道的小技巧等你来发现!欢迎关注我的公众号:「程序那些事」,懂技术,更懂你!
2023年03月24日
4 阅读
0 评论
0 点赞
1
...
79
80
81
...
109