在使用Amazon S3中的KMS密钥解密文件时出现错误

6

我正在尝试使用Amazon S3作为带有加密的文件系统。

我成功地使用KMS加密密钥(服务器端加密)将文件上传到AWS S3服务器。以下是可行的代码:

加密:

private static final String AWS_KMS_KEY = "---KMS Key---"
private static final String BUCKET_NAME = "---bucket name---"
private static final String keyName = "---display key name---"
private static final String filePath = "---File Path---"
private static final String ACCESS_KEY_ID = "---aws accesskey---"
private static final String SECRET_ACCESS_KEY = "---aws secret key---"

AWSCredentials awsCredentials = new BasicAWSCredentials(ACCESS_KEY_ID, SECRET_ACCESS_KEY);
AmazonS3 s3Client = AmazonS3ClientBuilder.standard().withCredentials(new AWSStaticCredentialsProvider(awsCredentials))
    .withRegion(Regions.US_WEST_2).withForceGlobalBucketAccessEnabled(true).build();

FileInputStream stream = new FileInputStream(filePath);

ObjectMetadata objectMetadata = new ObjectMetadata();
objectMetadata.setSSEAlgorithm(SSEAlgorithm.KMS.getAlgorithm());

PutObjectRequest putObjectRequest = new PutObjectRequest(amazonFileUploadLocationOriginal, keyName, stream, objectMetadata);
putObjectRequest.withCannedAcl(CannedAccessControlList.PublicRead);
putObjectRequest.withSSEAwsKeyManagementParams(new SSEAwsKeyManagementParams(AWS_KMS_KEY));

PutObjectResult result = s3Client.putObject(putObjectRequest);

我在进行服务器端解密时遇到了问题。我想要直接访问 AWS URL 以便进行解密并检索文件。以下是代码,但它无法正常工作:

对象读取:

没有 KMS 密钥的对象读取:

GetObjectRequest request = new GetObjectRequest(existingBucketName, amazonFileUploadLocationOriginal);
s3Client.getUrl(BUCKET_NAME, keyName); 

上述代码用于读取未使用KMS加密密钥的对象,但会出现以下错误:

错误代码:InvalidArgument

错误信息:使用AWS KMS托管密钥指定服务器端加密的请求需要AWS Signature Version 4。


使用KMS密钥读取对象:

GeneratePresignedUrlRequest genreq = new GeneratePresignedUrlRequest(BUCKET_NAME, keyName, HttpMethod.GET)
            .withSSEAlgorithm(SSEAlgorithm.KMS)
            .withKmsCmkId(AWS_KMS_KEY);

URL puturl = s3Client.generatePresignedUrl(genreq);

以下是用kms加密键预签名URL读取对象的代码,但会显示以下错误信息:

Code : SignatureDoesNotMatch

Message : The request signature we calculated does not match the signature you provided. Check your key and signing method.

请问这样做的方法正确吗?是否有任何建议?请帮忙解决。

1
我认为您需要强制使用签名版本4...但在生成GET URL时不要使用withSSEAlgorithm(SSEAlgorithm.KMS)。这可能会导致SDK对您将使用签名URL进行的实际请求内容做出错误的假设。 - Michael - sqlbot
谢谢 @Michael-sqlbot,它正在工作... - Jaimin Darji
1
现在我已经得到了正确的工作URL,可以自动下载PDF /图像文件,但我想要在浏览器查看器中显示,而不是自动下载。还有其他方法吗?或者有任何配置建议吗? - Jaimin Darji
如果您在S3控制台中检查对象元数据,它们是否显示正确的 Content-Type - Michael - sqlbot
如果您正在使用密钥管理服务(KMS)进行服务器端加密,则需要使用签名密钥生成预签名URL,该URL始终是新的,并且仅在有限的时间段内使用。如果您不使用服务器端加密,则无需生成预签名URL,直接访问您的存储桶文件即可。@Ahmed E. Eldeeb - Jaimin Darji
显示剩余3条评论
1个回答

1
如果签名不匹配,请使用以下代码手动添加参考 AWS Java SDK 手动设置签名版本 System.setProperty(SDKGlobalConfiguration.ENABLE_S3_SIGV4_SYSTEM_PROPERTY, "true"); 我们可以使用以下代码获取预先指定的URL。
GeneratePresignedUrlRequest genreq = new GeneratePresignedUrlRequest(BUCKET_NAME, keyName, HttpMethod.GET)
 .withExpiration(expiration);

URL puturl = s3Client.generatePresignedUrl(genreq);

这个URL将包含类似以下的到期时间和签名

https://mybucket.s3.amazonaws.com/abc_count.png?AWSAccessKeyId=AKIAJXXXXXXXXXXXXXXX&Expires=1503602631&Signature=ibOGfAovnhIF13DALdAgsdtg2s%3D

希望有人能帮助回答这个问题。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接