4

我需要帮助创建 RSA-SHA1 签名以用于 iOS 上的 3 腿 OAuth 实现。

我能够使用 CommonCrypto.h 使用 HMAC-SHA1 来做到这一点,但是这个库似乎不支持 RSA-SHA1。

你们中有人用 RSA 实现了 OAuth 签名吗?你能指出我可以找到更多信息的一些资源吗?

谢谢。

4

3 回答 3

13

Erik Villegas 的回答也是我的解决方案。但是我在使用此解决方案时遇到的已发布代码中有一个错误:secretFilewas opens with 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;
}
于 2014-05-13T09:32:09.917 回答
5

我终于找到了解决方案。这是一个方法,它将在您的包中查找 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

于 2013-06-26T23:36:35.893 回答
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;
}
于 2019-08-01T15:57:54.280 回答