github.com/Bytom/bytom@v1.1.2-0.20210127130405-ae40204c0b09/crypto/ed25519/chainkd/chainkd.go (about)

     1  package chainkd
     2  
     3  import (
     4  	"crypto/hmac"
     5  	"crypto/rand"
     6  	"crypto/sha512"
     7  	"io"
     8  
     9  	"github.com/bytom/bytom/crypto/ed25519"
    10  	"github.com/bytom/bytom/crypto/ed25519/ecmath"
    11  )
    12  
    13  type (
    14  	//XPrv external private key
    15  	XPrv [64]byte
    16  	//XPub external public key
    17  	XPub [64]byte
    18  )
    19  
    20  // NewXPrv takes a source of random bytes and produces a new XPrv.
    21  // If r is nil, crypto/rand.Reader is used.
    22  func NewXPrv(r io.Reader) (xprv XPrv, err error) {
    23  	if r == nil {
    24  		r = rand.Reader
    25  	}
    26  	var entropy [64]byte
    27  	_, err = io.ReadFull(r, entropy[:])
    28  	if err != nil {
    29  		return xprv, err
    30  	}
    31  	return RootXPrv(entropy[:]), nil
    32  }
    33  
    34  // RootXPrv takes a seed binary string and produces a new xprv.
    35  func RootXPrv(seed []byte) (xprv XPrv) {
    36  	h := hmac.New(sha512.New, []byte{'R', 'o', 'o', 't'})
    37  	h.Write(seed)
    38  	h.Sum(xprv[:0])
    39  	pruneRootScalar(xprv[:32])
    40  	return
    41  }
    42  
    43  // XPub derives an extended public key from a given xprv.
    44  func (xprv XPrv) XPub() (xpub XPub) {
    45  	var scalar ecmath.Scalar
    46  	copy(scalar[:], xprv[:32])
    47  
    48  	var P ecmath.Point
    49  	P.ScMulBase(&scalar)
    50  	buf := P.Encode()
    51  
    52  	copy(xpub[:32], buf[:])
    53  	copy(xpub[32:], xprv[32:])
    54  
    55  	return
    56  }
    57  
    58  // Child derives a child xprv based on `selector` string and `hardened` flag.
    59  // If `hardened` is false, child xpub can be derived independently
    60  // from the parent xpub without using the parent xprv.
    61  // If `hardened` is true, child key can only be derived from the parent xprv.
    62  func (xprv XPrv) Child(sel []byte, hardened bool) XPrv {
    63  	if hardened {
    64  		return xprv.hardenedChild(sel)
    65  	}
    66  	return xprv.nonhardenedChild(sel)
    67  }
    68  
    69  func (xprv XPrv) hardenedChild(sel []byte) (res XPrv) {
    70  	h := hmac.New(sha512.New, xprv[32:])
    71  	h.Write([]byte{'H'})
    72  	h.Write(xprv[:32])
    73  	h.Write(sel)
    74  	h.Sum(res[:0])
    75  	pruneRootScalar(res[:32])
    76  	return
    77  }
    78  
    79  func (xprv XPrv) nonhardenedChild(sel []byte) (res XPrv) {
    80  	xpub := xprv.XPub()
    81  
    82  	h := hmac.New(sha512.New, xpub[32:])
    83  	h.Write([]byte{'N'})
    84  	h.Write(xpub[:32])
    85  	h.Write(sel)
    86  	h.Sum(res[:0])
    87  
    88  	pruneIntermediateScalar(res[:32])
    89  
    90  	// Unrolled the following loop:
    91  	// var carry int
    92  	// carry = 0
    93  	// for i := 0; i < 32; i++ {
    94  	//         sum := int(xprv[i]) + int(res[i]) + carry
    95  	//         res[i] = byte(sum & 0xff)
    96  	//         carry = (sum >> 8)
    97  	// }
    98  
    99  	sum := int(0)
   100  
   101  	sum = int(xprv[0]) + int(res[0]) + (sum >> 8)
   102  	res[0] = byte(sum & 0xff)
   103  	sum = int(xprv[1]) + int(res[1]) + (sum >> 8)
   104  	res[1] = byte(sum & 0xff)
   105  	sum = int(xprv[2]) + int(res[2]) + (sum >> 8)
   106  	res[2] = byte(sum & 0xff)
   107  	sum = int(xprv[3]) + int(res[3]) + (sum >> 8)
   108  	res[3] = byte(sum & 0xff)
   109  	sum = int(xprv[4]) + int(res[4]) + (sum >> 8)
   110  	res[4] = byte(sum & 0xff)
   111  	sum = int(xprv[5]) + int(res[5]) + (sum >> 8)
   112  	res[5] = byte(sum & 0xff)
   113  	sum = int(xprv[6]) + int(res[6]) + (sum >> 8)
   114  	res[6] = byte(sum & 0xff)
   115  	sum = int(xprv[7]) + int(res[7]) + (sum >> 8)
   116  	res[7] = byte(sum & 0xff)
   117  	sum = int(xprv[8]) + int(res[8]) + (sum >> 8)
   118  	res[8] = byte(sum & 0xff)
   119  	sum = int(xprv[9]) + int(res[9]) + (sum >> 8)
   120  	res[9] = byte(sum & 0xff)
   121  	sum = int(xprv[10]) + int(res[10]) + (sum >> 8)
   122  	res[10] = byte(sum & 0xff)
   123  	sum = int(xprv[11]) + int(res[11]) + (sum >> 8)
   124  	res[11] = byte(sum & 0xff)
   125  	sum = int(xprv[12]) + int(res[12]) + (sum >> 8)
   126  	res[12] = byte(sum & 0xff)
   127  	sum = int(xprv[13]) + int(res[13]) + (sum >> 8)
   128  	res[13] = byte(sum & 0xff)
   129  	sum = int(xprv[14]) + int(res[14]) + (sum >> 8)
   130  	res[14] = byte(sum & 0xff)
   131  	sum = int(xprv[15]) + int(res[15]) + (sum >> 8)
   132  	res[15] = byte(sum & 0xff)
   133  	sum = int(xprv[16]) + int(res[16]) + (sum >> 8)
   134  	res[16] = byte(sum & 0xff)
   135  	sum = int(xprv[17]) + int(res[17]) + (sum >> 8)
   136  	res[17] = byte(sum & 0xff)
   137  	sum = int(xprv[18]) + int(res[18]) + (sum >> 8)
   138  	res[18] = byte(sum & 0xff)
   139  	sum = int(xprv[19]) + int(res[19]) + (sum >> 8)
   140  	res[19] = byte(sum & 0xff)
   141  	sum = int(xprv[20]) + int(res[20]) + (sum >> 8)
   142  	res[20] = byte(sum & 0xff)
   143  	sum = int(xprv[21]) + int(res[21]) + (sum >> 8)
   144  	res[21] = byte(sum & 0xff)
   145  	sum = int(xprv[22]) + int(res[22]) + (sum >> 8)
   146  	res[22] = byte(sum & 0xff)
   147  	sum = int(xprv[23]) + int(res[23]) + (sum >> 8)
   148  	res[23] = byte(sum & 0xff)
   149  	sum = int(xprv[24]) + int(res[24]) + (sum >> 8)
   150  	res[24] = byte(sum & 0xff)
   151  	sum = int(xprv[25]) + int(res[25]) + (sum >> 8)
   152  	res[25] = byte(sum & 0xff)
   153  	sum = int(xprv[26]) + int(res[26]) + (sum >> 8)
   154  	res[26] = byte(sum & 0xff)
   155  	sum = int(xprv[27]) + int(res[27]) + (sum >> 8)
   156  	res[27] = byte(sum & 0xff)
   157  	sum = int(xprv[28]) + int(res[28]) + (sum >> 8)
   158  	res[28] = byte(sum & 0xff)
   159  	sum = int(xprv[29]) + int(res[29]) + (sum >> 8)
   160  	res[29] = byte(sum & 0xff)
   161  	sum = int(xprv[30]) + int(res[30]) + (sum >> 8)
   162  	res[30] = byte(sum & 0xff)
   163  	sum = int(xprv[31]) + int(res[31]) + (sum >> 8)
   164  	res[31] = byte(sum & 0xff)
   165  
   166  	if (sum >> 8) != 0 {
   167  		panic("sum does not fit in 256-bit int")
   168  	}
   169  	return
   170  }
   171  
   172  // Child derives a child xpub based on `selector` string.
   173  // The corresponding child xprv can be derived from the parent xprv
   174  // using non-hardened derivation: `parentxprv.Child(sel, false)`.
   175  func (xpub XPub) Child(sel []byte) (res XPub) {
   176  	h := hmac.New(sha512.New, xpub[32:])
   177  	h.Write([]byte{'N'})
   178  	h.Write(xpub[:32])
   179  	h.Write(sel)
   180  	h.Sum(res[:0])
   181  
   182  	pruneIntermediateScalar(res[:32])
   183  
   184  	var (
   185  		f ecmath.Scalar
   186  		F ecmath.Point
   187  	)
   188  	copy(f[:], res[:32])
   189  	F.ScMulBase(&f)
   190  
   191  	var (
   192  		pubkey [32]byte
   193  		P      ecmath.Point
   194  	)
   195  	copy(pubkey[:], xpub[:32])
   196  	_, ok := P.Decode(pubkey)
   197  	if !ok {
   198  		panic("XPub should have been validated on initialization")
   199  	}
   200  
   201  	P.Add(&P, &F)
   202  	pubkey = P.Encode()
   203  	copy(res[:32], pubkey[:])
   204  
   205  	return
   206  }
   207  
   208  // Derive generates a child xprv by recursively deriving
   209  // non-hardened child xprvs over the list of selectors:
   210  // `Derive([a,b,c,...]) == Child(a).Child(b).Child(c)...`
   211  func (xprv XPrv) Derive(path [][]byte) XPrv {
   212  	res := xprv
   213  	for _, p := range path {
   214  		res = res.Child(p, false)
   215  	}
   216  	return res
   217  }
   218  
   219  // Derive generates a child xpub by recursively deriving
   220  // non-hardened child xpubs over the list of selectors:
   221  // `Derive([a,b,c,...]) == Child(a).Child(b).Child(c)...`
   222  func (xpub XPub) Derive(path [][]byte) XPub {
   223  	res := xpub
   224  	for _, p := range path {
   225  		res = res.Child(p)
   226  	}
   227  	return res
   228  }
   229  
   230  // Sign creates an EdDSA signature using expanded private key
   231  // derived from the xprv.
   232  func (xprv XPrv) Sign(msg []byte) []byte {
   233  	return Ed25519InnerSign(xprv.ExpandedPrivateKey(), msg)
   234  }
   235  
   236  // Verify checks an EdDSA signature using public key
   237  // extracted from the first 32 bytes of the xpub.
   238  func (xpub XPub) Verify(msg []byte, sig []byte) bool {
   239  	return ed25519.Verify(xpub.PublicKey(), msg, sig)
   240  }
   241  
   242  // ExpandedPrivateKey generates a 64-byte key where
   243  // the first half is the scalar copied from xprv,
   244  // and the second half is the `prefix` is generated via PRF
   245  // from the xprv.
   246  func (xprv XPrv) ExpandedPrivateKey() ExpandedPrivateKey {
   247  	var res [64]byte
   248  	h := hmac.New(sha512.New, []byte{'E', 'x', 'p', 'a', 'n', 'd'})
   249  	h.Write(xprv[:])
   250  	h.Sum(res[:0])
   251  	copy(res[:32], xprv[:32])
   252  	return res[:]
   253  }
   254  
   255  // PublicKey extracts the ed25519 public key from an xpub.
   256  func (xpub XPub) PublicKey() ed25519.PublicKey {
   257  	return ed25519.PublicKey(xpub[:32])
   258  }
   259  
   260  // s must be >= 32 bytes long and gets rewritten in place.
   261  // This is NOT the same pruning as in Ed25519: it additionally clears the third
   262  // highest bit to ensure subkeys do not overflow the second highest bit.
   263  func pruneRootScalar(s []byte) {
   264  	s[0] &= 248
   265  	s[31] &= 31 // clear top 3 bits
   266  	s[31] |= 64 // set second highest bit
   267  }
   268  
   269  // Clears lowest 3 bits and highest 23 bits of `f`.
   270  func pruneIntermediateScalar(f []byte) {
   271  	f[0] &= 248 // clear bottom 3 bits
   272  	f[29] &= 1  // clear 7 high bits
   273  	f[30] = 0   // clear 8 bits
   274  	f[31] = 0   // clear 8 bits
   275  }