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.

316 lines
10 KiB

4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
  1. package main
  2. import (
  3. "bytes"
  4. "context"
  5. "crypto/md5"
  6. "crypto/rand"
  7. "fmt"
  8. "io"
  9. "io/ioutil"
  10. math_rand "math/rand"
  11. "net/http"
  12. "net/url"
  13. "os"
  14. "time"
  15. "github.com/tencentyun/cos-go-sdk-v5"
  16. "github.com/tencentyun/cos-go-sdk-v5/crypto"
  17. "github.com/tencentyun/cos-go-sdk-v5/debug"
  18. )
  19. func log_status(err error) {
  20. if err == nil {
  21. return
  22. }
  23. if cos.IsNotFoundError(err) {
  24. // WARN
  25. fmt.Println("WARN: Resource is not existed")
  26. } else if e, ok := cos.IsCOSError(err); ok {
  27. fmt.Printf("ERROR: Code: %v\n", e.Code)
  28. fmt.Printf("ERROR: Message: %v\n", e.Message)
  29. fmt.Printf("ERROR: Resource: %v\n", e.Resource)
  30. fmt.Printf("ERROR: RequestId: %v\n", e.RequestID)
  31. // ERROR
  32. } else {
  33. fmt.Printf("ERROR: %v\n", err)
  34. // ERROR
  35. }
  36. os.Exit(1)
  37. }
  38. func cos_max(x, y int64) int64 {
  39. if x > y {
  40. return x
  41. }
  42. return y
  43. }
  44. func simple_put_object() {
  45. u, _ := url.Parse("https://test-1259654469.cos.ap-guangzhou.myqcloud.com")
  46. b := &cos.BaseURL{BucketURL: u}
  47. c := cos.NewClient(b, &http.Client{
  48. Transport: &cos.AuthorizationTransport{
  49. SecretID: os.Getenv("COS_SECRETID"),
  50. SecretKey: os.Getenv("COS_SECRETKEY"),
  51. Transport: &debug.DebugRequestTransport{
  52. RequestHeader: true,
  53. RequestBody: false,
  54. ResponseHeader: true,
  55. ResponseBody: false,
  56. },
  57. },
  58. })
  59. // Case1 上传对象
  60. name := "test/example2"
  61. fmt.Println("============== simple_put_object ======================")
  62. // 该标识信息唯一确认一个主加密密钥, 解密时,需要传入相同的标识信息
  63. // KMS加密时,该信息设置成EncryptionContext,最大支持1024字符,如果Encrypt指定了该参数,则在Decrypt 时需要提供同样的参数
  64. materialDesc := make(map[string]string)
  65. //materialDesc["desc"] = "material information of your master encrypt key"
  66. // 创建KMS客户端
  67. kmsclient, _ := coscrypto.NewKMSClient(c.GetCredential(), "ap-guangzhou")
  68. // 创建KMS主加密密钥,标识信息和主密钥一一对应
  69. kmsID := os.Getenv("KMSID")
  70. masterCipher, _ := coscrypto.CreateMasterKMS(kmsclient, kmsID, materialDesc)
  71. // 创建加密客户端
  72. client := coscrypto.NewCryptoClient(c, masterCipher)
  73. contentLength := 1024*1024*10 + 1
  74. originData := make([]byte, contentLength)
  75. _, err := rand.Read(originData)
  76. f := bytes.NewReader(originData)
  77. // 加密上传
  78. _, err = client.Object.Put(context.Background(), name, f, nil)
  79. log_status(err)
  80. math_rand.Seed(time.Now().UnixNano())
  81. rangeStart := math_rand.Intn(contentLength)
  82. rangeEnd := rangeStart + math_rand.Intn(contentLength-rangeStart)
  83. opt := &cos.ObjectGetOptions{
  84. Range: fmt.Sprintf("bytes=%v-%v", rangeStart, rangeEnd),
  85. }
  86. // 解密下载
  87. resp, err := client.Object.Get(context.Background(), name, opt)
  88. log_status(err)
  89. defer resp.Body.Close()
  90. decryptedData, _ := ioutil.ReadAll(resp.Body)
  91. if bytes.Compare(decryptedData, originData[rangeStart:rangeEnd+1]) != 0 {
  92. fmt.Println("Error: encryptedData != originData")
  93. }
  94. }
  95. func simple_put_object_from_file() {
  96. u, _ := url.Parse("https://test-1259654469.cos.ap-guangzhou.myqcloud.com")
  97. b := &cos.BaseURL{BucketURL: u}
  98. c := cos.NewClient(b, &http.Client{
  99. Transport: &cos.AuthorizationTransport{
  100. SecretID: os.Getenv("COS_SECRETID"),
  101. SecretKey: os.Getenv("COS_SECRETKEY"),
  102. Transport: &debug.DebugRequestTransport{
  103. RequestHeader: true,
  104. RequestBody: false,
  105. ResponseHeader: true,
  106. ResponseBody: false,
  107. },
  108. },
  109. })
  110. // Case1 上传对象
  111. name := "test/example1"
  112. fmt.Println("============== simple_put_object_from_file ======================")
  113. // 该标识信息唯一确认一个主加密密钥, 解密时,需要传入相同的标识信息
  114. // KMS加密时,该信息设置成EncryptionContext,最大支持1024字符,如果Encrypt指定了该参数,则在Decrypt 时需要提供同样的参数
  115. materialDesc := make(map[string]string)
  116. //materialDesc["desc"] = "material information of your master encrypt key"
  117. // 创建KMS客户端
  118. kmsclient, _ := coscrypto.NewKMSClient(c.GetCredential(), "ap-guangzhou")
  119. // 创建KMS主加密密钥,标识信息和主密钥一一对应
  120. kmsID := os.Getenv("KMSID")
  121. masterCipher, _ := coscrypto.CreateMasterKMS(kmsclient, kmsID, materialDesc)
  122. // 创建加密客户端
  123. client := coscrypto.NewCryptoClient(c, masterCipher)
  124. filepath := "test"
  125. fd, err := os.Open(filepath)
  126. log_status(err)
  127. defer fd.Close()
  128. m := md5.New()
  129. io.Copy(m, fd)
  130. originDataMD5 := m.Sum(nil)
  131. // 加密上传
  132. _, err = client.Object.PutFromFile(context.Background(), name, filepath, nil)
  133. log_status(err)
  134. // 解密下载
  135. _, err = client.Object.GetToFile(context.Background(), name, "./test.download", nil)
  136. log_status(err)
  137. fd, err = os.Open("./test.download")
  138. log_status(err)
  139. defer fd.Close()
  140. m = md5.New()
  141. io.Copy(m, fd)
  142. decryptedDataMD5 := m.Sum(nil)
  143. if bytes.Compare(decryptedDataMD5, originDataMD5) != 0 {
  144. fmt.Println("Error: encryptedData != originData")
  145. }
  146. }
  147. func multi_put_object() {
  148. u, _ := url.Parse("https://test-1259654469.cos.ap-guangzhou.myqcloud.com")
  149. b := &cos.BaseURL{BucketURL: u}
  150. c := cos.NewClient(b, &http.Client{
  151. Transport: &cos.AuthorizationTransport{
  152. SecretID: os.Getenv("COS_SECRETID"),
  153. SecretKey: os.Getenv("COS_SECRETKEY"),
  154. Transport: &debug.DebugRequestTransport{
  155. RequestHeader: true,
  156. RequestBody: false,
  157. ResponseHeader: true,
  158. ResponseBody: false,
  159. },
  160. },
  161. })
  162. // Case1 上传对象
  163. name := "test/example1"
  164. fmt.Println("============== multi_put_object ======================")
  165. // 该标识信息唯一确认一个主加密密钥, 解密时,需要传入相同的标识信息
  166. // KMS加密时,该信息设置成EncryptionContext,最大支持1024字符,如果Encrypt指定了该参数,则在Decrypt 时需要提供同样的参数
  167. materialDesc := make(map[string]string)
  168. //materialDesc["desc"] = "material information of your master encrypt key"
  169. // 创建KMS客户端
  170. kmsclient, _ := coscrypto.NewKMSClient(c.GetCredential(), "ap-guangzhou")
  171. // 创建KMS主加密密钥,标识信息和主密钥一一对应
  172. kmsID := os.Getenv("KMSID")
  173. masterCipher, _ := coscrypto.CreateMasterKMS(kmsclient, kmsID, materialDesc)
  174. // 创建加密客户端
  175. client := coscrypto.NewCryptoClient(c, masterCipher)
  176. contentLength := int64(1024*1024*10 + 1)
  177. originData := make([]byte, contentLength)
  178. _, err := rand.Read(originData)
  179. log_status(err)
  180. // 分块上传
  181. cryptoCtx := coscrypto.CryptoContext{
  182. DataSize: contentLength,
  183. // 每个分块需要16字节对齐
  184. PartSize: cos_max(1024*1024, (contentLength/16/3)*16),
  185. }
  186. v, _, err := client.Object.InitiateMultipartUpload(context.Background(), name, nil, &cryptoCtx)
  187. log_status(err)
  188. // 切分数据
  189. chunks, _, err := cos.SplitSizeIntoChunks(contentLength, cryptoCtx.PartSize)
  190. log_status(err)
  191. optcom := &cos.CompleteMultipartUploadOptions{}
  192. for _, chunk := range chunks {
  193. opt := &cos.ObjectUploadPartOptions{
  194. ContentLength: chunk.Size,
  195. }
  196. f := bytes.NewReader(originData[chunk.OffSet : chunk.OffSet+chunk.Size])
  197. resp, err := client.Object.UploadPart(context.Background(), name, v.UploadID, chunk.Number, f, opt, &cryptoCtx)
  198. log_status(err)
  199. optcom.Parts = append(optcom.Parts, cos.Object{
  200. PartNumber: chunk.Number, ETag: resp.Header.Get("ETag"),
  201. })
  202. }
  203. _, _, err = client.Object.CompleteMultipartUpload(context.Background(), name, v.UploadID, optcom)
  204. log_status(err)
  205. resp, err := client.Object.Get(context.Background(), name, nil)
  206. log_status(err)
  207. defer resp.Body.Close()
  208. decryptedData, _ := ioutil.ReadAll(resp.Body)
  209. if bytes.Compare(decryptedData, originData) != 0 {
  210. fmt.Println("Error: encryptedData != originData")
  211. }
  212. }
  213. func multi_put_object_from_file() {
  214. u, _ := url.Parse("https://test-1259654469.cos.ap-guangzhou.myqcloud.com")
  215. b := &cos.BaseURL{BucketURL: u}
  216. c := cos.NewClient(b, &http.Client{
  217. Transport: &cos.AuthorizationTransport{
  218. SecretID: os.Getenv("COS_SECRETID"),
  219. SecretKey: os.Getenv("COS_SECRETKEY"),
  220. Transport: &debug.DebugRequestTransport{
  221. RequestHeader: true,
  222. RequestBody: false,
  223. ResponseHeader: true,
  224. ResponseBody: false,
  225. },
  226. },
  227. })
  228. // Case1 上传对象
  229. name := "test/example1"
  230. fmt.Println("============== multi_put_object_from_file ======================")
  231. // 该标识信息唯一确认一个主加密密钥, 解密时,需要传入相同的标识信息
  232. // KMS加密时,该信息设置成EncryptionContext,最大支持1024字符,如果Encrypt指定了该参数,则在Decrypt 时需要提供同样的参数
  233. materialDesc := make(map[string]string)
  234. //materialDesc["desc"] = "material information of your master encrypt key"
  235. // 创建KMS客户端
  236. kmsclient, _ := coscrypto.NewKMSClient(c.GetCredential(), "ap-guangzhou")
  237. // 创建KMS主加密密钥,标识信息和主密钥一一对应
  238. kmsID := os.Getenv("KMSID")
  239. masterCipher, _ := coscrypto.CreateMasterKMS(kmsclient, kmsID, materialDesc)
  240. // 创建加密客户端
  241. client := coscrypto.NewCryptoClient(c, masterCipher)
  242. filepath := "test"
  243. stat, err := os.Stat(filepath)
  244. log_status(err)
  245. contentLength := stat.Size()
  246. // 分块上传
  247. cryptoCtx := coscrypto.CryptoContext{
  248. DataSize: contentLength,
  249. // 每个分块需要16字节对齐
  250. PartSize: cos_max(1024*1024, (contentLength/16/3)*16),
  251. }
  252. // 切分数据
  253. _, chunks, _, err := cos.SplitFileIntoChunks(filepath, cryptoCtx.PartSize)
  254. log_status(err)
  255. // init mulitupload
  256. v, _, err := client.Object.InitiateMultipartUpload(context.Background(), name, nil, &cryptoCtx)
  257. log_status(err)
  258. // part upload
  259. optcom := &cos.CompleteMultipartUploadOptions{}
  260. for _, chunk := range chunks {
  261. fd, err := os.Open(filepath)
  262. log_status(err)
  263. opt := &cos.ObjectUploadPartOptions{
  264. ContentLength: chunk.Size,
  265. }
  266. fd.Seek(chunk.OffSet, os.SEEK_SET)
  267. resp, err := client.Object.UploadPart(context.Background(), name, v.UploadID, chunk.Number, cos.LimitReadCloser(fd, chunk.Size), opt, &cryptoCtx)
  268. log_status(err)
  269. optcom.Parts = append(optcom.Parts, cos.Object{
  270. PartNumber: chunk.Number, ETag: resp.Header.Get("ETag"),
  271. })
  272. }
  273. // complete upload
  274. _, _, err = client.Object.CompleteMultipartUpload(context.Background(), name, v.UploadID, optcom)
  275. log_status(err)
  276. _, err = client.Object.GetToFile(context.Background(), name, "test.download", nil)
  277. log_status(err)
  278. }
  279. func main() {
  280. simple_put_object()
  281. simple_put_object_from_file()
  282. multi_put_object()
  283. multi_put_object_from_file()
  284. }