0.2.5 • Published 1 year ago

@bns-x/png v0.2.5

Weekly downloads
-
License
MIT
Repository
github
Last release
1 year ago

@bns-x/png

A library for verifying and creating "Verified PNGs".

A demo is available on Dots.

Why?

Cryptographic signatures are a mechanism that allows anyone to attest to certain information. Blockchains utilize this technology to verify whether a transaction came from a specific address.

With the growth of NFTs and especially Ordinals inscriptions, there is often a need to establish provenance around a specific image. For example, an artist may wish to use signatures to provably establish that they endorse an artwork.

This library provides an efficient mechanism for anyone to embed their signature in a PNG file, without effecting how the image is displayed.

How it works

PNG files are made up of many "chunks". These chunks contain information about the image, such as the dimensions, color profile, and raw pixel data. Chunks can also be used to include "extra" information, including arbitrary text.

This library utilizes PNG chunks to store signatures.

Creating signatures

The workflow for creating a signature chunk is:

1. Generate a hash of the PNG

For the purposes of this specification, it's not possible to immediately hash the image like any other file, because the file's hash will change after signatures are added. Instead, to generate a hash, you first need to remove any signature-based chunks. This way, a file's hash can remain the same after adding signatures.

2. Create a signature

When generating a signature, the "message" is of the format:

PNG_VERIFICATION:{pngHash}

Where pngHash is created from step 1.

3. Encode signature data

Once a signature is created, it must be encoded as follows:

NameFormatNotes
ProtocolNull-terminated stringUsed to denote the method for verifying signature data
Versionuint8To support future versions of this specification. At the moment, 1 is supported.
Signature DataBytes

The contents of "Signature Data" is dependent on the "protocol" label. For the "STX" protocol, the format is:

NameFormatNotes
Public key33 bytes
Signature64 or 65 bytesSignature in "RSV" format

4. Create a new chunk

This specification uses the zTXt chunk type, because it supports compressed data, which reduces the size of added signatures.

The "label" for the chunk must be verified-inscription. The compression flag must be 0, and the value must be the zlib compressed value of the encoded signature data bytes.

5. Add the chunk to the PNG

The chunk can be included anywhere other than as the last chunk of the PNG. This library appends the chunk as the second-to-last chunk in the file.

Verifying signatures

1. Create the PNG hash

Refer to the process from "creating inscriptions". This is the sha256 hash of the image, after removing signature chunks.

2. Extract verification chunks

A verification chunk is any chunk of the zTXt type with the verified-inscription label. There may be more than one verification chunk.

3. Verify chunk signatures

The methodology for verifying each chunk's signature is dependent on the protocol flag of that chunk. The message used to verify each signature is sha256("PNG_VERIFICATION" + sha256(pngHash)).

Using the library

To extract and verify all verification chunks, use getPngVerifications(pngFile).

import { PNG, getPngVerifications } from '@bns-x/png';

const url = 'https://www.dots.so/signed-example.png';
const response = await fetch(url);
const bytes = new Uint8Array(await response.arrayBuffer());
const png = PNG.decode(bytes);
const verifications = getPngVerifications(png);