title: How to generate HMAC-SHA1 signature for oAuth
body: <p>I'm using the code below for generating <code>HMAC-SHA1</code> signature, but I get this error during authentication request:</p>
  
  <blockquote>
    <p>"oauth_signature does not match expected value"</p>
  </blockquote>
  
  <p>Can anyone tell me how to generate correct signature? I also checked <a href="https://github.com/OAuthSwift/OAuthSwift" rel="nofollow noreferrer">oAuthSwift</a> library <code>allHTTPHeaderFields</code> for Tumblr and it works on this code.</p>
  
  <pre><code>Tumblr_oAuth-Bridging-Header.h
  #import &lt;CommonCrypto/CommonHMAC.h&gt;
  </code></pre>
  
  <p>And</p>
  
  <pre><code>class ViewController: UIViewController {
  
      let consumerKey = "SpFweFQePdB1I6GnbX2TKCrnD8sObObExERLtw1RBcaEZPFV26"
      let consumerSecret = "HCLK7WnNuZM7ohCoSqNixNhCs2YmASfnL8tkYaQvuh9DEj05o3"
      let requestTokenUrl = "www.tumblr.com/oauth/request_token"
      let authorizeUrl = "https://www.tumblr.com/oauth/authorize"
      let accessTokenUrl = "https://www.tumblr.com/oauth/access_token"
      let oauthTokenSecret = ""
  
      @IBAction func login(_ sender: Any) {
  
          let oauth_timestamp = String(Int64(Date().timeIntervalSince1970))
          let oauth_nonce = generateNonce()//: CFString = CFUUIDCreateString(nil, uuid)
  
          let parameters =  ["oauth_timestamp": "\(oauth_timestamp)", "oauth_callback": "oauth-swift://oauth-callback/tumblr", "oauth_signature_method": "HMAC-SHA1", "oauth_version": "1.0", "oauth_consumer_key": "SpFweFQePdB1I6GnbX2TKCrnD8sObObExERLtw1RBcaEZPFV26", "oauth_nonce": "\(oauth_nonce)"]
  
          let url = URL(string:"https://www.tumblr.com/oauth/request_token")
          let method = "POST"
  
          let encodedTokenSecret = self.oauthTokenSecret.urlEncoded
          let encodedConsumerSecret = self.consumerSecret.urlEncoded
  
          let signingKey = "\(encodedConsumerSecret)&amp;\(encodedTokenSecret)"
          print(parameters)
          var parameterComponents = parameters.urlEncodedQuery.components(separatedBy: "&amp;")
          parameterComponents.sort {
              let p0 = $0.components(separatedBy: "=")
              let p1 = $1.components(separatedBy: "=")
              if p0.first == p1.first { return p0.last ?? "" &lt; p1.last ?? "" }
              return p0.first ?? "" &lt; p1.first ?? ""
          }
  
          let parameterString = parameterComponents.joined(separator: "&amp;")
          let encodedParameterString = parameterString.urlEncoded
          let encodedURL = url?.absoluteString.urlEncoded
  
          let signatureBaseString = "\(method)&amp;\(String(describing: encodedURL))&amp;\(encodedParameterString)"
  
          let key = signingKey//.data(using: .utf8)!
          let msg = signatureBaseString//.data(using: .utf8)!
  
          let signature : String = msg.hmac(algorithm: HMACAlgorithm.SHA1, key: key)
          print("signature",signature)
  
          var request = URLRequest(url: URL(string: "https://www.tumblr.com/oauth/request_token")!)
  
          request.allHTTPHeaderFields = ["Authorization": "OAuth oauth_callback=\"oauth-swift%3A%2F%2Foauth-callback%2Ftumblr\", oauth_consumer_key=\"SpFweFQePdB1I6GnbX2TKCrnD8sObObExERLtw1RBcaEZPFV26\", oauth_nonce=\"\(oauth_nonce)\", oauth_signature=\"\(signature.urlEncoded)\", oauth_signature_method=\"HMAC-SHA1\", oauth_timestamp=\"\(oauth_timestamp)\", oauth_version=\"1.0\""]
  
          request.httpMethod = "POST"
          let task = URLSession.shared.dataTask(with: request) { data, response, error in
              guard let data = data, error == nil else {                                                 // check for fundamental networking error
                  print("error=\(String(describing: error))")
                  return
              }
  
              if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode != 200 {           // check for http errors
                  print("statusCode should be 200, but is \(httpStatus.statusCode)")
                  print("response = \(String(describing: response))")
              }
  
              let responseString = String(data: data, encoding: .utf8)
              print("responseString = \(String(describing: responseString))")
          }
          task.resume()
      }
  
      override func viewDidLoad() {
          super.viewDidLoad()
  
      }
  }
  public func generateNonce() -&gt; String {
      let uuidString = UUID().uuidString
      return uuidString.substring(to: 8)
  }
  enum HMACAlgorithm {
      case MD5, SHA1, SHA224, SHA256, SHA384, SHA512
  
      func toCCHmacAlgorithm() -&gt; CCHmacAlgorithm {
          var result: Int = 0
          switch self {
          case .MD5:
              result = kCCHmacAlgMD5
          case .SHA1:
              result = kCCHmacAlgSHA1
          case .SHA224:
              result = kCCHmacAlgSHA224
          case .SHA256:
              result = kCCHmacAlgSHA256
          case .SHA384:
              result = kCCHmacAlgSHA384
          case .SHA512:
              result = kCCHmacAlgSHA512
          }
          return CCHmacAlgorithm(result)
      }
  
      func digestLength() -&gt; Int {
          var result: CInt = 0
          switch self {
          case .MD5:
              result = CC_MD5_DIGEST_LENGTH
          case .SHA1:
              result = CC_SHA1_DIGEST_LENGTH
          case .SHA224:
              result = CC_SHA224_DIGEST_LENGTH
          case .SHA256:
              result = CC_SHA256_DIGEST_LENGTH
          case .SHA384:
              result = CC_SHA384_DIGEST_LENGTH
          case .SHA512:
              result = CC_SHA512_DIGEST_LENGTH
          }
          return Int(result)
      }
  }
  extension String {
      func hmac(algorithm: HMACAlgorithm, key: String) -&gt; String {
          let cKey = key.cString(using: String.Encoding.utf8)
          let cData = self.cString(using: String.Encoding.utf8)
          var result = [CUnsignedChar](repeating: 0, count: Int(algorithm.digestLength()))
          CCHmac(algorithm.toCCHmacAlgorithm(), cKey!, strlen(cKey!), cData!, strlen(cData!), &amp;result)
          let hmacData:NSData = NSData(bytes: result, length: (Int(algorithm.digestLength())))
          let hmacBase64 = hmacData.base64EncodedString(options: NSData.Base64EncodingOptions.lineLength76Characters)// Encoding76CharacterLineLength)
          return String(hmacBase64)
      }
  
      var urlEncoded: String {
          let customAllowedSet = CharacterSet(charactersIn: "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._~")
          return self.addingPercentEncoding(withAllowedCharacters: customAllowedSet)!
      }
  
      var urlQueryEncoded: String? {
          return self.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed)
      }
  
      func substring(to offset: String.IndexDistance) -&gt; String {
          let to = self.index(self.startIndex, offsetBy: offset)
          return String(self[..&lt;to])
      }
  }
  extension Dictionary {
  
      var urlEncodedQuery: String {
          var parts = [String]()
  
          for (key, value) in self {
              let keyString = "\(key)".urlEncoded
              let valueString = "\(value)".urlEncoded
              let query = "\(keyString)=\(valueString)"
              parts.append(query)
          }
  
          return parts.joined(separator: "&amp;")
      }
  
  }
  </code></pre>