6

I am working on a game, and one of the requirements per the licence agreement of the sound assets I am using is that they be distributed in a way that makes them inaccessible to the end user. So, I am thinking about aggregating them into a flat file, encrypting them, or some such. The problem is that the sound library I am using (Hekkus Sound System) only accepts a 'char*' file path and handles file reading internally. So, if I am to continue to use it, I will have to override the c stdio file functions to handle encryption or whatever I decide to do. This seems doable, but it worries me. Looking on the web I am seeing people running into strange frustrating problems doing this on platforms I am concerned with(Win32, Android and iOS).

Does there happen to be a cross-platform library out there that takes care of this? Is there a better approach entirely you would recommend?

Vigabrand
  • 161
  • 6
  • 4
    Could you decode them and write them undecoded into a /tmp file and then call the open and then unlink them right after the open? The file descriptor inside Hekkus would remain valid after the open. ( edit: The ram disk idea below seems better ) – Charlie Burns Sep 03 '13 at 16:27
  • 2
    Define "inaccessible". If you are playing sound on user's system, that sounds pretty accessible to me. Anyway, regarding Hekkus Sound System - author's web site says he offers sources to whoever is interested. So the easiest would probably be getting the source code and patching it. It is weird though that sound library does not abstract the way of getting data into it. – n0rd Sep 03 '13 at 16:36
  • 2
    Please, don't redefine reserved identifier in C, it would invoke undefined behavior. C99 draft standard says (Annex J, section J.2): **The behavior is undefined in the following circumstances: [...] The program attempts to declare a library function itself, rather than via a standard header, but the declaration does not have external linkage (7.1.2). The program declares or defines a reserved identifier, other than as allowed by 7.1.4 (7.1.3).** – LorenzoDonati4Ukraine-OnStrike Sep 03 '13 at 16:40
  • which toolchain do you use? – secmask Sep 03 '13 at 16:44
  • @charlie burns This may work, though it would be slower, and load time is already an issue. Is this reference counting behavior of file descriptors part of the standard (portable) ? – Vigabrand Sep 03 '13 at 16:44
  • @n0rd they don't want end users taking the files and using them themselves. Thanks, I totally missed that on the website, I will try. – Vigabrand Sep 03 '13 at 16:46
  • @secmask right now just msvc, I haven't started porting yet. – Vigabrand Sep 03 '13 at 16:48
  • @LorenzoDonati this would not redefine a reserved identifier, but rather changing the runtime linkage via os-specific calls – Vigabrand Sep 03 '13 at 16:50
  • I think you can depend on that open/unlink behavior on unix. I have no idea about windows. – Charlie Burns Sep 03 '13 at 16:52
  • Sorry, I misunderstood your sentence. *"I will have to override the c stdio file functions[...]"*. Anyway, by "changing the linkage[...]" do you mean you will link (possibly dynamically) against a different runtime? If so, are you sure changing the underliying implementation of file functions doesn't trigger undefined behavior? – LorenzoDonati4Ukraine-OnStrike Sep 03 '13 at 17:06

6 Answers6

7

Do you have the option of using a named pipe instead of an ordinary file? If so, you can present the pipe to the sound library as the file to read from, and you can decrypt your data and write it to the pipe, no problem. (See Beej's Guide for an explanation of named pipes.)

This isn't my real name
  • 4,869
  • 3
  • 17
  • 30
  • 2
    I don't understand. You seem to be saying that instead of passing sound data to the library, you have to pass it the name of a file. If this is the case, a named pipe, also called a FIFO, may be the solution. A named pipe presents as a file in the filesystem, so that whatever opens the file for reading finds itself on the receiving end of your pipe instead of reading an on-disk file. Thus, your program can create a named pipe, pass the _filename of the pipe_ to the sound library, and write decrypted audio data to write end of the pipe. – This isn't my real name Sep 03 '13 at 16:46
  • 1
    A named pipe on Unix is a file that can be fopen'ed like a regular file, therefore its name is a regular 'char *', and the audio library shouldn't have an issue reading from it. However, it must be created using the mkfifo function, for example in another thread of your program, and written into, else fopen will block (see http://stackoverflow.com/questions/580013/how-do-i-perform-a-non-blocking-fopen-on-a-named-pipe-mkfifo) – SirDarius Sep 03 '13 at 16:47
  • Named pipe platform independent? It also implies that you know how the lib opens the file on different platforms. – Martin Schlott Sep 03 '13 at 16:54
  • Unfortunately this seems to be linux only? – Vigabrand Sep 03 '13 at 17:44
  • Or rather, Windows has this facility, but it is not compatible with fopen unfortunately. – Vigabrand Sep 03 '13 at 17:49
  • 1
    You have specified Android and iOS as the platforms you are concerned with, and Google seems to indicate that both these platforms support POSIX. Windows, which you did not specify as a platform of interest, is well known to not support POSIX well (if at all), so no, this wouldn't work there. – This isn't my real name Sep 03 '13 at 19:58
  • 1
    Though, according to @Martin Schlott 's answer windows does have the same functionality (not POSIX of course), and is compatible w/ fopen, so this may work after all... – Vigabrand Sep 03 '13 at 21:34
  • I think this will work, so I will mark as answered unless i find out otherwise, ty – Vigabrand Sep 03 '13 at 22:18
  • I did that myself with a console app, expecting a file path. I gave it a named pipe, created with CreateFile and it worked perfect. Nevertheless, the behavior between Windows and POSIX based system is different, this left you no choice other than distinct between MS and the rest of the world. – Martin Schlott Sep 04 '13 at 06:56
5

Override stdio in a way that a lib you not knowing how it works exactly works in a way the developer hasn't in mind do not look like the right approach for me, as it isn't really easy. Implement a ramdrive needs so much effort that I recommend to search for another audio lib.

The Hekkus Sound System I found was build by a single person and last updated 2012. I wouldn't rely on a lib with only one person working on it without sharing the sources.

My advice, invest your time in searching for a proper sound lib instead of searching for a fishy work around for this one.

Martin Schlott
  • 4,369
  • 3
  • 25
  • 49
  • I hear you. But it would be unfortunate if it came to that, since apart from this issue Hekkus has proven itself to be a very high quality feature complete and easy to use library, despite being the work of one person, and is cross platform to the platforms I care about. Why do you say overriding stdio is hard? It seems like adding a thin layer which performs simple decryption shouldn't be too difficult, so long as I get the actual function overriding working. – Vigabrand Sep 03 '13 at 17:39
  • That may be, and it is totally your decision of course. Honestly, I do not know a way to override stdio's in a platform independent way. For e.g. a solution for Windows is to create a named pipe, you can build a path to a named pipe which can be opened by any stdio file function. There is a similar mechanism for linux, but I do not know if it is the same for any other platform like iPhone or Android. For Windows creating a named pipe you can use CreateFile of the windows API. As far as I know there is no platform independent named pipe library available (yet). – Martin Schlott Sep 03 '13 at 19:02
  • By "overriding stdio" what I had in mind was overriding fopen/fread/etc via dlsym on *nix and the equivalent (hmm is there one?) on windows – Vigabrand Sep 03 '13 at 20:14
  • But yeah you may well be right in needing a different library – Vigabrand Sep 03 '13 at 20:28
2

One possibility is to use a encrypted loopback filesystem (google for additional resources).

The way this works is that you put your assets on a encrypted filesystem, which actually lives in a simple file. This filesystem gets mounted someplace as a loopback device. Password needs to be supplied at attach / mount time. Once mounted, all files are available as regular files to your software. But otherwise, the files are encrypted and inaccessible.

Ziffusion
  • 8,779
  • 4
  • 29
  • 57
1

It's compiler-dependent and not a guaranteed feature, but many allow you to embed files/resources directly into the exe and read them in your code as if from disk. You could embed your sound files that way. It will significantly increase the size of your exe however.

Neil Kirk
  • 21,327
  • 9
  • 53
  • 91
1

Another UNIX-based approach:

The environment variable LD_PRELOAD can be used to override any shared library an executable has been linked against. All symbols exported by a library mentioned in LD_PRELOAD are resolved to that library, including calls to libc functions like open, read, and close. Using the libdl, it is also possible for the wrapping library to call through to the original implementation.

So, all you need to do is to start the process which uses the Hekkus Sound System in an environment that has LD_PRELOAD set appropriately, and you can do anything you like to the file that it reads.

Note, however, that there is absolutely no way that you can keep the data inaccessible from the user: the very fact that he has to be able to hear it means he has to have access. Even if all software in the chain would use encryption, and your user is not willing to hack hardware, it would not be exactly difficult to connect the audio output jack with an audio input jack, would it? And you can't forbid you user to use earphones, can you? And, of course, the kernel can see all audio output unencrypted and can send a copy somewhere else...

cmaster - reinstate monica
  • 38,891
  • 9
  • 62
  • 106
  • Looks like an interesting option, though I have to support windows as well. As to your second point, the sounds are not played individually, there is music and multiple sounds occurring, so it would not be very useful. – Vigabrand Sep 03 '13 at 21:51
  • Even though I've never done the like, I can think of methods to reverse engineer the original sounds, and they are not exactly complicated... But, of course, if your music source is happy with the original files encrypted, and is also happy with the possibility of extracting the music anyway, there would seem to be no problem. Just make sure, he cannot sue you when the music files appear on the internet... – cmaster - reinstate monica Sep 03 '13 at 22:26
0

The solution to your problem would be a ramdisk. http://en.wikipedia.org/wiki/RAM_drive Using a piece of memory in ram as if it was a disk. There is software available for this too. Caching databases in ram is becoming popular.

And it keeps the file from being on the disk that would make it easy accessible to the user.