github.com/nspcc-dev/neo-go@v0.105.2-0.20240517133400-6be757af3eba/pkg/crypto/keys/wif.go (about)

     1  package keys
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  
     7  	"github.com/nspcc-dev/neo-go/pkg/encoding/base58"
     8  	"github.com/nspcc-dev/neo-go/pkg/util/slice"
     9  )
    10  
    11  const (
    12  	// WIFVersion is the version used to decode and encode WIF keys.
    13  	WIFVersion = 0x80
    14  )
    15  
    16  // WIF represents a wallet import format.
    17  type WIF struct {
    18  	// Version of the wallet import format. Default to 0x80.
    19  	Version byte
    20  
    21  	// Bool to determine if the WIF is compressed or not.
    22  	Compressed bool
    23  
    24  	// A reference to the PrivateKey which this WIF is created from.
    25  	PrivateKey *PrivateKey
    26  
    27  	// A string representation of the WIF.
    28  	S string
    29  }
    30  
    31  // WIFEncode encodes the given private key into a WIF string.
    32  func WIFEncode(key []byte, version byte, compressed bool) (s string, err error) {
    33  	if version == 0x00 {
    34  		version = WIFVersion
    35  	}
    36  	if len(key) != 32 {
    37  		return s, fmt.Errorf("invalid private key length: %d", len(key))
    38  	}
    39  
    40  	buf := new(bytes.Buffer)
    41  	buf.WriteByte(version)
    42  	buf.Write(key)
    43  	if compressed {
    44  		buf.WriteByte(0x01)
    45  	}
    46  
    47  	s = base58.CheckEncode(buf.Bytes())
    48  	return
    49  }
    50  
    51  // WIFDecode decodes the given WIF string into a WIF struct.
    52  func WIFDecode(wif string, version byte) (*WIF, error) {
    53  	b, err := base58.CheckDecode(wif)
    54  	if err != nil {
    55  		return nil, err
    56  	}
    57  	defer slice.Clean(b)
    58  
    59  	if version == 0x00 {
    60  		version = WIFVersion
    61  	}
    62  	w := &WIF{
    63  		Version: version,
    64  		S:       wif,
    65  	}
    66  	switch len(b) {
    67  	case 33: // OK, uncompressed public key.
    68  	case 34: // OK, compressed public key.
    69  		// Check the compression flag.
    70  		if b[33] != 0x01 {
    71  			return nil, fmt.Errorf("invalid compression flag %d expecting %d", b[33], 0x01)
    72  		}
    73  		w.Compressed = true
    74  	default:
    75  		return nil, fmt.Errorf("invalid WIF length %d, expecting 33 or 34", len(b))
    76  	}
    77  
    78  	if b[0] != version {
    79  		return nil, fmt.Errorf("invalid WIF version got %d, expected %d", b[0], version)
    80  	}
    81  
    82  	// Derive the PrivateKey.
    83  	w.PrivateKey, err = NewPrivateKeyFromBytes(b[1:33])
    84  	if err != nil {
    85  		return nil, err
    86  	}
    87  
    88  	return w, nil
    89  }