cse-kms done
This commit is contained in:
2
cos.go
2
cos.go
@@ -22,7 +22,7 @@ import (
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
// Version current go sdk version
|
// Version current go sdk version
|
||||||
Version = "0.7.25"
|
Version = "0.7.26"
|
||||||
userAgent = "cos-go-sdk-v5/" + Version
|
userAgent = "cos-go-sdk-v5/" + Version
|
||||||
contentTypeXML = "application/xml"
|
contentTypeXML = "application/xml"
|
||||||
defaultServiceBaseURL = "http://service.cos.myqcloud.com"
|
defaultServiceBaseURL = "http://service.cos.myqcloud.com"
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package coscrypto
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"encoding/base64"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/tencentyun/cos-go-sdk-v5"
|
"github.com/tencentyun/cos-go-sdk-v5"
|
||||||
"io"
|
"io"
|
||||||
@@ -107,7 +108,10 @@ func (s *CryptoObjectService) Get(ctx context.Context, name string, opt *cos.Obj
|
|||||||
return s.ObjectService.Get(ctx, name, opt, id...)
|
return s.ObjectService.Get(ctx, name, opt, id...)
|
||||||
}
|
}
|
||||||
|
|
||||||
envelope := getEnvelopeFromHeader(&meta.Header)
|
envelope, err := getEnvelopeFromHeader(&meta.Header)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
if !envelope.IsValid() {
|
if !envelope.IsValid() {
|
||||||
return nil, fmt.Errorf("get envelope from header failed, object:%v", name)
|
return nil, fmt.Errorf("get envelope from header failed, object:%v", name)
|
||||||
}
|
}
|
||||||
@@ -208,20 +212,39 @@ func addCryptoHeaders(header *http.Header, cd *CipherData) {
|
|||||||
if cd.MatDesc != "" {
|
if cd.MatDesc != "" {
|
||||||
header.Add(COSClientSideEncryptionMatDesc, cd.MatDesc)
|
header.Add(COSClientSideEncryptionMatDesc, cd.MatDesc)
|
||||||
}
|
}
|
||||||
header.Add(COSClientSideEncryptionKey, string(cd.EncryptedKey))
|
// encrypted key
|
||||||
header.Add(COSClientSideEncryptionStart, string(cd.EncryptedIV))
|
strEncryptedKey := base64.StdEncoding.EncodeToString(cd.EncryptedKey)
|
||||||
|
header.Add(COSClientSideEncryptionKey, strEncryptedKey)
|
||||||
|
|
||||||
|
// encrypted iv
|
||||||
|
strEncryptedIV := base64.StdEncoding.EncodeToString(cd.EncryptedIV)
|
||||||
|
header.Add(COSClientSideEncryptionStart, strEncryptedIV)
|
||||||
|
|
||||||
header.Add(COSClientSideEncryptionWrapAlg, cd.WrapAlgorithm)
|
header.Add(COSClientSideEncryptionWrapAlg, cd.WrapAlgorithm)
|
||||||
header.Add(COSClientSideEncryptionCekAlg, cd.CEKAlgorithm)
|
header.Add(COSClientSideEncryptionCekAlg, cd.CEKAlgorithm)
|
||||||
}
|
}
|
||||||
|
|
||||||
func getEnvelopeFromHeader(header *http.Header) Envelope {
|
func getEnvelopeFromHeader(header *http.Header) (Envelope, error) {
|
||||||
var envelope Envelope
|
var envelope Envelope
|
||||||
|
|
||||||
envelope.CipherKey = header.Get(COSClientSideEncryptionKey)
|
envelope.CipherKey = header.Get(COSClientSideEncryptionKey)
|
||||||
|
decodedKey, err := base64.StdEncoding.DecodeString(envelope.CipherKey)
|
||||||
|
if err != nil {
|
||||||
|
return envelope, err
|
||||||
|
}
|
||||||
|
envelope.CipherKey = string(decodedKey)
|
||||||
|
|
||||||
envelope.IV = header.Get(COSClientSideEncryptionStart)
|
envelope.IV = header.Get(COSClientSideEncryptionStart)
|
||||||
|
decodedIV, err := base64.StdEncoding.DecodeString(envelope.IV)
|
||||||
|
if err != nil {
|
||||||
|
return envelope, err
|
||||||
|
}
|
||||||
|
envelope.IV = string(decodedIV)
|
||||||
|
|
||||||
envelope.MatDesc = header.Get(COSClientSideEncryptionMatDesc)
|
envelope.MatDesc = header.Get(COSClientSideEncryptionMatDesc)
|
||||||
envelope.WrapAlg = header.Get(COSClientSideEncryptionWrapAlg)
|
envelope.WrapAlg = header.Get(COSClientSideEncryptionWrapAlg)
|
||||||
envelope.CEKAlg = header.Get(COSClientSideEncryptionCekAlg)
|
envelope.CEKAlg = header.Get(COSClientSideEncryptionCekAlg)
|
||||||
return envelope
|
return envelope, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func isEncrypted(header *http.Header) bool {
|
func isEncrypted(header *http.Header) bool {
|
||||||
|
|||||||
@@ -104,10 +104,14 @@ func (s *CosTestSuite) TestMultiUpload_DecryptWithKey() {
|
|||||||
resp, err = s.CClient.Object.Head(context.Background(), name, nil)
|
resp, err = s.CClient.Object.Head(context.Background(), name, nil)
|
||||||
assert.Nil(s.T(), err, "HeadObject Failed")
|
assert.Nil(s.T(), err, "HeadObject Failed")
|
||||||
cipherKey := resp.Header.Get(coscrypto.COSClientSideEncryptionKey)
|
cipherKey := resp.Header.Get(coscrypto.COSClientSideEncryptionKey)
|
||||||
|
cipherKeybs, err := base64.StdEncoding.DecodeString(cipherKey)
|
||||||
|
assert.Nil(s.T(), err, "base64 Decode Failed")
|
||||||
cipherIV := resp.Header.Get(coscrypto.COSClientSideEncryptionStart)
|
cipherIV := resp.Header.Get(coscrypto.COSClientSideEncryptionStart)
|
||||||
key, err := s.Master.Decrypt([]byte(cipherKey))
|
cipherIVbs, err := base64.StdEncoding.DecodeString(cipherIV)
|
||||||
|
assert.Nil(s.T(), err, "base64 Decode Failed")
|
||||||
|
key, err := s.Master.Decrypt(cipherKeybs)
|
||||||
assert.Nil(s.T(), err, "Master Decrypt Failed")
|
assert.Nil(s.T(), err, "Master Decrypt Failed")
|
||||||
iv, err := s.Master.Decrypt([]byte(cipherIV))
|
iv, err := s.Master.Decrypt(cipherIVbs)
|
||||||
assert.Nil(s.T(), err, "Master Decrypt Failed")
|
assert.Nil(s.T(), err, "Master Decrypt Failed")
|
||||||
|
|
||||||
// 手动解密
|
// 手动解密
|
||||||
|
|||||||
@@ -75,10 +75,14 @@ func (s *CosTestSuite) TestPutGetDeleteObject_DecryptWithKey_10MB() {
|
|||||||
resp, err := s.CClient.Object.Head(context.Background(), name, nil)
|
resp, err := s.CClient.Object.Head(context.Background(), name, nil)
|
||||||
assert.Nil(s.T(), err, "HeadObject Failed")
|
assert.Nil(s.T(), err, "HeadObject Failed")
|
||||||
cipherKey := resp.Header.Get(coscrypto.COSClientSideEncryptionKey)
|
cipherKey := resp.Header.Get(coscrypto.COSClientSideEncryptionKey)
|
||||||
|
cipherKeybs, err := base64.StdEncoding.DecodeString(cipherKey)
|
||||||
|
assert.Nil(s.T(), err, "base64 Decode Failed")
|
||||||
cipherIV := resp.Header.Get(coscrypto.COSClientSideEncryptionStart)
|
cipherIV := resp.Header.Get(coscrypto.COSClientSideEncryptionStart)
|
||||||
key, err := s.Master.Decrypt([]byte(cipherKey))
|
cipherIVbs, err := base64.StdEncoding.DecodeString(cipherIV)
|
||||||
|
assert.Nil(s.T(), err, "base64 Decode Failed")
|
||||||
|
key, err := s.Master.Decrypt(cipherKeybs)
|
||||||
assert.Nil(s.T(), err, "Master Decrypt Failed")
|
assert.Nil(s.T(), err, "Master Decrypt Failed")
|
||||||
iv, err := s.Master.Decrypt([]byte(cipherIV))
|
iv, err := s.Master.Decrypt(cipherIVbs)
|
||||||
assert.Nil(s.T(), err, "Master Decrypt Failed")
|
assert.Nil(s.T(), err, "Master Decrypt Failed")
|
||||||
|
|
||||||
// 正常读取
|
// 正常读取
|
||||||
|
|||||||
@@ -64,6 +64,7 @@ func (kc *MasterKMSCipher) Encrypt(plaintext []byte) ([]byte, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
// https://cloud.tencent.com/document/product/573/34420 文档有误,返回的结果并没有base64编码
|
||||||
return []byte(*resp.Response.CiphertextBlob), nil
|
return []byte(*resp.Response.CiphertextBlob), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -39,6 +39,13 @@ func log_status(err error) {
|
|||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func cos_max(x, y int64) int64 {
|
||||||
|
if x > y {
|
||||||
|
return x
|
||||||
|
}
|
||||||
|
return y
|
||||||
|
}
|
||||||
|
|
||||||
func simple_put_object() {
|
func simple_put_object() {
|
||||||
u, _ := url.Parse("https://test-1259654469.cos.ap-guangzhou.myqcloud.com")
|
u, _ := url.Parse("https://test-1259654469.cos.ap-guangzhou.myqcloud.com")
|
||||||
b := &cos.BaseURL{BucketURL: u}
|
b := &cos.BaseURL{BucketURL: u}
|
||||||
@@ -196,7 +203,7 @@ func multi_put_object() {
|
|||||||
cryptoCtx := coscrypto.CryptoContext{
|
cryptoCtx := coscrypto.CryptoContext{
|
||||||
DataSize: contentLength,
|
DataSize: contentLength,
|
||||||
// 每个分块需要16字节对齐
|
// 每个分块需要16字节对齐
|
||||||
PartSize: (contentLength / 16 / 3) * 16,
|
PartSize: cos_max(1024*1024, (contentLength/16/3)*16),
|
||||||
}
|
}
|
||||||
v, _, err := client.Object.InitiateMultipartUpload(context.Background(), name, nil, &cryptoCtx)
|
v, _, err := client.Object.InitiateMultipartUpload(context.Background(), name, nil, &cryptoCtx)
|
||||||
log_status(err)
|
log_status(err)
|
||||||
@@ -268,7 +275,7 @@ func multi_put_object_from_file() {
|
|||||||
cryptoCtx := coscrypto.CryptoContext{
|
cryptoCtx := coscrypto.CryptoContext{
|
||||||
DataSize: contentLength,
|
DataSize: contentLength,
|
||||||
// 每个分块需要16字节对齐
|
// 每个分块需要16字节对齐
|
||||||
PartSize: (contentLength / 16 / 3) * 16,
|
PartSize: cos_max(1024*1024, (contentLength/16/3)*16),
|
||||||
}
|
}
|
||||||
// 切分数据
|
// 切分数据
|
||||||
_, chunks, _, err := cos.SplitFileIntoChunks(filepath, cryptoCtx.PartSize)
|
_, chunks, _, err := cos.SplitFileIntoChunks(filepath, cryptoCtx.PartSize)
|
||||||
|
|||||||
@@ -768,6 +768,9 @@ func SplitFileIntoChunks(filePath string, partSize int64) (int64, []Chunk, int,
|
|||||||
}
|
}
|
||||||
var partNum int64
|
var partNum int64
|
||||||
if partSize > 0 {
|
if partSize > 0 {
|
||||||
|
if partSize < 1024*1024 {
|
||||||
|
return 0, nil, 0, errors.New("partSize>=1048576 is required")
|
||||||
|
}
|
||||||
partNum = stat.Size() / partSize
|
partNum = stat.Size() / partSize
|
||||||
if partNum >= 10000 {
|
if partNum >= 10000 {
|
||||||
return 0, nil, 0, errors.New("Too many parts, out of 10000")
|
return 0, nil, 0, errors.New("Too many parts, out of 10000")
|
||||||
@@ -1066,6 +1069,9 @@ func (s *ObjectService) Upload(ctx context.Context, name string, filepath string
|
|||||||
func SplitSizeIntoChunks(totalBytes int64, partSize int64) ([]Chunk, int, error) {
|
func SplitSizeIntoChunks(totalBytes int64, partSize int64) ([]Chunk, int, error) {
|
||||||
var partNum int64
|
var partNum int64
|
||||||
if partSize > 0 {
|
if partSize > 0 {
|
||||||
|
if partSize < 1024*1024 {
|
||||||
|
return nil, 0, errors.New("partSize>=1048576 is required")
|
||||||
|
}
|
||||||
partNum = totalBytes / partSize
|
partNum = totalBytes / partSize
|
||||||
if partNum >= 10000 {
|
if partNum >= 10000 {
|
||||||
return nil, 0, errors.New("Too manry parts, out of 10000")
|
return nil, 0, errors.New("Too manry parts, out of 10000")
|
||||||
|
|||||||
Reference in New Issue
Block a user