yourkarma/JWT

View on GitHub
Sources/JWT/Algorithms/Base/JWTAlgorithmFactory.m

Summary

Maintainability
Test Coverage
//
//  JWTAlgorithmFactory.m
//  JWT
//
//  Created by Lobanov Dmitry on 07.10.15.
//  Copyright © 2015 Karma. All rights reserved.
//

#import "JWTAlgorithmFactory.h"
#import "JWTAlgorithmHSBase.h"
#import "JWTAlgorithmRSBase.h"
#import "JWTAlgorithmNone.h"
#import "JWTAlgorithmAsymmetricBase.h"
#import "JWTBase64Coder.h"

// not implemented.
// ES still not implemented. Look at implementation and readme in future releases.

@implementation JWTAlgorithmHolder

- (instancetype)initWithAlgorithm:(id<JWTAlgorithm>)algorithm {
    if (self = [super init]) {
        self.algorithm = algorithm;
    }
    return self;
}

- (NSString *)name {
    return self.algorithm.name;
}

- (NSData *)signHash:(NSData *)hash key:(NSData *)key error:(NSError *__autoreleasing *)error {
    return [self.algorithm signHash:hash key:key error:error];
}

- (BOOL)verifyHash:(NSData *)hash signature:(NSData *)signature key:(NSData *)key error:(NSError *__autoreleasing *)error {
    return [self.algorithm verifyHash:hash signature:signature key:key error:error];
}

- (NSData *)encodePayload:(NSString *)theString withSecret:(NSString *)theSecret {
    NSData *inputData = [theString dataUsingEncoding:NSUTF8StringEncoding];
    NSData *secretData = [theSecret dataUsingEncoding:NSUTF8StringEncoding];
    //[JWTBase64Coder dataWithBase64UrlEncodedString:theSecret];
    return [self encodePayloadData:inputData withSecret:secretData];
}

- (NSData *)encodePayloadData:(NSData *)theStringData withSecret:(NSData *)theSecretData {
    return [self signHash:theStringData key:theSecretData error:nil];
}

- (BOOL)verifySignedInput:(NSString *)input withSignature:(NSString *)signature verificationKey:(NSString *)verificationKey {
    NSData *inputData = [input dataUsingEncoding:NSUTF8StringEncoding]; //[JWTBase64Coder dataWithBase64UrlEncodedString:input];
    NSData *signatureData = [JWTBase64Coder dataWithBase64UrlEncodedString:signature];
    NSData *verificationKeyData = [verificationKey dataUsingEncoding:NSUTF8StringEncoding];

    return [self verifyHash:inputData signature:signatureData key:verificationKeyData error:nil];
    
//    return [self verifySignedInput:input withSignature:signature verificationKeyData:verificationKeyData];
}

- (BOOL)verifySignedInput:(NSString *)input withSignature:(NSString *)signature verificationKeyData:(NSData *)verificationKeyData {
    NSData *signatureData = [JWTBase64Coder dataWithBase64UrlEncodedString:signature];
    NSData *inputData = [input dataUsingEncoding:NSUTF8StringEncoding]; //[JWTBase64Coder dataWithBase64UrlEncodedString:input];
    return [self verifyHash:inputData signature:signatureData key:verificationKeyData error:nil ];
}

@end

@implementation JWTAlgorithmFactory

+ (BOOL)checkIfSecurityAPIAvailable {
    BOOL result = NO;
#if TARGET_OS_MAC && TARGET_OS_IPHONE // iOS >= 10
    result = [[NSProcessInfo processInfo] isOperatingSystemAtLeastVersion:(NSOperatingSystemVersion){10, 0, 0}];
#elif TARGET_OS_MAC && !TARGET_OS_IPHONE // macOS >= 10.12
    result = [[NSProcessInfo processInfo] isOperatingSystemAtLeastVersion:(NSOperatingSystemVersion){10, 12, 0}];
#endif
    return result;
}

+ (NSArray<id<JWTAlgorithm>> *)algorithms {
    if ([self checkIfSecurityAPIAvailable]) {
        return @[
                 [JWTAlgorithmNone new],
                 [JWTAlgorithmHSBase algorithm256],
                 [JWTAlgorithmHSBase algorithm384],
                 [JWTAlgorithmHSBase algorithm512],
                 [JWTAlgorithmAsymmetricBase withRS].with256,
                 [JWTAlgorithmAsymmetricBase withRS].with384,
                 [JWTAlgorithmAsymmetricBase withRS].with512,
                 [JWTAlgorithmAsymmetricBase withES].with256,
                 [JWTAlgorithmAsymmetricBase withES].with384,
                 [JWTAlgorithmAsymmetricBase withES].with512
                 ];
    }
    
    return @[
            [JWTAlgorithmNone new],
            [JWTAlgorithmHSBase algorithm256],
            [JWTAlgorithmHSBase algorithm384],
            [JWTAlgorithmHSBase algorithm512],
            [JWTAlgorithmRSBase algorithm256],
            [JWTAlgorithmRSBase algorithm384],
            [JWTAlgorithmRSBase algorithm512]
            ];

}

+ (id<JWTAlgorithm>)algorithmByName:(NSString *)name {
    id<JWTAlgorithm> algorithm = nil;
    
    NSString *algName = [name copy];
    
    NSUInteger index = [[self algorithms] indexOfObjectPassingTest:^BOOL(id<JWTAlgorithm> obj, NSUInteger idx, BOOL *stop) {
        // lowercase comparison
        return [obj.name isEqualToString:algName];
    }];
    
    if (index != NSNotFound) {
        algorithm = [self algorithms][index];
    }
    
    return algorithm;
}

@end