Hi again, thanks for the reply!
I have tried the .ecdsaSignatureMessageX962SHA384 algorithm before, but without converting the raw signature into X9.62 format.
This saves the day:
let dataSignatureX962 = try! P384.Signing.ECDSASignature(rawRepresentation: dataSignature).derRepresentation
It works now, thank you for your time and the support!
Post
Replies
Boosts
Views
Activity
Oh, sorry, it's a simple function to satisfy the base64 length requirements:
import Foundation
import CryptoKit
class JWTValidator {
static func validateSignature() {
let jwtToken = "eyJhbGciOiJFUzM4NCIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWUsImlhdCI6MTUxNjIzOTAyMn0.VUPWQZuClnkFbaEKCsPy7CZVMh5wxbCSpaAWFLpnTe9J0--PzHNeTFNXCrVHysAa3eFbuzD8_bLSsgTKC8SzHxRVSj5eN86vBPo_1fNfE7SHTYhWowjY4E_wuiC13yoj"
let publicKeyBase64 = "MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEC1uWSXj2czCDwMTLWV5BFmwxdM6PX9p+Pk9Yf9rIf374m5XP1U8q79dBhLSIuaojsvOT39UUcPJROSD1FqYLued0rXiooIii1D3jaW6pmGVJFhodzC31cy5sfOYotrzF"
let parts = jwtToken.components(separatedBy: ".")
let header = parts[0]
let payload = parts[1]
let signature = parts[2]
let dataPublicKey = Data(base64Encoded: publicKeyBase64)!
let dataSigned = (header + "." + payload).data(using: .ascii)!
let dataSignature = Data(base64Encoded: base64StringWithPadding(base64str: signature))!
if #available(iOS 14.0, *) {
let ck = try! P384.Signing.PublicKey(derRepresentation: dataPublicKey)
let x963 = ck.x963Representation
let publicKey = SecKeyCreateWithData(x963 as NSData, [
kSecAttrKeyType as String: kSecAttrKeyTypeECSECPrimeRandom,
kSecAttrKeyClass as String: kSecAttrKeyClassPublic,
] as NSDictionary, nil)!
print(publicKey)
// we have the SecKey representation of the public key.
// validate the JWT with the public key.
var validateError : Unmanaged<CFError>?
let algorithm: SecKeyAlgorithm = .eciesEncryptionStandardX963SHA384AESGCM
let result = SecKeyVerifySignature(publicKey,
algorithm,
dataSigned as NSData,
dataSignature as NSData,
&validateError)
if let validateError = validateError {
print(validateError)
}
print("JWT is valid: \(result)") // prints JWT is valid: false
}
}
static func base64StringWithPadding(base64str: String) -> String {
var newStr = base64str.replacingOccurrences(of: "-", with: "+")
.replacingOccurrences(of: "_", with: "/")
let count = newStr.count % 4
if count > 0 {
let amount = 4 - count
for _ in 0..<amount {
newStr += "="
}
}
return newStr
}
}
Hi, @escimo!
Were you able to try the example above?
Thank you!
I see now.
Here's the example:
import Foundation
import CryptoKit
let jwtToken = "eyJhbGciOiJFUzM4NCIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWUsImlhdCI6MTUxNjIzOTAyMn0.VUPWQZuClnkFbaEKCsPy7CZVMh5wxbCSpaAWFLpnTe9J0--PzHNeTFNXCrVHysAa3eFbuzD8_bLSsgTKC8SzHxRVSj5eN86vBPo_1fNfE7SHTYhWowjY4E_wuiC13yoj"
let publicKeyBase64 = "MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEC1uWSXj2czCDwMTLWV5BFmwxdM6PX9p+Pk9Yf9rIf374m5XP1U8q79dBhLSIuaojsvOT39UUcPJROSD1FqYLued0rXiooIii1D3jaW6pmGVJFhodzC31cy5sfOYotrzF"
let parts = jwtToken.components(separatedBy: ".")
let header = parts[0]
let payload = parts[1]
let signature = parts[2]
let dataPublicKey = Data(base64Encoded: publicKeyBase64)!
let dataSigned = (header + "." + payload).data(using: .ascii)!
let dataSignature = Data(base64Encoded: base64StringWithPadding(base64str: signature))!
let ck = try! P384.Signing.PublicKey(derRepresentation: dataPublicKey)
let x963 = ck.x963Representation
let publicKey = SecKeyCreateWithData(x963 as NSData, [
kSecAttrKeyType as String: kSecAttrKeyTypeECSECPrimeRandom,
kSecAttrKeyClass as String: kSecAttrKeyClassPublic,
] as NSDictionary, nil)!
print(publicKey)
// we have the SecKey representation of the public key.
// validate the JWT with the public key.
var validateError : Unmanaged<CFError>?
let algorithm: SecKeyAlgorithm = .eciesEncryptionStandardX963SHA384AESGCM
let result = SecKeyVerifySignature(publicKey,
algorithm,
dataSigned as NSData,
dataSignature as NSData,
&validateError)
if let validateError = validateError {
print(validateError)
}
print("JWT is valid: \(result)") // prints JWT is valid: false
I can't realise what should be the SecKeyAlgorithm (if that's the problem at all).
Thank you for the assistance!
If you post a self-contained example, I’d be happy to look at it.
I think I can't understand what kind of an example I need to provide.
It's just the JWTValidator that I have posted in the question.
My use case is:
I have a hardware bluetooth device with a JWT token. I have also the public key. The goal is to validate that JWT token with the existing public key and prove the device is the correct one.
So I'm trying to achieve this firstly with the JWT token and public key posted above (taken from the jwt.io standard ES384 example). Then I'll test with the real data from the product.
I'll be more than happy to provide any additional info you need!
Thank you!
Hi, Eskimo!
Thank you for the quick reply!
I'm using the ASN1Decoder because we're supporting iOS 12 +.
I have the public key in SecKey format, but I'm struggling to verify the provided JWT token with that key.
SecKeyVerifySignature always returns false. What am I missing?
To everyone, who is also struggling with this issue - I'm glad to inform you that building with the new Xcode 14.0 beta version seems to fix the issue, but introduces some new ones:
The widgets doesn't disappear anymore! They do disappear during the installation(which is normal), but appears again after the install completes.
Sometimes the today widgets displays "Unable to Load" after update.
The widgets built with the WidgetKit (the iOS 14+ widgets) shows only white (or black, depending on the device theme) on the screen after the update. Tapping on them opens the app, but the deep linking doesn't work. It looks like the widgets are gone. You can't add new one. The worst is phone reboot doesn't fix this bug. The only fix I've found so far is downgrading to version built with Xcode 13. Overall I can't run WidgetKit widget on iOS 15 iPhone. On iOS 16 simulator it works fine.
Tested on iOS 15.4.1. Build uploaded to TestFlight with Xcode 14.0 beta.
Now let's hope Apple will get it in order until the official Xcode version.
Exactly same with me! When I first install the version, which includes the watch app, the message is not sent. Only after restarting the iPhone it starts working. Tested on multiple iPhones and watches. But can't reproduce it on simulator.
What is the solution? To tell the users to restart the phone when they install the watch app? Ridiculous!!