ggerganov / ggwave

Tiny data-over-sound library
https://youtu.be/Zcgf77T71QM
MIT License
1.96k stars 158 forks source link

Sending files purely via sound #41

Open detrin opened 3 years ago

detrin commented 3 years ago

This project is exactly what I was looking for except the limitation for message length and the transfer of files. I suggest the possibility of sending files purely over sound, without any additional type of connection. This could be beneficial in environment without any internet connection and for secure transfer of private data (such as private keys) without any need of LAN network or any internet at all.

Not sure how difficult would be implement splicing data into 140 chars and then sending initial message with number of messages to be transmitted and then checksum in ending message. Or using less then 140 chars plus initial integer for the number of messages. Then receiver would request these messages to be sent again in case of transmission failure.

Hope this makes sense.

ggerganov commented 3 years ago

Hi, thanks for the suggestion.

In the following discussion I have explained what it would take to remove the 140 byte limit:

https://github.com/ggerganov/ggwave/discussions/34

Splicing a data file into 140-byte chunks is trivial. The problem is in designing a protocol for confirming which parts have been received and which haven't and then re-sending the latter, etc -- It gets complicated and it is not obvious what is the optimal way to implement this.

detrin commented 3 years ago

I am not sure either would be the optimal way to implement such protocol. However I have an idea. I am assuming waver is sending bytes and not just base64 code.

Receiver - R, Sender - S, Bob - B, Alice - A Data would be spitted into 255*139 chars (35445 bytes) long frames. Frame would consist of

Message would consist of

Now the protocol. Suppose Bob needs to send data to Alice. 1) B will split data into N frames and will send A in the first message N. (following part will be needed only in the first one-way transmission) 1-A) A has to confirm the message 1-B) B has to confirm A's confirmation message, this way we know that the transmission is ready to both directions 2) Now B will send one frame with 255 messages and the first checksum message. A will decode all messages, check for error messages with ECC in case all of them are correct she will check for checksum in the first message. If it is incorrect, she will mark all messages in the frame as corrupted. 3) B will keep sending frames, till none is left. A will be decoding them and marking the corrupted. 4) A knows what is N and she knows that number of data messages in frame is 255. She will stuck all the messages from frames onto each other and sent back only the offset between them. For example (0 - ok message, C - corrupted) 0000C0000CC0C will turn into 4401. Depending on the N (let's say for N > 10) she will compress these corruption offsets. These offset should be the same type as N ( for example int32). 5) Now the compressed or uncompressed information about corrupted message creates new data and A will repeat this protocol as S and B will be R. This will recursively repeat until A receives again only corrupted messages in new frames with new check sums. In case of errors she will repeat the whole procedure on new set of frames. 6) After all received messages checked with ECC and check sums in frames this process terminates by Alice not sending anything to Bob.

I hope this makes sense, I guess it is far from optimal, but it seems to me as relatively simple way how to transmit more than 140 of chars.

detrin commented 3 years ago

Regarding message length limited by ECC, maybe https://github.com/ArashPartow/schifra would be useful as https://github.com/mersinvald/Reed-Solomon seems to be older.

RealEnder commented 2 years ago

Looked at this as a possible data exfiltration channel from controlled environment, eg. DLP in action. Please take a look on Ozzillate. It continuously emits the audio sequence, so on the receiving part you can construct the file with missing/received with errors blocks. It's a bit like how torrent works, just with two nodes. Also Ozzillate currently uploads the file, which is not desired at all, but it should be perfectly doable only clientside using ggwave's code. It's pity it's still not opensource, but you'll get the idea.

ggerganov commented 2 years ago

I've seen Ozzillate before - if I remember correctly, they host your file on their server and simply transmit a link via sound. The actual file contents are served via HTTP - not over sound.

I think someone mentioned here the idea before of using fountain codes to get a continuous stream of audio data, where you can start listening at a random time and be able to reconstruct the original data. Not sure how difficult it would be to implement, but it seems like an interesting idea to explore.

RealEnder commented 2 years ago

Yep, just looked at the code/network interactions and it really just transfers the id through the audio channel :( It will be slow, but splitting the file in blocks + metadata, eg. [block_id?][block_length][offset][data][crc?] + file metadata(blocks_count, hash, maybe name) and just continuously emitting them until user stops the process manually should do the job. Will take a look on the fountain codes. BTW, 10x for your work, it's really great!

detrin commented 1 year ago

I am glad there was some activity. I am just curious @ggerganov what is your opinion on this feature?

wisplite commented 8 months ago

If anyone is still interested, I'm currently attempting to build a solution for this that is not only faster (16bps is a little slow for file transfer) and has error correction and such. I'll update here if people are interested.

wisplite commented 1 month ago

So, it's been a while. Life got in the way, and I haven't had much time to work on this, especially since it isn't super practical. I have a method that I'm pretty sure will guarantee a doubling of the speed (16bps to 32bps), at the cost of a little reliability, and I have the framework of a protocol that can automatically correct for broken data chunks, but I don't know how practical it will be.

Even assuming I managed to get my eventual plan working of pushing ggwave to its absolute limit and quadrupling the data rate, it would still take over 4 hours to transfer a single megabyte of data. We would need to push it to a couple of kbps before we have reasonable transfer rates at that size, which would require a completely new encoder and decoder (dial-up was just IP over sound and it could handle 56kbps, so it's theoretically possible).

I could still develop a proof of concept if people want me to, but don't expect to use it for more than a few kilobytes of data. This would be more than fine for the initial idea of sending private keys or something smaller, but it wouldn't be usable for general file transfer.