Raw Message Signing
Prerequisites
Overview
Raw Signing is a powerful feature within Fireblocks. As the Web3 world continues to rapidly evolve, Fireblocks provides the option to support additional chains and actions by signing an arbitrary message using the Fireblocks infrastructure.
Warning: Not enabled by default
Please note that raw message signing is not enabled by default in all workspaces and requires contacting the Fireblocks support team to activate.
Raw message example
The example below illustrates the use of the Raw Signing API for Bitcoin proof of address ownership.
Instead of passing a simple plaintext message for signature:
- Add
extraParameters
. - Within this object, add
rawMessageData
. - Within that object, add a
messages
array.
About messages
Each
message
should contain somecontent
.This is the content you would like to sign. It could be a serialized transaction that you have already constructed, for example, but the structure stays the same.
This creates a hexed SHA256 hash for a wrapped message.
import { createHash } from "crypto";
import { FireblocksSDK, PeerType, TransactionOperation, TransactionStatus } from "fireblocks-sdk";
async function signArbitraryMessage(fireblocks: FireblocksSDK, vaultAccountId, message, bip44addressIndex = 0) {
const wrappedMessage = "\x18Bitcoin Signed Message:\n" + String.fromCharCode(message.length) + message;
const hash = createHash('sha256').update(wrappedMessage, 'utf8').digest();
const content = createHash('sha256').update(hash).digest("hex");
const { status, id } = await fireblocks.createTransaction({
operation: TransactionOperation.RAW,
assetId: "BTC",
source: {
type: PeerType.VAULT_ACCOUNT,
id: vaultAccountId
},
note: `BTC Message: ${message}`,
extraParameters: {
rawMessageData: {
messages: [{
content,
bip44addressIndex
}]
}
}
});
let txInfo;
while(currentStatus != TransactionStatus.COMPLETED && currentStatus != TransactionStatus.FAILED) {
try {
console.log("keep polling for tx " + id + "; status: " + currentStatus);
txInfo = await apiClient.getTransactionById(id);
currentStatus = txInfo.status;
} catch (err) {
console.log("err", err);
}
await new Promise(r => setTimeout(r, 1000));
};
const signature = txInfo.signedMessages[0].signature;
console.log(JSON.stringify(signature));
const encodedSig = Buffer.from([Number.parseInt(signature.v,16) + 31]).toString("hex") + signature.fullSig;
console.log("Encoded Signature:", Buffer.from(encodedSig,"hex").toString("base64"));
}
signArbitraryMessage(fireblocks, "0", "INSERT TEXT HERE").then(console.log).catch(console.log);ireiir
def sign_arbitrary_message(fireblocks: FireblocksSDK, vault_id: str, message: str, bip44_address_index: int = 0):
wrapped_message = "\x18Bitcoin Signed Message:\n" + str(len(message)) + message
content = sha256(sha256(wrapped_message.encode('utf-8')).hexdigest()).hexdigest()
status, id = fireblocks.create_transaction(
tx_type=RAW,
asset_id="BTC",
source=TransferPeerPath(VAULT_ACCOUNT, vault_id),
note=f"BTC Message: {message}",
extra_parameters={
"rawMessageData":
RawMessage([UnsignedMessage(
content=content,
bip44addressIndex=bip44_address_index
)])
}
).values()
while status != TRANSACTION_STATUS_COMPLETED and status != TRANSACTION_STATUS_FAILED:
tx_info = fireblocks.get_transaction_by_id(id)
status = tx_info["status"]
signature = tx_info["signature"][0]
encoded_signature = bytes(int(signature["v", 16]) + 31).hex() + signature["fullSig"]
print(b64encode(bytes.fromhex(encoded_signature).decode()))
sign_arbitrary_message(fireblocks, "0", "INSERT TEXT HERE")
- Start by creating a transaction of type RAW, shown under
tx_type
(PY) oroperation
(JS). - Now, specify the source who is signing the message, which is the default vault (
Id 0
) in our case.
After sending the transaction for signing, wait for its completion so you can retrieve the signature.
The loop in the example above waits for the status of the transaction to be COMPLETED
, or until an issue arises.
Once the transaction is complete, we print the full signature by accessing the transaction object signedMessages
, then signature
, and finally - the fullSig
.
Updated 3 months ago