Assessment reports>Babylon Chain>Low findings>Finality provider BTC private key used as HMAC key for generating nonces
Category: Coding Mistakes

Finality provider BTC private key used as HMAC key for generating nonces

Low Severity
Informational Impact
Low Likelihood

Description

In GenerateRandomness, nonces are generated as the HMAC-SHA256 of the chainID and the block height that the nonce is for, keyed by the finality provider's private key:

func GenerateRandomness(key []byte, chainID []byte, height uint64) (*eots.PrivateRand, *eots.PublicRand) {
    // calculate the randomn hash of the key concatenated with chainID and height
    digest := hmac.New(sha256.New, key)
    digest.Write(append(sdk.Uint64ToBigEndian(height), chainID...))
    randPre := digest.Sum(nil)

    // ...
}

func (lm *LocalEOTSManager) getRandomnessPair(fpPk []byte, chainID []byte, height uint64, passphrase string) (*eots.PrivateRand, *eots.PublicRand, error) {
    record, err := lm.KeyRecord(fpPk, passphrase)
    if err != nil {
        return nil, nil, err
    }
    privRand, pubRand := randgenerator.GenerateRandomness(record.PrivKey.Serialize(), chainID, height)
    return privRand, pubRand, nil
}

Impact

Since the finality provider's private key is revealed upon slashing, this allows other parties to rederive the nonces for finality-provider votes, allowing them to sign messages with the same nonces that were committed to previously, which is more flexibility than is needed to carry out slashing.

Recommendations

Since currently all the randomness is stored in the finality provider's database, true randomness could be committed to and stored instead. If preserving the ability to regenerate the nonces from a constant amount of space is desired, use a separate uniformly-generated key for the HMAC-SHA256 key.

Remediation

Zellic © 2025Back to top ↑