Don't sleep through your next NFT forgery

Solving For Sleepminting

Clay Graham
3 min readApr 25, 2021

--

Recently Tim Schneider, from Artnet posted a great story about how a whitehat hacker managed to trick the blockchain into forging tokens that would forge the Provenance of the originator of the NFT to look as though it was the originating artist.

https://news.artnet.com/opinion/sleepminting-nftheft-monsieur-personne-1960744

In the opening days of April, an artist operating under the pseudonym Monsieur Personne (“Mr. Nobody”) tried to short-circuit the NFT hype machine by unleashing “sleepminting,” a process that complicates, if not corrodes, one of the value propositions underlying non-fungible tokens. His actions raise thorny questions about everything from coding, to copyright law, to consumer harm. Most importantly, though, they indicate that the market for crypto-collectibles may be scaling up faster than the technological foundation can support.

The Gray Market: How a Brazen Hack of That $69 Million Beeple Revealed the True Vulnerability of the NFT Market (and Other Insights) — Tim Schneider

While I find this article very interesting, in my opinion, this is a problem that can easily be solved merely by adding a signature to the metadata of the tokenURI which is required as part of the ERC721 specification.

Here is an example of common metadata that a token’s tokenURI commonly points to on IPFS:

{
"name": "CrytoLoa 70418a47",
"description": "Agents that live on the blockchain.",
"external_url": "http://localhost:3000/nfts/2",
"image": "ipfs://QmQEdpKHxit5zvUpXtVcs5EVha241CTYRhrdp6qSRcuMGL",
"attributes": [
{
"display_type": "number",
"trait_type": "Generation",
"value": 3
}
],
"model": "ipfs://QmUpF2He1Df2kJYq3kUX9mTrvYd9Gmw9yBeTP13BJdR2S1"
}

So with a metadata body like that it would be easy to generate a new token and using the sleepminting pattern there would be no way to verify that the token metadata was authored by the artist because the token metadata itself has not been signed as being created by the artist.

Artist RSA Keypair Signing To The Rescue

https://en.wikipedia.org/wiki/Public-key_cryptography

So that YOU can know that every token that I mint is created by me I am going to share my public key with you. Then when any art that I create and sell as an NFT is minted I am going to take the payload of the token metadata and sign it so you can verify that it came from me. Only I can create the signature because only I have the private key, and since no two NFTs will have the same payload that was signed, it wont be possible to forge the token.

So If I publish my PUBLIC key to the whole world as such:

-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA5a+7tnYw+vti8qcERzog
vsurNU5FQSG3Yy63ptiwFDuXq+nQMJ8EHsFeGq/Cch7UqKv5YlGMg7vw+tzR2veu
aV5M1PkeDbqll0C2GffF/2OfUmiPKrdrXsszEht4Yz8V45b8Bwm4RgBCs7Q6GveZ
3K4SUWQC2D2Mys/JIrXPTaxxW+wO6A77jbhnRQhCuMXxglRM7IsxBWjYLPSan366
eaH4PuBFHGGF6w3Z4TZohPpNWR0FW3CF6PJF1+cWZNnyMjzNo5e6W1GHUhwlUeTl
2NxwyuklqQYcH3bQqkcHqYbbfqEboi1mAwq8/ZdAWwT/BD0niL5n8KMfLkQ1Jfki
8QIDAQAB
-----END PUBLIC KEY-----

And now create an extra section of the metadata specifically for signing as a payload which contains an md5 hash of the entire text of the payload (minus the payload field).

{
"name": "CrytoLoa 70418a47",
"description": "Agents that live on the blockchain.",
"external_url": "http://localhost:3000/nfts/2",
"image": "ipfs://QmQEdpKHxit5zvUpXtVcs5EVha241CTYRhrdp6qSRcuMGL",
"attributes": [
{
"display_type": "number",
"trait_type": "Generation",
"value": 3
}
],
"model": "ipfs://QmUpF2He1Df2kJYq3kUX9mTrvYd9Gmw9yBeTP13BJdR2S1"
"payload":{
"md5": "a8e0593b60f95b2ad0f3cc0f4bcbe10a"
}

}

Signing the token

An now use basic signing with a private key:

openssl dgst -sha256 -sign claytantor_20210417.pem -out /tmp/sign.sha256 payload.txt
openssl base64 -in /tmp/sign.sha256 -out payload.sig
cat payload.sig
R8UKcHYytr94J8lE2RpqCNWCa31+tYCBVzbL6jycYS12trXMiVjWb+KPbyzNK9gQ
ew0ABB5Unxizm33oGgQTW6qWsCGMvbiQn95aBwaUKmBLPY0bhqSjds4d8gNCx23d
t2im+n8iX9/k/EzRqWahFO0FuWRiLKkTB0fE9eI1i9qTB/7hRyBDGTDPnlDIHF46
QB9qdR/zDbni/Aro9k6wWxznddzhl+GyGz5lf7+mDNEy3N3XRRK6zg5HqQS91vpg
EJ4HS8rHuaufGrrm39mxz/xkfqjkcgWQZOL9LN0RGP+eVKX5fi4UMjdrRZS1eBmj
8e18I1wI7Rxe2ZrOpeGb/A==

Now we add that signature to the token metadata so that the tokenURI will always return metadata that can be verified against the artist’s private key:

{
"name": "CrytoLoa 70418a47",
"description": "Agents that live on the blockchain.",
"external_url": "http://localhost:3000/nfts/2",
"image": "ipfs://QmQEdpKHxit5zvUpXtVcs5EVha241CTYRhrdp6qSRcuMGL",
"attributes": [
{
"display_type": "number",
"trait_type": "Generation",
"value": 3
}
],
"model": "ipfs://QmUpF2He1Df2kJYq3kUX9mTrvYd9Gmw9yBeTP13BJdR2S1"
"payload":{
"md5": "a8e0593b60f95b2ad0f3cc0f4bcbe10a"
},
"sig": "R8UKcHYytr94J8lE2RpqCNWCa31+tYCBVzbL6jycYS12trXMiVjWb+KPbyzNK9gQ
ew0ABB5Unxizm33oGgQTW6qWsCGMvbiQn95aBwaUKmBLPY0bhqSjds4d8gNCx23d
t2im+n8iX9/k/EzRqWahFO0FuWRiLKkTB0fE9eI1i9qTB/7hRyBDGTDPnlDIHF46
QB9qdR/zDbni/Aro9k6wWxznddzhl+GyGz5lf7+mDNEy3N3XRRK6zg5HqQS91vpg
EJ4HS8rHuaufGrrm39mxz/xkfqjkcgWQZOL9LN0RGP+eVKX5fi4UMjdrRZS1eBmj
8e18I1wI7Rxe2ZrOpeGb/A=="

}

At this point the token and the payload is ready for minting.

Verifying the token

This article doesnt try to go into the details on how one would use a library like web3 to get the token metadata from the etherium blockchain, its expected that you already know about that. Assuming you have done that and want to verify the token was minted by the artist.

Well, they did give you their public key…

echo "a8e0593b60f95b2ad0f3cc0f4bcbe10a">payload.txt echo "R8UKcHYytr94J8lE2RpqCNWCa31+tYCBVzbL6jycYS12trXMiVjWb+KPbyzNK9gQ
ew0ABB5Unxizm33oGgQTW6qWsCGMvbiQn95aBwaUKmBLPY0bhqSjds4d8gNCx23d
t2im+n8iX9/k/EzRqWahFO0FuWRiLKkTB0fE9eI1i9qTB/7hRyBDGTDPnlDIHF46
QB9qdR/zDbni/Aro9k6wWxznddzhl+GyGz5lf7+mDNEy3N3XRRK6zg5HqQS91vpg
EJ4HS8rHuaufGrrm39mxz/xkfqjkcgWQZOL9LN0RGP+eVKX5fi4UMjdrRZS1eBmj
8e18I1wI7Rxe2ZrOpeGb/A==">payload.sig
cat payload.sig |base64 -d >sig.binopenssl dgst -sha256 -verify claytantor_20210417.pub -signature sig.bin payload.txtVerified OK

Conclusion

Verification of signatures is a tried and true way to beat anyone trying to spoof. Its the basis of the JWT token standard and uses a similar pattern for request verification. Adding real signatures to the metadata of tokens is the easiest yet most powerful way to ensure a token’s Provenance

--

--