cubefs

Форк
0
143 строки · 3.9 Кб
1
// Copyright 2022 The CubeFS Authors.
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
6
//
7
//     http://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
12
// implied. See the License for the specific language governing
13
// permissions and limitations under the License.
14

15
package uptoken
16

17
import (
18
	"bytes"
19
	"crypto/hmac"
20
	"crypto/sha1"
21
	"encoding/binary"
22
	"encoding/hex"
23
	"time"
24

25
	"github.com/cubefs/cubefs/blobstore/common/proto"
26
)
27

28
const (
29
	// TokenSize max size of token array
30
	// clusterID + vid + bid + count + time + size
31
	TokenSize = 4 + 4 + 10 + 5 + 5 + 5
32
)
33

34
// UploadToken token between alloc and putat
35
// [0:8]   hmac (8) first 8 bytes of sha1 summary
36
// [8:16]  minBid (8) in the SliceInfo
37
// [16:20] count (4) in the SliceInfo
38
// [20:24] time (4) expired unix utc time, 0 means not expired
39
type UploadToken struct {
40
	Data   [TokenSize]byte
41
	Offset uint8
42
}
43

44
// IsValidBid returns the bid is valid or not
45
func (t *UploadToken) IsValidBid(bid proto.BlobID) bool {
46
	minBid, n := binary.Uvarint(t.Data[8:])
47
	if n <= 0 {
48
		return false
49
	}
50
	count, n := binary.Uvarint(t.Data[8+n:])
51
	if n <= 0 {
52
		return false
53
	}
54
	return minBid <= uint64(bid) && uint64(bid) < minBid+count
55
}
56

57
// IsValid returns the token is valid or not
58
func (t *UploadToken) IsValid(clusterID proto.ClusterID, vid proto.Vid, bid proto.BlobID,
59
	size uint32, secretKey []byte) bool {
60
	var (
61
		minBid, count, expiredTime uint64
62
		ok                         bool
63
	)
64

65
	data := t.Data[:]
66
	offset := 8
67
	next := func() (uint64, bool) {
68
		val, n := binary.Uvarint(data[offset:])
69
		if n <= 0 {
70
			return 0, false
71
		}
72
		offset += n
73
		return val, true
74
	}
75

76
	if minBid, ok = next(); !ok {
77
		return false
78
	}
79
	if count, ok = next(); !ok {
80
		return false
81
	}
82
	if !(minBid <= uint64(bid) && uint64(bid) < minBid+count) {
83
		return false
84
	}
85

86
	if expiredTime, ok = next(); !ok {
87
		return false
88
	}
89
	if expiredTime != 0 && time.Now().UTC().Unix() > int64(expiredTime) {
90
		return false
91
	}
92

93
	token := newUploadToken(clusterID, vid, proto.BlobID(minBid),
94
		uint32(count), size, uint32(expiredTime), secretKey)
95
	return bytes.Equal(token.Data[0:8], t.Data[0:8])
96
}
97

98
// NewUploadToken returns a token corresponding one SliceInfo in Location with expiration
99
// expiration = 0 means not expired forever
100
func NewUploadToken(clusterID proto.ClusterID, vid proto.Vid, bid proto.BlobID,
101
	count, size uint32, expiration time.Duration, secretKey []byte) UploadToken {
102
	expiredTime := uint32(0)
103
	if expiration != time.Duration(0) {
104
		expiredTime = uint32(time.Now().Add(expiration).UTC().Unix())
105
	}
106
	return newUploadToken(clusterID, vid, bid, count, size, expiredTime, secretKey)
107
}
108

109
func newUploadToken(clusterID proto.ClusterID, vid proto.Vid, bid proto.BlobID,
110
	count, size uint32, expiredTime uint32, secretKey []byte) UploadToken {
111
	var token UploadToken
112
	data := token.Data[:]
113
	binary.BigEndian.PutUint32(data[0:4], uint32(clusterID))
114
	binary.BigEndian.PutUint32(data[4:8], uint32(vid))
115

116
	offset := 8
117
	offset += binary.PutUvarint(data[offset:], uint64(bid))
118
	offset += binary.PutUvarint(data[offset:], uint64(count))
119
	offset += binary.PutUvarint(data[offset:], uint64(expiredTime))
120
	token.Offset = uint8(offset)
121
	offset += binary.PutUvarint(data[offset:], uint64(size))
122

123
	h := hmac.New(sha1.New, secretKey)
124
	h.Write(data[:offset])
125
	sum := h.Sum(nil)
126

127
	// replace clusterID and vid
128
	copy(data[0:8], sum[0:8])
129
	return token
130
}
131

132
// EncodeToken encode token to string
133
func EncodeToken(token UploadToken) string {
134
	return hex.EncodeToString(token.Data[:token.Offset])
135
}
136

137
// DecodeToken decode token from string
138
func DecodeToken(s string) UploadToken {
139
	var token UploadToken
140
	src, _ := hex.DecodeString(s)
141
	token.Offset = uint8(copy(token.Data[:], src))
142
	return token
143
}
144

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.