Can I use a BLS12-381 private key to sign Ethereum transactions

cryptographyprivate-keysecp256k1signaturetransactions

I'm new to cryptography and I've recently been studying BLS signatures. Please forgive me if I make any mistakes while writing.

I've tried generating a BLS key pair and using the private key to derive an Ethereum account and sign on-chain transactions. I used the 'mattrglobal' library to generate the BLS keys, and then passed the private key to the 'ethereumjs-wallet' library to derive an account.

const {
  generateBls12381G2KeyPair,
} = require("@mattrglobal/node-bbs-signatures");

const {
  default: { fromPrivateKey },
} = require("ethereumjs-wallet");

const keyPairTest = (async function () {

  const keyPair = await generateBls12381G2KeyPair();

  const wallet = fromPrivateKey(Buffer.from(keyPair.secretKey));

  console.log(`secretKey: ${Buffer.from(keyPair.secretKey).toString("hex")}`);
  console.log(`ethereum address: ${wallet.getAddressString()}`);

})();

Even though I was able to derive an Ethereum public key, I didn't expect to be able to sign valid Ethereum transactions, because I thought that the different curve parameters would prevent me from generating valid signatures for the transactions.

However, by directly using the private key on MetaMask (on the Sepolia testnet), I was able to perform a simple fund transfer transaction and deploy a smart contract.

How is this possible? Am I overlooking something?

It seems to me that it is generally not recommended to use the same key for two different types of signatures, is that correct?

Best Answer

Can I use a BLS12-381 private key to sign Ethereum transactions

Short answer: yes.

Why is this possible? Because the space in which the private keys live for BLS signatures on BLS12-381 is smaller than that in which keys for ECDSA over secp256k1 live.

Breaking it down

If we follow the code from generateBls12381G2KeyPair function we see that it uses gen_sk to generate the private key, which creates a random element of the field GF(r) where r is the prime order of the groups in the pairing construction for BLS12-381 (the private key is essentially a random number in the range [0,r-1]).

On the other hand, if we follow the code from fromPrivateKey we see that the private key for Ethereum must be in the range [0,n] where n is the order of the elliptic curve group for secp256k1.

Comparing the 2 numbers we see that clearly n>r so the validation checks in fromPrivateKey will pass.

r = 52435875175126190479447740508185965837690552500527637822603658699938581184513
n = 115792089237316195423570985008687907852837564279074904382605163141518161494337

It seems to me that it is generally not recommended to use the same key for two different types of signatures, is that correct?

I wouldn't recommend it because (AFAIK) there is no explicit security proof showing that one cannot use BLS & ECDSA signatures generated using the same private key to do things like forge new signatures or learn information about the private key. Having said that however, there is also no known way to do such attacks (again, AFAIK) so it's not publicly broken.

Related Topic