在ios中通过标头进行AWS授权失败

在ios中通过标头进行AWS授权失败,ios,swift,amazon-web-services,amazon-elastic-beanstalk,hmac,Ios,Swift,Amazon Web Services,Amazon Elastic Beanstalk,Hmac,我为GET请求创建了一个名为AWSS3RequestSignerGET的类。还创建字符串和数据扩展以生成字节数组。下面给出了所有代码。如果要运行此代码,需要导入CommonCrypto。此请求与PUT配合正常,但与GET配合无效。 我在GET请求中只删除了身体部位。我使用的是与PUT请求中使用的accessKeyId和secretAccessKey相同的 {“message”:“我们计算的请求签名与 您提供的签名。请检查您的AWS秘密访问密钥和签名 方法。有关详细信息,请参阅服务文档。“} 类A

我为GET请求创建了一个名为AWSS3RequestSignerGET的类。还创建
字符串
数据
扩展以生成字节数组。下面给出了所有代码。如果要运行此代码,需要导入
CommonCrypto
。此请求与
PUT
配合正常,但与
GET
配合无效。 我在
GET
请求中只删除了身体部位。我使用的是与
PUT
请求中使用的
accessKeyId
secretAccessKey
相同的

{“message”:“我们计算的请求签名与 您提供的签名。请检查您的AWS秘密访问密钥和签名 方法。有关详细信息,请参阅服务文档。“}

类AWSS3RequestSignerGET:NSObject{
私有let hmacShaTypeString=“AWS4-HMAC-SHA256”
私人出租awsRegion=“us-west-1”
私有let serviceType=“es”
私人出租aws4Request=“aws4\U请求”
私有let ISO8601格式:日期格式={
let formatter=DateFormatter()
formatter.calendar=日历(标识符:.iso8601)
formatter.locale=locale(标识符:“en_US_POSIX”)
formatter.timeZone=时区(秒自GMT:0)
formatter.dateFormat=“yyyyMMdd'T'hhmmsxxx”
返回格式化程序
}()
私有函数iso8601()->(完整:字符串,短:字符串){
让date=iso8601Formatter.string(from:date())
let index=date.index(date.startIndex,偏移量:8)
设shortDate=date.substring(to:index)
返回(完整:日期,短:短日期)
}
func signGET(请求:URLRequest,secretSigningKey:String,accessKeyId:String)->URLRequest{
var signedRequest=请求
let date=iso8601()
guard let url=signedRequest.url,let host=url.host
else{return.none}
signedRequest.addValue(主机,forHTTPHeaderField:“主机”)
signedRequest.addValue(date.full,用于httpheaderfield:“X-Amz-date”)
guard let headers=signedRequest.allHTTPHeaderFields,let method=signedRequest.httpMethod
else{return.none}
让signedHeaders=headers.map{$0.key.lowercased()}.sorted().joined(分隔符:“;”)
让canonicalRequestHash=[
方法,,
url.path,
url.query???“”,
headers.map{$0.key.lowercased()+”:“+$0.value}.sorted().joined(分隔符:“\n”),
"",
签名标题
].joined(分隔符:“\n”).sha256()
let credential=[date.short,awsRegion,serviceType,aws4Request]。已加入(分隔符:“/”)
让stringToSign=[
hmacShaTypeString,
date.full,
资质
规范请求哈希
].已加入(分隔符:“\n”)
guard let signature=signatureWith(stringToSign:stringToSign,secretAccessKey:secretSigningKey,shortDateString:date.short)
else{return nil}
让authorization=hmacShaTypeString+“Credential=“+accessKeyId+”/“+Credential+”,SignedHeaders=“+SignedHeaders+”,Signature=“+Signature
signedRequest.addValue(授权,用于HttpHeaderField:“授权”)
返回签名请求
}
private func getCredential(日期:String,accessKeyId:String)->String{
let credential=[日期,AWS区域,服务类型,aws4Request]。已加入(分隔符:“/”)
返回凭证
}
/*
DateKey=HMAC-SHA256(“AWS4”+“”,“”)
DateRegionKey=HMAC-SHA256(,“”)
DateRegionServiceKey=HMAC-SHA256(,“”)
SigningKey=HMAC-SHA256(,“aws4_请求”)
*/
private func signatureWith(stringToSign:String,secretAccessKey:String,shortDateString:String)->String{
让firstKey=“AWS4”+secretAccessKey
让dateKey=shortDateString.hmac(键串:firstKey)
让dateRegionKey=awsRegion.hmac(keyData:dateKey)
让dateRegionServiceKey=serviceType.hmac(keyData:dateRegionKey)
让signingKey=aws4Request.hmac(keyData:dateRegionServiceKey)
let signature=stringToSign.hmac(keyData:signingKey)
返回签名。toHexString()
}
}
扩展字符串{
func sha256()->字符串{
guard let data=self.data(使用:.utf8)else{return”“}
var hash=[UInt8](重复:0,计数:Int(CC_SHA256_DIGEST_LENGTH))
data.withUnsafeBytes{
_=CC_SHA256($0,CC_LONG(data.count)和散列)
}
让outputData=数据(字节:散列)
返回outputData.toHexString()
}
func hmac(键串:字符串)->数据{
变量摘要=[UInt8](重复:0,计数:Int(抄送摘要长度))
CCHmac(CCHmacAlgorithm(kCCHmacAlgSHA256)、键串、键串.count、self、self.count和摘要)
让数据=数据(字节:摘要)
返回数据
}
func hmac(键数据:数据)->数据{
设keyBytes=keyData.bytes()
让data=self.cString(使用:String.Encoding.utf8)
让dataLen=Int(self.lengthOfBytes(使用:String.Encoding.utf8))
var result=[UInt8](重复:0,计数:Int(CC_SHA256_DIGEST_LENGTH))
CCHmac(CCHmacAlgorithm(kCCHmacAlgSHA256)、keyBytes、keyData.count、data、dataLen和result);
返回数据(字节:结果)
}
}
扩展数据{
func toHexString()->String{
让hexString=self.map{String(格式:'%02x',$0)}.joined()
返回十六进制字符串
}
func bytes()->[UInt8]{
让数组=[UInt8](自)
返回数组
}
}

您有一个移动应用程序。不要将访问密钥嵌入应用程序,即使是在加密存储中。相反,使用AmazonCognito来管理应用程序中的用户身份。此服务允许您使用Ama登录对用户进行身份验证
class AWSS3RequestSignerGET: NSObject {
    
    private let hmacShaTypeString = "AWS4-HMAC-SHA256"
    private let awsRegion = "us-west-1"
    private let serviceType = "es"
    private let aws4Request = "aws4_request"
    
    private let iso8601Formatter: DateFormatter = {
        let formatter = DateFormatter()
        formatter.calendar = Calendar(identifier: .iso8601)
        formatter.locale = Locale(identifier: "en_US_POSIX")
        formatter.timeZone = TimeZone(secondsFromGMT: 0)
        formatter.dateFormat = "yyyyMMdd'T'HHmmssXXXXX"
        return formatter
    }()
    
    private func iso8601() -> (full: String, short: String) {
        let date = iso8601Formatter.string(from: Date())
        let index = date.index(date.startIndex, offsetBy: 8)
        let shortDate = date.substring(to: index)
        return (full: date, short: shortDate)
    }
    
    func signGET(request: URLRequest, secretSigningKey: String, accessKeyId: String) -> URLRequest? {
        var signedRequest = request
        
        let date = iso8601()
        
        guard let url = signedRequest.url, let host = url.host
            else { return .none }
        signedRequest.addValue(host, forHTTPHeaderField: "Host")
        signedRequest.addValue(date.full, forHTTPHeaderField: "X-Amz-Date")
        
        guard let headers = signedRequest.allHTTPHeaderFields, let method = signedRequest.httpMethod
            else { return .none }
        
        let signedHeaders = headers.map{ $0.key.lowercased() }.sorted().joined(separator: ";")
        
        let canonicalRequestHash = [
            method,
            url.path,
            url.query ?? "",
            headers.map{ $0.key.lowercased() + ":" + $0.value }.sorted().joined(separator: "\n"),
            "",
            signedHeaders
        ].joined(separator: "\n").sha256()
        
        let credential = [date.short, awsRegion, serviceType, aws4Request].joined(separator: "/")
        
        let stringToSign = [
            hmacShaTypeString,
            date.full,
            credential,
            canonicalRequestHash
            ].joined(separator: "\n")
        
        guard let signature = signatureWith(stringToSign: stringToSign, secretAccessKey: secretSigningKey, shortDateString: date.short)
            else { return nil }
        
        let authorization = hmacShaTypeString + " Credential=" + accessKeyId + "/" + credential + ", SignedHeaders=" + signedHeaders + ", Signature=" + signature
        signedRequest.addValue(authorization, forHTTPHeaderField: "Authorization")
        
        return signedRequest
    }
    
    private func getCredential(date: String, accessKeyId: String) -> String {
        let credential = [date, awsRegion, serviceType, aws4Request].joined(separator: "/")
        return credential
    }
    
    /*
 DateKey              = HMAC-SHA256("AWS4"+"<SecretAccessKey>", "<YYYYMMDD>")
 DateRegionKey        = HMAC-SHA256(<DateKey>, "<aws-region>")
 DateRegionServiceKey = HMAC-SHA256(<DateRegionKey>, "<aws-service>")
 SigningKey           = HMAC-SHA256(<DateRegionServiceKey>, "aws4_request")
 */
    private func signatureWith(stringToSign: String, secretAccessKey: String, shortDateString: String) -> String? {
        let firstKey = "AWS4" + secretAccessKey
        let dateKey = shortDateString.hmac(keyString: firstKey)
        let dateRegionKey = awsRegion.hmac(keyData: dateKey)
        let dateRegionServiceKey = serviceType.hmac(keyData: dateRegionKey)
        let signingKey = aws4Request.hmac(keyData: dateRegionServiceKey)
        let signature = stringToSign.hmac(keyData: signingKey)
      
        return signature.toHexString()
    }
}

extension String {
    
    func sha256() -> String {
        guard let data = self.data(using: .utf8) else { return "" }
        var hash = [UInt8](repeating: 0,  count: Int(CC_SHA256_DIGEST_LENGTH))
        data.withUnsafeBytes {
            _ = CC_SHA256($0, CC_LONG(data.count), &hash)
        }
        let outputData = Data(bytes: hash)
        return outputData.toHexString()
    }
    
    func hmac(keyString: String) -> Data {
        var digest = [UInt8](repeating: 0, count: Int(CC_SHA256_DIGEST_LENGTH))
        CCHmac(CCHmacAlgorithm(kCCHmacAlgSHA256), keyString, keyString.count, self, self.count, &digest)
        let data = Data(bytes: digest)
        return data
    }
    
    func hmac(keyData: Data) -> Data {
        let keyBytes = keyData.bytes()
        let data = self.cString(using: String.Encoding.utf8)
        let dataLen = Int(self.lengthOfBytes(using: String.Encoding.utf8))
        var result = [UInt8](repeating: 0, count: Int(CC_SHA256_DIGEST_LENGTH))
        CCHmac(CCHmacAlgorithm(kCCHmacAlgSHA256), keyBytes, keyData.count, data, dataLen, &result);
        
        return Data(bytes: result)
    }
}

 extension Data {
    func toHexString() -> String {
        let hexString = self.map{ String(format:"%02x", $0) }.joined()
        return hexString
    }
    
    func bytes() -> [UInt8] {
        let array = [UInt8](self)
        return array
    }
}