3D Printing Watermark that can't be removed

Watermark3D promises to secretly watermark any .stl file without affecting geometry… but does it work, word it work on the polypros, and can it be defeated?

1 Like

Did a little byte level analysis of two files via ipython with numpy-stl and hexdiff.

For the test I used https://www.thingiverse.com/thing:2186154 and the watermark of (c)2017 dwightaspencer.com. All rights reserved (disclaimer: clearly neither, I nor Doug are claiming a copyright on the original logo and I’m not keeping or publishing the resulting files from testing so no copyright claim on Doug’s original stl is being made at any point, only used a bit of text that i have a gpg hash of plus can quickly know by eye and memory for the binary values.)

From what I can see they change the original header by nulling out the first 79 bytes and then change bytes 81 and 82 which is the 32 bit unsigned integer for how many vectors are in the file.

Test file has 3859808256 vertex:

0x80: e6 10 00 00

vs watermarked3d file’s 171245568 vertex:

0x80: 0a 35 00 00

That’s a difference of 3688562688 vertices. Clearly there’s a bit of steganography going on here. After scrolliing through the binary section for the mesh I’m seeing areas from the diff that are ascii values. These values are not clearly one to one of my text but are there. It also appears that after a few of the original vertices theirs a few paired new ones. Plus the attribute byte on a few of them are changed too. So they’re padding vertices for the sake of hiding ascii values inside binary vectors and adding a checksum via attribute bytes, cool.

This does continue on for a bit in the rest of the file and at the end of the origin file segment there seems to be a lot more vectors but these do not show up to be regular vectors since the values repeat with a few minor variation but the big tell is a 4 byte stream that contently shows up c1 3333 cb followed by 8 bytes of data.

So the signature has been found c1 33 33 cb. If this is in the file then the app knows where to look and decode the next 8 bytes. At this point I’ll leave it to the next ingenious individual to do with as they please since today I’m wearing my white hat.

3 Likes

very nice. I may just use that service. thanks.

2 Likes

If I get the motivation then I might just make a better version that works with keybase and does nsa level stenography.

2 Likes

I thought a bit about this problem a while back, and realized a cool method would be to encode data by permutation of the order of vertices making up each triangle. No effect on file size or geometry, and if randomized beforehand and payload encrypted it should be pretty undetectable. But of course like any of these methods it could be stripped easily if you have a suspicion it exists.

1 Like

Interesting, though I would thing that it requires use of ECC algorithms and maybe an elliptic curve for the randomization.

IIRC, the order of the vertices is used with the “right-hand rule” to develop a normal to the surface indicating which way is “outside”.

If you flip the order (making an ABC/BCA/or CAB triangle into an ACB/CBA/or BAC triangle, you’ll reverse the face and potentially screw up the slicing algorithm.

Yup, but assuming you’ve defined a formula for ordering the vertices, you can distinguish between ABC, BCA and CAB which all have the same normal and produce the same geometry. So you can encode ~ 1.6 bits per triangle this way.

1 Like

So you can encode ~ 1.6 bits per triangle this way.
that would explain the rather large jump of 3688562688 vertices. Though if my math is right then that’s about 2.36 bytes which we’ll be missing a few since my text is 47 ASCII/UTF-8 bytes.

Sure with gzip compression one gets about a compression ratio of 73% but the results size is 66 bytes. So, thinking this over then if thier not directly encoding the string into the file then they’re putting an identifier and key of some sort and looking up the key in their backend.