yourkarma / JWT

A JSON Web Token implementation in Objective-C.
MIT License
351 stars 107 forks source link

Could not verify RS256 signature #183

Open stansmida opened 6 years ago

stansmida commented 6 years ago

New Issue Checklist

Issue Info

Info Value
Platform Name ios
Platform Version 11.2
CocoaLumberjack Version
Integration Method cocoapods
Xcode Version Xcode 9.2
Repro rate all the time (100%)
Demo project link

Issue Description and Steps

Self-explanatory code:

    let jwt = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.EkN-DOsnsuRjRO6BxXemmJDm3HbxrbRzXglbN2S4sOkopdU4IsDxTI8jO19W_A4K8ZPJijNLis4EZsHeY559a4DFOd50_OqgHGuERTqYZyuhtF39yxJPAjUESwxk2J5k_4zM3O-vtd1Ghyo4IbqKKSy6J9mTniYJPenn5-HIirE"
    let publicKey = "-----BEGIN PUBLIC KEY-----MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDdlatRjRjogo3WojgGHFHYLugdUWAY9iR3fy4arWNA1KoS8kVw33cJibXr8bvwUAUparCwlvdbH6dvEOfou0/gCFQsHUfQrSDv+MuSUMAe8jzKE4qW+jK+xQU9a03GUnKHkkle+Q0pX/g6jXZ7r1/xAK5Do2kQ+X5xK9cipRgEKwIDAQAB-----END PUBLIC KEY-----"
    let builder = JWTBuilder.decodeMessage(jwt)!.algorithmName(JWTAlgorithmNameRS256)!.secret(publicKey)!
    let decodedToken = builder.decode // This is nil
    print(builder.jwtError) // Error Domain=io.jwt Code=-97 "Invalid signature! It seems that signed part of jwt mismatch generated part by algorithm provided in header." UserInfo={NSLocalizedDescription=Invalid signature! It seems that signed part of jwt mismatch generated part by algorithm provided in header., errorDescription=JWTInvalidSignatureError}

The public key is correct and valid, (works on different platforms like Android, you can also test it via jwt.io). I tried to pass the key without begin/end delimiters without luck. I seriously don’t know how to use this framework… I appreciate any help. Thanks!

lolgear commented 6 years ago

Try to check it via JWTDesktop macOS application.

It seems this key is not well-formed ( has incorrect size ) for Apple Security framework. Look for related error in logs.

You could check Apple error ( It was hidden in case of exception ).

// JWTAlgorithmRSBaseMac
- (BOOL)checkKeyConsistency:(SecKeyRef)key {
    //  return YES; // add it.
    size_t keyLength = SecKeyGetBlockSize(key);
    size_t hashBytesSize = self.ccSHANumberDigestLength;
    Byte bitsPerByte = /*???*/sizeof(Byte) * CHAR_BIT;
    return keyLength == hashBytesSize * bitsPerByte;
}
stansmida commented 6 years ago

Sorry I really don't have time for that. I would expect you could investigate the problem. The public key is for sure correct and in standard format and this framework for some reason cannot process it. If you could please let me know what format of public key does Security framework expect, if it is possible to convert given key to that format. Any other library at https://jwt.io/#libraries-io is okay with the key, you are the only one for iOS with RS256 support but I'm struggling to use it.

lolgear commented 6 years ago

@stanislavsmida you don't have time to put your key in sandbox app in this repository. Interesting.

Most of these libraries use OpenSSL. Thus, their implementation is simple and naive. However, Apple doesn't recommend to use OpenSSL ( it was removed in earlier versions of iOS and macOS as unreliable ).

Security framework is more strict and neat in handling security-related transforms. Therefore, their library expect correct input.

Look at https://github.com/jsonwebtoken/jsonwebtoken.github.io/issues/276

lolgear commented 6 years ago

@stanislavsmida check latest master.

johntothee commented 6 years ago

@lolgear I'm seeing the same thing testing with 3.0.0-beta.8. I also tried a set of my own keys/token and using .secretData() instead of .secret()

        let secretData = Data(base64Encoded: publicKey, options: [.ignoreUnknownCharacters])
        let builder = JWTBuilder.decodeMessage(jwt)!.algorithmName("RS256")!.secretData(secretData)!

Error Domain=io.jwt Code=-97 "Invalid signature! It seems that signed part of jwt mismatch generated part by algorithm provided in header." UserInfo={NSLocalizedDescription=Invalid signature! It seems that signed part of jwt mismatch generated part by algorithm provided in header., errorDescription=JWTInvalidSignatureError}

johntothee commented 6 years ago

@stanislavsmida, I was able to get this to work using a different way of setting up the JWTBuilder referencing this issue: https://github.com/yourkarma/JWT/issues/152

        let jwt = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1aWQiOiIxIiwiY29tbWFuZCI6InZlcmlmeSIsImlhdCI6MTUyMDk3NDc2Mn0.JW6tHgGAG4989YS0S-cufr3XmR6FWx5zIqTy0TAKa1BeVoFF5dPthyL4u73ojY5Yx127eb3UddJFMNxRBBeJalK6tgEgBupoVEdUnZOSNhI22o_xplVmdf_0cGpE2E63IpxasUkGijJEkKme457g_areBVUFLtPwuQ-3XyiptMw3WAuDgXmIcfxBuU1v2RuJBXCT8zvU-bynQzndlndWoC5jU1f6gFaTebJK51W4weLinXn9cjwFiQ26GYHpWpXn0Pc6T2fe8d0Bjxfqz3QfzO7WxzIG2ZimiIEYQb2PFubEQU4UbBT3zBRAlPhd_7FY8hmjJCoIL9GjlPbZQ6ut0Q"
        let publicKey = "-----BEGIN PUBLIC KEY-----MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1REkFYbJJI8hmNlhEMOO3IikFlDzYERZfbfQVaLMQXQZfuiiRYEkfDfr8IW32Sn/6lHUzlTdpv4JjfpMRdKSAyrgZERzFQQHxuZ5SXbeT/vsSeBBiNvWrZG7irzYs5SLfE0KPiYcvXdwE7igWnM0CpY74DzHOp9t1FIyZbILsJGd+vyftvGF0u1Le/Z0t0ylR5LjMumoYCK7s6rfoIFb4cXISlUZfkTSBeCyxLn6zdjEkjT9miOsqaf2xucp4k9RVacs6LaYB07n1cAgNkI9BtrXqm3xwiYSWmBvVVX00/rodPTvdKDPvZdBYcvQWwgvjxYmqlnxiQ9ialYt2jHJ7QIDAQAB-----END PUBLIC KEY-----"
        let secretData = Data(base64Encoded: publicKey, options: [.ignoreUnknownCharacters])
        do {
            let crypto = try JWTCryptoKeyPublic(pemEncoded: publicKey, parameters: nil)
            let algorithm = JWTAlgorithmNameRS256
            guard let holder = JWTAlgorithmRSFamilyDataHolder().verifyKey(crypto as JWTCryptoKeyPublic)?.algorithmName(algorithm)?.secretData(Data()) else {
                return
            }

            guard let decoding: JWTDecodingBuilder = JWTDecodingBuilder.decodeMessage(jwt).addHolder(holder) as? JWTDecodingBuilder else{
                return
            }
            print(decoding.decode.successResult as Any)
            print(decoding.decode.errorResult?.error as Any)
        }
        catch {
            print(error)
        }

good luck

tmm1 commented 6 years ago

@johntothee How do you actually read the decoded message?

EDIT: decoding.decode.successResult.payload

johntothee commented 6 years ago

@tmm1 if you're just debugging, you can paste the encoded message here: https://jwt.io/ and it will tell you the contents of the header and payload. To verify the signature if you use asymmetric keys there are methods in the class to do that. I'm creating a signed token in swift and sending it to another app running node.js So I'm not sure how to do that off the top of my head. Good Luck.