Browse Source

cse-kms done

master
jojoliang 4 years ago
parent
commit
05379cf310
  1. 2
      cos.go
  2. 33
      crypto/crypto_object.go
  3. 8
      crypto/crypto_object_part_test.go
  4. 8
      crypto/crypto_object_test.go
  5. 1
      crypto/master_kms_cipher.go
  6. 11
      example/crypto/crypto_sample.go
  7. 6
      object.go

2
cos.go

@ -22,7 +22,7 @@ import (
const (
// Version current go sdk version
Version = "0.7.25"
Version = "0.7.26"
userAgent = "cos-go-sdk-v5/" + Version
contentTypeXML = "application/xml"
defaultServiceBaseURL = "http://service.cos.myqcloud.com"

33
crypto/crypto_object.go

@ -2,6 +2,7 @@ package coscrypto
import (
"context"
"encoding/base64"
"fmt"
"github.com/tencentyun/cos-go-sdk-v5"
"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...)
}
envelope := getEnvelopeFromHeader(&meta.Header)
envelope, err := getEnvelopeFromHeader(&meta.Header)
if err != nil {
return nil, err
}
if !envelope.IsValid() {
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 != "" {
header.Add(COSClientSideEncryptionMatDesc, cd.MatDesc)
}
header.Add(COSClientSideEncryptionKey, string(cd.EncryptedKey))
header.Add(COSClientSideEncryptionStart, string(cd.EncryptedIV))
// encrypted key
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(COSClientSideEncryptionCekAlg, cd.CEKAlgorithm)
}
func getEnvelopeFromHeader(header *http.Header) Envelope {
func getEnvelopeFromHeader(header *http.Header) (Envelope, error) {
var envelope Envelope
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)
decodedIV, err := base64.StdEncoding.DecodeString(envelope.IV)
if err != nil {
return envelope, err
}
envelope.IV = string(decodedIV)
envelope.MatDesc = header.Get(COSClientSideEncryptionMatDesc)
envelope.WrapAlg = header.Get(COSClientSideEncryptionWrapAlg)
envelope.CEKAlg = header.Get(COSClientSideEncryptionCekAlg)
return envelope
return envelope, nil
}
func isEncrypted(header *http.Header) bool {

8
crypto/crypto_object_part_test.go

@ -104,10 +104,14 @@ func (s *CosTestSuite) TestMultiUpload_DecryptWithKey() {
resp, err = s.CClient.Object.Head(context.Background(), name, nil)
assert.Nil(s.T(), err, "HeadObject Failed")
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)
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")
iv, err := s.Master.Decrypt([]byte(cipherIV))
iv, err := s.Master.Decrypt(cipherIVbs)
assert.Nil(s.T(), err, "Master Decrypt Failed")
// 手动解密

8
crypto/crypto_object_test.go

@ -75,10 +75,14 @@ func (s *CosTestSuite) TestPutGetDeleteObject_DecryptWithKey_10MB() {
resp, err := s.CClient.Object.Head(context.Background(), name, nil)
assert.Nil(s.T(), err, "HeadObject Failed")
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)
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")
iv, err := s.Master.Decrypt([]byte(cipherIV))
iv, err := s.Master.Decrypt(cipherIVbs)
assert.Nil(s.T(), err, "Master Decrypt Failed")
// 正常读取

1
crypto/master_kms_cipher.go

@ -64,6 +64,7 @@ func (kc *MasterKMSCipher) Encrypt(plaintext []byte) ([]byte, error) {
if err != nil {
return nil, err
}
// https://cloud.tencent.com/document/product/573/34420 文档有误,返回的结果并没有base64编码
return []byte(*resp.Response.CiphertextBlob), nil
}

11
example/crypto/crypto_sample.go

@ -39,6 +39,13 @@ func log_status(err error) {
os.Exit(1)
}
func cos_max(x, y int64) int64 {
if x > y {
return x
}
return y
}
func simple_put_object() {
u, _ := url.Parse("https://test-1259654469.cos.ap-guangzhou.myqcloud.com")
b := &cos.BaseURL{BucketURL: u}
@ -196,7 +203,7 @@ func multi_put_object() {
cryptoCtx := coscrypto.CryptoContext{
DataSize: contentLength,
// 每个分块需要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)
log_status(err)
@ -268,7 +275,7 @@ func multi_put_object_from_file() {
cryptoCtx := coscrypto.CryptoContext{
DataSize: contentLength,
// 每个分块需要16字节对齐
PartSize: (contentLength / 16 / 3) * 16,
PartSize: cos_max(1024*1024, (contentLength/16/3)*16),
}
// 切分数据
_, chunks, _, err := cos.SplitFileIntoChunks(filepath, cryptoCtx.PartSize)

6
object.go

@ -768,6 +768,9 @@ func SplitFileIntoChunks(filePath string, partSize int64) (int64, []Chunk, int,
}
var partNum int64
if partSize > 0 {
if partSize < 1024*1024 {
return 0, nil, 0, errors.New("partSize>=1048576 is required")
}
partNum = stat.Size() / partSize
if partNum >= 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) {
var partNum int64
if partSize > 0 {
if partSize < 1024*1024 {
return nil, 0, errors.New("partSize>=1048576 is required")
}
partNum = totalBytes / partSize
if partNum >= 10000 {
return nil, 0, errors.New("Too manry parts, out of 10000")

Loading…
Cancel
Save