我正在创建一个集成了PayPal API for iOS的iPhone应用程序。 API在发送请求时需要API凭据。我读了PayPal API并说它
永远不要将Express Checkout请求从您的移动应用程序直接发送到PayPal。这些请求需要您的PayPal API凭据。将凭据放在移动设备上会使您和PayPal面临不可接受的安全风险。仅从安全服务器发送快速结账请求。
我的问题是,存储API凭据的最佳方式是什么,以减少我的凭据被暴露或被黑客攻击的可能性?将凭据附加到iPhone构建有风险吗?为什么或如何?是否将这些凭据存储在安全的服务器上足够可靠?
编辑:iOS上的钥匙串访问api如何帮助我解决这个问题?答案 0 :(得分:3)
将API密钥放入应用程序是完全不安全的。通过各种技术,任何可以下载应用程序或通过手机上的应用程序获取手的人都可以直接阅读API密钥。即使您执行了@MatthiasBauch建议并稍后下载该秘密,这也成立。即使您执行@Rexeisen建议并对字符串进行模糊处理,它也会成立。
您最好的选择是使用Apple的内置订阅服务来处理付款(这可能不适用,但它们会减少,但可能比您在手机上可以做的更安全)
即使您不想或不想这样做,也可以为应用的每个实例提供一个唯一的ID,当他们使用您控制的服务器下载时,他们会注册该ID。那个服务器而不是paypal凭证,并将代表他们进行api呼叫。这样,如果任何给定的手机被盗/其服务器的API密钥被读取,您只需撤销该密钥,您的PayPal API密钥仍然是安全的。重要提示:在您真正撤销该应用程序的密钥之前,拥有它的任何人仍然可以使用它来制作支持服务器支持的内容。这可能是一件非常糟糕的事情。
答案 1 :(得分:1)
由于您可以在任何应用程序上运行Strings实用程序(尝试它,它有点可怕)并从代码中获取字符串,因此存在风险。一般来说,我建议在应用程序中打包秘密,但将它们留在其他地方的安全服务器上。如果你必须将它放在应用程序中,你可以做的一件事就是对字符串进行模糊处理,这一点并不明显。
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];
}
这将进行非常简单的混淆,并且不会显示在字符串中。