You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
141 lines
3.8 KiB
141 lines
3.8 KiB
package coscrypto
|
|
|
|
import (
|
|
"crypto/rand"
|
|
"encoding/binary"
|
|
"fmt"
|
|
"io"
|
|
math_rand "math/rand"
|
|
"time"
|
|
)
|
|
|
|
const (
|
|
COSClientSideEncryptionKey string = "x-cos-meta-client-side-encryption-key"
|
|
COSClientSideEncryptionStart = "x-cos-meta-client-side-encryption-start"
|
|
COSClientSideEncryptionCekAlg = "x-cos-meta-client-side-encryption-cek-alg"
|
|
COSClientSideEncryptionWrapAlg = "x-cos-meta-client-side-encryption-wrap-alg"
|
|
COSClientSideEncryptionMatDesc = "x-cos-meta-client-side-encryption-matdesc"
|
|
COSClientSideEncryptionUnencryptedContentLength = "x-cos-meta-client-side-encryption-unencrypted-content-length"
|
|
COSClientSideEncryptionUnencryptedContentMD5 = "x-cos-meta-client-side-encryption-unencrypted-content-md5"
|
|
COSClientSideEncryptionDataSize = "x-cos-meta-client-side-encryption-data-size"
|
|
COSClientSideEncryptionPartSize = "x-cos-meta-client-side-encryption-part-size"
|
|
UserAgent = "User-Agent"
|
|
)
|
|
|
|
const (
|
|
CosKmsCryptoWrap = "KMS/TencentCloud"
|
|
AesCtrAlgorithm = "AES/CTR/NoPadding"
|
|
EncryptionUaSuffix = "COSEncryptionClient"
|
|
)
|
|
|
|
type MasterCipher interface {
|
|
Encrypt([]byte) ([]byte, error)
|
|
Decrypt([]byte) ([]byte, error)
|
|
GetWrapAlgorithm() string
|
|
GetMatDesc() string
|
|
}
|
|
|
|
type ContentCipherBuilder interface {
|
|
ContentCipher() (ContentCipher, error)
|
|
ContentCipherEnv(Envelope) (ContentCipher, error)
|
|
GetMatDesc() string
|
|
}
|
|
|
|
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
|
|
}
|
|
|
|
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)
|
|
}
|
|
|
|
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: | nonce: 8 bytes | Serial number: 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
|
|
}
|