我們在需要存儲文件的數(shù)據(jù)落盤加密時猾编,就會用到這種簡單的服務(wù)端加密實現(xiàn)秃诵;
使用的前提是:
- S3存儲服務(wù)端支持https寥裂;
- S3存儲服務(wù)端實現(xiàn)了AES256加密
下面我們以go的aws sdk來進行舉例个榕,本例是訪問私有簽發(fā)證書的服務(wù):
import (
"bytes"
"context"
"crypto/md5"
"crypto/tls"
"crypto/x509"
"encoding/json"
"fmt"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
credentials2 "github.com/aws/aws-sdk-go/aws/credentials"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/iam"
"github.com/aws/aws-sdk-go/service/s3"
"github.com/aws/aws-sdk-go/service/s3/s3manager"
"github.com/minio/minio-go/v7"
"github.com/minio/minio-go/v7/pkg/credentials"
"github.com/minio/minio-go/v7/pkg/encrypt"
"io"
"io/ioutil"
"net"
"net/http"
"time"
)
var(
ak = "accessKeyValue" //文件服務(wù)分配的賬號
sk = "secretKeyValue" //文件服務(wù)分配的秘鑰
endPoint = "https://127.0.0.1:9000" // 存儲服務(wù)的地址
region = "default" //適用范圍
svc *s3.S3 // aws s3 的client
iamSvc *iam.IAM
uploader *s3manager.Uploader
s3Client *minio.Client // minio s3的client
)
func Init(){
cres := credentials2.NewStaticCredentials(ak, sk, "")
cfg := aws.NewConfig().WithRegion(region).WithEndpoint(endPoint).WithCredentials(cres).WithS3ForcePathStyle(
true).WithMaxRetries(0).WithDisableSSL(true)
// 這段代碼就是跳過證書校驗忠烛,不然會報X509的錯誤
tr := &http.Transport{
TLSClientConfig: &tls.Config{
InsecureSkipVerify: true,
},
}
cfg.HTTPClient = &http.Client{
Transport: tr,
}
sess, err := session.NewSession(cfg)
if err != nil {
fmt.Println(err)
}
// sws S3 的client
svc = s3.New(sess)
iamSvc = iam.New(sess, cfg)
// minio 的client
s3Client, err = minio.New("127.0.0.1:9000", &minio.Options{
Creds: credentials.NewStaticV4(ak, sk, ""),
Secure: true,
Transport: tr,
})
if err != nil {
fmt.Println(err)
return
}
}
func main(){
Init()
t := time.Now()
bucketName := "test-ssec"
objectID := time.Now().Format("20060102150405")
createBucket(bucketName)
putSSECObject([]byte("2222-2222-2222-2222"), bucketName, "", objectID)
getSSECObject(bucketName,objectID)
putSSECObjectMinio([]byte("2222-2222-2222-2222"), bucketName, "", objectID)
fmt.Println(time.Since(t))
}
// 創(chuàng)建bucket
func createBucket(bucketName string) {
input := &s3.CreateBucketInput{
Bucket: aws.String(bucketName),
}
result, err := svc.CreateBucket(input)
fmt.Printf("CreateBucket %v \n", result)
if err != nil {
if aerr, ok := err.(awserr.Error); ok {
switch aerr.Code() {
case s3.ErrCodeBucketAlreadyExists:
fmt.Println(s3.ErrCodeBucketAlreadyExists, aerr.Error())
case s3.ErrCodeBucketAlreadyOwnedByYou:
fmt.Println(s3.ErrCodeBucketAlreadyOwnedByYou, aerr.Error())
default:
fmt.Println(aerr.Error())
}
} else {
fmt.Println(err.Error())
}
}
}
// aws s3 client 通過SSE-C 的方式上傳文件
func putSSECObject(dataImage []byte, bucketName, contentType, objectID string){
t := time.Now()
inputObject := &s3.PutObjectInput{
Bucket: aws.String(bucketName),
Key: aws.String(objectID),
ContentType: aws.String(contentType),
Body: bytes.NewReader(dataImage),
ContentLength: aws.Int64(int64(len(dataImage))),
// 目前只支持 AES256
SSECustomerAlgorithm: aws.String("AES256"),
// 秘鑰的是32位的字符串(下面的是 32byteslongsecretkeymustprovided aws會幫我們做base64編碼)
SSECustomerKey: aws.String("32byteslongsecretkeymustprovided"),
// 原始秘鑰的MD5值坯墨,切記是base64之前的秘鑰
SSECustomerKeyMD5: aws.String("7PpPLAK26ONlVUGOWlusfg=="),
}
fmt.Println(int64(len(dataImage)))
resp, err := svc.PutObject(inputObject)
if err != nil {
fmt.Println(err.Error())
}
fmt.Printf("upload resp: %v cost time : %v \n",resp, time.Since(t))
}
// aws s3 client 通過SSE-C 的方式下載文件
func getSSECObject(bucketName, objectID string){
t := time.Now()
inputObject := &s3.GetObjectInput{
Bucket: aws.String(bucketName),
Key: aws.String(objectID),
// 目前只支持 AES256
SSECustomerAlgorithm: aws.String("AES256"),
// 秘鑰的256位base64編碼的字符串(下面的是 32byteslongsecretkeymustprovided 做了base64編碼)
SSECustomerKey: aws.String("32byteslongsecretkeymustprovided"),
// 原始秘鑰的MD5值寂汇,切記是base64之前的秘鑰
SSECustomerKeyMD5: aws.String("7PpPLAK26ONlVUGOWlusfg=="),
}
resp, err := svc.GetObject(inputObject)
if err != nil {
fmt.Println(err.Error())
}
fmt.Printf("get resp: %v cost time : %v \n",resp, time.Since(t))
res, err := ioutil.ReadAll(resp.Body)
if err != nil {
fmt.Println(err.Error())
}
fmt.Println(string(res))
}
// minio client 上傳文件
func putSSECObjectMinio(dataImage []byte, bucketName, contentType, objectID string){
sse,_ := encrypt.NewSSEC([]byte("32byteslongsecretkeymustprovided"))
resp, err := s3Client.PutObject(context.Background(), bucketName,objectID,bytes.NewReader(dataImage),
int64(len(dataImage)),
minio.PutObjectOptions{
ServerSideEncryption: sse,
})
if err != nil {
fmt.Printf("putSSECObjectMinio err : %v \n" ,err)
}
fmt.Printf("putSSECObjectMinio %v\n", resp)
}