简介

随着航海征程的推进,乔巴的背包是越来越鼓,也越来越大了。看着轻装上阵的伙伴们,它的内心是复杂的。

乔巴 OS :我也想找个地方储存一下我的背包,可是我又担心背包里面的内容,被人窃取了可怎么好?

针对乔巴的需求,QingStor 对象存储提供了一套完整的解决方案。既能满足你多种多样的数据存取的需求,同时,还能确保你的数据安全。

本文中用到的相关名词有:

file

什么是加密

QingStor 对象存储提供怎样的方案,来消除乔巴的担忧呢?我们先来看看存/取数据的流程:

file

通过上图,我们可以知道,乔巴要将背包存起来,首先需要将背包运送到存储地点(QingStor 对象存储)。

当前已经有比较成熟的做法用来保障数据在传输过程中的安全,也就是通用的 SSL 协议,这里不做详细说明了。

除此之外,乔巴也可以给自己的背包加个锁,即:客户端加密。这部分操作,是由乔巴自发完成并监管的。这里也不做具体说明。

等背包运输到 QingStor 了,QingStor 再对背包进行加密,这个就是服务端的数据加密。

为了消除乔巴的担忧,QingStor 对象存储提供了一套完整的解决方案:SSL 协议 + 服务端数据加密。

具体怎么做的呢?下面我们来详细说一下整个的加密/解密过程吧。好期待哦!

加密过程

乔巴现在想把背包(数据)交由 QingStor 对象存储,那么整个过程如下:

  1. 乔巴在自己的背包上贴上密钥,根据密钥生成的 MD5 值,和加密算法等标签。并保留这些信息。
  2. 乔巴将贴有这些标签的背包,交给 QingStor 对象存储。
  3. QingStor 在收到乔巴提交的背包后,先取下密钥,计算出密钥的 MD5 值。
  4. QingStor 取下乔巴背包上的 MD5 值,与计算出的 MD5 值进行比对,以确认密钥在提交过程中没有被修改。
  5. 如果 QingStor 发现 MD5 值不一致了,提醒乔巴,背包内容可能会被窃取,需重新对背包贴标签,并再次提交。
  6. 如果 QingStor 发现 MD5 值一致时,说明密钥没有被修改,背包提交过程中是安全的,这个时候从背包上取下加密算法,对背包里面的数据进行加密。
  7. 为了确保背包里面的数据仅乔巴一个人可以获取,在加密完成后,QingStor 丢弃背包上的密钥,仅保留根据密钥计算出来的 MD5 值,用于取数据时的认证。

至此,乔巴就可以拿着加密信息离开了。

解密过程

一段时间后,乔巴要从 QingStor 取回背包了,那么整个过程又是怎样的呢?

  1. 乔巴提出取数据的申请,并在申请里面提交当时存储背包时的标签:密钥,根据密钥生成的 MD5 值,和加密算法给 QingStor。
  2. QingStor 收到乔巴提交的申请后,先取下密钥,计算出 MD5 值。
  3. QingStor 再取下乔巴取包申请上的 MD5 值,与计算出的 MD5 进行比对,以确认密钥在提交过程中没有被修改。
  4. 若 QingStor 发现两个 MD5 值不一致,提醒乔巴,根据约定,你这个背包取不了,需重新回去找找密钥,再次提交申请啊。
  5. 若 QingStor 发现两个 MD5 值一致,说明这个申请是合法的。
  6. QingStor 用乔巴提交的密钥将背包数据进行数据。
  7. QingStor 将解密后的背包返回给乔巴。

至此,乔巴就可以拿到自己的原始背包了。

如何使用加密

乔巴:也就是说我只要保存好我的密钥就行了,是么?

QingStor:是的呢,密钥可要保存好哦,弄丢了,背包里面的东西就谁也不能获取到了,包括你自己哦。

乔巴:果然是够安全了,那我们就开始来办手续吧。

加密请求头

根据前文提到的,我们知道,需要给乔巴的背包贴上三个标签以实现对背包的加密。那么这个标签要怎么写呢?内容格式如下:

file

备注:

  • QingStor 对象存储目前支持的加密算法仅有 AES256。
  • QingStor 对象存储要求密钥的明文必须具有 32 个字节长度。且,密钥必须进行 Base64 编码处理。
  • 为了确认密钥在传输过程中的完整性,这里也需要用户提供原始密钥的 MD5 值,且该 MD5 值也必须进行 Base64 编码处理。

标签贴好了,那么如何提交请求呢?QingStor 对象存储提供多种 API,用以满足用户的多种请求类型。详细内容如下:

基础操作

GET Object

若乔巴想从指定的存储空间,获取之前存储的加密对象(背包),可以使用 GET Object,并携带该加密对象的加密信息。即:加密请求头。

具体可以这样做:

请求示例:

    GET /myphoto.jpg HTTP/1.1
    Host: mybucket.pek3a.qingstor.com
    Date: Wed, 21 Jul 2021 01:32:07 GMT
    Authorization: authorization string
    Connection: close
    Content-Type: application/octet-stream
    X-Qs-Encryption-Customer-Algorithm: AES256
    X-Qs-Encryption-Customer-Key: your key
    X-Qs-Encryption-Customer-Key-Md5: md5 of your key
    

响应示例:

    HTTP/1.1 200 OK
    Server: nginx
    Date: Wed, 21 Jul 2021 01:32:44 GMT
    Last-Modified: Tue, 20 Jul 2021 10:29:28 GMT
    Content-Type: application/octet-stream
    Content-Length: 712012
    Connection: keep-alive
    ETag: "7c1fa24c1049ea04713e38a876531b3b"
    X-Qs-Encryption-Customer-Algorithm: AES256
    X-Qs-Encryption-Customer-Key-Md5: md5 of your key
    x-qs-raw-version-id: '596774173842344405
    x-qs-request-id: 412b0b33cb5df691
    x-qs-storage-class: STANDARD
    [712012 bytes of object data]


PUT Object

若乔巴需要将待存储至指定空间的对象(背包)进行加密,可以使用 PUT Object,并携带加密信息。

具体可以这样做:

请求示例:

    PUT /myphoto.jpg HTTP/1.1
    Host: mybucket.pek3a.qingstor.com
    Date: Tue, 20 Jul 2021 10:28:51 GMT
    Content-Length: 7987
    Authorization: authorization string
    X-Qs-Encryption-Customer-Algorithm: AES256
    X-Qs-Encryption-Customer-Key: your key
    X-Qs-Encryption-Customer-Key-Md5: md5 of your key

响应示例:

    HTTP/1.1 201 CREATED
    Server: nginx
    Date: Tue, 20 Jul 2021 10:29:28 GMT
    ETag: "7c1fa24c1049ea04713e38a876531b3b"
    Content-Length: 0
    Connection: close
    X-Qs-Encryption-Customer-Algorithm: 'AES256'
    X-Qs-Encryption-Customer-Key-Md5: md5 of your key
    x-qs-request-id: c60578c617907748


PUT Object - Copy

若乔巴想要对已经存储在 QingStor 的加密对象(背包),进行备份,可以使用PUT Object - Copy ,对源对象(背包)进行拷贝。

拷贝后的对象,不会包含源对象的加密信息,乔巴需要再次提供加密信息,对目标对象进行加密。

由于拷贝的过程涉及到:

  1. 读取源对象。
  2. 将源对象写入目标存储空间。

根据前文说明,我们知道,若需读取 QingStor 的加密对象(背包),我们需要提供该加密对象的加密信息。成功读取后,再将该对象写入存储空间时,我们需要提供加密信息,对该对象进行加密。

整个过程,我们需要提供两个加密信息:源对象的加密信息与目标对象的加密信息。为了区分这两个加密信息,QingStor 对象存储用到如下请求头来标明源对象的加密信息:

file

请求示例:

    PUT /myphoto.jpg HTTP/1.1
    Host: mybucket.pek3a.qingstor.com
    Date: Wed, 21 Jul 2021 03:06:32 GMT
    Content-Type: application/octet-stream
    Authorization: authorization string
    X-Qs-Copy-Source: /source-bucket/source-object
    X-Qs-Copy-Source-Encryption-Customer-Algorithm: AES256
    X-Qs-Copy-Source-Encryption-Customer-Key: original object key
    X-Qs-Copy-Source-Encryption-Customer-Key-Md5:original object key's md5
    X-Qs-Encryption-Customer-Algorithm: AES256
    X-Qs-Encryption-Customer-Key: new object key
    X-Qs-Encryption-Customer-Key-Md5: new object key's md5

响应示例:

    HTTP/1.1 201 CREATED
    Server: nginx
    Date: Wed, 21 Jul 2021 03:11:02 GMT
    ETag: "7c1fa24c1049ea04713e38a876531b3b"
    Content-Length: 0
    Content-Type: text/plain
    Connection: close
    X-Qs-Encryption-Customer-Algorithm: 'AES256'
    X-Qs-Encryption-Customer-Key-Md5: md5 of your key
    x-qs-request-id: c60578c617907748


PUT Object - Move

若乔巴需要将自己已经提交储存的背包移动一下存储位置,比如从一个存储空间移动到另外一个存储空间,那可以通过 PUT Object - Move 来操作。

因为移动背包不涉及到背包数据的读写,因此该操作是无需提供加密背包时所使用的加密信息,即:无需提供源对象加密请求头。

移动后的背包(目标对象),仍然保留源背包(源对象)加密时所使用的加密信息。

请求示例:

    PUT /myphoto.jpg HTTP/1.1
    Host: mybucket.pek3a.qingstor.com
    Date: Wed, 21 Jul 2021 03:11:02 GMT
    Authorization: authorization string
    X-Qs-move-source: /source-bucket/source-object
    X-Qs-Copy-Source-Encryption-Customer-Algorithm: AES256
    X-Qs-Copy-Source-Encryption-Customer-Key: original object key
    X-Qs-Copy-Source-Encryption-Customer-Key-Md5:original object key's md5
    X-Qs-Encryption-Customer-Algorithm: AES256
    X-Qs-Encryption-Customer-Key: new object key
    X-Qs-Encryption-Customer-Key-Md5: new object key's md5

响应示例:

    HTTP/1.1 201 CREATED
    Server: QingStor
    Date: Wed, 21 Jul 2021 03:11:02 GMT
    ETag: "0c2f573d81194064b129e940edcefe9b"
    Content-Length: 0
    Connection: close
    X-Qs-Encryption-Customer-Algorithm: 'AES256'
    X-Qs-Encryption-Customer-Key-Md5: md5 of your key
    x-qs-request-id: c60578c617907748


HEAD Object

当乔巴存储的东西越来越多了,搞不清楚每个背包里有什么内容,这个时候可以使用 HEAD Object 来获取一下这些背包的相关信息。因为不涉及到背包数据的读写,因此该操作无需提供加密背包时所使用的加密信息,即:无需提供源对象的加密请求头。

若乔巴手里的密钥太多,不确定密钥与背包是否匹配,也可以使用 HEAD Object 来操作,这个时候就需要提供背包加密时所使用的加密信息,即:需要提供源对象的加密请求头,用以验证该加密信息的算法与密钥是否正确。

请求示例:

HEAD /myphoto.jpg HTTP/1.1
Host: mybucket.pek3a.qingstor.com
Date: Wed, 21 Jul 2021 06:13:33 GMT
Connection:close
Authorization: authorization string
X-Qs-Encryption-Customer-Algorithm: AES256
X-Qs-Encryption-Customer-Key: your key
X-Qs-Encryption-Customer-Key-Md5:your key's md5

响应示例:

HTTP/1.1 200 OK
Server: nginx
Date: Wed, 21 Jul 2021 06:13:33 GMT
Last-Modified: Tue, 20 Jul 2021 10:29:28 GMT
ETag: "0c2f573d81194064b129e940edcefe9b"
Content-Type: application/octet-stream
Content-Length: 7987
Connection: keep-alive
X-Qs-Encryption-Customer-Algorithm: AES256
X-Qs-Encryption-Customer-Key-Md5: key's md5
x-qs-storage-class: STANDARD
x-qs-request-id: aa08cf7a43f611e5886952542e6ce14b

分段上传

若乔巴待存储的背包过大,如超过 5G,这个时候,乔巴需要将背包进行一下切分,分为多个小背包进行传输。待 QingStor 收到该背包的所有分片后,QingStor 会将这些分片进行组装,再次整理为一个背包进行存储。

具体做法,参考如下内容:

Initiate Multipart Upload

首先,乔巴需要通知 QingStor,它需要加密分段上传。这个时候,需要用到带有加密信息的 Initiate Multipart Upload 操作来完成。

请求示例:

    POST /large-object?uploads HTTP/1.1
    Host: mybucket.pek3a.qingstor.com
    Date: Wed, 21 Jul 2021 06:58:47 GMT
    Authorization: authorization string
    X-Qs-Encryption-Customer-Algorithm: AES256
    X-Qs-Encryption-Customer-Key: your key
    X-Qs-Encryption-Customer-Key-Md5: your key's md5

响应示例:

    HTTP/1.1 200 OK
    Server: QingStor
    Date: Wed, 21 Jul 2021 06:59:24 GMT
    Content-Type: application/json
    Content-Length: 90
    Connection: keep-alive
    X-Qs-Encryption-Customer-Algorithm: AES256
    X-Qs-Encryption-Customer-Key-Md5: your key
    x-qs-request-id: f697b777721f033e
    x-qs-request-id: 37fed66c441a11e5b95f52542e6ce14b
    {
            "bucket":"test-rose",
            "key":"example_key8",
            "upload_id":"84947437bc00e22"
    }

备注:

  • 这个过程中,QingStor 仅保存密钥的 MD5 值,用于验证后续上传分段的密钥是否正确。
  • QingStor 将丢弃乔巴提交的密钥信息。

Upload Object Part

QingStor 收到乔巴加密分段上传的请求,并做好相关准备操作后,告诉乔巴,你可以继续上传分段了。这个时候,乔巴可以使用携带有加密信息的 Upload Object Part 来进行操作。

备注:

  • 由于是同一个背包(对象)的不同分片,故加密信息应与初始化分段时提供的加密信息保持一致。
  • 该操作需包含有初始化加密分段上传阶段的 upload_id 字段。

请求示例:

    PUT /large-object?upload_id=4d26b37a469230619604ecdc0e314782&part_number=0 HTTP/1.1
    Host: mybucket.pek3a.qingstor.com
    Date: Wed, 21 Jul 2021 06:59:24 GMT
    Content-Length: 7987
    Authorization: authorization string
    X-Qs-Encryption-Customer-Algorithm: AES256
    X-Qs-Encryption-Customer-Key: your key
    X-Qs-Encryption-Customer-Key-Md5: your key's md5

响应示例:

    HTTP/1.1 201 CREATED
    Server: QingStor
    Date: Wed, 21 Jul 2021 06:59:24 GMT
    Content-Length: 0
    Connection: close
    X-Qs-Encryption-Customer-Algorithm: 'AES256'
    X-Qs-Encryption-Customer-Key-Md5: md5 of your key
    x-qs-request-id: 37fed66c441a11e5b95f52542e6ce14b


Copy Object Part

QingStor 也支持对加密分段的拷贝操作。与拷贝加密对象对象的操作相同,需要提供额外的请求头:

file

备注:

  • 拷贝时,提供的源对象加密信息与初始化分段时提供的加密信息保持一致。
  • 目标对象的加密信息重新给定。•该操作需包含有初始化加密分段上传阶段的 upload_id 字段.

请求示例:

    PUT /large-object?upload_id=4d26b37a469230619604ecdc0e314782&
    Host: mybucket.pek3a.qingstor.com
    Date: Wed, 21 Jul 2021 03:06:32 GMT
    Content-Type: application/octet-stream
    Authorization: authorization string
    X-Qs-Copy-Source: /source-bucket/source-object
    X-Qs-Copy-Source-Encryption-Customer-Algorithm: AES256
    X-Qs-Copy-Source-Encryption-Customer-Key: original object key
    X-Qs-Copy-Source-Encryption-Customer-Key-Md5:original object key's md5
    X-Qs-Encryption-Customer-Algorithm: AES256
    X-Qs-Encryption-Customer-Key: new object key
    X-Qs-Encryption-Customer-Key-Md5: new object key's md5

响应示例:

    HTTP/1.1 201 CREATED
    Server: QingStor
    Date: Wed, 21 Jul 2021 03:11:02 GMT
    ETag: "7c1fa24c1049ea04713e38a876531b3b"
    Content-Length: 0
    Content-Type: text/plain
    Connection: close
    X-Qs-Encryption-Customer-Algorithm: 'AES256'
    X-Qs-Encryption-Customer-Key-Md5: md5 of your key
    x-qs-request-id: c60578c617907748


Complete Multipart Upload

当乔巴的加密分段上传完成后,这个时候,就需要用到带有加密信息的 Initiate Multipart Upload 操作来通知 QingStor 加密分段上传完成。

备注:

  • 该操作不能单独使用。
  • 该操作不涉及到背包数据的读取,故无需提交加密请求头。
  • 该操作需包含有初始化加密分段上传阶段的 upload_id 字段。

请求示例:

    POST /large-object?upload_id=4d26b37a469230619604ecdc0e314782 HTTP/1.1
    Host: mybucket.<zone-id>.qingstor.com
    Date: Wed, 21 Jul 2021 03:06:32 GMT
    Authorization: authorization string
    ETag: "0c2f573d81194064b129e940edcefe9b"
    {
            "object_parts": [
                    {"part_number": 0, "etag": "c837682353601f7fc0a2ccb6bc8f4654"},
                    {"part_number": 1, "etag": "28e2c0c6574a1ef20ac41d16a012a7c1"}
            ]
    }

响应示例:

    HTTP/1.1 201 CREATED
    Server: QingStor
    Date: Wed, 21 Jul 2021 03:06:32 GMT
    Content-Length: 0
    Connection: close
    x-qs-request-id: 37fed66c441a11e5b95f52542e6ce14b


Abort Multipart Upload

在加密分段上传的过程中,乔巴发现传错背包了,或者其他原因需要终止加密分段上传,可以在完成分段上传前,提前终止加密分段上传,这个时候,就可以使用 Abort Multipart Upload。使用该操作后,已经上传成功的分段也将从 QingStor 删除。

备注:

  • 该操作不能单独使用。
  • 该操作无需提交加密请求头。
  • 该操作需包含有初始化加密分段上传阶段的 upload_id 字段。

请求示例:

    DELETE /large-object?upload_id=4d26b37a469230619604ecdc0e314782 HTTP/1.1
    Host: mybucket.pek3a.qingstor.com
    Date: Wed, 21 Jul 2021 03:06:32 GMT
    Content-Length: 0
    Authorization: authorization string

响应示例:

    HTTP/1.1 204 NoContent
    Server: QingStor
    Date: Wed, 21 Jul 2021 03:06:32 GMT
    Content-Length: 0
    Connection: close
    x-qs-request-id: 37fed66c441a11e5b95f52542e6ce14b


结尾

至此,我们知道,QingStor 在完成对乔巴提交的对象加密后,将丢弃乔巴提交的用于解密该对象的密钥。也就是说,一旦该对象加密存储后,只有拥有该密钥的人,才能对该对象进行下载解密。

就好比家里的保险柜钥匙丢了,你打电话给这个保险柜的生产厂家,如果厂家说他能帮你打开,那这恰恰说明这个保险柜不是那么的保险。所以从保险角度来说,厂家也没有备用钥匙的。

所以一定要保管好自己的密钥哦!

作者

池桂梅 QingStor 存储产品文档工程师

本文由博客一文多发平台 OpenWrite 发布!

青云技术社区
40 声望13 粉丝

青云QingCloud 技术内容平台,汇聚云原生、容器、数据库、存储等前沿技术,关注技术创新,拥抱开发者,乐于分享。Born To Learn And Share !