Looking for a way to edit a GLB file as a string in runtime

What would prevent a 3rd party to use the code from your final website to decrypt your file?

Nothing can ultimately prevent that. Your website renders content on the end user’s computer. Anything you upload to the user’s WebGL context can ultimately be scraped, with enough work. Native code is more obfuscated but still cannot really be protected from this.

I usually point to this reference:

IMO, if you must protect your content then the best approach is (1) a clear copyright, and (2) sufficient obfuscation that accessing the assets would obviously require reverse-engineering rather than just web scraping. E.g., have your public URLs serve content that is encoded, batched, or opaque in some other way.

But is it really that much reverse engineering necessary? Three’s buffer interface is pretty simple, and its obvious when three uploads this stuff to the GPU. I almost feel there should be an extension made for the browsers that’s capable of ripping these geometries just to put this question to rest once and for all :slight_smile:

Yeah, the point of the obfuscation is (IMHO) not that it actually stops a scraper, but that if you had to take someone to court they couldn’t convincingly try to argue, “Oh I just opened this publicly-accessible URL and got a cool file, how could I have known that was not mine?”. Either way the defense is more legal than technical, or possibly just there to satisfy a non-technical project stakeholder.

These days you could even reconstruct a mesh from a screen recording, with some effort…

1 Like

So we are going to create a couple of scripts, That’s going to add some random pieces of code into the GLB file and After Threejs Downloads the file and Before Loading the file, We are going to remove the injected code to make it right again. After that some Obfuscation of the code. All these should add atleast a couple of layers of security.

1 Like

@Sarge I have converted my GLB model into an arraybuffer (Typed array), I am trying to use it in GLTF Loader with the Parse method, But I am not able to load the model. I get “RangeError: Offset is outside the bounds of the DataView”

This is my test code to read and decode the GLB

function Read(){
    document.getElementById('inputfile')
    .addEventListener('change', function() {
    
    var fr=new FileReader();
    fr.onload=function(){				
        let binary = new TextEncoder().encode(fr.result);
        let arrayBuffer = binary.buffer;
        console.log(binary);
        console.log(arrayBuffer);

        let originalBinary = binary.slice(0, binary.length - 3);
        let newArrayBuffer = originalBinary.buffer;
        
        console.log(newArrayBuffer);
        document.getElementById('resultArea').value = "Old " + binary[binary.length-1] + "\n" + "New " + originalBinary[originalBinary.length - 1];

        loadModelFromBuffer(newArrayBuffer);

    }
    
    fr.readAsText(this.files[0]);
})      
}

This is the GLTF Parser Method

function loadModelFromBuffer(buffer) { 
 
const loader = new GLTFLoader();
    //loader.setMeshoptDecoder(MeshoptDecoder);
    loader.parse(buffer, "", function(gltf) {                
        console.log(gltf.scene);
    },
    function(error){
        console.log(error);
    });
}

See Looking for a way to edit a GLB file as a string in runtime - #15 by donmccurdy. I would strongly recommend testing your workflow with simple content you can visually inspect, not a full GLB that needs to be parsed further. Even just new Uint8Array([1,2,3,4,5]).

It seems concerning that your transmitted result is a string and not a binary blob. The GLB is binary content, i obviously can’t see your data but TextEncoder should not be involved in converting an encrypted binary blob to an unencrypted binary blob.

Well I did this simple one and am getting the results, But I am not sure what I am looking for here in the case of GLB, Would it be possible to let me know what is the GLTF Loader Parse method code snippet I have to use to parse a GLB file, Because I am not doing any encryption/decryption at the moment, I just want to load the GLB file using the Parse Method.

–Code as suggested by you—

function SimpleBinaryParser(){

    let array = new Uint8Array([1,2,3,4,5]);

    let binary = new TextEncoder().encode(array);

    let text = new TextDecoder().decode(binary);

    console.log("Binary " + binary); //Prints - Binary 49,44,50,44,51,44,52,44,53
    console.log("Text " + text); //Prints - Text 1,2,3,4,5
}

Also I would like to let you know in my previous code, This line,
let binary = new TextEncoder().encode(fr.result);

Returns binary as a UInt8Array…

Adding to the above post, I am using the original GLB model and with these two lines,

let binary = new TextEncoder().encode(fr.result);
console.log(binary);

let arrayBuffer = binary.buffer;
console.log(arrayBuffer);

I am getting the console result as an UInt8Array and an arraybuffer (Attaching a screenshot)

I am trying to load the Arraybuffer in to the GLTFLoader.Parse method which results in the error
"RangeError: Offset is outside the bounds of the DataView”

Omg, I accidentally tried using “filereader.readAsArrayBuffer(this.files[0]);” instead of “readastext” and It works. My model is getting loaded.

Now I’ll backtrack and try to decode the GLB model, Edit the Arraybuffer and Push it as input.