簡體   English   中英

HMAC SHA256 JWT簽名不正確

[英]HMAC SHA256 JWT Signature is incorrect

答案:

我現在正在使用的功能不是下面的hmac func ...

func base64Encoded(algorithm: CryptoAlgorithm, key: String) -> String {
  let hmac = self.hmac(algorithm: algorithm, key: key)
  let digestLen = algorithm.digestLength
  let dataResult = NSData(bytes: hmac, length: digestLen)
  hmac.deallocateCapacity(digestLen)

  return dataResult.base64EncodedString()
}

func hash(algorithm: CryptoAlgorithm, key: String) -> String {
  let hmac = self.hmac(algorithm: algorithm, key: key)
  let digestLen = algorithm.digestLength
  let hash = NSMutableString()

  for i in 0..<digestLen {
    hash.appendFormat("%02x", hmac[i])
  }

  hmac.deallocateCapacity(digestLen)

  return hash as String 
}

func hmac(algorithm: CryptoAlgorithm, key: String) -> UnsafeMutablePointer<CUnsignedChar> {
  let str = self.cString(using: String.Encoding.utf8)
  let strLen = Int(self.lengthOfBytes(using: String.Encoding.utf8))
  let digestLen = algorithm.digestLength

  let result = UnsafeMutablePointer<CUnsignedChar>(allocatingCapacity: digestLen)

  let keyStr = key.cString(using: String.Encoding.utf8)
  let keyLen = Int(key.lengthOfBytes(using: String.Encoding.utf8))

  CCHmac(algorithm.HMACAlgorithm, keyStr!, keyLen, str!, strLen, result)

  return result
}

原始帖子

我有一個JWT,我正在嘗試驗證簽名。 這是JWT ...

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJhcGkudGVzdC5jb20vdjEvYXV0aCIsImV4cCI6MTQ2OTk3ODQ5OCwic3ViIjoiMTIzNDU2Nzg5MCIsImVtYWlsIjoidGVzdEB0ZXN0LmNvbSIsInJvbGVzIjpbImFkbWluIiwiY3VzdG9tZXIiXSwicGVybWlzc2lvbnMiOlsidGVzdC5wcm9maWxlIiwidGVzdC5wcm9maWxlLmNvbnRhY3QiLCJ0ZXN0LnByb2ZpbGUuZGV2aWNlIiwidGVzdC5wcm9maWxlLmFwcCJdfQ.GfLxXOL978Pm5GYMI0WTBEVcMrfVj2jJb-Il_XzO7g4

我在Swift 3中工作,我更新了此SO回答https://stackoverflow.com/a/24411522/741626中的方法。 這就是這些方法現在的樣子。

import Foundation

enum CryptoAlgorithm {
  case MD5, SHA1, SHA224, SHA256, SHA384, SHA512

    var HMACAlgorithm: 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)
}

var digestLength: Int {
  var result: Int32 = 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: CryptoAlgorithm, key: String) -> String {
  let str = self.cString(using: String.Encoding.utf8)
  let strLen = Int(self.lengthOfBytes(using: String.Encoding.utf8))
  let digestLen = algorithm.digestLength

  let result = UnsafeMutablePointer<CUnsignedChar>(allocatingCapacity: digestLen)

  let keyStr = key.cString(using: String.Encoding.utf8)
  let keyLen = Int(key.lengthOfBytes(using: String.Encoding.utf8))

  CCHmac(algorithm.HMACAlgorithm, keyStr!, keyLen, str!, strLen, result)

  let hash = NSMutableString()
  for i in 0..<digestLen {
    hash.appendFormat("%02x", result[i])
  }

  result.deallocateCapacity(digestLen)

  return hash as String

}

我能夠成功base64Decode標頭和有效載荷,但是當我嘗試驗證簽名時,它總是錯誤的(看起來不像AND太長了)。

我嘗試過的

1我嘗試了幾個JWT-總是以相同的方式出錯

2我已經硬編碼了sha256常量,以確保我沒有使用錯誤的編碼/長度

3我已經嘗試了許多類型的String.Encoding,但是盡管它們總是按預期生成不同的結果,但是它們都不生成所需的簽名。

4我使用了Objective-C方法來生成hmac,以嘗試排除我向Swift 3的轉換是否中斷了任何事情。 結果相同,這是Objective C代碼。

+ (NSData *)hmacSha256:(NSString *)string key:(NSString *)key;
{
  NSData *dataIn = [string dataUsingEncoding:NSUTF8StringEncoding];
  NSData *keyIn = [key dataUsingEncoding:NSUTF8StringEncoding];
  NSMutableData *macOut = [NSMutableData dataWithLength:CC_SHA256_DIGEST_LENGTH];

  CCHmac( kCCHmacAlgSHA256,
       keyIn.bytes,
       keyIn.length,
       dataIn.bytes,
       dataIn.length,
       macOut.mutableBytes);

  return macOut;
}

該代碼源自此處: https : //stackoverflow.com/a/31003443/741626 我寧願不將Objective-C代碼插入我的Swift項目,但如果需要的話,我會的!

這是我的電話功能

func decodeToken(token: String) {
  let array = token.characters.split(isSeparator: { $0 == "." })
.map(String.init)

  let header:String = String(array[0])
  let payload:String = String(array[1])
  let signature:String = String(array[2])

  let encodedString = header + "." + payload
  let hmac = encodedString.hmac(algorithm: .SHA256, key: "")
}

編輯

當我運行代碼時,生成的hmac是

19f2f15ce2fdefc3e6e4660c23459304455c32b7d58f68c96fe225fd7cceee0e

我已經三重檢查了機密是否正確,即“” (空字符串)

我究竟做錯了什么?

我真的很想在客戶端應用程序中測試我收到的令牌是否值得信任,而不是掩飾這一點。 如果有人有任何想法,我做錯了,那將很棒。

實際上,您生成的值是正確的。 只是您正在查看HMAC值的十六進制表示形式(以及哈希函數),而JWT哈希當然是base64url編碼的。

為了驗證哈希,比較字節值而不是編碼值很重要。 編碼值僅用於人類消費(十六進制)或通過需要文本的協議進行傳輸(base64url)。


執行字節數組比較時,請確保它是時間常數,否則可能會引入漏洞。

一種方法是對字節進行XOR,然后將結果與OR生成結果字節。 然后針對00h測試該結果字節(任何其他值表示無效的比較)。 首先拒絕大小不正確的數組。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM