如何保证应用程序 - 后端的通信?

问题描述:

我有一个iOS应用,也是我使用,到目前为止,管理APNS(苹果推送通知)小后端。注册过程仅仅是一个GET调用与参数,以我的后端,并且因为没有身份验证或任何其他形式的控制,我担心有人可能只是我的超载假冒设备登记后端。

I have one iOS app and also a small backend that I use so far to manage the apns (Apple Push Notifications). The registration process is just a GET call with parameters to my backend, and since there is no 'authentication' or any other kind of control, I fear that anybody could just overload my backend with fake devices registering.

所以,主要的问题是:我怎么能做出这样的程序送入用信息到后端传输的时候没有认证保障

So the main question is: how could I make this kind of app-sending-info-to-backend transmissions secure when there is no authentication?

这是我脑海使用令牌注册设备时,应用程序必须提供正在产生某种HASH的一个简单的想法......

One simple idea that comes to my mind is generating some kind of HASH using the token that the app must supply when registering the device...

有没有办法彻底解决这个问题。这是不可能知道的,这是你的应用程序正在连接。所有你能做的就是加少许迷惑。

There is no way to completely solve this problem. It is not possible to know that it is your app that is connecting. All you can do is add a little obfuscation.

您最好的第一步是使用 SSL与固定证书做出人在这方面的中间人攻击更难。客户端证书可以帮助,但有一点痛设立,不给你买了很多比其他解决方案。

Your best first step is to use SSL with a pinned certificate to make Man-in-the-Middle attacks harder. Client-side certs can help, but are a bit of a pain to set up and aren't going to buy you a lot over other solutions.

如果你有一个固定的证书和SSL,刚刚与相处发送一个共享的秘密很可能是因为你需要那样好。从发布更改的秘密释放,因此您可以老化旧的。如果有人逆向工程您的应用程序足以击败了固定证书(或直接读取共享密钥),那么他们要打破这些方法的所有的休息了。

If you have a pinned certificate and SSL, just sending a shared secret along with the GET is probably as good as you need. Change the secret from release to release so you can age out old ones. If someone has reverse-engineered your app enough to beat the pinned certificate (or to read the shared secret directly), then they're going to break all the rest of these approaches, too.

即便如此,这里有一些更是添加一些额外的层:

Even so, here are some more that add a little extra layer:

Bidirectional与AES 共享秘密的验证是一个很好的和简单的方法,但需要握手(即你不能用一个GET这样做)。当然你也可以只实现这种单向的(这样服务器验证的关键,而不是客户端),但你仍然需要一个握手。

Bidirectional shared-secret verification with AES is a good and simple approach, but requires a handshake (i.e. you can't do it with a single GET). You can of course just implement this one-way (so the server verifies the key, but not the client), but you still need a handshake.

如果您想将身份验证令牌保存到一个GET,不能固定您的SSL证书,你可以让你的GET幂等(哪个好REST调用应该是这样),那么这是一个简单的实现:

If you want to keep your auth token to a single GET and can't pin your SSL certificate, and you can make your GETs idempotent (which good REST calls should be anyway), then this is a simple implementation:


  • 构造GET请求

  • 计算HMAC(SHA-256,共享秘密,得请求,16字节)

  • 发送HMAC与GET请求一起

在iOS上,这看起来是这样的:

On iOS, this would look something like:

NSData *key = ...random 32 bytes shared with server...;
NSURLRequest *request = ...;

// Allocate some memory for the HMAC
NSMutableData *hmac = [NSMutableData dataWithCapacity:CC_SHA256_DIGEST_LENGTH];

// Convert your URL into data. This assumes that this is a GET request, so the URL
// has everything. This also assumes that the GET is idempotent, so if someone
// replays this GET request, you don't care.
NSData *requestData = [[[request URL] absoluteString] dataUsingEncoding:NSUTF8StringEncoding];

// Compute the HMAC
CCHmac(kCCHmacAlgSHA256,
       [key bytes],
       [key length],
       [requestData bytes],
       [requestData length],
       [hmac mutableBytes]);

// Truncate the HMAC (this is common practice. It's slightly better, and at least no
// worse, to send half the HMAC rather than the whole HMAC).
NSData *token = [hmac subdataWithRange:NSMakeRange(0, [hmac length] / 2)];

NSURLRequest *finalRequest = ... add the token to your request ...

您当然会计算在服务器端同样的事情。你可以认为这是签订GET。如果您的要求是不一样的,你真的应该努力解决的反正。如果你不能修复它,你可以时间戳融入哈希和扔掉太旧要求,或者您以前见过。 (在这一过程中,你做出GET幂等....)

You would of course compute the same thing on the server side. You can think of this as "signing the GET." If your requests are not idempotent, you really should be working on fixing that anyway. If you can't fix it, you can integrate a timestamp into the hash and throw away requests that are too old or you've seen before. (In doing this, you've made your GET idempotent....)

当你升级你的应用程序,你应该改变你的共享密钥。这样,你可以最终老化已发现旧的共享机密。

When you upgrade your app, you should probably change your shared secret. That way you can eventually age out old shared secrets that have been discovered.

是的,这些都可以逆向工程。的任何的试图进行身份验证的应用程序(而不是用户)可以被逆向工程。因此,保持它的简单,而且更注重它是否真的发生了,你会怎么恢复。

Yes, these can all be reverse engineered. Anything that tries to authenticate the app (rather than the user) can be reverse engineered. So keep it simple, and focus more on how you would recover if it did happen.

如果可能的话,添加用户身份验证。它更强大。

And if at all possible, add user authentication. It's much more powerful.