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?

10
  • 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 ) Commented Sep 3, 2013 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. Commented Sep 3, 2013 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). Commented Sep 3, 2013 at 16:40
  • which toolchain do you use? Commented Sep 3, 2013 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) ? Commented Sep 3, 2013 at 16:44

6 Answers 6

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.)

Sign up to request clarification or add additional context in comments.

9 Comments

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.
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 stackoverflow.com/questions/580013/…)
Named pipe platform independent? It also implies that you know how the lib opens the file on different platforms.
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.
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...
|
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.

4 Comments

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.
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).
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
But yeah you may well be right in needing a different library
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.

4 Comments

This seems to be a linux-only concept?
Most *nix OS (including MacOS) seem to have it en.wikipedia.org/wiki/Loop_device. Also, since Android is a Linux derivative, it should have it too.
I will also be releasing on windows though.
I am sure you can find something. sourceforge.net/projects/freeotfe.mirror
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.

4 Comments

This doesn't work transparently though, so the library would not be able to open these "files".
@Vigabrand Why not? Just load them into an array of bytes.
the char* refers to a file name in the Hekkus API
@Vigabrand I couldn't find the Hekkus API documentation to see if there are alternative ways.
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...

2 Comments

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.
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...
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.

5 Comments

On an Android? An iPad?
I wouldn't really like it if a game or application added a new drive to the system while running. Besides, I don't know if there is a portable solution, and it would probably require root/adminstrator permissions.
The question shows that the asker is more on the beginner site of developing. Implementing a ramdisk does not look like a proper advice. Additional I know no ramdisk which is working platform independent.
@Martin Schlott Hrm not necessarily LOL
Didn't want to offend you.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.