-
Notifications
You must be signed in to change notification settings - Fork 0
/
crypto.go
118 lines (96 loc) · 2.46 KB
/
crypto.go
1
2
3
4
5
6
7
8
9
10
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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
package crypto
import (
"bytes"
"crypto/sha256"
"errors"
"math/big"
"reflect"
"github.com/btcsuite/btcutil/base58"
)
const alphabet = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
//B58cencode encodes a byte array into base58 with prefix
func B58cencode(payload []byte, prefix []byte) string {
n := make([]byte, (len(prefix) + len(payload)))
copy(n, append(prefix, payload...))
b58c := Encode(n)
return b58c
}
// B58cdecode -
func B58cdecode(payload string, prefix []byte) []byte {
b58c, _ := Decode(payload)
return b58c[len(prefix):]
}
// Encode -
func Encode(dataBytes []byte) string {
// Performing SHA256 twice
sha256hash := sha256.New()
sha256hash.Write(dataBytes)
middleHash := sha256hash.Sum(nil)
sha256hash = sha256.New()
sha256hash.Write(middleHash)
hash := sha256hash.Sum(nil)
checksum := hash[:4]
dataBytes = append(dataBytes, checksum...)
// For all the "00" versions or any prepended zeros as base58 removes them
zeroCount := 0
for _, b := range dataBytes {
if b == 0 {
zeroCount++
} else {
break
}
}
// Performing base58 encoding
encoded := base58.Encode(dataBytes)
for i := 0; i < zeroCount; i++ {
encoded = "1" + encoded
}
return encoded
}
// Decode -
func Decode(encoded string) ([]byte, error) {
zeroCount := 0
for i := 0; i < len(encoded); i++ {
if encoded[i] == 49 {
zeroCount++
} else {
break
}
}
dataBytes, err := b58decode(encoded)
if err != nil {
return []byte{}, err
}
if len(dataBytes) <= 4 {
return []byte{}, errors.New("invalid decode length")
}
data, checksum := dataBytes[:len(dataBytes)-4], dataBytes[len(dataBytes)-4:]
for i := 0; i < zeroCount; i++ {
data = append([]byte{0}, data...)
}
// Performing SHA256 twice to validate checksum
sha256hash := sha256.New()
sha256hash.Write(data)
middleHash := sha256hash.Sum(nil)
sha256hash = sha256.New()
sha256hash.Write(middleHash)
hash := sha256hash.Sum(nil)
if !reflect.DeepEqual(checksum, hash[:4]) {
return []byte{}, errors.New("data and checksum don't match")
}
return data, nil
}
func b58decode(data string) ([]byte, error) {
decimalData := new(big.Int)
alphabetBytes := []byte(alphabet)
multiplier := big.NewInt(58)
for _, value := range data {
pos := bytes.IndexByte(alphabetBytes, byte(value))
if pos == -1 {
return nil, errors.New("character not found in alphabet")
}
decimalData.Mul(decimalData, multiplier)
decimalData.Add(decimalData, big.NewInt(int64(pos)))
}
return decimalData.Bytes(), nil
}