Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Optional Field: Author Proof #2

Open
whoabuddy opened this issue Mar 9, 2023 · 7 comments
Open

Optional Field: Author Proof #2

whoabuddy opened this issue Mar 9, 2023 · 7 comments

Comments

@whoabuddy
Copy link
Contributor

How can we prove the author is the author?

For .sats names, it'd be interesting to explore a BIP-322 or some kind of structured data signed by the wallet.

For .btc names, we could implement a similar structure using SIP-018.

@whoabuddy
Copy link
Contributor Author

Dropping some notes from some earlier conversations and after a Discord conversation with @pradel - some good ideas here!

BIP322 Proof of UTXO and related signing ideas:

BIP322 text:
https://github.com/bitcoin/bips/blob/master/bip-0322.mediawiki#user-content-Full_Proof_of_Funds

Electrum and Sparrow implement signatures, and this page had some resources with a timeline:
https://bitcoinops.org/en/topics/generic-signmessage/

This wiki gets into the details for signing with different address types, but not sure if it's following BIP322 or an alternative to it:
https://en.bitcoin.it/wiki/Message_signing

These were some use case explorations that show some good ideas toward what's possible
https://hackmd.io/@bc-interns-2022/HyJC-yBt5

Here was a pull request related to two different implementations between Trezor and Electrum with some good discussion on supported formats and links to the sign message methods in bitcoinjs-message. Looks like BlueWallet adopted it as well.
bitcoinjs/bitcoinjs-message#29

...and a JS library! 🔎
https://github.com/bitcoinjs/bitcoinjs-message/

Also some talk here if the library should continue to be maintained or archived, the PR included an update to TypeScript:
bitcoinjs/bitcoinjs-message#38
bitcoinjs/bitcoinjs-message#39

Trezor's resources here as well:

https://trezor.io/learn/a/sign-verify

sign_message.py
https://github.com/trezor/trezor-firmware/blob/79632d32c79e02c7801d14c1aabd2822c8204892/core/src/apps/bitcoin/sign_message.py

verify_message.py
https://github.com/trezor/trezor-firmware/blob/79632d32c79e02c7801d14c1aabd2822c8204892/core/src/apps/bitcoin/verify_message.py

Address Ownership Proof Protocol

There were a few mentions of AOPP but not much information following that, resources are below and may be another way to prove ownership.

https://aopp.group/
https://gitlab.com/aopp/address-ownership-proof-protocol/-/blob/master/README.md

From the website:

Adopting the digital signature standards that Bitcoin uses makes it straightforward to implement for developers.

This was the GitHub discussion about the implementation but haven't seen much more.

Other Implementations

Nostrocket: micro-dao funding for projects

Using BIP-322 to prove funds:

https://nostrocket.org/
https://github.com/nostrocket

Mirror format for signatures:

 "authorship": {
    "contributor": "0x12105a90a4CfeF063eDfA3Bd8b7db816087e01b6",
    "signingKey": "{\"crv\":\"P-256\",\"ext\":true,\"key_ops\":[\"verify\"],\"kty\":\"EC\",\"x\":\"35OfTI7WFOVwnj-Qd-nQAp6XpJG-fCDAoOV2PpwRN7s\",\"y\":\"cbEMNrq_LTWb9YkO7soplOgEkbWI6jY28YAy3LIfo7c\"}",
    "signature": "0x8da0ebe3b8009ee7978489c3f4e3bd1b81dbe88ec3dba66cbcd18133151dced0478218b68e19e9a7ae8bf2bd6fdacd06022fe4ceafa710b765319a8bff8593191b",
    "signingKeySignature": "cBee8_F9SWSV0ZCE293iKTo0DwfY6XjWb8A4JknZNuxwsSZ51q_Zvs1SK_xs8PFaePr-qUJFcUFiipTvUb-kIQ",
    "signingKeyMessage": "I authorize publishing on mirror.xyz from this device using:\n{\"crv\":\"P-256\",\"ext\":true,\"key_ops\":[\"verify\"],\"kty\":\"EC\",\"x\":\"35OfTI7WFOVwnj-Qd-nQAp6XpJG-fCDAoOV2PpwRN7s\",\"y\":\"cbEMNrq_LTWb9YkO7soplOgEkbWI6jY28YAy3LIfo7c\"}",
    "algorithm": {
      "name": "ECDSA",
      "hash": "SHA-256"
    }
  },

There is also a digest field shown on articles, which is a unique ID to query the different version of the post.

"digest": "QZqHyzWFJuXl3Ac_JScjLQI2AQsKIXP8JNbCKrAtOJo"

Arweave tx example: https://viewblock.io/arweave/tx/YUOCMG1EJW3vfbYYpIUcJbn0BBhL6yC2bFuSZo-CDNI

@whoabuddy
Copy link
Contributor Author

Let's start simple and iterate! Initially the signature could just be a signed message of all the other fields in the payload.

Credit to @pradel for that idea and the first signed news item on the standard:
https://inscribe.news/api/news/892a90d8f022a6c329835aa0f7f7f3102a7375fe9aa7a6f672e418cf954e1c0ei0
https://inscribe.news/api/content/892a90d8f022a6c329835aa0f7f7f3102a7375fe9aa7a6f672e418cf954e1c0ei0
https://inscribe.news/api/info/892a90d8f022a6c329835aa0f7f7f3102a7375fe9aa7a6f672e418cf954e1c0ei0

@whoabuddy
Copy link
Contributor Author

Also adding Paul Miller's library for noble curves here, which was recently audited by Trail of Bits:

https://github.com/paulmillr/noble-curves
https://twitter.com/paulmillr/status/1633804139472777218?s=20

secp256k1 has schnorr signature implementation which follows BIP340:

import { schnorr } from '@noble/curves/secp256k1';
const priv = schnorr.utils.randomPrivateKey();
const pub = schnorr.getPublicKey(priv);
const msg = new TextEncoder().encode('hello');
const sig = schnorr.sign(msg, priv);
const isValid = schnorr.verify(sig, msg, pub);
console.log(isValid);

@whoabuddy
Copy link
Contributor Author

Following up on this, Sigle has a working implementation for proving the authorship of a single post. :clapping:

Fields Used

const parsedData = {
  p: 'ons',
  op: 'post',
  id: data.id,
  author: user?.username,
  authorAddress: user?.profile?.stxAddress?.mainnet,
  title: data.title,
  body: data.content,
  url: `${appConfig.appDomain}/${user?.username}/${storyId}`,
  signature: signedData ?? undefined,
};

Signing Method

Using the sign method from stacks/connect for creating a SIP-018 signed message.

const handleSign = async () => {
  await sign({
    network: new StacksMainnet(),
    message: JSON.stringify(parsedData),
    onFinish: async ({ signature }) => {
      setSignedData(signature);
    },
  });
};

Verification Method

Using stacks/transactions to:

  • get the public key from the signature
  • get the address from the public key
  • verify the author address = recovered address

Using the publicKeyFromSignatureRsv method from .

// Call the api to get the inscription data
let data = await fetch(
  `https://inscribe.news/api/content/${inscriptionId}`
);
if (!data.ok) {
  return toast.error('Invalid response from api');
}
let json = await data.json();
if (json.p !== 'ons' || json.op !== 'post' || !json.signature) {
  return toast.error('Invalid data');
}


const message = JSON.stringify({ ...json, signature: undefined });
// We verify the signature is valid
const recoveredPublicKey = publicKeyFromSignatureRsv(
  bytesToHex(hashMessage(message)),
  createMessageSignature(json.signature)
);
const recoveredAddress = getAddressFromPublicKey(recoveredPublicKey);
if (json.authorAddress !== recoveredAddress) {
  console.log(json.authorAddress, recoveredAddress);
  return toast.error(`address does not belong to publicKey`);
}
if (
  !verifyMessageSignatureRsv({
    message,
    publicKey: recoveredPublicKey,
    signature: json.signature,
  })
) {
  return toast.error(`Signature does not belong to issuer`);
}

@whoabuddy
Copy link
Contributor Author

Looking at the logic above it does prove that the authorAddress is the one who posted, and would be curious if this same idea would be possible on the Bitcoin side, cc @yknl and @markmhx. It'd be nice to have them both work generally the same!

@pradel am I correct that this would just prove the authorAddress but not the author field? I think it'd be more powerful if we could make sure a BNS/BNSx name there was in fact the author, otherwise there could be some confusion if I sign from a random address claiming to be whoabuddy.btc and it passes verification.

On that note, it'd be great to define something that works for both .btc and .sats so both Stacks and Bitcoin have the option to prove authorship of a single post. 🤔

@whoabuddy
Copy link
Contributor Author

This could be helpful on the Bitcoin side!
https://github.com/secretkeylabs/sats-connect

@markmhendrickson
Copy link

Curious if the more recently supported BIP0322 signing works for this out of the box? https://hirowallet.gitbook.io/developers/bitcoin/sign-messages

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants