Hello, I am working on simple task, i have a JWT and I need to verify it's signature.
My sample data:
JWT eyJhbGciOiJFUzI1NiIsImtpZCI6IjhEWVpUTFRPVUtNSjdUU0w4SFZVVTlUVEdXMV9NTVVSSURJV1JUVE0iLCJ0eXAiOiJKV1QifQ.eyJub25jZSI6Indkd2R3ZHdkIiwiZGF0ZVRpbWUiOiIyMDIzLTEwLTEzVDEyOjQ4OjQwWiJ9.nWBfRne9VOKV4NGt32gWtoA5fUKzu0RzkhUYSYwUA7cvalsABUcWrpEk0fhztPZDK7KrDF8P2Pquhoxq4p-FUg
Public key (JWK)
{
"kid": "8DYZTLTOUKMJ7TSL8HVUU9TTGW1_MMURIDIWRTTM",
"use": "sig",
"kty": "EC",
"alg": "ES256",
"crv": "P-256",
"x": "8dyzTlToUkMJ7tsl8HVuU9tTGw1_mmuridIWrttMRCs",
"y": "AVqGlqJ88QgP_uVLea7gIUnA-p9iYwnJyYt7o-uH4oU"
}
When you put the data to the [https://jwt.io] you get "Signature Verified" message. So the data should be ok.
I have implementation in Objective-C, but i get this weird error message when the SecKeyVerifySignature is called.
Here is my code:
#import <Cocoa/Cocoa.h>
#import <CommonCrypto/CommonDigest.h>
NSString* base64StringWithPadding(NSString *encodedString) {
NSString* stringTobeEncoded = [[encodedString stringByReplacingOccurrencesOfString:@"-" withString:@"+"]
stringByReplacingOccurrencesOfString:@"_" withString:@"/"];
int paddingCount = encodedString.length % 4;
for (int i = 0; i < paddingCount; i++) {
stringTobeEncoded = [stringTobeEncoded stringByAppendingString:@"="];
}
return stringTobeEncoded;
}
SecKeyRef restorePublicKey(NSString *x, NSString *y) {
NSString *xBase64Padd = base64StringWithPadding(x);
NSString *yBase64Padd = base64StringWithPadding(y);
NSData *xData = [[NSData alloc] initWithBase64EncodedString:xBase64Padd
options:kNilOptions]; //32bytes
NSData *yData = [[NSData alloc] initWithBase64EncodedString:yBase64Padd
options:kNilOptions]; //32bytes
NSMutableData *publicKeyData = [NSMutableData data];
// Append the constant byte '04' to indicate uncompressed format
const unsigned char uncompressedByte = 0x04;
[publicKeyData appendBytes:&uncompressedByte length:1];
// Append the X-coordinate and Y-coordinate
[publicKeyData appendData:xData];
[publicKeyData appendData:yData];
NSDictionary *keyAttributes = @{
(id)kSecAttrKeyType: (id)kSecAttrKeyTypeECSECPrimeRandom,
(id)kSecAttrKeyClass: (id)kSecAttrKeyClassPublic,
(id)kSecAttrKeySizeInBits: @256,
(id)kSecAttrIsPermanent:@NO
};
CFErrorRef error = NULL;
SecKeyRef publicKeyRef =
SecKeyCreateWithData(
(__bridge CFDataRef)publicKeyData,
(__bridge CFDictionaryRef)keyAttributes,
&error
);
if(!publicKeyRef) {
NSError *err = CFBridgingRelease(error);
NSLog(@"%@", err.description);
}
return publicKeyRef;
}
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSDictionary *jwk =
@{
@"kid": @"8DYZTLTOUKMJ7TSL8HVUU9TTGW1_MMURIDIWRTTM",
@"use": @"sig",
@"kty": @"EC",
@"alg": @"ES256",
@"crv": @"P-256",
@"x": @"8dyzTlToUkMJ7tsl8HVuU9tTGw1_mmuridIWrttMRCs",
@"y": @"AVqGlqJ88QgP_uVLea7gIUnA-p9iYwnJyYt7o-uH4oU"
};
SecKeyRef publicKeyRef = restorePublicKey(jwk[@"x"], jwk[@"y"]);
NSString* header = @"eyJhbGciOiJFUzI1NiIsImtpZCI6IjhEWVpUTFRPVUtNSjdUU0w4SFZVVTlUVEdXMV9NTVVSSURJV1JUVE0iLCJ0eXAiOiJKV1QifQ";
NSString* payload = @"eyJub25jZSI6Indkd2R3ZHdkIiwiZGF0ZVRpbWUiOiIyMDIzLTEwLTEzVDEyOjQ4OjQwWiJ9";
NSString* signature = @"nWBfRne9VOKV4NGt32gWtoA5fUKzu0RzkhUYSYwUA7cvalsABUcWrpEk0fhztPZDK7KrDF8P2Pquhoxq4p-FUg";
NSString *headerAndPayload = [NSString stringWithFormat:@"%@.%@", header, payload];
NSData *signedData = [headerAndPayload dataUsingEncoding:NSUTF8StringEncoding];
NSString *signatureBase64Padd = base64StringWithPadding(signature);
NSData *signatureData = [[NSData alloc] initWithBase64EncodedString:signatureBase64Padd
options:kNilOptions];
bool canVerify = SecKeyIsAlgorithmSupported(publicKeyRef, kSecKeyOperationTypeVerify, kSecKeyAlgorithmECDSASignatureMessageX962SHA256);
if(canVerify) {
CFErrorRef error = NULL;
BOOL verifyStatus =
SecKeyVerifySignature(
publicKeyRef,
kSecKeyAlgorithmECDSASignatureMessageX962SHA256,
(__bridge CFDataRef)signedData,
(__bridge CFDataRef)signatureData,
&error
);
if(error) {
NSError *err = CFBridgingRelease(error);
NSLog(@"%@", err.description);
}
} else {
NSLog(@"Cannot verify.");
}
}
return NSApplicationMain(argc, argv);
}
I dont know where is the problem. I've tried everything.