Thanks! It's great to be working on something so interesting.
Thanks a lot for your comments, I'll attempt to answer them point-by-point.
1) Why have stream dedicated servers? Why can't all of the servers use any of the streams?
Servers can use as many streams as they have the capacity for. Obviously if the use of Bitmessage grows significantly then it would be impractical for any one server to operate permanently in all streams (the same as any other full node).
2) Will there be a warning to the user of the app that this data is being tracked?
3) Adding identifiers to the messages would kill a lot of the security and privacy that bitmessage offers. Yes it makes it much harder to implement a mobile version (without some thought) but I hate to say that development would stop if it were forced to do that. At least the majority of users would stop using it once they understand. You point this out in the pdf, I am just stating it for the glancing readers.
I think this is the most difficult problem. I'm glad you've picked up on this, because I really want to find a way of making this work without degrading the privacy and security of the network.
Thankfully I think I may have come up with a solution, although I really haven't had time to think it through in any depth. I've just started trying to work out if it's at all feasible, so there's lots still to be worked out, but I wanted to record it here in case someone else beats me to the punch.
The basic problem is that in order for Bitmessage's flooding technique for message distribution to work, you have to receive all messages which may be addressed to you and be able to decrypt any that are actually for you. Clearly we can't allow the server to decrypt all mobile client messages and forward them on, as that would mean a total loss of security. Therefore at the moment the server has no way of knowing which messages to forward to the mobile clients it serves.
To overcome this, you could have a system in which messages to be sent to Android clients are encrypted twice, using two different addresses. The message is encrypted once for the server, and once for the Android client.
When an Android client generates a new address (A) in a given stream, it will send that address and the corresponding public keys to the server it is registered with in that stream. The server will then also generate a new address (B), and record the two together as a pair (A and B). The server then publishes these two addresses and 4 public keys to the rest of the stream, as if it had generated both addresses itself. The server will then send B to the client, so that it also has the pair of addresses.
Now when the user of the Android client (Alice) wants to give someone (Bob) their address, they give them the address pair A and B. When Bob wants to send a message to Alice, he first creates the real message for Alice and encrypts it using the public encryption key for address A. Then he takes the encrypted message for A (EMA) and encrypts it with the public keys for address B, creating encrypted message for B (EMB).
Bob then sends EMB through the Bitmessage stream in question. Eventually it arrives at the server, which acts as a full node in that stream. The server decrypts EMB, producing EMA, and recognises that the address it has used to decrypt EMB corresponds to the address pair A and B. Now when the Android client which generated address A polls the server to check for messages, the server can forward EMA to the Android client, which can then decrypt and read it.
This is a totally half-baked idea, but I think it might work, and if it does then it would free us from having to add an identifier to messages. I'll spend some time trying to think it through now.
EDIT: One of the most obvious problems with this idea would be that the user of the Android client would have to give out two addresses (A and B) to anyone that wanted to send them a message. Perhaps this could be solved as follows:
When an Android client creates a new address (A), it sends the address and the two public keys for that address (A1
) to one of the servers that operates in that address's stream.
The server then generates a second address (B) and creates a new record in its database of A and B as a pair.
The server then calculates a third address (C). The hash part of this address has four public keys as inputs - the public encryption and signing keys for addresses A and B (A1
The server then publishes C to the rest of the nodes in the stream, along with the public keys A1
. These keys could be distributed either as two standard pubkey objects or as a one double-size pubkey object.
The server then sends address C to the Android client. The user of the Android client can then give out address C to their contacts.
The two stage encryption and decryption process can then proceed as above, with the change that only address C is needed to request and verify the 4 public keys needed.
Separate point: When sending a message to an Android client proof of work could be done only once, for the outer layer of encryption, to avoid creating extra work.
EDIT 2: Having given some thought to the double-encryption idea, I think that it would work, but it would only be worthwhile if we were able to place some degree of trust in the servers. Using the same terminology as above, address C will have to be passed around to many different servers, along with the corresponding 6 keys that the server has access to. This would mean someone could easily set up a rogue server or to grab them. They could then decrypt the outer layer of any messages sent to that address, which defeats the purpose of the double encryption.
Therefore perhaps the best approach would be to return to the idea of adding a hash of the destination address into the message header, but have this only apply to messages for Android clients, so that it does not degrade the security of the rest of the network. Android clients would generate 'mobile addresses' of a separate version from those generated by PC clients. Then when any user wants to send a message to a 'mobile address', they will include a hash of that address in the message header.
In the worst case this allows a network eavesdropper to detect when you are sent a message (and possibly what size it is). To do this, the attacker has to first find out your address, in order to match it with the hash seen over the network. This would only represent a small possible loss of privacy for users of the Android client, and would not effect users of the PC client at all.
Given the extent to which mobile users' activities are tracked anyway, this would not be a particularly great concern. Indeed, someone who found it objectionable could simply use the PC client instead. In addition, this solution would be far simpler to code and maintain.
4) The biggest problem with Lowering PoW is that it makes it vastly easier for people to maliciously flood the network. Even if it was only from android phones, they could be emulated on a pc. Flooding is the main purpose of PoW, not spam. Again, you touch on this I just wanted to make sure you understand the reason for the PoW.
Overall, the main problem is PoW is it not? Assuming that there is an option to only connect on wifi, 4g, etc then the network traffic really isn't too bad. Yes the messages.dat could become quite big, but this can be alleviated by lowering the storage time of messages. Also it could periodically check in with servers instead of keeping the connection open. I (naively) think that a receive-only mobile client would be quite straight forward. You wouldn't even have to generate an address if you were receiving broadcasts.
Offloading PoW would have to be done with an account or paid subscription or other verification technique. Otherwise it really would leave the door open to malicious attacks.
You're right, I have been conflating flooding and spam, even through they're not the same thing. Thanks for pointing that out.
The proof of work issue is a significant concern, but at the moment I think it will be ok to just have the proof of work done by the Android client locally. It will be a problem for useability, but there are things we can do (e.g. working in the background) to make the problem less serious. I think that having the server do the proof of work is probably out of the question, so it will probably have to be done on the phone itself, one way or another. Someone could build a mechanism which links the phone to their PC client and has the PC do the proof of work, but I think that's outside the reasonable scope of the project at the moment.
5) Maintaining security and anonymity as much as possible. What if there was a transaction fee paid by bitcoin from the mobile user? It could be a small fee, but it would go towards someone letting you use their machine to generate the PoW. Your servers could essentially act as a proxy and staging area so that the only information that the PoW miner would know, is that it is a mobile phone (although it could be a pc user just as easily so that is not certain)
I agree that this could work, but at the moment I don't think it's a better solution than just having the mobile client do the proof of work locally and finding ways to mitigate the useability problem which that produces. Obviously adding Bitcoin integration would make the development of the mobile client significantly more complicated, and would tie its success to that of Bitcoin. If in a few years Bitcoin is extremely popular then this might be a better way of doing it, but at the moment I think it would create a set of problems greater than the one it would solve.