Thursday, March 19, 2026
HomeBitcoinprivateness - The right way to combination Schnorr PrivateKeys and PublicKeys from...

privateness – The right way to combination Schnorr PrivateKeys and PublicKeys from untrusted sources to create stealth addresses?

Alice needs to donate to Bob anonymously.
Alice needs to create a bitcoin “stealth” tackle for Bob (which can’t be related to Bob on the blockchain explorer) utilizing shnorr signatures.

Alice has Bob’s Schnorr PublicKey1 from his donation web site.
Alice produces on her laptop computer a brand new (privateKey2, publicKey2) pair.
Alice creates aggregated PubKey1 + PubKey2 utilizing Schnorr’s aggregated public keys function.
Alice sends bitcoins to the aggregated tackle(PubKey1 + PubKey2).
Alice shares the privKey2 with Bob through a safe end-to-end channel.

Later, Bob logs in and retrieves the PrivKey2 that Alice shared.
Bob then calculates aggregated PrivKey1 + PrivKey2 and spends the unspent transaction.

I used to be capable of obtain PubKey1 + PubKey2 with the Musig2 aggregation operate that makes use of tags.

import * as musig2 from '@scure/btc-signer/musig2.js'
import {randomBytes} from "@noble/ciphers/utils.js"
import {schnorr} from "@noble/curves/secp256k1.js"

//alice pair
privateKey2 = randomBytes(32)
publicKey2 = musig2.IndividualPubkey(privateKey1)

const individualsPublicKeys = [publicKey1, publicKey2]; // Acquire all particular person public keys
const sortedPublicKeys = musig2.sortKeys(individualsPublicKeys); // Type public keys lexicographically (as required by MuSig2)
const aggregatePublicKey = musig2.keyAggregate(sortedPublicKeys).aggPublicKey.toBytes(true) // Extract combination public key (33 bytes)

console.log(aggregatePublicKey)//PublicKey1 + PublicKey2

//...
//Alice ship cash to handle(aggregatePublicKey)
//...

the right way to compute combination privateKey1 + privateKey2 to spend the cash ?

signature = schnorr.signal(msg, aggregatePrivateKey)
schnorr.confirm(signature, msg, aggregatePublicKey);

However how does Bob compute the aggregated non-public key in JavaScript utilizing the @scure/btc-signer @noble/curves/secp256k1 libraries? Is there a vulnerability whereas computing the aggregated non-public key? Bob distrusts Alice as a result of she may very well be an terrible adversary who may attempt to steal Bob’s non-public key.

I do know Bob can implement musig2 partial signature, however my entire code already makes use of musig2 partial signature, thus this is able to end in a two-step recursion. On this situation, I’m uncertain the right way to use musig2 partial signature.

LE:

I imagine I’ve labored it out. To combination non-public keys, I imagine Bob has to simply add them utilizing the Level.Fn.

Bob can generate the merged non-public key

var aggrPriv = schnorr.Level.Fn.create(  schnorr.Level.Fn.fromBytes(Priv1) +  schnorr.Level.Fn.fromBytes(Priv2) )
console.log( 'aggrPriv', schnorr.Level.Fn.toBytes( aggrPriv ) )

Alice can generate the merged public Key

var aggrPub = schnorr.Level.ZERO;
aggrPub = aggrPub.add(schnorr.Level.fromBytes(Pub1.bytes))
aggrPub = aggrPub.add(schnorr.Level.fromBytes(Pub2.bytes))
console.log('aggrPub', aggrPub.toBytes(true) )

console.log( equalBytes( schnorrGetPoint(aggrPriv).bytes, aggrPub.toBytes(true)) )

each matches in console. Bob now can use aggrPriv to spends the cash he acquired from Alice.

Is the aggregation of Schnorr non-public keys safe? Do I’ve to carry out any extra verifications?

RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Most Popular

Recent Comments