Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions examples/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
"license": "Apache-2.0",
"scripts": {
"send-lovelace-example": "ts-node src/send-lovelace-example.ts",
"sign-data-example": "ts-node src/sign-data-example.ts",
"bip39-example": "ts-node src/bip39-example.ts",
"donate-to-treasury-example": "ts-node src/donate-to-treasury-example.ts",
"drep-pubkey-example": "ts-node src/drep-pubkey-example.ts",
Expand Down
66 changes: 66 additions & 0 deletions examples/src/sign-data-example.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/**
* Copyright 2025 Biglup Labs.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

/* IMPORTS ********************************************************************/

import * as Cometa from '@biglup/cometa';
import { TerminalProgressMonitor, getBlockfrostProjectIdFromEnv, getPassword, printHeader } from './utils';

/* CONSTANTS ******************************************************************/

const MNEMONICS =
'antenna whale clutch cushion narrow chronic matrix alarm raise much stove beach mimic daughter review build dinner twelve orbit soap decorate bachelor athlete close';

/* DEFINITIONS ****************************************************************/

const monitor = new TerminalProgressMonitor();

/**
* Sign data with CIP-008 using Cometa.
*/
const messageSigningExample = async () => {
await Cometa.ready();

printHeader('Sign data Example', 'This example will sign some data with CIP-008 standard.');

const provider = new Cometa.BlockfrostProvider({
network: Cometa.NetworkMagic.Preprod,
projectId: ''
});

monitor.logInfo('Creating wallet from mnemonics...');
const wallet = await Cometa.SingleAddressWallet.createFromMnemonics({
credentialsConfig: {
account: 0,
paymentIndex: 0,
stakingIndex: 0
},
getPassword: () => Promise.resolve(new Uint8Array([0x00])),
mnemonics: MNEMONICS.split(' '),
provider
});

const address = (await wallet.getRewardAddresses())[0];
monitor.logInfo(`Signing data with ${address.toBech32()}`);
const { key, signature } = await wallet.signData(address.toAddress(), Cometa.utf8ToHex('Hello, Cometa!'));
monitor.logInfo('Data signed successfully!');

monitor.logInfo(`Cose Key: ${key}`);
monitor.logInfo(`Cose Sign1: ${signature}`);
};

messageSigningExample().catch((error) => monitor.logFailure(`Error: ${error.message}`));
2 changes: 1 addition & 1 deletion libcardano-c/cardano_c.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@biglup/cometa",
"version": "1.0.111",
"version": "1.0.112",
"description": "Cometa JS is a lightweight and high performance library designed to streamline transaction building and smart contract interactions on the Cardano blockchain",
"engines": {
"node": ">=16.0.0",
Expand Down
1 change: 1 addition & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,4 @@ export * from './module';
export * from './provider';
export * from './txBuilder';
export * from './wallet';
export * from './messageSigning';
41 changes: 40 additions & 1 deletion src/keyHandlers/SecureKeyHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

/* IMPORTS *******************************************************************/

import { Bip32PublicKey, Ed25519PublicKey } from '../crypto';
import { Bip32PublicKey, Ed25519PrivateKey, Ed25519PublicKey } from '../crypto';
import { VkeyWitnessSet } from '../common';

/* DEFINITIONS ****************************************************************/
Expand Down Expand Up @@ -92,6 +92,27 @@ export interface Bip32SecureKeyHandler {
*/
signTransaction(txCbor: string, derivationPaths: DerivationPath[]): Promise<VkeyWitnessSet>;

/**
* Signs arbitrary data using a BIP32-derived key.
* @param data - The hex-encoded data to be signed.
* @param derivationPath - The derivation path specifying which key to use for signing.
*
* @returns {Promise<{ signature: string; key: string }>} A promise that resolves with an object containing the signature and the public key.
*/
signData(data: string, derivationPath: DerivationPath): Promise<{ signature: string; key: string }>;

/**
* Retrieves the securely stored private key.
*
* @param derivationPath - The derivation path specifying which key to retrieve.
*
* @warning This operation exposes the private key in memory and should be used with extreme caution.
* The caller is responsible for securely handling and wiping the key from memory after use.
*
* @returns {Promise<Ed25519PrivateKey>} A promise that resolves with the private key.
*/
getPrivateKey(derivationPath: DerivationPath): Promise<Ed25519PrivateKey>;

/**
* Derives and returns an extended account public key from the root key.
*
Expand Down Expand Up @@ -126,6 +147,24 @@ export interface Ed25519SecureKeyHandler {
*/
signTransaction(transaction: string): Promise<VkeyWitnessSet>;

/**
* Signs arbitrary data using the securely stored Ed25519 private key.
* @param data - The hex-encoded data to be signed.
*
* @returns {Promise<{ signature: string; key: string }>} A promise that resolves with an object containing the signature and the public key.
*/
signData(data: string): Promise<{ signature: string; key: string }>;

/**
* Retrieves the securely stored private key.
*
* @warning This operation exposes the private key in memory and should be used with extreme caution.
* The caller is responsible for securely handling and wiping the key from memory after use.
*
* @returns {Promise<Ed25519PrivateKey>} A promise that resolves with the private key.
*/
getPrivateKey(): Promise<Ed25519PrivateKey>;

/**
* Retrieves the public key corresponding to the securely stored private key.
*
Expand Down
61 changes: 60 additions & 1 deletion src/keyHandlers/SoftwareBip32SecureKeyHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,10 @@
/* IMPORTS ********************************************************************/

import { AccountDerivationPath, Bip32SecureKeyHandler, DerivationPath } from './SecureKeyHandler';
import { Bip32PrivateKey, Bip32PublicKey, Crc32, Emip003 } from '../crypto';
import { Bip32PrivateKey, Bip32PublicKey, Crc32, Ed25519PrivateKey, Emip003 } from '../crypto';
import { VkeyWitness, VkeyWitnessSet } from '../common';
import { getModule } from '../module';
import { hexToUint8Array } from '../cometa';
import { readBlake2bHashData, readTransactionFromCbor, unrefObject } from '../marshaling';

/* DEFINITIONS ****************************************************************/
Expand Down Expand Up @@ -209,6 +210,64 @@ export class SoftwareBip32SecureKeyHandler implements Bip32SecureKeyHandler {
return witnesses;
}

/**
* Signs arbitrary data using a BIP32-derived key.
* @param data - The hex-encoded data to be signed.
* @param path - The derivation path specifying which key to use for signing.
*
* @returns {Promise<{ signature: string; key: string }>} A promise that resolves with an object containing the signature and the public key.
*/
public async signData(data: string, path: DerivationPath): Promise<{ signature: string; key: string }> {
const entropy = await this.getDecryptedSeed();

try {
const rootKey = Bip32PrivateKey.fromBip39Entropy(new Uint8Array(), entropy);

const pathIndices = [path.purpose, path.coinType, path.account, path.role, path.index];
const signingKey = rootKey.derive(pathIndices);
const publicKey = signingKey.getPublicKey();
const signature = signingKey.toEd25519Key().sign(hexToUint8Array(data));

return {
key: publicKey.toEd25519Key().toHex(),
signature: signature.toHex()
};
} finally {
entropy.fill(0);
}
}

/**
* Retrieves the securely stored private key.
*
* @param derivationPath - The derivation path specifying which key to retrieve.
*
* @warning This operation exposes the private key in memory and should be used with extreme caution.
* The caller is responsible for securely handling and wiping the key from memory after use.
*
* @returns {Promise<Ed25519PrivateKey>} A promise that resolves with the private key.
*/
public async getPrivateKey(derivationPath: DerivationPath): Promise<Ed25519PrivateKey> {
const entropy = await this.getDecryptedSeed();

try {
const rootKey = Bip32PrivateKey.fromBip39Entropy(new Uint8Array(), entropy);

const pathIndices = [
derivationPath.purpose,
derivationPath.coinType,
derivationPath.account,
derivationPath.role,
derivationPath.index
];
const signingKey = rootKey.derive(pathIndices);

return signingKey.toEd25519Key();
} finally {
entropy.fill(0);
}
}

/**
* Derives and returns an extended account public key.
*
Expand Down
41 changes: 41 additions & 0 deletions src/keyHandlers/SoftwareEd25519SecureKeyHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { Crc32, Ed25519PrivateKey, Ed25519PublicKey, Emip003 } from '../crypto';
import { Ed25519SecureKeyHandler } from './SecureKeyHandler';
import { VkeyWitness, VkeyWitnessSet } from '../common';
import { getModule } from '../module';
import { hexToUint8Array } from '../cometa';
import { readBlake2bHashData, readTransactionFromCbor, unrefObject } from '../marshaling';

/* DEFINITIONS ****************************************************************/
Expand Down Expand Up @@ -198,6 +199,46 @@ export class SoftwareEd25519SecureKeyHandler implements Ed25519SecureKeyHandler
}
}

/**
* Signs arbitrary data using the securely stored Ed25519 private key.
* @param data - The hex-encoded data to be signed.
*
* @returns {Promise<{ signature: string; key: string }>} A promise that resolves with an object containing the signature and the public key.
*/
public async signData(data: string): Promise<{ signature: string; key: string }> {
const decryptedKey = await this.getDecryptedKey();

try {
const privateKey = Ed25519PrivateKey.fromExtendedBytes(decryptedKey);
const publicKey = privateKey.getPublicKey();
const signature = privateKey.sign(hexToUint8Array(data));

return {
key: publicKey.toHex(),
signature: signature.toHex()
};
} finally {
decryptedKey.fill(0);
}
}

/**
* Retrieves the securely stored private key.
*
* @warning This operation exposes the private key in memory and should be used with extreme caution.
* The caller is responsible for securely handling and wiping the key from memory after use.
*
* @returns {Promise<Ed25519PrivateKey>} A promise that resolves with the private key.
*/
public async getPrivateKey(): Promise<Ed25519PrivateKey> {
const decryptedKey = await this.getDecryptedKey();

const privateKey = Ed25519PrivateKey.fromExtendedBytes(decryptedKey);
decryptedKey.fill(0);

return privateKey;
}

/**
* Retrieves the public key corresponding to the securely stored private key.
*
Expand Down
Loading