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

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

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

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

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

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

注意

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

SDK 还提供数据完整性保护的全局设置,您可以在外部进行设置,您可以在AWS SDKs 和工具参考指南中阅读这些设置。

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

上传对象

当您使用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 版本而异,如下表所示。

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

亚马逊 S3 模块版本为 适用于 Go 的 AWS SDK 校验和行为
早于 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 会根据该算法自动计算和校验和。CRC32SDK 会对所有版本的 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方法下载对象时,当的ChecksumMode字段设置为时,SDK 会自动验证校验和。GetObjectInput types.ChecksumModeEnabled

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

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

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