JWT проверяет подпись, используя HMACSHA256, и показывает «Недействительную подпись» Swift - PullRequest
2 голосов
/ 20 мая 2019

У меня есть вопрос по поводу JWT.
Я пытаюсь создать собственную подпись и использовать секретный ключ с жестким кодом "hello1234567890987654321test1234".
И я использую свою функцию для создания подписи и отправляю на https://jwt.io/ для декодирования.
Тогда этот веб-сайт покажет мне «Неверная подпись».
Что не так со мной в функции HMACSHA256?
И я нашел «-», «_» на веб-сайте и преобразовал «+», «/» в мою выходную подпись.
Как исправить мою выходную подпись?
Эта подпись верна?

Я также нахожу два метода поиска HMACSHA256 в Google. Я не знаю, что лучше.
пожалуйста, дайте мне несколько советов по выбору этого.
Спасибо.

Изображение: Question Image.

Method1:

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 hmac1(algorithm: CryptoAlgorithm, key: String) -> String {
        var result: [CUnsignedChar]
        if let ckey = key.cString(using: String.Encoding.utf8), let cdata = self.cString(using: String.Encoding.utf8) {
            result = Array(repeating: 0, count: Int(algorithm.digestLength))
            CCHmac(algorithm.HMACAlgorithm, ckey, ckey.count-1, cdata, cdata.count-1, &result)
        } else {
            fatalError("Nil returned when processing input strings as UTF8")
        }

        return Data(bytes: result, count: result.count).base64EncodedString()
    }
}

Метод2:

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

    func toCCHmacAlgorithm() -> 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() -> 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 hmac2(algorithm: HMACAlgorithm, key: String) -> 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!), &result)
        let hmacData:NSData = NSData(bytes: result, length: (Int(algorithm.digestLength())))
        let hmacBase64 = hmacData.base64EncodedString(options: .lineLength76Characters)
        return String(hmacBase64)
    }
}

Использование:

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        let headerString: String = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9"
        let payloadString: String = "eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ"
        let totalString: String = headerString + "." + payloadString

        let signature1 = totalString.hmac1(algorithm: .SHA256, key: "hello1234567890987654321test1234")
        let signature2 = totalString.hmac2(algorithm: .SHA256, key: "hello1234567890987654321test1234")

        print("signature1 : \(signature1)") // signature1 : L9YSDasvO2B5i8FZUczC+MAtSsTuM0Dj+FEpfn6uoRs=
        print("signature2 : \(signature2)") // signature2 : L9YSDasvO2B5i8FZUczC+MAtSsTuM0Dj+FEpfn6uoRs=

    }
}

1 Ответ

1 голос
/ 20 мая 2019

Проблема в кодировке. JWT использует кодировку base64url :

JWT представляется как последовательность URL-безопасных частей, разделенных символами точки ('.').Каждая часть содержит значение в кодировке base64url.

, но вы используете кодировку base64 в подписи, как показано в примере кода.

Разница между base64url-кодировкой и base64-кодировкой заключается в том, что символы '+' и '/' из обычного вывода base64 будут заменены на '-' и '_' иТрейлинг '=' (отступ) будет опущен.

Вы говорите:

И я нашел "-", "_" в веб-сайте и преобразовал "+", "/"в моей выходной подписи.

С '-' и '_' вместо '+' и '/' вы получите правильный вывод.

Если у вас есть закодированная base64url подпись, такая как

1025 * eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.L9YSDasvO2B5i8FZUczC-MAtSsTuM0Dj-FEpfn6uoRs

подпись Виль быть проверено.

...