Problem Statement
You are tasked with developing a simple blockchain wallet application that can generate a new wallet (a pair of public and private keys), sign transactions, and display the address associated with the public key. Your wallet should be able to handle basic cryptocurrency transactions in a simulated environment. The focus is on understanding how wallets securely manage keys and sign transactions using asymmetric cryptography.
Your application should include the following functionalities:
- Generate a new wallet by creating a pair of public and private keys.
- Display the address derived from the public key.
- Sign a transaction with the private key to authorize it.
- Verify that a given signature corresponds to a specific message and public key.
Concepts
- public key cryptography
- private key management
- transaction signing
Constraints
- Use elliptic curve cryptography for key generation and signing
- Implement secure storage of private keys in memory (no hardcoding)
- Ensure all cryptographic operations are performed securely
Security Notes
- Never expose private keys
- Always verify signatures before accepting transactions
- Be cautious with storing sensitive data in memory
Solutions
Javascript Solution
const EC = require('elliptic').ec;
const ec = new EC('secp256k1');
// Wallet class to manage key pairs, signing transactions, and verifying signatures.
class Wallet {
constructor() {
// Generate a new key pair and store them securely in memory.
this.keyPair = ec.genKeyPair();
this.publicKey = this.keyPair.getPublic('hex'); // Public key in hexadecimal format
}
// Method to generate the wallet address from the public key.
getAddress() {
return this.publicKey;
}
// Method to sign a transaction with the private key.
signTransaction(transaction) {
const hashTx = ec.keyFromPrivate(this.keyPair.getPrivate('hex')).sign(transaction);
return hashTx.toDER('hex'); // Return signature in DER format as hexadecimal string
}
// Static method to verify a given signature corresponds to a specific message and public key.
static verifySignature(publicKey, transaction, signature) {
const key = ec.keyFromPublic(publicKey, 'hex');
return key.verify(transaction, signature);
}
}
// Example usage:
const myWallet = new Wallet(); // Create a new wallet instance
console.log('Address:', myWallet.getAddress()); // Display the address
const transaction = 'Transfer 10 coins'; // Example transaction
const signature = myWallet.signTransaction(transaction); // Sign the transaction with private key
console.log('Signature:', signature);
// Verify the signature using public key and original message
const isVerified = Wallet.verifySignature(myWallet.publicKey, transaction, signature);
console.log('Is Signature Verified?', isVerified); This solution implements a simple blockchain wallet application with the required functionalities. The Wallet class uses elliptic curve cryptography (secp256k1) to generate and manage key pairs securely in memory without hardcoding them. It provides methods to get the address derived from the public key, sign transactions using the private key, and verify signatures for given messages and public keys.
The constructor of the Wallet class generates a new key pair when an instance is created, storing both the public and private keys. The getAddress method returns the public key in hexadecimal format as the wallet's address. The signTransaction method signs a provided transaction using the private key associated with the wallet, returning the signature in DER format.
The static verifySignature method allows for verifying whether a given signature corresponds to a specific message and public key by reconstructing the key from its hexadecimal representation and checking the validity of the signature against the transaction data. This ensures secure transactions can only be accepted if properly signed.
This implementation adheres to best practices by never exposing private keys, verifying signatures before accepting transactions, and being cautious with sensitive data stored in memory.