I’m looking for a solution to obfuscate geometry data as much as possible.
First off I precise that I’m not looking for a perfect solution, as I know it does not exist. I’m only looking for methods of making it really hard to steal proprietary and somewhat sensible 3D models ( branded product prototypes in my case ). Showing previews is not an option, so I gave up an offering a perfect protection.
I’ve followed this interesting thread, and concluded that in addition to encrypting the file, it’s maybe worth encrypting the geometry itself, so that it’s decoded in the vertex shader.
I was thinking that I could apply matrices to vertex positions in the server, and through uniforms in the client vertex shader, applying the right matrix on the right vertex to make them look right. I don’t think I can hide the matrices much, but at least one would have to uncrypt the file, find the matrices, find out which applies to which vertex, write a tool to apply these matrices and make a file from the buffers…
Anybody made something like that ?
Do you have any advice on how to make it even more tedious to steal a file ?
How long the previously described method would take you to crack ? ( assuming you also have to find out how it works )
PS: the good thing is I don’t have to worry about textures at all.
Server side rendering would make it prohibitively impossible to copy geometry at the client.
I’ve never tried that, but is it really possible to stream images for realtime display ? Or it’s just to display still preview images ?
it’s hugely ambitious, but you could have a combination of the real time scene on the client side that is created from geometries that you don’t care about protecting,
and then add sprites to your scene that use server side rendered textures of the 3d model according to client camera matrix.
The generated textures would always suffer from some kind of latency. And would get worse depending on your compress/decompression algorithm. Low quality jpg is probably the fastest to transfer compromise. i.e, generate image --> send image down socket --> use image on client.
torque3d many years ago, had this concept called autobillboarding, where a texture was created containing multiple renders of the mesh from different angles. It would dynamically update the billboard (sprite in threejs) with the correct section of the texture depending on camera matrix. See the sample image of the trees texture halfway down this page to get the idea.
Making sense of Autobillboards | Torque 3D Professional | Forums | Community | GarageGames.com
Ah isn’t it what we see in games like doom where an object like a monster is a bunch of billboards, shown one at a time depending on the object angle from the camera ?
I really love how it looks, and it does indeed conceal the original model. Is that what you were referring to ?
It’s a bit ill-suited to my usecase unfortunately… I’m doing a jewelry viewer for professional CAD, the point is to offer something as realistic as possible. Here is an example, this particular model is mine so I don’t mind sharing it : https://gvr.to/#v/NcwJAg94s7Q
@felixmariotto that’s a cool app!
I’ve been looking into protecting gltf models too, I was wondering if you know about the possibility of password protecting the folder of models on the server and adding a <php require once “unlock.php” ?> in the html, so when you visit the main page.html, unlock.php gives access to the model folder to load to the user, but if someone tries to access site/models/gltf/model.gltf directly in the browser they would need a password as the php would not be called?
Not sure if this makes sense? would love to know more about php so something like this could work
@forerunrun You could use AWS S3 for your file storage, and require your bucket to be accessed with credentials. Set the credentials as environment variable of your server, then only your server can get the files with AWS API then forward them to your clients.
Personally I think that obfuscation is nearly pointless. It takes 1 determined individual in this case to steal your work. While you invest a lot of work to narrow it down to this 1 person.
Obfuscating the code is one thing, since the structure of the code has much more value typically than it’s apparent function. For geometry you don’t really have such a thing, since the way geometry looks is all there is to it (for graphics that is).
That being said, I suggest some continuous function based transform, something that would distort the model, like a sine wave. It’s fairly easy to revert in code if you know the function, and it makes manual reversal nearly impossible.
Another thing, you may want to just scramble the order of vertices and indices, and have a de-scrambler in your code that follows the model loader. You would have plain geometry in memory, but if someone wants to steal your geometry, they would need to find a way to access relevant piece of memory, and extract the data, then convert it to a usable format. The advantage of this approach is that you don’t have to modify the renderer, it’s a load-time penalty only, and depending on your scrambler - it can be very efficient. Heck, you can even encrypt the whole .bin portion of the .gltf file (if you use such, and decrypt it in code). Personally I wouldn’t do that, since the more standardized your method is - the easier it is to understand and reverse by someone who knows what they are doing.
Hope that helps.
Thank you @Usnul for your suggestions !
Yes the idea of a distortion function is interesting, I hope I can do that losslessly though, because of floating point imprecision… I will do some tests now anyway and see what happens.
About the vertex index scrambler, I was wary of the performance issue on de-scrambling… Do you think something performant can be made to un-scramble a geometry with ~5 million vertices ? I will do my tests for that as well anyway… Now that I think about it again I could scramble chunks of vertices to improve performance, that would be equally complex to repair I imagine, maybe more depending on how I do my chunking. Chunks could overlap for instance.
In case you were curious about the SSR way of protecting your geometry. I don’t think my example is high quality enough for your use case, but you can see it anyway.
No geometry is transferred to the client at all, the browser client doesn’t even have threejs running on it. It’s just server side images created from the threejs renderer running on the nodejs server and sent using a socket.
This is a $5 a month ubuntu in New York generating the images in real time.
Realtime SSR Demo using Threejs server side: https://ssr.sbcode.net/
I believe “de-scrambling” would be quite fast. Depending on your method, as long as there’s no branching and you inline all of your code - 5m vertices should be just a couple of hundreds of ms at most. You could also employ a webworker if this seems like a hard penalty.