github.com/yinchengtsinghua/golang-Eos-dpos-Ethereum@v0.0.0-20190121132951-92cc4225ed8e/crypto/ecies/ecies.go (about)

     1  
     2  //此源码被清华学神尹成大魔王专业翻译分析并修改
     3  //尹成QQ77025077
     4  //尹成微信18510341407
     5  //尹成所在QQ群721929980
     6  //尹成邮箱 yinc13@mails.tsinghua.edu.cn
     7  //尹成毕业于清华大学,微软区块链领域全球最有价值专家
     8  //https://mvp.microsoft.com/zh-cn/PublicProfile/4033620
     9  //版权所有(c)2013 Kyle Isom<kyle@tyrfingr.is>
    10  //版权所有(c)2012 The Go作者。版权所有。
    11  //
    12  //以源和二进制形式重新分配和使用,有或无
    13  //允许修改,前提是以下条件
    14  //遇见:
    15  //
    16  //*源代码的再分配必须保留上述版权。
    17  //注意,此条件列表和以下免责声明。
    18  //*二进制形式的再分配必须复制上述内容
    19  //版权声明、此条件列表和以下免责声明
    20  //在提供的文件和/或其他材料中,
    21  //分布。
    22  //*无论是谷歌公司的名称还是其
    23  //贡献者可用于支持或推广源自
    24  //本软件未经事先明确书面许可。
    25  //
    26  //本软件由版权所有者和贡献者提供。
    27  //“原样”和任何明示或暗示的保证,包括但不包括
    28  //仅限于对适销性和适用性的暗示保证
    29  //不承认特定目的。在任何情况下,版权
    30  //所有人或出资人对任何直接、间接、附带的,
    31  //特殊、惩戒性或后果性损害(包括但不包括
    32  //仅限于采购替代货物或服务;使用损失,
    33  //数据或利润;或业务中断),无论如何引起的
    34  //责任理论,无论是合同责任、严格责任还是侵权责任。
    35  //(包括疏忽或其他)因使用不当而引起的
    36  //即使已告知此类损坏的可能性。
    37  
    38  package ecies
    39  
    40  import (
    41  	"crypto/cipher"
    42  	"crypto/ecdsa"
    43  	"crypto/elliptic"
    44  	"crypto/hmac"
    45  	"crypto/subtle"
    46  	"fmt"
    47  	"hash"
    48  	"io"
    49  	"math/big"
    50  )
    51  
    52  var (
    53  	ErrImport                     = fmt.Errorf("ecies: failed to import key")
    54  	ErrInvalidCurve               = fmt.Errorf("ecies: invalid elliptic curve")
    55  	ErrInvalidParams              = fmt.Errorf("ecies: invalid ECIES parameters")
    56  	ErrInvalidPublicKey           = fmt.Errorf("ecies: invalid public key")
    57  	ErrSharedKeyIsPointAtInfinity = fmt.Errorf("ecies: shared key is point at infinity")
    58  	ErrSharedKeyTooBig            = fmt.Errorf("ecies: shared key params are too big")
    59  )
    60  
    61  //公钥是椭圆曲线公钥的表示形式。
    62  type PublicKey struct {
    63  	X *big.Int
    64  	Y *big.Int
    65  	elliptic.Curve
    66  	Params *ECIESParams
    67  }
    68  
    69  //将ECIES公钥导出为ECDSA公钥。
    70  func (pub *PublicKey) ExportECDSA() *ecdsa.PublicKey {
    71  	return &ecdsa.PublicKey{Curve: pub.Curve, X: pub.X, Y: pub.Y}
    72  }
    73  
    74  //将ECDSA公钥导入为特定的公钥。
    75  func ImportECDSAPublic(pub *ecdsa.PublicKey) *PublicKey {
    76  	return &PublicKey{
    77  		X:      pub.X,
    78  		Y:      pub.Y,
    79  		Curve:  pub.Curve,
    80  		Params: ParamsFromCurve(pub.Curve),
    81  	}
    82  }
    83  
    84  //private key是椭圆曲线私钥的表示。
    85  type PrivateKey struct {
    86  	PublicKey
    87  	D *big.Int
    88  }
    89  
    90  //将ECIES私钥导出为ECDSA私钥。
    91  func (prv *PrivateKey) ExportECDSA() *ecdsa.PrivateKey {
    92  	pub := &prv.PublicKey
    93  	pubECDSA := pub.ExportECDSA()
    94  	return &ecdsa.PrivateKey{PublicKey: *pubECDSA, D: prv.D}
    95  }
    96  
    97  //将ECDSA私钥导入为ECIES私钥。
    98  func ImportECDSA(prv *ecdsa.PrivateKey) *PrivateKey {
    99  	pub := ImportECDSAPublic(&prv.PublicKey)
   100  	return &PrivateKey{*pub, prv.D}
   101  }
   102  
   103  //生成椭圆曲线公钥/私钥对。如果参数为零,
   104  //将选择该键的推荐默认参数。
   105  func GenerateKey(rand io.Reader, curve elliptic.Curve, params *ECIESParams) (prv *PrivateKey, err error) {
   106  	pb, x, y, err := elliptic.GenerateKey(curve, rand)
   107  	if err != nil {
   108  		return
   109  	}
   110  	prv = new(PrivateKey)
   111  	prv.PublicKey.X = x
   112  	prv.PublicKey.Y = y
   113  	prv.PublicKey.Curve = curve
   114  	prv.D = new(big.Int).SetBytes(pb)
   115  	if params == nil {
   116  		params = ParamsFromCurve(curve)
   117  	}
   118  	prv.PublicKey.Params = params
   119  	return
   120  }
   121  
   122  //MaxSharedKeyLength返回共享密钥的最大长度
   123  //可以生成公钥。
   124  func MaxSharedKeyLength(pub *PublicKey) int {
   125  	return (pub.Curve.Params().BitSize + 7) / 8
   126  }
   127  
   128  //用于建立加密密钥的ECDH密钥协议方法。
   129  func (prv *PrivateKey) GenerateShared(pub *PublicKey, skLen, macLen int) (sk []byte, err error) {
   130  	if prv.PublicKey.Curve != pub.Curve {
   131  		return nil, ErrInvalidCurve
   132  	}
   133  	if skLen+macLen > MaxSharedKeyLength(pub) {
   134  		return nil, ErrSharedKeyTooBig
   135  	}
   136  
   137  	x, _ := pub.Curve.ScalarMult(pub.X, pub.Y, prv.D.Bytes())
   138  	if x == nil {
   139  		return nil, ErrSharedKeyIsPointAtInfinity
   140  	}
   141  
   142  	sk = make([]byte, skLen+macLen)
   143  	skBytes := x.Bytes()
   144  	copy(sk[len(sk)-len(skBytes):], skBytes)
   145  	return sk, nil
   146  }
   147  
   148  var (
   149  	ErrKeyDataTooLong = fmt.Errorf("ecies: can't supply requested key data")
   150  	ErrSharedTooLong  = fmt.Errorf("ecies: shared secret is too long")
   151  	ErrInvalidMessage = fmt.Errorf("ecies: invalid message")
   152  )
   153  
   154  var (
   155  	big2To32   = new(big.Int).Exp(big.NewInt(2), big.NewInt(32), nil)
   156  	big2To32M1 = new(big.Int).Sub(big2To32, big.NewInt(1))
   157  )
   158  
   159  func incCounter(ctr []byte) {
   160  	if ctr[3]++; ctr[3] != 0 {
   161  		return
   162  	}
   163  	if ctr[2]++; ctr[2] != 0 {
   164  		return
   165  	}
   166  	if ctr[1]++; ctr[1] != 0 {
   167  		return
   168  	}
   169  	if ctr[0]++; ctr[0] != 0 {
   170  		return
   171  	}
   172  }
   173  
   174  //NIST SP 800-56串联密钥派生函数(见第5.8.1节)。
   175  func concatKDF(hash hash.Hash, z, s1 []byte, kdLen int) (k []byte, err error) {
   176  	if s1 == nil {
   177  		s1 = make([]byte, 0)
   178  	}
   179  
   180  	reps := ((kdLen + 7) * 8) / (hash.BlockSize() * 8)
   181  	if big.NewInt(int64(reps)).Cmp(big2To32M1) > 0 {
   182  		fmt.Println(big2To32M1)
   183  		return nil, ErrKeyDataTooLong
   184  	}
   185  
   186  	counter := []byte{0, 0, 0, 1}
   187  	k = make([]byte, 0)
   188  
   189  	for i := 0; i <= reps; i++ {
   190  		hash.Write(counter)
   191  		hash.Write(z)
   192  		hash.Write(s1)
   193  		k = append(k, hash.Sum(nil)...)
   194  		hash.Reset()
   195  		incCounter(counter)
   196  	}
   197  
   198  	k = k[:kdLen]
   199  	return
   200  }
   201  
   202  //message tag根据
   203  //秒1,3.5。
   204  func messageTag(hash func() hash.Hash, km, msg, shared []byte) []byte {
   205  	mac := hmac.New(hash, km)
   206  	mac.Write(msg)
   207  	mac.Write(shared)
   208  	tag := mac.Sum(nil)
   209  	return tag
   210  }
   211  
   212  //为ctr模式生成初始化向量。
   213  func generateIV(params *ECIESParams, rand io.Reader) (iv []byte, err error) {
   214  	iv = make([]byte, params.BlockSize)
   215  	_, err = io.ReadFull(rand, iv)
   216  	return
   217  }
   218  
   219  //symeencrypt使用中指定的块密码执行ctr加密
   220  //参数。
   221  func symEncrypt(rand io.Reader, params *ECIESParams, key, m []byte) (ct []byte, err error) {
   222  	c, err := params.Cipher(key)
   223  	if err != nil {
   224  		return
   225  	}
   226  
   227  	iv, err := generateIV(params, rand)
   228  	if err != nil {
   229  		return
   230  	}
   231  	ctr := cipher.NewCTR(c, iv)
   232  
   233  	ct = make([]byte, len(m)+params.BlockSize)
   234  	copy(ct, iv)
   235  	ctr.XORKeyStream(ct[params.BlockSize:], m)
   236  	return
   237  }
   238  
   239  //symmdecrypt使用中指定的块密码执行ctr解密。
   240  //参数
   241  func symDecrypt(params *ECIESParams, key, ct []byte) (m []byte, err error) {
   242  	c, err := params.Cipher(key)
   243  	if err != nil {
   244  		return
   245  	}
   246  
   247  	ctr := cipher.NewCTR(c, ct[:params.BlockSize])
   248  
   249  	m = make([]byte, len(ct)-params.BlockSize)
   250  	ctr.XORKeyStream(m, ct[params.BlockSize:])
   251  	return
   252  }
   253  
   254  //Encrypt使用第1节5.1中指定的ECIES对消息进行加密。
   255  //
   256  //s1和s2包含不属于结果的共享信息
   257  //密文。s1被输入到键派生中,s2被输入到mac中。如果
   258  //未使用共享信息参数,它们应为零。
   259  func Encrypt(rand io.Reader, pub *PublicKey, m, s1, s2 []byte) (ct []byte, err error) {
   260  	params := pub.Params
   261  	if params == nil {
   262  		if params = ParamsFromCurve(pub.Curve); params == nil {
   263  			err = ErrUnsupportedECIESParameters
   264  			return
   265  		}
   266  	}
   267  	R, err := GenerateKey(rand, pub.Curve, params)
   268  	if err != nil {
   269  		return
   270  	}
   271  
   272  	hash := params.Hash()
   273  	z, err := R.GenerateShared(pub, params.KeyLen, params.KeyLen)
   274  	if err != nil {
   275  		return
   276  	}
   277  	K, err := concatKDF(hash, z, s1, params.KeyLen+params.KeyLen)
   278  	if err != nil {
   279  		return
   280  	}
   281  	Ke := K[:params.KeyLen]
   282  	Km := K[params.KeyLen:]
   283  	hash.Write(Km)
   284  	Km = hash.Sum(nil)
   285  	hash.Reset()
   286  
   287  	em, err := symEncrypt(rand, params, Ke, m)
   288  	if err != nil || len(em) <= params.BlockSize {
   289  		return
   290  	}
   291  
   292  	d := messageTag(params.Hash, Km, em, s2)
   293  
   294  	Rb := elliptic.Marshal(pub.Curve, R.PublicKey.X, R.PublicKey.Y)
   295  	ct = make([]byte, len(Rb)+len(em)+len(d))
   296  	copy(ct, Rb)
   297  	copy(ct[len(Rb):], em)
   298  	copy(ct[len(Rb)+len(em):], d)
   299  	return
   300  }
   301  
   302  //解密-解密特定的密文。
   303  func (prv *PrivateKey) Decrypt(c, s1, s2 []byte) (m []byte, err error) {
   304  	if len(c) == 0 {
   305  		return nil, ErrInvalidMessage
   306  	}
   307  	params := prv.PublicKey.Params
   308  	if params == nil {
   309  		if params = ParamsFromCurve(prv.PublicKey.Curve); params == nil {
   310  			err = ErrUnsupportedECIESParameters
   311  			return
   312  		}
   313  	}
   314  	hash := params.Hash()
   315  
   316  	var (
   317  		rLen   int
   318  		hLen   int = hash.Size()
   319  		mStart int
   320  		mEnd   int
   321  	)
   322  
   323  	switch c[0] {
   324  	case 2, 3, 4:
   325  		rLen = (prv.PublicKey.Curve.Params().BitSize + 7) / 4
   326  		if len(c) < (rLen + hLen + 1) {
   327  			err = ErrInvalidMessage
   328  			return
   329  		}
   330  	default:
   331  		err = ErrInvalidPublicKey
   332  		return
   333  	}
   334  
   335  	mStart = rLen
   336  	mEnd = len(c) - hLen
   337  
   338  	R := new(PublicKey)
   339  	R.Curve = prv.PublicKey.Curve
   340  	R.X, R.Y = elliptic.Unmarshal(R.Curve, c[:rLen])
   341  	if R.X == nil {
   342  		err = ErrInvalidPublicKey
   343  		return
   344  	}
   345  	if !R.Curve.IsOnCurve(R.X, R.Y) {
   346  		err = ErrInvalidCurve
   347  		return
   348  	}
   349  
   350  	z, err := prv.GenerateShared(R, params.KeyLen, params.KeyLen)
   351  	if err != nil {
   352  		return
   353  	}
   354  
   355  	K, err := concatKDF(hash, z, s1, params.KeyLen+params.KeyLen)
   356  	if err != nil {
   357  		return
   358  	}
   359  
   360  	Ke := K[:params.KeyLen]
   361  	Km := K[params.KeyLen:]
   362  	hash.Write(Km)
   363  	Km = hash.Sum(nil)
   364  	hash.Reset()
   365  
   366  	d := messageTag(params.Hash, Km, c[mStart:mEnd], s2)
   367  	if subtle.ConstantTimeCompare(c[mEnd:], d) != 1 {
   368  		err = ErrInvalidMessage
   369  		return
   370  	}
   371  
   372  	m, err = symDecrypt(params, Ke, c[mStart:mEnd])
   373  	return
   374  }