ios swift中的亚马逊AWS服务器端加密



在我的应用程序中,我将用户附加的图像上传到S3 bucket中,其中使用了服务器端加密。

我们在安卓系统中使用了以下代码来实现这一点,并且成功了。

try
{
SSECustomerKey sseCustomerKey = new SSECustomerKey(BuildConfig.S3_AES_ENCRYPT_KEY);
CognitoCachingCredentialsProvider sCredProvider = new CognitoCachingCredentialsProvider(mContext, AWSCognitoPoolId, Regions.fromName(Regions.US_EAST_1.getName()));
AmazonS3Client sS3Client = new AmazonS3Client(sCredProvider);
PutObjectRequest putRequest = new PutObjectRequest(BuildConfig.S3_BUCKET_NAME, file.getName(), file).withSSECustomerKey(sseCustomerKey);
sS3Client.putObject(putRequest);
sS3Client.setRegion(Region.getRegion(Regions.fromName(Regions.US_EAST_1.getName())));
}

但在iOS中,它不起作用。请找到以下iOS代码。

let transferManager = AWSS3TransferManager.default()
let uploadRequest = AWSS3TransferManagerUploadRequest()
uploadRequest?.bucket = bucketName
uploadRequest?.body = fileURL
uploadRequest?.key = imageName[i]
uploadRequest?.serverSideEncryption = .AES256
uploadRequest?.sseCustomerKey = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
uploadRequest?.contentType = "image/jpeg"
transferManager.upload(uploadRequest!).continueWith(block: { (task) -> AnyObject? in
if let error = task.error as NSError? {
if error.domain == AWSS3TransferManagerErrorDomain as String {
if let errorCode = AWSS3TransferManagerErrorType(rawValue: error.code) {
switch (errorCode) {
case .cancelled, .paused:
DispatchQueue.main.async {
}
break;
default:
print("upload() failed: [(error)]")
break;
}
} else {
print("upload() failed: [(error)]")
}
} else {
print("upload() failed: [(error)]")
}
}
return nil
})

我在iOS 中得到以下错误

upload((失败:[Error Domain=com.amazonaws.AWS3ErrorDomain Code=0"(null("UserInfo={RequestId=C7302D0F4DD27397,主机Id=Dm3itGpwZNcpPq28qfFkKDlB2VFbOzIYn01T270QzzVXJ9lmZWU2bX7oPXyXrG5A86OpfTrXSHw=,消息=使用客户提供的密钥进行服务器端加密与指定的加密方法不兼容,ArgumentValue=AES256,Code=InvalidArgument,ArgumentName=x-amz-server-side-encryption}]

请给我看看这个

我建议您使用TransferUtility而不是TransferManager。TransferManager正处于弃用状态,并且不具备TransferUtility所具有的所有功能。下面是一个代码片段,展示了如何使用服务器端加密上传文件。

let transferUtility = AWSS3TransferUtility.default()
let uploadExpression = AWSS3TransferUtilityUploadExpression()
uploadExpression.setValue("AES256", forRequestHeader: "x-amz-server-side-encryption")
uploadExpression.progressBlock = {(task, progress) in
print("Upload progress: ", progress.fractionCompleted)
}
let uploadCompletionHandler = { (task: AWSS3TransferUtilityUploadTask, error: Error?) -> Void in
if let error = error {
//Error completing transfer. Handle Error
}
else {
//Successfully uploaded.
......
return nil
}
}
transferUtility.uploadData(
data,
bucket: "bucket",
key: "key",
contentType: "contenttype",
expression: uploadExpression,
completionHandler: uploadCompletionHandler
).continueWith (block: { (task) -> Any? in
if let error = task.error {
//Error initiating transfer. Handle error
}
return nil
})
}

以下是有关如何使用TransferUtility的更多信息的链接-https://docs.aws.amazon.com/aws-mobile/latest/developerguide/how-to-transfer-files-with-transfer-utility.html

现在已经很多年了,但这个答案仍然会帮助一些人,并节省我所经历的搜索时间,TransferManager被弃用,所以现在我们使用transferUtility s3上传文件,但如果我们想加密文件,我们必须在头中发送3个密钥

expression.setValue("AES256", forRequestHeader: "x-amz-server-side-encryption-customer-algorithm")
expression.setValue(base64String, forRequestHeader: "x-amz-server-side-encryption-customer-key")
expression.setValue(md5String, forRequestHeader: "x-amz-server-side-encryption-customer-key-MD5")

这3个密钥是必要的,否则传输实用程序不会上传文件并给你一个错误,x-amz-server-side-encryption-customer算法这个密钥用于告诉你想要使用哪种加密算法,对于其他2个密钥,我们必须生成它们,示例代码是这样生成base64String和md5,有很多方法可以生成密钥,你可以查看CryptoSwift文档,我使用了Salt,这使它比暴力攻击更安全

let input: Array<UInt8> = [0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9]
let password: [UInt8] = Array("s33krit".utf8)
let salt: [UInt8] = Array("nacllcan".utf8)
let iv: Array<UInt8> = AES.randomIV(AES.blockSize)

DispatchQueue.global().async {
do {
let key = try PKCS5.PBKDF2(password: password, salt: salt, iterations: 4096, keyLength: 32, variant: .sha2(.sha224)).calculate()
let encrypted = try AES(key: key, blockMode: CBC(iv: iv), padding: .pkcs7).encrypt(input)
let base64String: String = encrypted.toBase64()
let md5Data = encrypted.md5()
let md5DataBase64 = md5Data.toBase64()
print("Encrypted:(encrypted),n Base64String:(base64String)")
print("md5:(md5Data),n md5String:(md5DataBase64)")
completion(base64String,md5DataBase64)
} catch {
print(error)
}
}

您必须使用CryptoSwift生成这些md5和base64String密钥以发送到标头中,这将把加密的文件上传到AWS,要打开或解密它,您必须使用相同的base64密钥

希望这将帮助某人并节省数小时的时间

最新更新