Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/300.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在.NET中带有KMS的AWS S3客户端加密在传输的最后一部分上发出协议冲突异常_C#_.net_Amazon Web Services - Fatal编程技术网

C# 在.NET中带有KMS的AWS S3客户端加密在传输的最后一部分上发出协议冲突异常

C# 在.NET中带有KMS的AWS S3客户端加密在传输的最后一部分上发出协议冲突异常,c#,.net,amazon-web-services,C#,.net,Amazon Web Services,下面的代码尝试使用多部分传输、客户端信封加密和AmazonKMS服务将17MB的测试文件复制到S3存储桶,以处理数据加密密钥。多部分块大小为5MB 在传输最后一个(部分)块时,如果IsLastPart标志设置为true,则对UploadPart的调用将生成一个System.Net.ProtocolViolationException异常,指示要写入流的字节超过指定的内容长度字节大小。 这表明内容长度html标头未更新,以反映加密引擎添加到最后一个密码块以进行正确对齐所需的“pad字节”。因此,当

下面的代码尝试使用多部分传输、客户端信封加密和AmazonKMS服务将17MB的测试文件复制到S3存储桶,以处理数据加密密钥。多部分块大小为5MB

在传输最后一个(部分)块时,如果
IsLastPart
标志设置为
true
,则对
UploadPart
的调用将生成一个
System.Net.ProtocolViolationException
异常,指示要写入流的
字节超过指定的内容长度字节大小。

这表明内容长度html标头未更新,以反映加密引擎添加到最后一个密码块以进行正确对齐所需的“pad字节”。因此,当添加这些最后的字节时,它们超过了给定的内容长度并生成了此错误

如果
IsLastPart
未设置(即左
false
),则操作成功,但下载和解密后操作也失败

注意:
KmsAlgorithm
类不是由AWS.NET SDK提供的。这个类来自另一个堆栈溢出,因为.NET版本的AWS SDK没有像Java SDK那样提供KMS和S3之间的连接来支持信封加密

那么,使用客户端加密和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();
    }
静态字符串bucketName=“*************************************”;
静态字符串keyName=“test.encrypted.bin”;
静态字符串uploadSourcePath=“c:\\temp\\test.bin”;
静态长零件尺寸=5*1024*1024;
静态字符串uploadId=“”;
静态void Main(字符串[]参数)
{
if(checkRequiredFields())
{
字符串cmkId=“*************************************”;
//准备我们的KMS客户和kmsAlgorithm
使用(AmazonKeyManagementServiceClient kmsClient=new AmazonKeyManagementServiceClient())
使用(KMSAlgorithm kmsAlgo=新的KMSAlgorithm(kmsClient,cmkId))
{
//使用算法对象生成加密材质对象
EncryptionMaterials EncryptionMaterials=新的EncryptionMaterials(kmsAlgo);
//现在准备一个S3加密客户端
使用(AmazonS3EncryptionClient cryptoClient=新的AmazonS3EncryptionClient(encryptionMaterials))
{
//启动指定bucket和key值的多部分上传请求
InitiateMultipartUploadResponse initResp=cryptoClient.InitiateMultipartUpload(
新的InitiateMultipartUploadRequest()
{
BucketName=BucketName,
Key=keyName
});
uploadId=initResp.uploadId;
long fileLength=newfileinfo(uploadSourcePath).Length;
long contentLength=文件长度;
long bytes剩余=文件长度;
List partETags=新列表();
int partNumber=0;
while(字节剩余>0)
{
长传输大小=字节剩余>零件大小?零件大小:字节剩余;
long partIndex=文件长度-剩余字节数;
partNumber++;
上传部分响应响应=
cryptoClient.UploadPart(
新建UploadPartRequest()
{
BucketName=BucketName,
Key=keyName,
FilePath=uploadSourcePath,
FilePosition=partIndex,
零件尺寸=转移尺寸,
零件号=零件号,
UploadId=UploadId,
IsLastPart=transferSize

对于任何错误和帮助,我们深表歉意。

感谢您尝试在链接帖子中使用我的实现

虽然我没有读过任何明确支持这一点的文章,但我认为AmazonS3加密客户端可能与多部分上传不兼容。虽然它不是确定的,但我还没有找到一个在多部分上传上同时使用AmazonS3加密客户端的Java示例(SDK有一个KMS实现)。我怀疑的原因是,文件是使用链式块加密的,如果多部分上传的每个部分都是逐段加密的,链式块将被破坏,每个部分的单独初始化向量将丢失以进行解密


我想知道的唯一方法就是首先用Java测试它。

在经过大量测试和在git hub上进行了少量代码探索之后
      while (bytesRemaining > 0)
      {
          long transferSize = bytesRemaining > partSize ? partSize : bytesRemaining;
          long partIndex = fileLength - bytesRemaining;

          bytesRemaining -= transferSize;
          bool isLastPart = bytesRemaining == 0;

          partNumber++;

          UploadPartResponse resp =
              cryptoClient.UploadPart(
                  new UploadPartRequest()
                  {
                      BucketName   = bucketName,
                      Key          = keyName,
                      FilePath     = uploadSourcePath,
                      FilePosition = partIndex,
                      PartSize     = isLastPart ? 0 : transferSize,
                      PartNumber   = partNumber,
                      UploadId     = uploadId,
                      IsLastPart   = isLastPart 
                  });

          partETags.Add( new PartETag( partNumber, resp.ETag ));
      }