OSDN Git Service

add package
[bytom/vapor.git] / vendor / github.com / multiformats / go-multihash / multihash.go
1 // Package multihash is the Go implementation of
2 // https://github.com/multiformats/multihash, or self-describing
3 // hashes.
4 package multihash
5
6 import (
7         "encoding/binary"
8         "encoding/hex"
9         "errors"
10         "fmt"
11         "math"
12
13         b58 "github.com/mr-tron/base58/base58"
14 )
15
16 // errors
17 var (
18         ErrUnknownCode      = errors.New("unknown multihash code")
19         ErrTooShort         = errors.New("multihash too short. must be >= 2 bytes")
20         ErrTooLong          = errors.New("multihash too long. must be < 129 bytes")
21         ErrLenNotSupported  = errors.New("multihash does not yet support digests longer than 127 bytes")
22         ErrInvalidMultihash = errors.New("input isn't valid multihash")
23
24         ErrVarintBufferShort = errors.New("uvarint: buffer too small")
25         ErrVarintTooLong     = errors.New("uvarint: varint too big (max 64bit)")
26 )
27
28 // ErrInconsistentLen is returned when a decoded multihash has an inconsistent length
29 type ErrInconsistentLen struct {
30         dm *DecodedMultihash
31 }
32
33 func (e ErrInconsistentLen) Error() string {
34         return fmt.Sprintf("multihash length inconsistent: %v", e.dm)
35 }
36
37 // constants
38 const (
39         ID         = 0x00
40         SHA1       = 0x11
41         SHA2_256   = 0x12
42         SHA2_512   = 0x13
43         SHA3_224   = 0x17
44         SHA3_256   = 0x16
45         SHA3_384   = 0x15
46         SHA3_512   = 0x14
47         SHA3       = SHA3_512
48         KECCAK_224 = 0x1A
49         KECCAK_256 = 0x1B
50         KECCAK_384 = 0x1C
51         KECCAK_512 = 0x1D
52
53         SHAKE_128 = 0x18
54         SHAKE_256 = 0x19
55
56         BLAKE2B_MIN = 0xb201
57         BLAKE2B_MAX = 0xb240
58         BLAKE2S_MIN = 0xb241
59         BLAKE2S_MAX = 0xb260
60
61         DBL_SHA2_256 = 0x56
62
63         MURMUR3 = 0x22
64
65         X11 = 0x1100
66 )
67
68 func init() {
69         // Add blake2b (64 codes)
70         for c := uint64(BLAKE2B_MIN); c <= BLAKE2B_MAX; c++ {
71                 n := c - BLAKE2B_MIN + 1
72                 name := fmt.Sprintf("blake2b-%d", n*8)
73                 Names[name] = c
74                 Codes[c] = name
75                 DefaultLengths[c] = int(n)
76         }
77
78         // Add blake2s (32 codes)
79         for c := uint64(BLAKE2S_MIN); c <= BLAKE2S_MAX; c++ {
80                 n := c - BLAKE2S_MIN + 1
81                 name := fmt.Sprintf("blake2s-%d", n*8)
82                 Names[name] = c
83                 Codes[c] = name
84                 DefaultLengths[c] = int(n)
85         }
86 }
87
88 // Names maps the name of a hash to the code
89 var Names = map[string]uint64{
90         "id":           ID,
91         "sha1":         SHA1,
92         "sha2-256":     SHA2_256,
93         "sha2-512":     SHA2_512,
94         "sha3":         SHA3_512,
95         "sha3-224":     SHA3_224,
96         "sha3-256":     SHA3_256,
97         "sha3-384":     SHA3_384,
98         "sha3-512":     SHA3_512,
99         "dbl-sha2-256": DBL_SHA2_256,
100         "murmur3":      MURMUR3,
101         "keccak-224":   KECCAK_224,
102         "keccak-256":   KECCAK_256,
103         "keccak-384":   KECCAK_384,
104         "keccak-512":   KECCAK_512,
105         "shake-128":    SHAKE_128,
106         "shake-256":    SHAKE_256,
107         "x11":          X11,
108 }
109
110 // Codes maps a hash code to it's name
111 var Codes = map[uint64]string{
112         ID:           "id",
113         SHA1:         "sha1",
114         SHA2_256:     "sha2-256",
115         SHA2_512:     "sha2-512",
116         SHA3_224:     "sha3-224",
117         SHA3_256:     "sha3-256",
118         SHA3_384:     "sha3-384",
119         SHA3_512:     "sha3-512",
120         DBL_SHA2_256: "dbl-sha2-256",
121         MURMUR3:      "murmur3",
122         KECCAK_224:   "keccak-224",
123         KECCAK_256:   "keccak-256",
124         KECCAK_384:   "keccak-384",
125         KECCAK_512:   "keccak-512",
126         SHAKE_128:    "shake-128",
127         SHAKE_256:    "shake-256",
128         X11:          "x11",
129 }
130
131 // DefaultLengths maps a hash code to it's default length
132 var DefaultLengths = map[uint64]int{
133         ID:           -1,
134         SHA1:         20,
135         SHA2_256:     32,
136         SHA2_512:     64,
137         SHA3_224:     28,
138         SHA3_256:     32,
139         SHA3_384:     48,
140         SHA3_512:     64,
141         DBL_SHA2_256: 32,
142         KECCAK_224:   28,
143         KECCAK_256:   32,
144         MURMUR3:      4,
145         KECCAK_384:   48,
146         KECCAK_512:   64,
147         SHAKE_128:    32,
148         SHAKE_256:    64,
149         X11:          64,
150 }
151
152 func uvarint(buf []byte) (uint64, []byte, error) {
153         n, c := binary.Uvarint(buf)
154
155         if c == 0 {
156                 return n, buf, ErrVarintBufferShort
157         } else if c < 0 {
158                 return n, buf[-c:], ErrVarintTooLong
159         } else {
160                 return n, buf[c:], nil
161         }
162 }
163
164 // DecodedMultihash represents a parsed multihash and allows
165 // easy access to the different parts of a multihash.
166 type DecodedMultihash struct {
167         Code   uint64
168         Name   string
169         Length int    // Length is just int as it is type of len() opearator
170         Digest []byte // Digest holds the raw multihash bytes
171 }
172
173 // Multihash is byte slice with the following form:
174 // <hash function code><digest size><hash function output>.
175 // See the spec for more information.
176 type Multihash []byte
177
178 // HexString returns the hex-encoded representation of a multihash.
179 func (m *Multihash) HexString() string {
180         return hex.EncodeToString([]byte(*m))
181 }
182
183 // String is an alias to HexString().
184 func (m *Multihash) String() string {
185         return m.HexString()
186 }
187
188 // FromHexString parses a hex-encoded multihash.
189 func FromHexString(s string) (Multihash, error) {
190         b, err := hex.DecodeString(s)
191         if err != nil {
192                 return Multihash{}, err
193         }
194
195         return Cast(b)
196 }
197
198 // B58String returns the B58-encoded representation of a multihash.
199 func (m Multihash) B58String() string {
200         return b58.Encode([]byte(m))
201 }
202
203 // FromB58String parses a B58-encoded multihash.
204 func FromB58String(s string) (m Multihash, err error) {
205         b, err := b58.Decode(s)
206         if err != nil {
207                 return Multihash{}, ErrInvalidMultihash
208         }
209
210         return Cast(b)
211 }
212
213 // Cast casts a buffer onto a multihash, and returns an error
214 // if it does not work.
215 func Cast(buf []byte) (Multihash, error) {
216         dm, err := Decode(buf)
217         if err != nil {
218                 return Multihash{}, err
219         }
220
221         if !ValidCode(dm.Code) {
222                 return Multihash{}, ErrUnknownCode
223         }
224
225         return Multihash(buf), nil
226 }
227
228 // Decode parses multihash bytes into a DecodedMultihash.
229 func Decode(buf []byte) (*DecodedMultihash, error) {
230
231         if len(buf) < 2 {
232                 return nil, ErrTooShort
233         }
234
235         var err error
236         var code, length uint64
237
238         code, buf, err = uvarint(buf)
239         if err != nil {
240                 return nil, err
241         }
242
243         length, buf, err = uvarint(buf)
244         if err != nil {
245                 return nil, err
246         }
247
248         if length > math.MaxInt32 {
249                 return nil, errors.New("digest too long, supporting only <= 2^31-1")
250         }
251
252         dm := &DecodedMultihash{
253                 Code:   code,
254                 Name:   Codes[code],
255                 Length: int(length),
256                 Digest: buf,
257         }
258
259         if len(dm.Digest) != dm.Length {
260                 return nil, ErrInconsistentLen{dm}
261         }
262
263         return dm, nil
264 }
265
266 // Encode a hash digest along with the specified function code.
267 // Note: the length is derived from the length of the digest itself.
268 func Encode(buf []byte, code uint64) ([]byte, error) {
269
270         if !ValidCode(code) {
271                 return nil, ErrUnknownCode
272         }
273
274         start := make([]byte, 2*binary.MaxVarintLen64, 2*binary.MaxVarintLen64+len(buf))
275         spot := start
276         n := binary.PutUvarint(spot, code)
277         spot = start[n:]
278         n += binary.PutUvarint(spot, uint64(len(buf)))
279
280         return append(start[:n], buf...), nil
281 }
282
283 // EncodeName is like Encode() but providing a string name
284 // instead of a numeric code. See Names for allowed values.
285 func EncodeName(buf []byte, name string) ([]byte, error) {
286         return Encode(buf, Names[name])
287 }
288
289 // ValidCode checks whether a multihash code is valid.
290 func ValidCode(code uint64) bool {
291         _, ok := Codes[code]
292         return ok
293 }