使用校验和实现数据完整性保护 - 适用于 Go 的 AWS SDK v2

本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。

使用校验和实现数据完整性保护

Amazon Simple Storage Service (Amazon S3) 允许您在上传对象时指定校验和。当您指定校验和时,校验和与对象一起存储,并且可以在下载对象时验证该校验和。

传输文件时,校验和可提供额外的数据层完整性。使用校验和,您可以通过确认收到文件与原始文件是否匹配来验证数据一致性。有关 Amazon S3 校验和的更多信息,请参阅 Amazon Simple Storage Service 用户指南,包括支持的算法

您可以灵活地选择最适合自己需求的算法,并让 SDK 计算校验和。或者,您也可以使用任一受支持的算法,提供预先计算好的校验和值。

注意

Amazon S3 模块的 v1.74.1 版本开始,该 SDK 通过自动计算上传文件的 CRC32 校验和来提供默认的完整性保护。如果您未提供预先计算的校验和值,或未指定 SDK 计算校验和时应使用的算法,SDK 将自动计算此校验和。

该 SDK 还提供了可在外部设置的数据完整性保护全局设置,您可以在 AWS SDK 和工具参考指南中查阅相关说明。

我们在两个请求阶段讨论校验和:上传对象和下载对象。

上传对象

当您使用 putObject 方法上传对象并提供校验和算法时,SDK 会计算指定算法的校验和。

以下代码段展示了上传具有 CRC32 校验和的对象的请求。当 SDK 发送请求时,它会计算 CRC32 校验和并上传对象。Amazon S3 会计算校验和并将其与 SDK 提供的校验和进行对比,从而验证内容的完整性。然后 Amazon S3 将校验和与对象一起存储。

out, err := s3Client.PutObject(context.Background(), &s3.PutObjectInput{ Bucket: aws.String("bucket"), Key: aws.String("key"), ChecksumAlgorithm: types.ChecksumAlgorithmCrc32, Body: strings.NewReader("Hello World"), })

如果您未在请求中提供校验和算法,则校验和行为将根据您使用的 SDK 版本而异,具体如下表所示。

未提供校验和算法时的校验和行为

适用于 Go 的 AWS SDK 的 Amazon S3 模块版本 校验和行为
v1.74.1 之前的版本 SDK 不会自动计算基于 CRC 的校验和,也不会在请求中提供该值。
v1.74.1 或更高版本

SDK 采用 CRC32 算法计算校验和,并在请求中提供该值。Amazon S3 通过计算自己的 CRC32 校验和来验证传输的完整性,并将其与 SDK 提供的校验和进行对比。如果校验和匹配,则校验和将与对象一起保存。

使用预先计算的校验和值

与请求一起提供的预先计算校验和值会禁用 SDK 的自动计算,而是使用提供的值。

以下示例展示了具有预先计算的 SHA256 校验和的请求。

out, err := s3Client.PutObject(context.Background(), &s3.PutObjectInput{ Bucket: aws.String("bucket"), Key: aws.String("key"), ChecksumCRC32: aws.String("checksumvalue"), Body: strings.NewReader("Hello World"), })

如果 Amazon S3 确定指定算法的校验和值不正确,服务就会返回错误响应。

分段上传

您也可以将校验和用于分段上传。

适用于 Go 的 AWS SDK 提供了两个将校验和用于分段上传的选项。第一个选项使用指定 CRC32 算法的传输管理器进行上传。

s3Client := s3.NewFromConfig(cfg) transferManager := manager.NewUploader(s3Client) out, err := transferManager.Upload(context.Background(), &s3.PutObjectInput{ Bucket: aws.String("bucket"), Key: aws.String("key"), Body: large file to trigger multipart upload, ChecksumAlgorithm: types.ChecksumAlgorithmCrc32, })

如果您在使用传输管理器上传时未提供校验和算法,则 SDK 会根据 CRC32 算法自动计算校验和。SDK 会对所有版本的 SDK 执行此计算。

第二个选项使用 Amazon S3 客户端来执行分段上传。如果用此方法来指定校验和,则您必须指定在启动上传时使用的算法。您还必须为每个分段请求指定算法,并提供每个分段在上传后计算得出的校验和。

s3Client := s3.NewFromConfig(cfg) createMultipartUploadOutput, err := s3Client.CreateMultipartUpload(context.Background(), &s3.CreateMultipartUploadInput{ Bucket: aws.String("bucket"), Key: aws.String("key"), ChecksumAlgorithm: types.ChecksumAlgorithmCrc32, }) if err != nil { log.Fatal("err create multipart upload ", err) } var partsBody []io.Reader // this is just an example parts content, you should load your target file in your code partNum := int32(1) var completedParts []types.CompletedPart for _, body := range partsBody { uploadPartOutput, err := s3Client.UploadPart(context.Background(), &s3.UploadPartInput{ Bucket: aws.String("bucket"), Key: aws.String("key"), ChecksumAlgorithm: types.ChecksumAlgorithmCrc32, Body: body, PartNumber: aws.Int32(partNum), UploadId: createMultipartUploadOutput.UploadId, }) if err != nil { log.Fatal("err upload part ", err) } completedParts = append(completedParts, types.CompletedPart{ PartNumber: aws.Int32(partNum), ETag: uploadPartOutput.ETag, ChecksumCRC32: uploadPartOutput.ChecksumCRC32, }) partNum++ } completeMultipartUploadOutput, err := s3Client.CompleteMultipartUpload(context.Background(), &s3.CompleteMultipartUploadInput{ Bucket: aws.String("bucket"), Key: aws.String("key"), UploadId: createMultipartUploadOutput.UploadId, MultipartUpload: &types.CompletedMultipartUpload{ Parts: completedParts, }, }) if err != nil { log.Fatal("err complete multipart upload ", err) }

下载对象

如果使用 GetObject 方法下载对象,当 GetObjectInputChecksumMode 字段设置为 types.ChecksumModeEnabled 时,SDK 会自动验证校验和。

以下代码段中的请求引导 SDK 通过计算校验和并比较值来验证响应中的校验和。

out, err := s3Client.GetObject(context.Background(), &s3.GetObjectInput{ Bucket: aws.String("bucket"), Key: aws.String("key"), ChecksumMode: types.ChecksumModeEnabled, })

如果上传对象时没有使用校验和,则不会进行验证。