Assessment reports>Babylon Genesis Chain>Addendum>Nonce reuse in adaptor signatures allows recovering signing key tests

Nonce reuse in adaptor signatures allows recovering signing key tests

Unit tests to demonstrate the empirical key-recovery probabilities

func TestAdaptorSigRecoverNonceReuse(t *testing.T) {
    successes := 0
    for i := 0; i < 1000; i++ {
        sk, err := btcec.NewPrivateKey()
        require.NoError(t, err)
        pk := sk.PubKey()
        encKey1, _, err := asig.GenKeyPair()
        require.NoError(t, err)
        encKey2, _, err := asig.GenKeyPair()
        require.NoError(t, err)

        msg := []byte(fmt.Sprintf("test"))

        msgHash := chainhash.HashB(msg)

        asig1, err := asig.EncSign(sk, encKey1, msgHash)
        require.NoError(t, err)
        asig2, err := asig.EncSign(sk, encKey2, msgHash)
        require.NoError(t, err)

        recoveredSk := asig.RecoverNonceReuse(pk, asig1, asig2, msgHash)

        if sk.Key == recoveredSk.Key {
            successes += 1
        }
    }
    fmt.Printf("Individual message successes: %v\n", successes)
}

func TestAdaptorSigRecoverNonceReuseIndependent(t *testing.T) {
    successes := 0
    for i := 0; i < 1000; i++ {
        subSuccesses := 0
        sk, err := btcec.NewPrivateKey()
        require.NoError(t, err)
        pk := sk.PubKey()
        encKey1, _, err := asig.GenKeyPair()
        require.NoError(t, err)
        encKey2, _, err := asig.GenKeyPair()
        require.NoError(t, err)

        for j := 0; j < 10; j++ {
            msg := []byte(fmt.Sprintf("test%d", j))

            msgHash := chainhash.HashB(msg)

            asig1, err := asig.EncSign(sk, encKey1, msgHash)
            require.NoError(t, err)
            asig2, err := asig.EncSign(sk, encKey2, msgHash)
            require.NoError(t, err)

            recoveredSk := asig.RecoverNonceReuse(pk, asig1, asig2, msgHash)

            if sk.Key == recoveredSk.Key {
                subSuccesses += 1
            }
        }
        if subSuccesses > 0 {
            successes += 1
        }
    }
    fmt.Printf("Independent message successes: %v\n", successes)
}

func TestAdaptorSigRecoverNonceReuseCombinatorial(t *testing.T) {
    successes := 0
    numEncKeys := 6
    for i := 0; i < 1000; i++ {
        sk, err := btcec.NewPrivateKey()
        require.NoError(t, err)
        pk := sk.PubKey()

        msg := []byte(fmt.Sprintf("test"))
        msgHash := chainhash.HashB(msg)

        encKeys := make([]*asig.EncryptionKey, numEncKeys)
        sigs := make([]*asig.AdaptorSignature, numEncKeys)

        for j := 0; j < numEncKeys; j++ {
            encKey, _, err := asig.GenKeyPair()
            require.NoError(t, err)
            encKeys[j] = encKey
            sig, err := asig.EncSign(sk, encKey, msgHash)
            require.NoError(t, err)
            sigs[j] = sig
        }

        outer:
        for j := 0; j < numEncKeys; j++ {
            for k := 0; k < j; k++ {
                if j == k {
                    continue;
                }
                recoveredSk := asig.RecoverNonceReuse(pk, sigs[j], sigs[k], msgHash)
                if sk.Key == recoveredSk.Key {
                    successes += 1
                    break outer
                }
            }
        }
    }
    fmt.Printf("Combinatorial message successes: %v\n", successes)
}
Zellic © 2025Back to top ↑