cse-kms done

This commit is contained in:
jojoliang
2021-05-14 19:54:02 +08:00
parent 70b911ba7e
commit 05379cf310
7 changed files with 57 additions and 12 deletions

2
cos.go
View File

@@ -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"

View File

@@ -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 {

View File

@@ -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")
// 手动解密 // 手动解密

View File

@@ -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")
// 正常读取 // 正常读取

View File

@@ -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
} }

View File

@@ -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)

View File

@@ -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")