0

我正在创建一个集成了适用于 iOS 的 PayPal API 的 iPhone 应用程序。API 在发送请求时需要 API 凭据。我阅读了 PayPal API,它说

切勿从您的移动应用程序直接向 PayPal 发送 Express Checkout 请求。这些请求需要您的 PayPal API 凭据。将您的凭据放在移动设备上会使您和 PayPal 面临不可接受的安全风险。仅从安全服务器发送 Express Checkout 请求。

我的问题是,存储 API 凭据以减少我的凭据被暴露或被黑客入侵的可能性的最佳方式是什么?将凭据附加到 iPhone 版本是否有风险?为什么或如何?将这些凭据存储在安全的服务器上是否足够可靠?

编辑:iOS 上的钥匙串访问 api 如何帮助我解决这个问题?

4

2 回答 2

3

将 API 密钥放入您的应用程序是完全不安全的。通过多种技术,任何可以下载该应用程序或拿到带有该应用程序的手机的人都可以简单地读取 API 密钥。即使您按照@MatthiasBauch 的建议进行操作并稍后下载秘密,这仍然成立。即使您执行@Rexeisen 建议的操作并混淆字符串,它也成立。

你最好的选择是使用苹果的内置订阅服务来处理付款(这可能不适用,他们会削减,但可能比你在手机上做的更安全)

即使您不想或不能这样做,也可以为应用程序的每个实例提供一个唯一 ID,当他们使用您控制的服务器下载时,他们会注册该 ID。该服务器具有贝宝凭据,并将代表他们进行 api 调用。这样,如果任何给定的手机被盗/读取了服务器的 api 密钥,您可以简单地撤销该密钥,并且您的 paypal API 密钥仍然是安全的。重要警告:在您真正撤消该应用程序的密钥之前,拥有它的任何人仍然可以使用它来制作您的服务器支持的任何调用。这可能是一件非常糟糕的事情。

于 2012-05-22T16:25:15.460 回答
1

这是有风险的,因为您几乎可以在任何应用程序上运行字符串实用程序(尝试一下,这有点吓人)并从代码中获取字符串。一般来说,我建议将秘密打包在应用程序中,但将它们放在其他地方的安全服务器上。如果您必须将其放入应用程序中,您可以做的一件事是混淆字符串,使其不明显。

NSString *secret = kTwitterClientSecret;
NSData *secretData = [secret dataUsingEncoding:NSUTF8StringEncoding];
NSString *key = @"Twitter";
[secretData obfuscateOrDeobfuscateWithKey:key];
NSString *documentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
NSString *path = [NSString stringWithFormat:@"%@/%@-%@", documentsPath, key, @"output"];
[secretData writeToFile:path atomically:NO];
NSLog(@"Wrote obfuscated data to: %@", documentsPath);

其中 obfuscateOrDeobfuscateWithKey 是 NSData 上的一个类别

// Inspiration from: http://iosdevelopertips.com/cocoa/obfuscation-encryption-of-string-nsstring.html
- (void)obfuscateOrDeobfuscateWithKey:(NSString *)key
{
    // Get pointer to data to obfuscate
    char *dataPtr = (char *) [self bytes];

    // Get pointer to key data
    char *keyData = (char *) [[key dataUsingEncoding:NSUTF8StringEncoding] bytes];

    // Points to each char in sequence in the key
    char *keyPtr = keyData;
    int keyIndex = 0;

    // For each character in data, xor with current value in key
    for (int x = 0; x < [self length]; x++) {
        // Replace current character in data with current character xor'd with current key value.
        // Bump each pointer to the next character.
        *dataPtr = *dataPtr ^ *keyPtr;
        dataPtr++;
        keyPtr++;

        // If at end of key data, reset count and set key pointer back to start of key value
        if (++keyIndex == [key length]) {
            keyIndex = 0, keyPtr = keyData;
        }
    }
}

然后你可以声明一个常量就像

static unsigned char const kTwitterClientSecret[] = {
    0x00, 0x00, 0x00, ... etc ... 
};
static unsigned int const kTwitterClientSecret_len = LENGTH;

然后要找回字符串,您可以这样做

[NSString deobfuscatedStringWithBytes:kTwitterClientSecret length:kTwitterClientSecret_len key:@"Twitter"];

这是 NSString 上的一个类别

+ (NSString *)deobfuscatedStringWithBytes:(const void *)bytes length:(NSUInteger)length key:(NSString *)key
{
    NSData *deobfuscatedData = [NSData dataWithBytes:bytes length:length];
    [deobfuscatedData obfuscateOrDeobfuscateWithKey:key];
    return [[NSString alloc] initWithData:deobfuscatedData encoding:NSUTF8StringEncoding];
}

这将进行非常简单的混淆,并且不会出现在字符串中。

于 2012-05-22T15:36:46.500 回答