-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathreader.go
144 lines (122 loc) · 3.21 KB
/
reader.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
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
package cryptoStorage
import (
"bytes"
"crypto/aes"
"crypto/cipher"
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"encoding/json"
"encoding/pem"
"fmt"
"hash"
"io"
"github.com/pingcap/tidb/br/pkg/storage"
)
// 解密
func rsaDecrypt(privateData []byte, cipherText []byte) ([]byte, error) {
block, _ := pem.Decode(privateData)
if block == nil {
return nil, fmt.Errorf("private key error")
}
priv, err := x509.ParsePKCS1PrivateKey(block.Bytes)
if err != nil {
return nil, err
}
return rsa.DecryptPKCS1v15(rand.Reader, priv, cipherText)
}
type CryptoReader struct {
storage.ExternalFileReader
header *Header
buf []byte
stream cipher.Stream
hash hash.Hash
}
func NewCryptoReader(dataReader storage.ExternalFileReader, privateData []byte, header *Header) (*CryptoReader, error) {
r := &CryptoReader{
ExternalFileReader: dataReader,
header: header,
hash: NewHash(header.HashType),
}
if r.hash == nil {
return nil, fmt.Errorf("hash is nil")
}
err := r.initCipherStream(privateData)
if err != nil {
return nil, fmt.Errorf("init reader failed: %w", err)
}
return r, nil
}
func (r *CryptoReader) initCipherStream(privateData []byte) error {
if len(r.header.EncKey) == 0 {
return fmt.Errorf("header enc key is nil")
}
key, err := rsaDecrypt(privateData, r.header.EncKey)
if err != nil {
return fmt.Errorf("decrypt key failed: %w", err)
}
r.header.key = key
block, err := aes.NewCipher(key)
if err != nil {
return fmt.Errorf("new cipher failed: %w", err)
}
r.stream = cipher.NewCFBDecrypter(block, r.header.IV)
return nil
}
// Read: 实现Reader接口
func (r *CryptoReader) Read(p []byte) (int, error) {
buf := r.buf // 使用缓存
if n := len(p); n > len(buf) {
buf = make([]byte, n)
} else {
buf = buf[:n]
}
n, externalErr := r.ExternalFileReader.Read(buf)
if externalErr != nil && externalErr != io.EOF {
return n, externalErr
}
// 如果获取值不到buf的长度,只解密真实的值
r.stream.XORKeyStream(p[:n], buf[:n])
_, err := r.hash.Write(p[:n])
if err != nil {
return 0, fmt.Errorf("write hash failed: %w", err)
}
// 先计算最后一段加密值,再返回 EOF
if externalErr == io.EOF {
return n, io.EOF
}
return n, nil
}
func (r *CryptoReader) Close() error {
return r.ExternalFileReader.Close()
}
func (r *CryptoReader) CheckSum() error {
hash := r.hash.Sum(nil)
// 计算hash结果与文件头的进行比较,不相等表示文件被篡改
if !bytes.Equal(r.header.Hash, hash) {
return fmt.Errorf("decrypt failed: file hash not match, header: %x, decrypted: %x", r.header.Hash, hash)
}
return nil
}
func (r *CryptoReader) Header() *Header {
return r.header
}
func ReadHeaderV1(headerReader storage.ExternalFileReader) (*Header, error) {
header, err := ParseHeaderV1(headerReader)
if err != nil {
return nil, fmt.Errorf("parse header failed: %w", err)
}
return header, nil
}
func ReadHeaderV2(headerReader storage.ExternalFileReader) (*Header, error) {
data, err := io.ReadAll(headerReader)
if err != nil {
return nil, fmt.Errorf("read header failed: %w", err)
}
header := &Header{}
err = json.Unmarshal(data, header)
if err != nil {
return nil, fmt.Errorf("parse header failed: %w", err)
}
return header, nil
}