diff --git a/proj-xcode/PowerAuth2/PowerAuthSDK.m b/proj-xcode/PowerAuth2/PowerAuthSDK.m index 05fa5d58..801dcf77 100644 --- a/proj-xcode/PowerAuth2/PowerAuthSDK.m +++ b/proj-xcode/PowerAuth2/PowerAuthSDK.m @@ -401,6 +401,60 @@ - (NSData*) biometryRelatedKeyWithAuthentication:(nonnull PowerAuthKeychainAuthe #endif } + +- (PowerAuthCoreSignatureUnlockKeys*) signatureKeysForAuthentication:(nonnull PowerAuthAuthentication*)authentication + error:(NSError **)error +{ + // Validate authentication object usage + [authentication validateUsage:NO]; + + // Generate signature key encryption keys + NSData *possessionKey = nil; + NSData *biometryKey = nil; + if (authentication.usePossession) { + if (authentication.overridenPossessionKey) { + possessionKey = authentication.overridenPossessionKey; + } else { + possessionKey = [self deviceRelatedKey]; + } + } + if (authentication.useBiometry) { + if (authentication.overridenBiometryKey) { + // application specified a custom biometry key + biometryKey = authentication.overridenBiometryKey; + } else { + // default biometry key should be fetched + biometryKey = [self biometryRelatedKeyWithAuthentication:authentication.keychainAuthentication error:error]; + if (!biometryKey) { + return nil; + } + } + } + + // Prepare signature unlock keys structure + PowerAuthCoreSignatureUnlockKeys *keys = [[PowerAuthCoreSignatureUnlockKeys alloc] init]; + keys.possessionUnlockKey = possessionKey; + keys.biometryUnlockKey = biometryKey; + keys.userPassword = authentication.password; + if (error) { *error = nil; } + return keys; +} + +- (PowerAuthCoreSignatureFactor) determineSignatureFactorForAuthentication:(PowerAuthAuthentication*)authentication +{ + PowerAuthCoreSignatureFactor factor = 0; + if (authentication.usePossession) { + factor |= PowerAuthCoreSignatureFactor_Possession; + } + if (authentication.password != nil) { + factor |= PowerAuthCoreSignatureFactor_Knowledge; + } + if (authentication.useBiometry) { + factor |= PowerAuthCoreSignatureFactor_Biometry; + } + return factor; +} + - (id) fetchEncryptedVaultUnlockKey:(PowerAuthAuthentication*)authentication reason:(PA2VaultUnlockReason)reason callback:(void(^)(NSString * encryptedEncryptionKey, NSError *error))callback @@ -552,27 +606,33 @@ - (void) cancelAllPendingTasks requestData.platform = [PowerAuthSystem platform]; requestData.deviceInfo = [PowerAuthSystem deviceInfo]; - PowerAuthCoreEciesEncryptor * decryptor = [[_sessionInterface writeTaskWithSession:^id _Nullable(PowerAuthCoreSession * _Nonnull session) { + // Start an activation + error = [_sessionInterface writeTaskWithSession:^NSError*(PowerAuthCoreSession * session) { return [self prepareActivation:activation forRequest:request requestData:requestData session:session]; - }] extractResult:&error]; - - if (!decryptor) { + }]; + if (error) { callback(nil, error); return nil; } - + // The create activation endpoint needs a custom object processing where we encrypt the inner data // with a different encryptor. We have to do this in the HTTP client's queue to guarantee that time - // service is already synchronized. - PA2RestApiEndpoint * endpoint = [PA2RestApiEndpoint createActivationWithCustomStep:^NSError *{ + // service is already synchronized and tempoerary key is acquired. + PA2RestApiEndpoint * endpoint = [PA2RestApiEndpoint createActivationWithCustomStep:^NSError*(PA2RestApiEndpoint * endpoint) { // Encrypt payload and put it directly to the request object. NSError * localError = nil; - request.activationData = [PA2ObjectSerialization encryptObject:requestData - encryptor:decryptor - error:&localError]; + PowerAuthCoreEciesEncryptor * decryptor = [self encryptorWithId:PA2EncryptorId_ActivationPayload error:&localError];; + if (decryptor && !localError) { + request.activationData = [PA2ObjectSerialization encryptObject:requestData + encryptor:decryptor + error:&localError]; + } + if (!localError) { + endpoint.customData = decryptor; + } return localError; }]; @@ -586,7 +646,7 @@ - (void) cancelAllPendingTasks if (status == PowerAuthRestApiResponseStatus_OK) { // Validate response from the server return [self validateActivationResponse:response - decryptor:decryptor + decryptor:endpoint.customData session:session]; } [session resetSession:NO]; @@ -765,10 +825,10 @@ - (NSString*) activationFingerprint The method requires request & request data and if everything's right, then request.activationData is prepared and metods returns a new decryptor, required for response decryption. */ -- (PA2Result*) prepareActivation:(PowerAuthActivation*)activation - forRequest:(PA2CreateActivationRequest*)request - requestData:(PA2CreateActivationRequestData*)requestData - session:(PowerAuthCoreSession*)session +- (NSError*) prepareActivation:(PowerAuthActivation*)activation + forRequest:(PA2CreateActivationRequest*)request + requestData:(PA2CreateActivationRequestData*)requestData + session:(PowerAuthCoreSession*)session { BOOL resetState = YES; NSError * localError = nil; @@ -783,16 +843,8 @@ - (NSString*) activationFingerprint if (resultStep1) { // Keep device's public key in requestData requestData.devicePublicKey = resultStep1.devicePublicKey; - - // Now we need to ecrypt request data with the Layer2 encryptor. - PowerAuthCoreEciesEncryptor * privateEncryptor = [self encryptorWithId:PA2EncryptorId_ActivationPayload error:&localError]; - if (!localError) { - // Everything looks OS, so finally, try notify other apps that this instance started the activation. - localError = [_sessionInterface startExternalPendingOperation:PowerAuthExternalPendingOperationType_Activation]; - if (!localError) { - return [PA2Result success:privateEncryptor]; - } - } + // Everything looks OS, so finally, try notify other apps that this instance started the activation. + localError = [_sessionInterface startExternalPendingOperation:PowerAuthExternalPendingOperationType_Activation]; } else { localError = PA2MakeError(PowerAuthErrorCode_InvalidActivationData, nil); } @@ -800,10 +852,10 @@ - (NSString*) activationFingerprint resetState = NO; // Don't reset state, there's already existing or pendign activation localError = PA2MakeError(PowerAuthErrorCode_InvalidActivationState, nil); } - if (resetState) { + if (localError && resetState) { [session resetSession:NO]; } - return [PA2Result failure:localError]; + return localError; } /** @@ -1039,6 +1091,45 @@ - (NSString*) offlineSignatureWithAuthentication:(PowerAuthAuthentication*)authe } +/** + This private method implements both online & offline signature calculations. Unlike the public interfaces, method accepts + PA2HTTPRequestData object as a source for data for signing and returns structured PA2HTTPRequestDataSignature object. + */ +- (PowerAuthCoreHTTPRequestDataSignature*) signHttpRequestData:(PowerAuthCoreHTTPRequestData*)requestData + authentication:(PowerAuthAuthentication*)authentication + error:(NSError**)error +{ + [self checkForValidSetup]; + + return [[_sessionInterface writeTaskWithSession:^PA2Result* (PowerAuthCoreSession * session) { + // Check if there is an activation present + if (!session.hasValidActivation) { + return [PA2Result failure:PA2MakeError(PowerAuthErrorCode_MissingActivation, nil)]; + } + + // Determine authentication factor type + PowerAuthCoreSignatureFactor factor = [self determineSignatureFactorForAuthentication:authentication]; + if (factor == 0) { + return [PA2Result failure:PA2MakeError(PowerAuthErrorCode_WrongParameter, nil)]; + } + + // Generate signature key encryption keys + NSError * localError = nil; + PowerAuthCoreSignatureUnlockKeys *keys = [self signatureKeysForAuthentication:authentication error:&localError]; + if (keys == nil) { // Unable to fetch Touch ID related record - maybe user or iOS canacelled the operation? + return [PA2Result failure:localError]; + } + + // Compute signature for provided values and return result. + PowerAuthCoreHTTPRequestDataSignature * signature = [session signHttpRequestData:requestData keys:keys factor:factor]; + if (signature == nil) { + return [PA2Result failure:PA2MakeError(PowerAuthErrorCode_SignatureError, nil)]; + } + return [PA2Result success:signature]; + + }] extractResult:error]; +} + - (BOOL) verifyServerSignedData:(nonnull NSData*)data signature:(nonnull NSString*)signature masterKey:(BOOL)masterKey @@ -1049,6 +1140,7 @@ - (BOOL) verifyServerSignedData:(nonnull NSData*)data signedData.signingDataKey = masterKey ? PowerAuthCoreSigningDataKey_ECDSA_MasterServerKey : PowerAuthCoreSigningDataKey_ECDSA_PersonalizedKey; signedData.data = data; signedData.signatureBase64 = signature; + signedData.signatureFormat = PowerAuthCoreSignatureFormat_ECDSA_DER; return [session verifyServerSignedData: signedData]; }]; } @@ -1388,6 +1480,7 @@ - (NSData*) generateInvalidBiometricKey - (id) signDataWithDevicePrivateKey:(PowerAuthAuthentication*)authentication data:(NSData*)data + format:(PowerAuthCoreSignatureFormat)format callback:(void(^)(NSData *signature, NSError *error))callback { return [self fetchEncryptedVaultUnlockKey:authentication reason:PA2VaultUnlockReason_SIGN_WITH_DEVICE_PRIVATE_KEY callback:^(NSString *encryptedEncryptionKey, NSError *error) { @@ -1399,7 +1492,8 @@ - (NSData*) generateInvalidBiometricKey signature = [_sessionInterface readTaskWithSession:^id (PowerAuthCoreSession * session) { return [session signDataWithDevicePrivateKey:encryptedEncryptionKey keys:keys - data:data]; + data:data + format:format]; }]; // Propagate error if (!signature) { @@ -1409,6 +1503,17 @@ - (NSData*) generateInvalidBiometricKey // Call back to application callback(signature, error); }]; + +} + +- (id) signDataWithDevicePrivateKey:(PowerAuthAuthentication*)authentication + data:(NSData*)data + callback:(void(^)(NSData *signature, NSError *error))callback +{ + return [self signDataWithDevicePrivateKey:authentication + data:data + format:PowerAuthCoreSignatureFormat_ECDSA_DER + callback:callback]; } - (id) signJwtWithDevicePrivateKey:(PowerAuthAuthentication*)authentication @@ -1424,6 +1529,7 @@ - (NSData*) generateInvalidBiometricKey // Calculate signature return [self signDataWithDevicePrivateKey:authentication data:[signedData dataUsingEncoding:NSASCIIStringEncoding] + format:PowerAuthCoreSignatureFormat_ECDSA_JOSE callback:^(NSData * signature, NSError * error) { // Handle error if (error) { diff --git a/proj-xcode/PowerAuth2/private/PA2EncryptedRequest.h b/proj-xcode/PowerAuth2/private/PA2EncryptedRequest.h index db127c4e..90bc9371 100644 --- a/proj-xcode/PowerAuth2/private/PA2EncryptedRequest.h +++ b/proj-xcode/PowerAuth2/private/PA2EncryptedRequest.h @@ -22,6 +22,7 @@ - (id) initWithCryptogram:(PowerAuthCoreEciesCryptogram*)cryptogram; +@property (nonatomic, strong) NSString * temporaryKeyId; @property (nonatomic, strong) NSString * ephemeralPublicKey; @property (nonatomic, strong) NSString * encryptedData; @property (nonatomic, strong) NSString * mac; diff --git a/proj-xcode/PowerAuth2/private/PA2EncryptedRequest.m b/proj-xcode/PowerAuth2/private/PA2EncryptedRequest.m index c7218acf..17e8ba99 100644 --- a/proj-xcode/PowerAuth2/private/PA2EncryptedRequest.m +++ b/proj-xcode/PowerAuth2/private/PA2EncryptedRequest.m @@ -37,6 +37,9 @@ - (id) initWithCryptogram:(PowerAuthCoreEciesCryptogram*)cryptogram - (NSDictionary*) toDictionary { NSMutableDictionary * dict = [NSMutableDictionary dictionaryWithCapacity:3]; + if (_temporaryKeyId) { + dict[@"temporaryKeyId"] = _temporaryKeyId; + } if (_ephemeralPublicKey) { dict[@"ephemeralPublicKey"] = _ephemeralPublicKey; } diff --git a/proj-xcode/PowerAuth2/private/PA2GetTemporaryKeyRequest.m b/proj-xcode/PowerAuth2/private/PA2GetTemporaryKeyRequest.m index 0973360e..f83b0ff9 100644 --- a/proj-xcode/PowerAuth2/private/PA2GetTemporaryKeyRequest.m +++ b/proj-xcode/PowerAuth2/private/PA2GetTemporaryKeyRequest.m @@ -21,9 +21,9 @@ @implementation PA2GetTemporaryKeyRequest - (NSDictionary *)toDictionary { if (_activationId) { - return @{ @"appKey" : _appKey, @"activationId": _activationId, @"challenge" : _challenge }; + return @{ @"applicationKey" : _appKey, @"activationId": _activationId, @"challenge" : _challenge }; } else { - return @{ @"appKey" : _appKey, @"challenge" : _challenge }; + return @{ @"applicationKey" : _appKey, @"challenge" : _challenge }; } } diff --git a/proj-xcode/PowerAuth2/private/PA2GetTemporaryKeyResponse.m b/proj-xcode/PowerAuth2/private/PA2GetTemporaryKeyResponse.m index 89b01a44..78416dd8 100644 --- a/proj-xcode/PowerAuth2/private/PA2GetTemporaryKeyResponse.m +++ b/proj-xcode/PowerAuth2/private/PA2GetTemporaryKeyResponse.m @@ -23,13 +23,13 @@ - (instancetype) initWithDictionary:(NSDictionary *)dicti { self = [super init]; if (self) { - _appKey = PA2ObjectAs(dictionary[@"appKey"], NSString); + _appKey = PA2ObjectAs(dictionary[@"applicationKey"], NSString); _activationId = PA2ObjectAs(dictionary[@"activationId"], NSString); _challenge = PA2ObjectAs(dictionary[@"challenge"], NSString); - _keyId = PA2ObjectAs(dictionary[@"keyId"], NSString); _publicKey = PA2ObjectAs(dictionary[@"publicKey"], NSString); - _expiration = [PA2ObjectAs(dictionary[@"expiration"], NSNumber) unsignedLongLongValue]; - _serverTime = [PA2ObjectAs(dictionary[@"serverTime"], NSNumber) unsignedLongLongValue]; + _keyId = PA2ObjectAs(dictionary[@"sub"], NSString); + _expiration = [PA2ObjectAs(dictionary[@"exp_ms"], NSNumber) unsignedLongLongValue]; + _serverTime = [PA2ObjectAs(dictionary[@"iat_ms"], NSNumber) unsignedLongLongValue]; } return self; } diff --git a/proj-xcode/PowerAuth2/private/PA2GetTemporaryKeyTask.m b/proj-xcode/PowerAuth2/private/PA2GetTemporaryKeyTask.m index 25a36e2d..fed271a6 100644 --- a/proj-xcode/PowerAuth2/private/PA2GetTemporaryKeyTask.m +++ b/proj-xcode/PowerAuth2/private/PA2GetTemporaryKeyTask.m @@ -46,6 +46,7 @@ - (instancetype) initWithHttpClient:(PA2HttpClient*)httpClient if (self) { _client = httpClient; _sessionProvider = sessionProvider; + _applicationKey = applicationKey; _deviceRelatedKey = deviceRelatedKey; _encryptorScope = encryptorScope; _delegate = delegate; @@ -162,16 +163,17 @@ - (PA2GetTemporaryKeyResponse*) processResponseJwt:(PA2JwtObject*)responseJwt er return nil; } if (![jwtHeaderObj.typ isEqualToString:@"JWT"]) { - *error = PA2MakeError(PowerAuthErrorCode_NetworkError, @"Unsupported JWT response"); + *error = PA2MakeError(PowerAuthErrorCode_NetworkError, @"Unsupported JWT type in response"); } if (![jwtHeaderObj.alg isEqualToString:@"ES256"]) { *error = PA2MakeError(PowerAuthErrorCode_NetworkError, @"Unsupported JWT algorithm in response"); return nil; } PowerAuthCoreSignedData * signedData = [[PowerAuthCoreSignedData alloc] init]; - signedData.data = [[[jwtHeader stringByAppendingString:@"."] stringByAppendingString:jwtPayload] dataUsingEncoding:NSASCIIStringEncoding]; - signedData.signature = [[NSData alloc] initWithJwtEncodedString:jwtSignature]; signedData.signingDataKey = _isApplicationScope ? PowerAuthCoreSigningDataKey_ECDSA_MasterServerKey : PowerAuthCoreSigningDataKey_ECDSA_PersonalizedKey; + signedData.signatureFormat = PowerAuthCoreSignatureFormat_ECDSA_JOSE; + signedData.data = [[NSString stringWithFormat:@"%@.%@", jwtHeader, jwtPayload] dataUsingEncoding:NSUTF8StringEncoding]; + signedData.signature = [[NSData alloc] initWithJwtEncodedString:jwtSignature]; BOOL valid = [_sessionProvider readBoolTaskWithSession:^BOOL(PowerAuthCoreSession * session) { return [session verifyServerSignedData:signedData]; }]; diff --git a/proj-xcode/PowerAuth2/private/PA2HttpRequest.m b/proj-xcode/PowerAuth2/private/PA2HttpRequest.m index c071effd..64cc1277 100644 --- a/proj-xcode/PowerAuth2/private/PA2HttpRequest.m +++ b/proj-xcode/PowerAuth2/private/PA2HttpRequest.m @@ -74,9 +74,9 @@ - (NSMutableURLRequest*) buildRequestWithHelper:(id)help } // Execute custom step before the request is serialized. - NSError * (^beforeSerialization)(void) = _endpoint.beforeRequestSerialization; + NSError * (^beforeSerialization)(PA2RestApiEndpoint*) = _endpoint.beforeRequestSerialization; if (beforeSerialization) { - NSError * customStepError = beforeSerialization(); + NSError * customStepError = beforeSerialization(_endpoint); if (customStepError) { if (error) *error = customStepError; return nil; diff --git a/proj-xcode/PowerAuth2/private/PA2JwtObject.m b/proj-xcode/PowerAuth2/private/PA2JwtObject.m index 8b6a18d3..978993d3 100644 --- a/proj-xcode/PowerAuth2/private/PA2JwtObject.m +++ b/proj-xcode/PowerAuth2/private/PA2JwtObject.m @@ -40,7 +40,7 @@ - (instancetype) initJwtWithAlg:(NSString *)alg - (instancetype) initWithDictionary:(NSDictionary *)dictionary { return [self initWithTyp:PA2ObjectAs(dictionary[@"typ"], NSString) - withAlg:PA2ObjectAs(dictionary[@"typ"], NSString)]; + withAlg:PA2ObjectAs(dictionary[@"alg"], NSString)]; } - (NSDictionary *)toDictionary diff --git a/proj-xcode/PowerAuth2/private/PA2ObjectSerialization.m b/proj-xcode/PowerAuth2/private/PA2ObjectSerialization.m index c85048e7..4d852485 100644 --- a/proj-xcode/PowerAuth2/private/PA2ObjectSerialization.m +++ b/proj-xcode/PowerAuth2/private/PA2ObjectSerialization.m @@ -129,7 +129,9 @@ + (PA2EncryptedRequest*) encryptObject:(id)object return nil; } // Finally, construct a request body from cryptogram - return [[PA2EncryptedRequest alloc] initWithCryptogram:cryptogram]; + PA2EncryptedRequest * encryptedRequest = [[PA2EncryptedRequest alloc] initWithCryptogram:cryptogram]; + encryptedRequest.temporaryKeyId = encryptor.associatedMetaData.temporaryKeyId; + return encryptedRequest; } diff --git a/proj-xcode/PowerAuth2/private/PA2RestApiEndpoint.h b/proj-xcode/PowerAuth2/private/PA2RestApiEndpoint.h index 570c0c62..bd8b96ca 100644 --- a/proj-xcode/PowerAuth2/private/PA2RestApiEndpoint.h +++ b/proj-xcode/PowerAuth2/private/PA2RestApiEndpoint.h @@ -63,11 +63,14 @@ @property (nonatomic, assign, readonly) BOOL requireSynchronizedTime; /// Contains block that will be executed on networking queue, before the request is serialized. -@property (nonatomic, strong, readonly) NSError *(^beforeRequestSerialization)(void); +@property (nonatomic, strong, readonly) NSError *(^beforeRequestSerialization)(PA2RestApiEndpoint * endpoint); + +/// Arbitrary data produced in custom serialization steps. +@property (nonatomic, strong) id customData; #pragma mark - Endpoint construction -+ (instancetype) createActivationWithCustomStep:(NSError*(^)(void))customStep; ++ (instancetype) createActivationWithCustomStep:(NSError*(^)(PA2RestApiEndpoint * endpoint))customStep; + (instancetype) getActivationStatus; + (instancetype) removeActivation; diff --git a/proj-xcode/PowerAuth2/private/PA2RestApiEndpoint.m b/proj-xcode/PowerAuth2/private/PA2RestApiEndpoint.m index 8e0d884c..4bf93b08 100644 --- a/proj-xcode/PowerAuth2/private/PA2RestApiEndpoint.m +++ b/proj-xcode/PowerAuth2/private/PA2RestApiEndpoint.m @@ -29,7 +29,7 @@ @implementation PA2RestApiEndpoint #pragma mark - Activation -+ (instancetype) createActivationWithCustomStep:(NSError*(^)(void))customStep ++ (instancetype) createActivationWithCustomStep:(NSError*(^)(PA2RestApiEndpoint * endpoint))customStep { PA2RestApiEndpoint * endpoint = [[PA2RestApiEndpoint alloc] initWithPath:@"/pa/v3/activation/create" request:[PA2CreateActivationRequest class] diff --git a/proj-xcode/PowerAuth2/private/PowerAuthSDK+Private.m b/proj-xcode/PowerAuth2/private/PowerAuthSDK+Private.m index d7d196a3..ecb35279 100644 --- a/proj-xcode/PowerAuth2/private/PowerAuthSDK+Private.m +++ b/proj-xcode/PowerAuth2/private/PowerAuthSDK+Private.m @@ -31,9 +31,9 @@ - (PowerAuthCoreEciesEncryptor*) encryptorWithId:(PA2EncryptorId)encryptorId err } - (PowerAuthAuthorizationHttpHeader*) authorizationHeaderForData:(NSData*)data - endpoint:(PA2RestApiEndpoint*)endpoint - authentication:(PowerAuthAuthentication*)authentication - error:(NSError**)error + endpoint:(PA2RestApiEndpoint*)endpoint + authentication:(PowerAuthAuthentication*)authentication + error:(NSError**)error { return [[self.sessionProvider writeTaskWithSession:^PA2Result* _Nullable(PowerAuthCoreSession * _Nonnull session) { if (self.hasPendingProtocolUpgrade || self.hasProtocolUpgradeAvailable) { diff --git a/proj-xcode/PowerAuth2IntegrationTests/PowerAuthServer/PowerAuthTestServerAPI.m b/proj-xcode/PowerAuth2IntegrationTests/PowerAuthServer/PowerAuthTestServerAPI.m index 76d5e8a2..ff001a57 100644 --- a/proj-xcode/PowerAuth2IntegrationTests/PowerAuthServer/PowerAuthTestServerAPI.m +++ b/proj-xcode/PowerAuth2IntegrationTests/PowerAuthServer/PowerAuthTestServerAPI.m @@ -348,7 +348,7 @@ - (PATSTokenValidationResponse*) validateTokenRequest:(PATSTokenValidationReques { [self checkForValidConnection]; NSArray * params; - if (_testServerConfig.serverMaxProtovolVersion == PATS_P32) { + if (_testServerConfig.serverMaxProtovolVersion >= PATS_P32) { params = @[ request.tokenIdentifier, request.tokenDigest, request.nonce, request.timestamp, request.protocolVersion]; } else { params = @[ request.tokenIdentifier, request.tokenDigest, request.nonce, request.timestamp]; diff --git a/proj-xcode/PowerAuth2Tests/PA2ObjectSerializationTests.m b/proj-xcode/PowerAuth2Tests/PA2ObjectSerializationTests.m index 6b57f1ac..05e2e901 100644 --- a/proj-xcode/PowerAuth2Tests/PA2ObjectSerializationTests.m +++ b/proj-xcode/PowerAuth2Tests/PA2ObjectSerializationTests.m @@ -16,6 +16,7 @@ #import #import +#import #import "PA2ObjectSerialization.h" #import "PA2PrivateMacros.h" @@ -56,4 +57,15 @@ - (void) testJwtSerialization XCTAssertTrue([@"eyJ0ZXh0Ijoi8J-SqT8_In0" isEqualToString:serializedData]); } +- (void) testJwtDataConversion +{ + for (NSUInteger i = 0; i < 1000; i++) { + NSUInteger len = arc4random_uniform(129); + NSData * input = [PowerAuthCoreCryptoUtils randomBytes:len]; + NSString * inputB64url = [input jwtEncodedString]; + NSData * output = [[NSData alloc] initWithJwtEncodedString:inputB64url]; + XCTAssertEqualObjects(input, output); + } +} + @end diff --git a/src/PowerAuth/Session.cpp b/src/PowerAuth/Session.cpp index f5693071..6ae250fe 100644 --- a/src/PowerAuth/Session.cpp +++ b/src/PowerAuth/Session.cpp @@ -750,7 +750,7 @@ namespace powerAuth CC7_LOG("Session %p: HmacSign: You have to provide possession key.", this); return EC_WrongParam; } - signing_key = crypto::HMAC_SHA256(cc7::MakeRange(_setup.applicationSecret), plain.transportKey); + signing_key = protocol::DeriveSecretKeyFromIndex(plain.transportKey, cc7::FromBase64String(_setup.applicationSecret)); } data.signature = crypto::HMAC_SHA256(data.data, signing_key); return data.signature.empty() ? EC_Encryption : EC_Ok;