【发布时间】:2016-10-19 00:56:46
【问题描述】:
以下代码尝试使用多部分传输、客户端信封加密和 Amazon KMS 服务将 17MB 测试文件复制到 S3 存储桶以处理数据加密密钥。多部分块大小为 5MB。
在传输最后一个(部分)块时,仅如果IsLastPart 标志设置为true,对UploadPart 的调用会生成一个System.Net.ProtocolViolationException,指示:Bytes to be written to the stream exceed the Content-Length bytes size specified.
这表明 Content-Length html 标头未更新以反映加密引擎添加到最后一个密码块以进行正确对齐的必要“填充字节”。结果,当添加这些最终字节时,它们超出了给定的 Content-Length 并产生了此错误。
如果IsLastPart未设置(即留下false),则操作成功,但下载和解密操作也失败。
注意:KmsAlgorithm 类并非由 AWS .NET 开发工具包提供。这个类来自另一个 Stack Overflow posting,因为 .NET 版本的 AWS SDK 没有像 Java SDK 那样在 KMS 和 S3 之间提供 connector class 来支持信封加密。
那么,使用客户端加密和 KMS 托管密钥将多部分上传发送到 S3 的正确方法是什么?
static string bucketName = "*****************************";
static string keyName = "test.encrypted.bin";
static string uploadSourcePath = "c:\\temp\\test.bin";
static long partSize = 5 * 1024 * 1024;
static String uploadId = "";
static void Main(string[] args)
{
if (checkRequiredFields())
{
String cmkId = "************************************";
// Prepare our KMS client and kmsAlgorithm
using (AmazonKeyManagementServiceClient kmsClient = new AmazonKeyManagementServiceClient())
using (KMSAlgorithm kmsAlgo = new KMSAlgorithm(kmsClient, cmkId))
{
// Generate the encryption materials object with the algorithm object
EncryptionMaterials encryptionMaterials = new EncryptionMaterials(kmsAlgo);
// Now prepare an S3 crypto client
using (AmazonS3EncryptionClient cryptoClient = new AmazonS3EncryptionClient(encryptionMaterials))
{
// Initiate the multipart upload request specifying the bucket and key values
InitiateMultipartUploadResponse initResp = cryptoClient.InitiateMultipartUpload(
new InitiateMultipartUploadRequest()
{
BucketName = bucketName,
Key = keyName
});
uploadId = initResp.UploadId;
long fileLength = new FileInfo(uploadSourcePath).Length;
long contentLength = fileLength;
long bytesRemaining = fileLength;
List<PartETag> partETags = new List<PartETag>();
int partNumber = 0;
while (bytesRemaining > 0)
{
long transferSize = bytesRemaining > partSize ? partSize : bytesRemaining;
long partIndex = fileLength - bytesRemaining;
partNumber++;
UploadPartResponse resp =
cryptoClient.UploadPart(
new UploadPartRequest()
{
BucketName = bucketName,
Key = keyName,
FilePath = uploadSourcePath,
FilePosition = partIndex,
PartSize = transferSize,
PartNumber = partNumber,
UploadId = uploadId,
IsLastPart = transferSize < AwsS3FileSystemSample1.Program.partSize
});
partETags.Add( new PartETag( partNumber, resp.ETag ));
bytesRemaining -= transferSize;
}
// Now complete the transfer
CompleteMultipartUploadResponse compResp = cryptoClient.CompleteMultipartUpload(
new CompleteMultipartUploadRequest()
{
Key = keyName,
BucketName = bucketName,
UploadId = initResp.UploadId,
PartETags = partETags
});
}
}
}
Console.WriteLine("Press any key to continue...");
Console.ReadKey();
}
对于任何错误和任何帮助,我们深表歉意。
【问题讨论】:
标签: c# .net amazon-web-services