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

4 years ago
4 years ago
4 years ago
  1. package coscrypto
  2. import (
  3. "crypto/rand"
  4. "encoding/binary"
  5. "fmt"
  6. "io"
  7. math_rand "math/rand"
  8. "time"
  9. )
  10. const (
  11. COSClientSideEncryptionKey string = "x-cos-meta-client-side-encryption-key"
  12. COSClientSideEncryptionStart = "x-cos-meta-client-side-encryption-start"
  13. COSClientSideEncryptionCekAlg = "x-cos-meta-client-side-encryption-cek-alg"
  14. COSClientSideEncryptionWrapAlg = "x-cos-meta-client-side-encryption-wrap-alg"
  15. COSClientSideEncryptionMatDesc = "x-cos-meta-client-side-encryption-matdesc"
  16. COSClientSideEncryptionUnencryptedContentLength = "x-cos-meta-client-side-encryption-unencrypted-content-length"
  17. COSClientSideEncryptionUnencryptedContentMD5 = "x-cos-meta-client-side-encryption-unencrypted-content-md5"
  18. COSClientSideEncryptionDataSize = "x-cos-meta-client-side-encryption-data-size"
  19. COSClientSideEncryptionPartSize = "x-cos-meta-client-side-encryption-part-size"
  20. UserAgent = "User-Agent"
  21. )
  22. const (
  23. CosKmsCryptoWrap = "KMS/TencentCloud"
  24. AesCtrAlgorithm = "AES/CTR/NoPadding"
  25. EncryptionUaSuffix = "COSEncryptionClient"
  26. )
  27. type MasterCipher interface {
  28. Encrypt([]byte) ([]byte, error)
  29. Decrypt([]byte) ([]byte, error)
  30. GetWrapAlgorithm() string
  31. GetMatDesc() string
  32. }
  33. type ContentCipherBuilder interface {
  34. ContentCipher() (ContentCipher, error)
  35. ContentCipherEnv(Envelope) (ContentCipher, error)
  36. GetMatDesc() string
  37. }
  38. type ContentCipher interface {
  39. EncryptContent(io.Reader) (io.ReadCloser, error)
  40. DecryptContent(io.Reader) (io.ReadCloser, error)
  41. Clone(cd CipherData) (ContentCipher, error)
  42. GetEncryptedLen(int64) int64
  43. GetCipherData() *CipherData
  44. GetAlignLen() int
  45. }
  46. type Envelope struct {
  47. IV string
  48. CipherKey string
  49. MatDesc string
  50. WrapAlg string
  51. CEKAlg string
  52. UnencryptedMD5 string
  53. UnencryptedContentLen string
  54. }
  55. func (el Envelope) IsValid() bool {
  56. return len(el.IV) > 0 &&
  57. len(el.CipherKey) > 0 &&
  58. len(el.WrapAlg) > 0 &&
  59. len(el.CEKAlg) > 0
  60. }
  61. func (el Envelope) String() string {
  62. return fmt.Sprintf("IV=%s&CipherKey=%s&WrapAlg=%s&CEKAlg=%s", el.IV, el.CipherKey, el.WrapAlg, el.CEKAlg)
  63. }
  64. type CipherData struct {
  65. IV []byte
  66. Key []byte
  67. MatDesc string
  68. WrapAlgorithm string
  69. CEKAlgorithm string
  70. EncryptedIV []byte
  71. EncryptedKey []byte
  72. }
  73. func (cd *CipherData) RandomKeyIv(keyLen int, ivLen int) error {
  74. math_rand.Seed(time.Now().UnixNano())
  75. // Key
  76. cd.Key = make([]byte, keyLen)
  77. if _, err := io.ReadFull(rand.Reader, cd.Key); err != nil {
  78. return err
  79. }
  80. // sizeof uint64
  81. if ivLen < 8 {
  82. return fmt.Errorf("ivLen:%d less than 8", ivLen)
  83. }
  84. // IV: | nonce: 8 bytes | Serial number: 8 bytes |
  85. cd.IV = make([]byte, ivLen)
  86. if _, err := io.ReadFull(rand.Reader, cd.IV[0:ivLen-8]); err != nil {
  87. return err
  88. }
  89. // only use 4 byte,in order not to overflow when SeekIV()
  90. randNumber := math_rand.Uint32()
  91. cd.SetIV(uint64(randNumber))
  92. return nil
  93. }
  94. func (cd *CipherData) SetIV(iv uint64) {
  95. ivLen := len(cd.IV)
  96. binary.BigEndian.PutUint64(cd.IV[ivLen-8:], iv)
  97. }
  98. func (cd *CipherData) GetIV() uint64 {
  99. ivLen := len(cd.IV)
  100. return binary.BigEndian.Uint64(cd.IV[ivLen-8:])
  101. }
  102. func (cd *CipherData) SeekIV(startPos uint64) {
  103. cd.SetIV(cd.GetIV() + startPos/uint64(len(cd.IV)))
  104. }
  105. func (cd *CipherData) Clone() CipherData {
  106. var cloneCd CipherData
  107. cloneCd = *cd
  108. cloneCd.Key = make([]byte, len(cd.Key))
  109. copy(cloneCd.Key, cd.Key)
  110. cloneCd.IV = make([]byte, len(cd.IV))
  111. copy(cloneCd.IV, cd.IV)
  112. cloneCd.EncryptedIV = make([]byte, len(cd.EncryptedIV))
  113. copy(cloneCd.EncryptedIV, cd.EncryptedIV)
  114. cloneCd.EncryptedKey = make([]byte, len(cd.EncryptedKey))
  115. copy(cloneCd.EncryptedKey, cd.EncryptedKey)
  116. return cloneCd
  117. }