My knowledge of cryptography is beyond shallow, and I have a problem I cannot solve.
Trezor wallets have two message signing formats: "Trezor" and "Electrum".
I have a method in my code, that is retrieving the public key from messages signed using BTC wallets (i am using bitcoinj
library):
public VerificationStatus verifyMessage(String walletAddress, String phrase, String signature) {
Address signingAddress = null;
Address addressFromKey = null;
try {
signingAddress = Address.fromString(null, walletAddress);
ECKey ecKey = ECKey.signedMessageToKey(phrase, signature);
addressFromKey = Address.fromKey(signingAddress.getParameters(), ecKey, signingAddress.getOutputScriptType());
} catch (SignatureException exception) {
LOGGER.error(exception.getMessage());
}
return determineVerificationStatus(signingAddress, addressFromKey);
}
When I sign a message using either Electrum wallet or Trezor with the option "Electrum" format selected, everything works fine.
Example data for Electrum signed message:
address: bc1qpluptcvxpvyzsmqzy8jrmdt3m985t6z95s24nu
message: MESSAGE
signature: H41bIfNhn1vT5yzgFUA3rZE7FNCM8epMrINVbzOefOImYs42hEIUHuoY/UkMd9ljjYkaci7fVJgCTUE6hPJN3Cg=
But when I try to use the "Trezor" format, for which the signature looks different:
address: bc1qpluptcvxpvyzsmqzy8jrmdt3m985t6z95s24nu
message: MESSAGE
signature: J41bIfNhn1vT5yzgFUA3rZE7FNCM8epMrINVbzOefOImYs42hEIUHuoY/UkMd9ljjYkaci7fVJgCTUE6hPJN3Cg=
I get an SignatureException
thrown by ECKey.signedMessageToKey(phrase, signature);
, with an exception message:
Header byte out of range: 40
As I mentioned at the beginning of this question: my knowledge about cryptography is almost non-existent, but from what I suspect - Trezor is signing the message using something else, another algorithm, and this causes the ECKey.signedMessageToKey()
method throw an exception telling that header byte is out of range
My question is - how is Trezor creating the signature using the so called "Trezor format", and how could I solve this problem programatically?