forked from aliyun/aliyun-oss-go-sdk
-
Notifications
You must be signed in to change notification settings - Fork 0
/
crypto_type.go
128 lines (106 loc) · 2.97 KB
/
crypto_type.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
package osscrypto
import (
"crypto/rand"
"encoding/binary"
"fmt"
"io"
math_rand "math/rand"
"time"
)
// MasterCipher encrypt or decrpt CipherData
// support master key: rsa && ali kms
type MasterCipher interface {
Encrypt([]byte) ([]byte, error)
Decrypt([]byte) ([]byte, error)
GetWrapAlgorithm() string
GetMatDesc() string
}
// ContentCipherBuilder is used to create ContentCipher for encryting object's data
type ContentCipherBuilder interface {
ContentCipher() (ContentCipher, error)
ContentCipherEnv(Envelope) (ContentCipher, error)
GetMatDesc() string
}
// ContentCipher is used to encrypt or decrypt object's data
type ContentCipher interface {
EncryptContent(io.Reader) (io.ReadCloser, error)
DecryptContent(io.Reader) (io.ReadCloser, error)
Clone(cd CipherData) (ContentCipher, error)
GetEncryptedLen(int64) int64
GetCipherData() *CipherData
GetAlignLen() int
}
// Envelope is stored in oss object's meta
type Envelope struct {
IV string
CipherKey string
MatDesc string
WrapAlg string
CEKAlg string
UnencryptedMD5 string
UnencryptedContentLen string
}
func (el Envelope) IsValid() bool {
return len(el.IV) > 0 &&
len(el.CipherKey) > 0 &&
len(el.WrapAlg) > 0 &&
len(el.CEKAlg) > 0
}
func (el Envelope) String() string {
return fmt.Sprintf("IV=%s&CipherKey=%s&WrapAlg=%s&CEKAlg=%s", el.IV, el.CipherKey, el.WrapAlg, el.CEKAlg)
}
// CipherData is secret key information
type CipherData struct {
IV []byte
Key []byte
MatDesc string
WrapAlgorithm string
CEKAlgorithm string
EncryptedIV []byte
EncryptedKey []byte
}
func (cd *CipherData) RandomKeyIv(keyLen int, ivLen int) error {
math_rand.Seed(time.Now().UnixNano())
// Key
cd.Key = make([]byte, keyLen)
if _, err := io.ReadFull(rand.Reader, cd.Key); err != nil {
return err
}
// sizeof uint64
if ivLen < 8 {
return fmt.Errorf("ivLen:%d less than 8", ivLen)
}
// IV:reserve 8 bytes
cd.IV = make([]byte, ivLen)
if _, err := io.ReadFull(rand.Reader, cd.IV[0:ivLen-8]); err != nil {
return err
}
// only use 4 byte,in order not to overflow when SeekIV()
randNumber := math_rand.Uint32()
cd.SetIV(uint64(randNumber))
return nil
}
func (cd *CipherData) SetIV(iv uint64) {
ivLen := len(cd.IV)
binary.BigEndian.PutUint64(cd.IV[ivLen-8:], iv)
}
func (cd *CipherData) GetIV() uint64 {
ivLen := len(cd.IV)
return binary.BigEndian.Uint64(cd.IV[ivLen-8:])
}
func (cd *CipherData) SeekIV(startPos uint64) {
cd.SetIV(cd.GetIV() + startPos/uint64(len(cd.IV)))
}
func (cd *CipherData) Clone() CipherData {
var cloneCd CipherData
cloneCd = *cd
cloneCd.Key = make([]byte, len(cd.Key))
copy(cloneCd.Key, cd.Key)
cloneCd.IV = make([]byte, len(cd.IV))
copy(cloneCd.IV, cd.IV)
cloneCd.EncryptedIV = make([]byte, len(cd.EncryptedIV))
copy(cloneCd.EncryptedIV, cd.EncryptedIV)
cloneCd.EncryptedKey = make([]byte, len(cd.EncryptedKey))
copy(cloneCd.EncryptedKey, cd.EncryptedKey)
return cloneCd
}