1
我試圖在iOS中實現萬事達MoneySend API。 API需要雙腿oauth來授權請求。是否有任何雙腿OAuth庫支持iOS的RSA-SHA1簽名?
的標準是:
- 的OAuth應該使用
RSA-SHA1
用於生成簽名。 - 請求方法應該是
PUT
- 由於請求有一個正文,需要包含body hash。
我們擁有的是PrivetKey的ConsumerKey和.p12文件。我tryed許多圖書館一樣RestKit
,ASIHTTPRequest
,OAuthConsumer
等
最後,我結束了這段代碼:
#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中的任何開源庫?
夥計們,請幫我在這...感謝和問候
感謝您的答覆,其實我在尋找一個雙向OAuth開源庫。使用'openssl'我可以做到這兩個框架的能力。而這個'chilkatsoft'是有償服務:( –
> chilkatsoft有償服務 是的,GitHub是更好的方式,但你需要花費大量的時間來找到最好的解決方案,如果你沒有時間搜索,只需要購買chilkatsoft^_^ PS可能Base64庫工作不正確使用驗證庫https://github.com/nicklockwood/Base64 – Bimawa
Base64工作正常我檢查輸入和輸出與在線工具我相信有一些邏輯錯誤OAuth實現了' - (void)requestWithOAuth'方法,這就是爲什麼我在尋找雙腿OAuth庫。 –