Steganography NFT: What can it be used for?

I revisited the NFT Standard article and determined that my initial idea of pseudo-steganography is likely the only viable way to achieve Mr Kaine’s vision. I don’t see any other way, based on research I’ve done about modern steganography capabilities.

I’ll explain why in this post.

TL;DR
I propose that we concatenate an encrypted, variable size data container to carrier data. We may potentially use LSB to embed the Virtual Hologram in the carrier data.


Excerpt from the Medium Article:

When you create an NFT, you should have the option to add additional content that can only be revealed by the NFT holder. Such content can be anything.
High definition content, messages, video content, access to secret communities, discount codes, or even smart contracts, treasures, and easter eggs are all potential candidates for unlockable content.


Mr Kaine knows people will be minting JPEGs, but stipulates that the solution should permit any content to be embedded in the carrier data.

I only know of one way this can be achieved.
Since the embedded data can be of variable size and can potentially be greater than the size of the original carrier data, we must find a steganographic technique that:

  • is extremely flexible,
    • in terms of file size, file type
  • is cryptographically malleable
    • in terms of asset transferability
  • is not constrained by the size of the input data
  • can be parsed by anyone to certify authenticity (Spectral Attestation)
  • ideally, is accessible to mobile wallets and devices with less compute capabilities

A core limitation of modern steganographic techniques is the size of the carrier.

Generally, steganography introduces changes in the original file’s data in order to hide other data; replacing original data with anything else tends to lead to data loss.
You can’t replace bits and expect all the information to remain intact.

Of course, slight changes to the file may be imperceivable to humans, but there’s a relation between how much data that can be stuffed in carrier bits and visual/auditory/spatial degradation of carrier data quality.

Low impact to original bits
- more likely to maintain original file quality
- less capacity for the embedded file

Higher impact to original bits
- less likely to maintain original file quality
- more capacity for the embedded file

This is why steganography is generally lossy. Same applies to compression.

About lossless steganography...

There are few lossless solutions and they do not fit our needs. They rely on the chance that the carrier data contains the same subset of bits as the embedded data.
I’m not confident this will work for every file and users cannot be limited by their selection of files.
If you find any lossless solutions that could work in our context, please let me know.


Mr Kaine outlines two options in his article: LSB and BPCS.

LSB is primitive, popular, easy to implement for many file types, but it has the embedded data size constraint.

BPCS is a newer technique that depends on spatial noise in the carrier data to hide information, and it seems to be only applicable to image files.
It works well with image data of a realistic setting with lots of different shades, colors, edges, objects, etc, but fares poorly with flat, cartoon-like graphics.
It takes advantage of visual chaos; cartoons tend to have large areas of the same pixel color.

For example, BPCS would offer much higher capacity for the image on the left.


The final reason why those two methods won’t work – We need to encrypt the embedded contents, because our software is open source and the ledger is public.

A malicious actor will scrape all the carrier data by querying the ledger and extract the embedded payloads of each NFT.

I’ve tested AES-256-CBC and AES-256-GCM in Dart; we should expect ~4x file size output or greater. I could try other encryption schemes, as well.

Some results from a few tests:

Show results

Input files

  • input.png = 180 KB
  • secret.png = 120 KB
  • secret.mp4 = 17230 KB

Unencrypted Output

  • input.png + secret.png => output.png = 299 KB
  • input.png + secret.mp4 => output.png = 17410 KB

AES-256-CBC Output

  • input.png + encrypted(secret.png) => output.png = 907 KB
  • input.png + encrypted(secret.mp4) => output.png = 105174 KB

AES-256-GCM Output

  • input.png + encrypted(secret.png) => output.png = 908 KB
  • input.png + encrypted(secret.mp4) => output.png = 78925 KB

Here’s some binwalk output, they’re all the same:

Show binwalk output
$ binwalk output.png

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
0             0x0             PNG image, 900 x 900, 8-bit/color RGBA, non-interlaced
41            0x29            Zlib compressed data, compressed

Visual representation of my proposal:
image

Note: The Virtual Hologram (VH) is likely to be a small value, like the container’s header (H) and trailer (T).

Alternatively, since the Virtual Hologram may be short and a fixed length (tbd), we could potentially leverage LSB to embed that in the carrier data for all file types.


I’ve updated my pseudo-steganography PoC but haven’t published it yet.
There are still some cryptography-related logistics I need to work out.

I welcome any feedback regarding my posts on this topic. I’m seeking criticism of the approach, in case there are flaws I haven’t considered.

If I don’t hear from anyone, I might just “do it myself.”

3 Likes