ec7e17ffa6
Simplifies a lot of code and removes some duplication. Unfortunately I had to move test_util random functions in same commit to avoid cycle dependencies. One of these random functions was also used in core/transaction testing, to simplify things I've just dropped it there and used a static string (which is nice to have for a test anyway). There is still sha256 left in wallet (but it needs to pass Hash structure into the signing function).
117 lines
2.5 KiB
Go
117 lines
2.5 KiB
Go
package crypto
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"math/big"
|
|
|
|
"github.com/CityOfZion/neo-go/pkg/crypto/hash"
|
|
"github.com/pkg/errors"
|
|
)
|
|
|
|
const prefix rune = '1'
|
|
|
|
var decodeMap = map[rune]int64{
|
|
'1': 0, '2': 1, '3': 2, '4': 3, '5': 4,
|
|
'6': 5, '7': 6, '8': 7, '9': 8, 'A': 9,
|
|
'B': 10, 'C': 11, 'D': 12, 'E': 13, 'F': 14,
|
|
'G': 15, 'H': 16, 'J': 17, 'K': 18, 'L': 19,
|
|
'M': 20, 'N': 21, 'P': 22, 'Q': 23, 'R': 24,
|
|
'S': 25, 'T': 26, 'U': 27, 'V': 28, 'W': 29,
|
|
'X': 30, 'Y': 31, 'Z': 32, 'a': 33, 'b': 34,
|
|
'c': 35, 'd': 36, 'e': 37, 'f': 38, 'g': 39,
|
|
'h': 40, 'i': 41, 'j': 42, 'k': 43, 'm': 44,
|
|
'n': 45, 'o': 46, 'p': 47, 'q': 48, 'r': 49,
|
|
's': 50, 't': 51, 'u': 52, 'v': 53, 'w': 54,
|
|
'x': 55, 'y': 56, 'z': 57,
|
|
}
|
|
|
|
// Base58Decode decodes the base58 encoded string.
|
|
func Base58Decode(s string) ([]byte, error) {
|
|
var (
|
|
startIndex = 0
|
|
zero = 0
|
|
)
|
|
for i, c := range s {
|
|
if c == prefix {
|
|
zero++
|
|
} else {
|
|
startIndex = i
|
|
break
|
|
}
|
|
}
|
|
|
|
var (
|
|
n = big.NewInt(0)
|
|
div = big.NewInt(58)
|
|
)
|
|
for _, c := range s[startIndex:] {
|
|
charIndex, ok := decodeMap[c]
|
|
if !ok {
|
|
return nil, fmt.Errorf(
|
|
"invalid character '%c' when decoding this base58 string: '%s'", c, s,
|
|
)
|
|
}
|
|
n.Add(n.Mul(n, div), big.NewInt(charIndex))
|
|
}
|
|
|
|
out := n.Bytes()
|
|
buf := make([]byte, zero+len(out))
|
|
copy(buf[zero:], out)
|
|
|
|
return buf, nil
|
|
}
|
|
|
|
// Base58Encode encodes a byte slice to be a base58 encoded string.
|
|
func Base58Encode(bytes []byte) string {
|
|
var (
|
|
lookupTable = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
|
|
x = new(big.Int).SetBytes(bytes)
|
|
r = new(big.Int)
|
|
m = big.NewInt(58)
|
|
zero = big.NewInt(0)
|
|
encoded string
|
|
)
|
|
|
|
for x.Cmp(zero) > 0 {
|
|
x.QuoRem(x, m, r)
|
|
encoded = string(lookupTable[r.Int64()]) + encoded
|
|
}
|
|
|
|
return encoded
|
|
}
|
|
|
|
// Base58CheckDecode decodes the given string.
|
|
func Base58CheckDecode(s string) (b []byte, err error) {
|
|
b, err = Base58Decode(s)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
for i := 0; i < len(s); i++ {
|
|
if s[i] != '1' {
|
|
break
|
|
}
|
|
b = append([]byte{0x00}, b...)
|
|
}
|
|
|
|
if len(b) < 5 {
|
|
return nil, errors.New("invalid base-58 check string: missing checksum.")
|
|
}
|
|
|
|
if !bytes.Equal(hash.Checksum(b[:len(b)-4]), b[len(b)-4:]) {
|
|
return nil, errors.New("invalid base-58 check string: invalid checksum.")
|
|
}
|
|
|
|
// Strip the 4 byte long hash.
|
|
b = b[:len(b)-4]
|
|
|
|
return b, nil
|
|
}
|
|
|
|
// Base58checkEncode encodes b into a base-58 check encoded string.
|
|
func Base58CheckEncode(b []byte) string {
|
|
b = append(b, hash.Checksum(b)...)
|
|
|
|
return Base58Encode(b)
|
|
}
|