Implementing schnorr crypto driver on the Earthstar

Implementing schnorr crypto driver on the Earthstar
Photo by Jeswin Thomas / Unsplash

What is schnorr?

Schnorr signature - Wikipedia

What's Earthstar?

Earthstar is a small and resilient distributed storage protocol designed with a strong focus on simplicity, and the social realities of peer-to-peer computing kept in mind.

Now, what and why ?

My use case was to reduce keys proliferation, I have an app that was working with multiple keys , fortunately Earthstare allows setting crypto driver of your own choice, all you have to do is define static class like below and  hence I wrote one.

import { CryptoDriverNoble, setGlobalCryptoDriver } from "earthstar";

import { schnorr } from "@noble/curves/secp256k1";
import { sha256 } from "@noble/hashes/sha256";
import { ICryptoDriver, KeypairBytes } from "earthstar";
import { UpdatableHash } from "./updateHash";

import { createHash } from "sha256-uint8array";

import { bytesToHex } from "@noble/hashes/utils";

// Utility function to convert string to Uint8Array
function stringToBytes(str: string) {
  return new TextEncoder().encode(str);
}

export const CryptoDriverSchnorr: ICryptoDriver = class {
  static async sha256(input: string | Uint8Array): Promise<Uint8Array> {
    if (typeof input === "string") {
      input = stringToBytes(input);
    }
    return Promise.resolve(sha256(input));
  }

  static updatableSha256() {
    return new UpdatableHash({
      hash: sha256.create(),
      update: (hash, data) => hash.update(data),
      digest: (hash) => hash.digest(),
    });
  }

  static async generateKeypairBytes(): Promise<KeypairBytes> {
    //get from local
    let privateKey;
    let publicKey;

    // Attempt to get the private key from localStorage
    const storedKey = localStorage.getItem("keys");

    if (storedKey) {
      // If a private key exists in localStorage, use it
      privateKey = Uint8Array.from(Buffer.from(storedKey, "hex"));
      publicKey = schnorr.getPublicKey(privateKey);
    } else {
      // If no private key is found in localStorage, generate a new keypair
      privateKey = schnorr.utils.randomPrivateKey();
      publicKey = schnorr.getPublicKey(privateKey);

    }

    return {
      pubkey: publicKey,
      secret: privateKey,
    };
  }

  static async sign(
    keypairBytes: KeypairBytes,
    msg: string | Uint8Array
  ): Promise<Uint8Array> {
    if (typeof msg === "string") {
      msg = stringToBytes(msg);
    }
    const messageHash = sha256(msg);
    return schnorr.sign(keypairBytes.secret, messageHash);
  }

  static async verify(
    publicKey: Uint8Array,
    sig: Uint8Array,
    msg: string | Uint8Array
  ): Promise<boolean> {
    if (typeof msg === "string") {
      msg = stringToBytes(msg);
    }
    const messageHash = sha256(msg);
    return schnorr.verify(sig, messageHash, publicKey);
  }
};
Driver

So, its quite sweet and simple, I am working on a simple social media that lets user operate without censorship do check it out here at and yes database is Earthstar and Nostr.

Now, moving ahead how to use the above driver just do this where ever you are planning to use the service like

const setCryptoDriver = async () => {
    return setGlobalCryptoDriver(CryptoDriverSchnorr);
  };
Usage