Hi 游客

更多精彩,请登录!

比特池塘 区块链技术 正文

Neo中hash算法,加密算法使用介绍

空港训港j
320 0 0
区块链是基于加密算法,共识算法,p2p网络和经济激励的一个系统,加密算法在里面起到了非常关键的作用,总结一下Neo使用到的加密算法吧。
$ M. ]! u$ {! k: L7 O关于区块链中密码学的介绍,yeasy大牛的文章已经介绍的非常好,下文主要通过和Neo结合,加上一些自己的理解,去讲述一下加密算法的使用方法。8 Y) L- L4 @+ r( j) p: F* U
Hash 算法: J- w# U- m- A9 J& W1 n
Hash (哈希或散列)算法是信息技术领域非常基础也非常重要的技术。它能任意长度的二进制值(明文)映射为较短的固定长度的二进制值(Hash 值),并且不同的明文很难映射为相同的 Hash 值。3 k' B& i/ r- ^, e1 y/ J# s6 @
; @5 X" k- N3 {% [+ x6 y3 d0 `4 r
注意上一篇文章说明了如何将hash后的字符串保存到Neo的UInt256类型,其中一个前提就是结果集合在[0-15]之间。
% b- d% \6 c+ @+ t$ x  U哈希完全不等于加密,很多时候开发人员都对用户表中的密码进行哈希后保存,实际上不叫做加密,只是相当于把密码的“特征指纹”保存下来,而对非法攻击者来说,在不知道真实的“密码”的情况下,得到有相同指纹的密码是极为困难的。- u6 l% s! G2 H/ m
一个优秀的 hash 算法,将能实现:
6 p6 v/ G0 {3 l4 `- N. E正向快速:给定明文和 hash 算法,在有限时间和有限资源内能计算出 hash 值。逆向困难:给定(若干) hash 值,在有限时间内很难(基本不可能)逆推出明文。输入敏感:原始输入信息修改一点信息,产生的 hash 值看起来应该都有很大不同。冲突避免:很难找到两段内容不同的明文,使得它们的 hash 值一致(发生冲突)。
% J* e. s, \3 i
! \2 N/ I; @; J8 T
目前,一般认为 MD5 和 SHA1 已经不够安全,推荐至少使用 SHA2-256 算法。5 ~! w. h2 ^* ?" ?, F. w& |+ ~/ M: p
一般的,Hash 算法都是算力敏感型,意味着计算资源是瓶颈,主频越高的 CPU 进行 Hash 的速度也越快。
( l5 T- b7 n+ L8 ~3 i也有一些 Hash 算法不是算力敏感的,例如 scrypt,需要大量的内存资源,节点不能通过简单的增加更多 CPU 来获得 hash 性能的提升。
# B" r- F) d. ~: p6 G# }Neo中的hash算法
1 X8 r. ^% ?  Q; e7 c( ?. |+ [- ?  ~scrypt
8 `8 k, M/ r$ M* l( G" p8 Fscrpyt算法是由著名的FreeBSD黑客 Colin Percival为他的备份服务 Tarsnap开发的,当初的设计是为了降低CPU负荷,尽量少的依赖cpu计算,利用CPU闲置时间进行计算,因此scrypt不仅计算所需时间长,而且占用的内存也多,使得并行计算多个摘要异常困难,因此利用rainbow table进行暴力攻击更加困难。scrypt没有在生产环境中大规模应用,并且缺乏仔细的审察和广泛的函数库支持。所以scrpyt一直没有推广开,但是由于其内存依赖的设计特别符合当时对抗专业矿机的设计,成为数字货币算法发展的一个主要应用方向。( j4 J( E, ]% w7 C, k1 c6 z
scrypt的参数
3 s+ R* s4 J$ t- q) p7 m7 nhttps://stackoverflow.com/questions/11126315/what-are-optimal-scrypt-work-factors9 [1 h" S: K: N" Y
Cpercival mentioned in his slides from 2009 something around
3 x2 r' K- f' K% N1 s  S2 P(N = 2^14, r = 8, p = 1) for 9 C7 f6 O$ j5 m( B
scrypt特点
$ [" a2 ]% t% e! p9 o) @scrpyt的出名主要是因为莱特币为了抵抗比特币矿机采用的一个算法,可以指定内存和cpu的使用量,可以用参数确定hash的时间。
) i# @; A+ M& s5 E% gNeo中如何使用scrypt
( l5 r# u/ a5 A! l. z( r+ d// in NEP6Account8 M8 @$ B* |( j3 T. m' v
   public NEP6Account(NEP6Wallet wallet, $ i& I5 |7 p& Y  S5 C' ^' o
              UInt160 scriptHash, KeyPair key, string password)
) \' i+ b/ r& `4 G* B' L8 T9 o$ C            : this(wallet,
' g( k# y" I' h              scriptHash,
8 J& T1 g' q; j5 E, [" k3 z, K              key.Export(password, wallet.Scrypt.N, wallet.Scrypt.R, wallet.Scrypt.P))
2 I+ i6 [8 V5 S, \3 `        {
- t5 b1 [: w5 f" K% I/ j* b; \            this.key = key;
- H2 _1 K# V* \  L        }
, ]" Q) H3 t6 t/ x" u9 y  }// in class KeyPair3 G; G' z8 z6 ^3 ^# l0 j0 S
public string Export(string passphrase, int N = 16384, int r = 8, int p = 8)
0 |9 t) H7 e3 a{
8 P% N: N  i! ^    using (Decrypt())
" E6 D% G; J! f& n. e9 [5 Q6 X    {$ J; k( |# e: k
        UInt160 script_hash = Contract.  p4 r' _# B  [' r
            CreateSignatureRedeemScript(PublicKey).ToScriptHash();6 {/ w0 S' @+ M: K$ a, d& D
        - y( n- O7 M% p9 X6 [+ ?
        string address = Wallet.ToAddress(script_hash);
0 J' }# {9 }- d$ k) }0 V2 V        byte[] addresshash = Encoding.ASCII.GetBytes(address)
" t5 E2 ]' z8 Z3 w1 }4 c, s$ @! f            .Sha256().Sha256().Take(4).ToArray();
$ Y5 x, n; E3 ?$ ^1 h+ a        / Q$ L0 @, c4 `2 G; Z
        byte[] derivedkey = SCrypt.DeriveKey(/ N1 N, D* x7 o5 q' Q
            Encoding.UTF8.GetBytes(passphrase), addresshash, N, r, p, 64);; q2 q' _1 m+ W" [& f+ m$ s
        
8 Y, E* D. y8 U0 t3 c        byte[] derivedhalf1 = derivedkey.Take(32).ToArray();) a- ^9 p% ~. ^1 M9 ], h
        byte[] derivedhalf2 = derivedkey.Skip(32).ToArray();3 O% _  L+ W* o5 q* {5 C
        
- |) U4 ]* w/ _, x3 k5 d$ V3 ~, l        byte[] encryptedkey = XOR(PrivateKey, derivedhalf1)% i* N# d% ]( {' ^2 ?5 r
            .AES256Encrypt(derivedhalf2);" S' p+ W1 D  A0 t
        
* s- ^# W  V) x        byte[] buffer = new byte[39];
7 v- y! g2 c$ W$ _& n        buffer[0] = 0x01;+ M8 j" Y0 H+ S. {# n
        buffer[1] = 0x42;
. K; P) O6 W' o% ^' h4 R        buffer[2] = 0xe0;
$ K9 T9 @5 d! c. p( l8 z        Buffer.BlockCopy(addresshash, 0, buffer, 3, addresshash.Length);- Y/ J9 p2 Y) `" ]8 }
        Buffer.BlockCopy(encryptedkey, 0, buffer, 7, encryptedkey.Length);
: o" m5 i# {* f/ ?/ \0 _+ F2 s        return buffer.Base58CheckEncode();( z4 L7 n) p7 k% i
    }
4 b' }8 r" u0 Y: S5 A}, \  I/ M0 K- r/ W6 V; {
可见SCrypt.DeriveKey方法参与了加密密钥的生成过程。后面解密也必然使用到了这个hash算法。所以该hash算法参与了加密过程,而加密密钥用AES256Encrypt生成。可以确定的是,使用该算法的逆过程,可以解密出密钥来,这个比WIF要安全。2 V9 g. |  X3 `& g4 k6 m5 N$ j
Murmur3
$ r  K% k7 k6 Z! v3 [MurmurHash 是一种非加密型哈希函数,适用于一般的哈希检索操作。[1][2][3]由Austin Appleby在2008年发明,[4][5] 并出现了多个变种,[6] 都已经发布到了公有领域(public domain)。与其它流行的哈希函数相比,对于规律性较强的key,MurmurHash的随机分布特征表现更良好。[7]8 a" {6 X+ O2 ?5 E# U; l$ D  @
Murmur3特点
; V( ]/ [, W" G! e1.碰撞率低  x! c4 A& i/ D0 a5 J
2.计算速度快1 M* _: f* M+ d. F/ G9 S2 N
3.擅长大文件的hash
' y; j% ^, {9 t; R; K; fNeo中如何使用Murmur3
; _, ~8 ]6 X3 K- W$ ]5 v
4 k0 I' `$ ^+ r) X# I& j% `; U" CNeo中Murmur3
) v( M" y7 x6 m4 \, V% B- ]Murmur3的具体算法,以后再研究,现在大致知道,Neo用Murmur3生成key,也在BloomFilter中使用了。
: s  E6 {- W* x% kRIPEMD-160
4 w0 w0 V3 A' X$ ?  j8 E% x$ X/ PNeo中用这个算法来生成短一点的hash值,script hash就是用了这个算法。6 l: z0 [( `/ C: a6 }
// in neo-compiler/neo/neo/Core/Helper.cs3 X  y8 c3 G2 w. K& G. T
public static UInt160 ToScriptHash(this byte[] script)* J! v6 Z  p1 U( B
        {
# |$ o$ k# P1 ^/ g0 s: B            return new UInt160(Crypto.Default.Hash160(script));& B1 }+ R7 E  I/ ]: b
        }1 j: e, K& {4 l
RIPEMD-160算法的特点
0 a% @, f$ C0 L2 u4 k7 F, T, d6 K0 x; ORIPEMD-160能表现出理想的 雪崩效应 (例如将 d 改成 c,即微小的变化就能产生一个完全不同的哈希值):7 C* h+ _$ r8 p% h" N
加密算法体系
, E' a9 I; z1 m7 H( M现代加密算法的典型组件包括:加解密算法、加密密钥、解密密钥。其中,加解密算法自身是固定不变的,一般是公开可见的;密钥则往往每次不同,并且需要保护起来,一般来说,对同一种算法,密钥长度越长,则加密强度越大。' G: L! B6 j) n
加密过程中,通过加密算法和加密密钥,对明文进行加密,获得密文。
) a) \* N) t- {% {( o% }7 r解密过程中,通过解密算法和解密密钥,对密文进行解密,获得明文。( v, K2 b3 x& L  y
根据加解密的密钥是否相同,算法可以分为对称加密(symmetric cryptography,又称公共密钥加密,common-key cryptography)和非对称加密(asymmetric cryptography,又称公钥加密,public-key cryptography)。两种模式适用于不同的需求,恰好形成互补,很多时候也可以组合使用,形成混合加密机制。
" m% f0 I0 \; E6 g并非所有加密算法的强度都可以从数学上进行证明。公认的高强度加密算法是在经过长时间各方面实践论证后,被大家所认可,不代表其不存在漏洞。但任何时候,自行发明加密算法都是一种不太明智的行为。* ]4 u$ i$ U: U$ m* c( r% _
对称加密
( r$ q% U* j( I4 V0 ]9 }/ R顾名思义,加解密的密钥是相同的。+ _1 k# @/ s3 R' Z4 D/ I
对称加密优缺点
( \" a& C* Q- j2 z& l优点是加解密效率高(速度快,空间占用小),加密强度高。- j# z0 G0 P& U8 l$ d+ D( m
缺点是参与多方都需要持有密钥,一旦有人泄露则安全性被破坏;另外如何在不安全通道下分发密钥也是个问题。
+ o2 D! G7 {4 G* F, v0 s6 k5 L适用于大量数据的加解密;不能用于签名场景;需要提前分发密钥。
' M: w  x* ]6 `$ e# A对称加密实现
+ |' E0 l2 o- e0 t对称密码从实现原理上可以分为两种:分组密码和序列密码。前者将明文切分为定长数据块作为加密单位,应用最为广泛。后者则只对一个字节进行加密,且密码不断变化,只用在一些特定领域,如数字媒介的加密等。# ?+ W) U- S/ @! Z. U/ p
代表算法包括 DES、3DES、AES、IDEA 等。: f, _& f& z3 N3 Q  I5 \8 z
DES(Data Encryption Standard):经典的分组加密算法,1977 年由美国联邦信息处理标准(FIPS)所采用 FIPS-46-3,将 64 位明文加密为 64 位的密文,其密钥长度为 56 位 + 8 位校验。现在已经很容易被暴力破解。
) H6 G! {' \. \8 j  ]2 P8 M! ^3DES:三重 DES 操作:加密 –> 解密 –> 加密,处理过程和加密强度优于 DES,但现在也被认为不够安全。9 q# b) R# ~9 L6 [' L& m( Z
AES(Advanced Encryption Standard):美国国家标准研究所(NIST)采用取代 DES 成为对称加密实现的标准,1997~2000 年 NIST 从 15 个候选算法中评选 Rijndael 算法(由比利时密码学家 Joan Daemon 和 Vincent Rijmen 发明)作为 AES,标准为 FIPS-197。AES 也是分组算法,分组长度为 128、192、256 位三种。AES 的优势在于处理速度快,整个过程可以数学化描述,目前尚未有有效的破解手段。
( \$ C, e, E( G3 i注:分组加密每次只能处理固定长度的明文,因此过长的内容需要采用一定模式进行加密,《实用密码学》中推荐使用 密文分组链接(Cipher Block Chain,CBC)、计数器(Counter,CTR)模式。2 V- O! o9 E8 C8 `
Neo中的AES" C1 S3 ^3 U2 k) m% r5 ~
在钱包的加解密中,使用了该算法。
( |- o' \. v7 r/ k* J下图的代码在/neo/Wallets/Wallet.cs中,NEP是neo enhancement proposal的意思。参数nep2就是符合这个格式的一个Neo钱包文件。
# y4 {: K7 I1 |4 i, ^4 M$ s6 q7 P9 ~) i- X5 s) k, l
拿到私钥; L7 Y( B, M( s
具体的过程,后面再仔细研究分享出来。6 f( Q/ K8 y1 R% [- n! e! v7 _( L
非对称加密
8 m) \# w6 X# m& u! D  j6 `8 Q非对称加密是现代密码学历史上最为伟大的发明,可以很好的解决对称加密需要的提前分发密钥问题。顾名思义,加密密钥和解密密钥是不同的,分别称为公钥和私钥。公钥一般是公开的,人人可获取的,私钥一般是个人自己持有,不能被他人获取。
* S2 d; C, R4 ^非对称加密优缺点
. k5 X4 C$ L- L, M' w9 z1.优点是公私钥分开,不安全通道也可使用。# V6 y( g7 b' V% N! Q* r
2.缺点是加解密速度慢,一般比对称加解密算法慢两到三个数量级;同时加密强度相比对称加密要差。- N5 W& o8 ^2 j! Q! l/ Z
非对称加密代表算法% |9 H$ G5 N& @9 l! ^
非对称加密算法的安全性往往需要基于数学问题来保障,目前主要有基于大数质因子分解、离散对数、椭圆曲线等几种思路。
4 ^: u8 x% w' v( R1 B" r, D代表算法包括:RSA、ElGamal、椭圆曲线(Elliptic Curve Crytosystems,ECC)系列算法。
0 b/ |; ^9 u7 [1.RSA:经典的公钥算法,1978 年由 Ron Rivest、Adi Shamir、Leonard Adleman 共同提出,三人于 2002 年获得图灵奖。算法利用了对大数进行质因子分解困难的特性,但目前还没有数学证明两者难度等价,或许存在未知算法在不进行大数分解的前提下解密。. ]3 I$ ?( v/ n* j# w7 {3 t% i; k
2.Diffie-Hellman 密钥交换:基于离散对数无法快速求解,可以在不安全的通道上,双方协商一个公共密钥。: e) Q5 @5 V, c) s/ V( ]
3.ElGamal:由 Taher ElGamal 设计,利用了模运算下求离散对数困难的特性。被应用在 PGP 等安全工具中。
  V" r0 R% ^3 r, T1 b5 k( F4.椭圆曲线算法(Elliptic curve cryptography,ECC):现代备受关注的算法系列,基于对椭圆曲线上特定点进行特殊乘法逆运算难以计算的特性。最早在 1985 年由 Neal Koblitz 和 Victor Miller 分别独立提出。ECC 系列算法一般被认为具备较高的安全性,但加解密计算过程往往比较费时。一般适用于签名场景或密钥协商,不适于大量数据的加解密。; ~% K/ c8 a/ w) e1 ^& |5 D
RSA 算法等已被认为不够安全,一般推荐采用椭圆曲线系列算法。
$ b; p3 I1 w+ z/ ?Neo中的数字签名算法
# d( I* r7 z$ ?在Neo中,也使用了非对称加密算法,我们通过代码来看看是如何使用的。  I+ d3 s) k) l  Q# m/ z7 c' A
public virtual WalletAccount Import(X509Certificate2 cert)
8 y0 l, p" V, Z7 G4 R9 O        {
( E  ~( W( C  M            byte[] privateKey;$ U( V& z: X% @; @/ q# u
            using (ECDsa ecdsa = cert.GetECDsaPrivateKey())3 I  i7 N/ f, N  \" A
            {( @2 b0 ~& i! _. T: V" b
                privateKey = ecdsa.ExportParameters(true).D;
: L3 y# i. H0 l+ q            }% Y+ B8 `) q3 A$ ~5 Z/ U- D
            WalletAccount account = CreateAccount(privateKey);4 v: T9 X; i" R% G8 s( Y* L  v6 }
            Array.Clear(privateKey, 0, privateKey.Length);
( L1 d8 z. @! y0 ~: ]+ k/ _9 t3 Z            return account;
1 y" d7 a: A, b9 B        }- \/ |! }; S% Z* T: R4 ~
X509Certificate2是数字证书,和我们在https里面使用的是一样的,从里面拿出私钥后,创建钱包。
$ S5 |. ]$ k4 l$ D2 ]9 b% _总结
; v' ]$ @% f: ~+ x) a$ S5 m! E9 k目前只是简单的介绍了一下Neo中加密算法的使用情况,这些加密算法的原理和实现也是很有意思的,后面看看怎么实现的,再分享出来。; Y. t' k; ?# J5 _2 C
参考资料
) |1 W1 f1 M. {4 c- u区块链技术指南) b* H. B8 P- y
MurMurHash3, an ultra fast hash algorithm for C# / .NET
2 g- U$ L6 f3 [scrypt算法的前世今生(从零开始学区块链 192)/ |8 I, Z, t+ c7 }% G+ H# L
Wallet import format
BitMere.com 比特池塘系信息发布平台,比特池塘仅提供信息存储空间服务。
声明:该文观点仅代表作者本人,本文不代表比特池塘立场,且不构成建议,请谨慎对待。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

成为第一个吐槽的人

空港训港j 小学生
  • 粉丝

    0

  • 关注

    0

  • 主题

    3