2013-05-28 76 views
1

我試圖在iOS中實現萬事達MoneySend API。 API需要雙腿oauth來授權請求​​。是否有任何雙腿OAuth庫支持iOS的RSA-SHA1簽名?

的標準是:

  1. 的OAuth應該使用RSA-SHA1用於生成簽名。
  2. 請求方法應該是PUT
  3. 由於請求有一個正文,需要包含body hash。

我們擁有的是PrivetKey的ConsumerKey和.p12文件。我tryed許多圖書館一樣RestKitASIHTTPRequestOAuthConsumer

最後,我結束了這段代碼:

#import "NSStringAdditions.h" 
#import "ASIHTTPRequest.h" 
#import "sha.h" 
#import "rsa.h" 
#import "pem.h" 
#import "objects.h" 

#define SANDBOX_CONSUMER_KEY @"" 
#define PRIVETKEY @"" 

@interface MC_TestApi() 
<NSURLConnectionDelegate> 
{ 
    NSMutableData *responseData; 
    NSURLConnection *urlConnection; 
} 
@end 

@implementation MC_TestApi 

- (NSString*)oAuthBodyHash:(NSData*)body 
{ 
    unsigned char digest[SHA_DIGEST_LENGTH]; 

    SHA1([body bytes], [body length], (unsigned char*)&digest); 

    unsigned c = SHA_DIGEST_LENGTH; 
    uint8_t *bytes = malloc(sizeof(*bytes) * c); 

    unsigned i; 
    for (i = 0; i < c; i++) 
    { 
     int byte = (unsigned int)digest[i]; 
     bytes[i] = (uint8_t)byte; 
    } 
    NSData *strData = [NSData dataWithBytesNoCopy:bytes length:c freeWhenDone:YES]; 

    return [NSString base64StringFromData:strData length:strData.length ]; 
} 

- (NSString *)sha1RsaText: (NSString *)text 
{ 
    NSString *path = [[NSBundle mainBundle] pathForResource: @"MCOpenAPI" ofType: @"pem"]; 
    FILE *secretFile = fopen([path cStringUsingEncoding: NSUTF8StringEncoding], "r"); 
    if (secretFile==NULL){ 
     printf("ERROR opening RSA Keys failed test.pem\n"); 
     return nil; 
    } 


    NSData *clearTextData = [text dataUsingEncoding: NSUTF8StringEncoding]; 
    unsigned char encryptedData[40]; 
    RSA *rsa = (RSA *)PEM_read_RSAPrivateKey(secretFile, &rsa, NULL, NULL); 

    unsigned int encryptionLength = 40; //RSA_size(rsa); 

    RSA_sign(NID_sha1, [clearTextData bytes], [clearTextData length], encryptedData, &encryptionLength, rsa); 

    unsigned c = 20; 
    uint8_t *bytes = malloc(sizeof(*bytes) * c); 

    unsigned i; 
    for (i = 0; i < c; i++) 
    { 
     int byte = (unsigned int)encryptedData[i]; 
     bytes[i] = (uint8_t)byte; 
    } 
    NSData *strData = [NSData dataWithBytesNoCopy:bytes length:c freeWhenDone:YES]; 

    return [NSString base64StringFromData:strData length:strData.length ]; 
} 

- (NSString *)urlEncodeValue:(NSString *)str 
{ 
    NSString *result = (NSString *) CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, 
                           (CFStringRef)str, 
                           NULL, 
                           CFSTR(":/?#[]@!$&'()*+,;="), 
                           kCFStringEncodingUTF8)); 
    return result; 
} 

-(void)requestWithOAuth { 

    NSUInteger time = [[NSDate date] timeIntervalSince1970]; 

    NSString *timestamp = [NSString stringWithFormat: @"%d", time]; 
    NSString *urlString = @"https://sandbox.api.mastercard.com/moneysend/eligibility/v1/pan"; 
    NSString *nonce = @"1234567890"; 
    NSString *consumerKey = SANDBOX_CONSUMER_KEY; 

    NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"%@?Format=XML",urlString]]; 
    NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url]; 
    [request setHTTPMethod:@"PUT"]; 
    [request setValue:@"application/xml" forHTTPHeaderField:@"content-type"]; 

    NSString *bodyString = @"<?xml version=\"1.0\" encoding=\"UTF-8\" ?> <PanEligibilityRequest> <SendingAccountNumber>5555555555559999</SendingAccountNumber> </PanEligibilityRequest>"; 

    NSData *body = [bodyString dataUsingEncoding:NSUTF8StringEncoding]; 
    NSString *bodyLength = [NSString stringWithFormat:@"%d",[body length]]; 
    [request setValue:bodyLength forHTTPHeaderField:@"content-length"]; 

    NSString *oAuthBodyHash = [self oAuthBodyHash:body]; 

    NSString *header = [NSString stringWithFormat:@"oauth_timestamp=\"%@\",oauth_nonce=\"%@\",oauth_version=\"1.0\",oauth_body_hash=\"%@\",oauth_consumer_key=\"%@\",oauth_signature_method=\"RSA-SHA1\"",timestamp,nonce,oAuthBodyHash,SANDBOX_CONSUMER_KEY]; 

    NSMutableDictionary *parameters = [NSMutableDictionary dictionaryWithObjectsAndKeys: 
             consumerKey,@"oauth_consumer_key", 
             nonce,@"oauth_nonce", 
             @"RSA-SHA1",@"oauth_signature_method", 
             timestamp,@"oauth_timestamp", 
             @"1.0",@"oauth_version", 
             oAuthBodyHash,@"oauth_body_hash", 
             @"XML",@"Format", 
             nil]; 
    NSArray *keys = [parameters allKeys]; 

    NSSortDescriptor* sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:nil ascending:YES selector:@selector(localizedCompare:)]; 
    keys = [keys sortedArrayUsingDescriptors:[NSArray arrayWithObject:sortDescriptor]]; 
    NSString *test = @""; 
    for (NSUInteger i = 0; i<[keys count]; i++) { 
     NSString *key = [keys objectAtIndex:i]; 
     NSString *str = [NSString stringWithFormat:@"%@=%@",key,[parameters objectForKey:key]]; 
     if (i!=([parameters count]-1)) 
      str = [str stringByAppendingString:@","]; 
     test = [test stringByAppendingString:str]; 
    } 

    NSString *signatureString = [NSString stringWithFormat: @"PUT&%@%%26%@", 
           [self urlEncodeValue: urlString], 
           [self urlEncodeValue: [test stringByReplacingOccurrencesOfString: @"," withString: @"&"]]]; 

    NSString *signature = [self sha1RsaText: signatureString]; 
    NSString *finalAuthHeader = [NSString stringWithFormat: @"OAuth %@,oauth_signature=\"%@\"", header, signature]; 
    [request setValue:finalAuthHeader forHTTPHeaderField:@"Authorization"]; 

    [request setHTTPBody:body]; 

    urlConnection = [[NSURLConnection alloc] initWithRequest:request delegate:self]; 
    [urlConnection start]; 
} 

#pragma mark - NSURLConnectionDelegate 

- (void) connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response 
{ 
    NSHTTPURLResponse* httpResponse = (NSHTTPURLResponse*)response; 
    int code = [httpResponse statusCode]; 
    NSLog(@"in didReceiveResponse %i %@",code,[NSHTTPURLResponse localizedStringForStatusCode:code]); 

    responseData = nil; 
    responseData = [[NSMutableData alloc] init]; 
    [responseData setLength:0]; 
} 

- (void) connection:(NSURLConnection *)connection didReceiveData:(NSData *)data 
{ 
    NSLog(@"in didReceiveData "); 
    [responseData appendData:data]; 
} 

- (void) connection:(NSURLConnection *)connection didFailWithError:(NSError *)error 
{ 
    [UIApplication sharedApplication].networkActivityIndicatorVisible = NO; 
    NSLog(@"\n\n ERORR \n\n%@",[NSString stringWithFormat:@"Connection failed: %@", [error description]]); 
} 

- (void) connectionDidFinishLoading:(NSURLConnection *)connection 
{ 
    if (responseData) { 
     NSString *newStr = [NSString stringWithUTF8String:[responseData bytes]]; 
     NSLog(@"XML: %@",newStr); 

    } 
    responseData = nil; 
} 

@end 

我的問題是:

  • 我是什麼在這裏做錯了嗎?

  • 有沒有我可以使用的iOS中的任何開源庫?

夥計們,請幫我在這...感謝和問候

回答

0

嘗試使用chilkatsoft 或只是本地CommonCrypto (an Apple framework)

+0

感謝您的答覆,其實我在尋找一個雙向OAuth開源庫。使用'openssl'我可以做到這兩個框架的能力。而這個'chilkatsoft'是有償服務:( –

+0

> chilkatsoft有償服務 是的,GitHub是更好的方式,但你需要花費大量的時間來找到最好的解決方案,如果你沒有時間搜索,只需要購買chilkatsoft^_^ PS可能Base64庫工作不正確使用驗證庫https://github.com/nicklockwood/Base64 – Bimawa

+0

Base64工作正常我檢查輸入和輸出與在線工具我相信有一些邏輯錯誤OAuth實現了' - (void)requestWithOAuth'方法,這就是爲什麼我在尋找雙腿OAuth庫。 –