我需要帮助创建一个RSA-SHA1签名,以便在iOS上的三脚OAuth实现中使用。
我能够使用CommonCrypto.h使用HMAC-SHA1执行此操作,但此库似乎不支持RSA-SHA1。
您是否有人使用RSA实施OAuth签名?你能指点我一些能找到更多信息的资源吗?
感谢。
答案 0 :(得分:13)
The answer by Erik Villegas对我来说也是解决方案。但是在使用此解决方案时我遇到的已发布代码中存在一个错误:secretFile
已使用fopen()
打开,因此必须使用fclose()
- (NSString *)RSASHA1HashForString:(NSString *)source {
NSLog(@"encrypting %@", source);
if (source == nil) return nil;
OpenSSL_add_all_algorithms();
NSString *signature = nil;
// make a SHA-1 digest of the source string
const char* sourceChars = [source UTF8String];
unsigned char digest[SHA_DIGEST_LENGTH];
SHA1((const unsigned char *)sourceChars, strlen(sourceChars), digest);
NSString *path = [[NSBundle mainBundle] pathForResource:@"privatekey" ofType:@"pem"];
const char *pathCString = [path cStringUsingEncoding:NSUTF8StringEncoding];
FILE *secretFile = fopen(pathCString, "r");
RSA *rsa = NULL;
PEM_read_RSAPrivateKey(secretFile, &rsa, NULL, NULL);
if (rsa != NULL) {
unsigned int sigLen = 0;
unsigned char *sigBuff = malloc(RSA_size(rsa));
int result = RSA_sign(NID_sha1, digest, (unsigned int) sizeof(digest),
sigBuff, &sigLen, rsa);
if (result != 0) {
NSData *sigData = [NSData dataWithBytes:sigBuff length:sigLen];
signature = [self base64forData:sigData];
}
free(sigBuff);
RSA_free(rsa);
}
fclose(secretFile);
NSLog(@"generated signature: %@", signature);
return signature;
}
答案 1 :(得分:5)
我终于找到了解决方案。下面是一个方法,它将在bundle中查找privatekey.pem文件,并使用传入的字符串创建RSA-SHA1签名。您需要添加openssl库。您可以将此项目用作参考:https://github.com/x2on/OpenSSL-for-iPhone
- (NSString *)RSASHA1HashForString:(NSString *)source {
NSLog(@"encrypting %@", source);
if (source == nil) return nil;
OpenSSL_add_all_algorithms();
NSString *signature = nil;
// make a SHA-1 digest of the source string
const char* sourceChars = [source UTF8String];
unsigned char digest[SHA_DIGEST_LENGTH];
SHA1((const unsigned char *)sourceChars, strlen(sourceChars), digest);
NSString *path = [[NSBundle mainBundle] pathForResource:@"privatekey" ofType:@"pem"];
const char *pathCString = [path cStringUsingEncoding:NSUTF8StringEncoding];
FILE *secretFile = fopen(pathCString, "r");
RSA *rsa = NULL;
PEM_read_RSAPrivateKey(secretFile, &rsa, NULL, NULL);
if (rsa != NULL) {
unsigned int sigLen = 0;
unsigned char *sigBuff = malloc(RSA_size(rsa));
int result = RSA_sign(NID_sha1, digest, (unsigned int) sizeof(digest),
sigBuff, &sigLen, rsa);
if (result != 0) {
NSData *sigData = [NSData dataWithBytes:sigBuff length:sigLen];
signature = [self base64forData:sigData];
}
free(sigBuff);
RSA_free(rsa);
}
NSLog(@"generated signature: %@", signature);
return signature;
}
如果要实施OAuth,则需要将签名库传递给此方法。更多信息可以在这里找到:http://oauth.net/core/1.0a/#anchor13
答案 2 :(得分:0)
这里是使用核心安全性iOS框架的实现。 密钥应转换为pkcs12格式。 算法名称为“ kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA1 ”
- (NSString *)getStringSHA1RSASignature:(NSString *)str
{
NSString *path = [[NSBundle bundleForClass:[self class]]
pathForResource:@"rsaPrivate.pfx" ofType:@"pkcs12"];
NSData *p12data = [NSData dataWithContentsOfFile:path];
NSMutableDictionary * options = [[NSMutableDictionary alloc] init];
[options setObject:@" your password " forKey:(id)kSecImportExportPassphrase];
CFArrayRef items = CFArrayCreate(NULL, 0, 0, NULL);
OSStatus securityError = SecPKCS12Import((CFDataRef)p12data, (CFDictionaryRef)options, &items);
CFDictionaryRef identityDict = CFArrayGetValueAtIndex(items, 0);
SecIdentityRef identityApp =
(SecIdentityRef)CFDictionaryGetValue(identityDict,
kSecImportItemIdentity);
assert(securityError == noErr);
SecKeyRef privateKeyRef;
SecIdentityCopyPrivateKey(identityApp, &privateKeyRef);
/// have a key
NSData *input = [str dataUsingEncoding:NSUTF8StringEncoding];
CFErrorRef error = nil;
///////////////////////////////// "SHA1withRSA" java
CFDataRef signature = SecKeyCreateSignature(privateKeyRef, kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA1, (CFDataRef)input, &error);
NSAssert(signature != nil, @"");
NSString *result = [(__bridge NSData *)signature base64EncodedStringWithOptions:0];
CFRelease(signature);
NSAssert(result != nil, @"");
NSLog(@"generated signature: %@", result);
return result;
}