Hello, guys!
I'm having trouble to validate JWT with EC algorithm in iOS.
I have generated JWT and public key from jwt.io using the ES384 algorithm and I have the following validator:
let jwtToken = "eyJhbGciOiJFUzM4NCIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWUsImlhdCI6MTUxNjIzOTAyMn0.VUPWQZuClnkFbaEKCsPy7CZVMh5wxbCSpaAWFLpnTe9J0--PzHNeTFNXCrVHysAa3eFbuzD8_bLSsgTKC8SzHxRVSj5eN86vBPo_1fNfE7SHTYhWowjY4E_wuiC13yoj"
let publicKey = "MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEC1uWSXj2czCDwMTLWV5BFmwxdM6PX9p+Pk9Yf9rIf374m5XP1U8q79dBhLSIuaojsvOT39UUcPJROSD1FqYLued0rXiooIii1D3jaW6pmGVJFhodzC31cy5sfOYotrzF"
let isValid = JWTValidator.validateSignature(forToken: jwtToken, withPublicKey: publicKey)
print(isValid) // always false
import ASN1Decoder
class JWTValidator {
static func validateSignature(forToken token: String, withPublicKey publicKeyText: String) -> Bool {
let parts = token.components(separatedBy: ".")
let header = parts[0]
let payload = parts[1]
let signature = parts[2]
guard let dataPublicKey = Data(base64Encoded: publicKeyText),
let dataSigned = (header + "." + payload).data(using: .ascii),
let dataSignature = Data(base64Encoded: base64StringWithPadding(base64str: signature)) else {
print("Failed to get signature!")
return false
}
var secKeyCreateError : Unmanaged<CFError>?
guard let publicKey: SecKey = DerDecoder().decodePublicKey(dataPublicKey,&secKeyCreateError) else {
print("Failed to create SecKey : %@", secKeyCreateError!.takeRetainedValue().localizedDescription)
return false
}
var validateError : Unmanaged<CFError>?
let algorithm: SecKeyAlgorithm = .ecdsaSignatureMessageX962SHA384
let result = SecKeyVerifySignature(peerPublicKey,
algorithm,
dataSigned as NSData,
dataSignature as NSData,
&validateError)
if let validateError = validateError {
print(validateError)
}
return result
}
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
}
}
class DerDecoder {
func decodePublicKey(_ data: Data, _ error: UnsafeMutablePointer<Unmanaged<CFError>?>?) -> SecKey? {
guard
let asn1 = try? ASN1DERDecoder.decode(data: data),
let keyData = asn1.first?.sub(1)?.value as? Data
else {
return nil
}
return SecKeyCreateWithData(
keyData as CFData,
[
kSecAttrKeyType as String: kSecAttrKeyTypeECSECPrimeRandom,
kSecAttrKeyClass as String: kSecAttrKeyClassPublic,
] as CFDictionary,
error
)
}
}
Initially I had some troubles to get the SecKey, but the ASN1Decoder solved that issue. Now I'm struggling to get it validated. I'm always getting false. I don't know what SecKeyAlgorithm to use.
These are the errors I'm getting:
EC signature verification failed (ccerr -7)
or
algorithm not supported by the key <SecKeyRef curve type: kSecECCurveSecp384r1, algorithm id: 3, key type: ECPublicKey, version: 4, block size: 384 bits, y: B2F393DFD51470F2513920F516A60BB9E774AD78A8A088A2D43DE3696EA9986549161A1DCC2DF5732E6C7CE628B6BCC5, x: 0B5B964978F6733083C0C4CB595E41166C3174CE8F5FDA7E3E4F587FDAC87F7EF89B95CFD54F2AEFD74184B488B9AA23, addr: 0x102e26140>
Any help will be highly appreciated!
Edit
If I use RS256 algorithm from jwt.io, without ASN1Decoder and
let algorithm: SecKeyAlgorithm = .rsaSignatureMessagePKCS1v15SHA256
there's no issue at all.
Post
Replies
Boosts
Views
Activity
We had "Today widgets" that worked perfect for a long time. After introducing the new Widgets Extension we added a Widgets Bundle to our app. Now after every app update the old widgets disappear from "Today view" and can be bring back ONLY by rebooting the iPhone. Sometime when they disappear, in today view appears the first widget from the Widgets Bundle. I've tested other apps too and it happens every time to apps that support old and new widgets (Xiaomi Home app for example).
Does anyone have a clue how to fix that?