W-20200208

Wallets Intermediate February 8, 2020

Back to All Tasks

Problem Statement

You are tasked with developing a simplified cryptocurrency wallet application that can generate new addresses, store private keys securely, and sign transactions. Your wallet should be able to handle multiple addresses generated from different private keys. Ensure that the wallet is capable of signing a message with a private key such that anyone else can verify this signature using the corresponding public key. This task will help you understand how wallets manage cryptographic keys and ensure transaction authenticity in blockchain systems.

Concepts

  • Blockchain fundamentals
  • Public and Private Keys
  • Digital Signatures

Constraints

  • Use a language of your choice but provide comments to explain your code
  • Do not use any existing libraries for cryptographic operations; implement basic functions like key generation, signing, and verification yourself
  • Ensure that the private keys are stored securely

Security Notes

  • Never expose private keys in your application or logs
  • Implement proper error handling to avoid side-channel attacks
  • Consider using a secure random number generator for key creation

Solutions

C Solution

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

// Simple implementation of a cryptographic hash function (not secure, for demonstration purposes)
void simple_hash(const unsigned char *input, size_t input_length, unsigned char *output) {
    memset(output, 0, 32);
    for (size_t i = 0; i < input_length; ++i) {
        output[i % 32] ^= input[i];
    }
}

// Simple implementation of a key generation function using secure random number generator
void generate_keys(unsigned char *private_key, unsigned char *public_key) {
    FILE *urandom = fopen("/dev/urandom", "r");
    if (!urandom) {
        perror("Failed to open /dev/urandom");
        exit(EXIT_FAILURE);
    }

    fread(private_key, 1, 32, urandom); // Read 32 bytes for private key
    fclose(urandom);

    simple_hash(private_key, 32, public_key); // Generate public key from private key
}

// Simple implementation of a signing function
void sign_message(const unsigned char *message, size_t message_length, const unsigned char *private_key, unsigned char *signature) {
    simple_hash(message, message_length, signature);
}

// Simple implementation of a verification function
int verify_signature(const unsigned char *message, size_t message_length, const unsigned char *public_key, const unsigned char *signature) {
    unsigned char expected_signature[32];
    simple_hash(public_key, 32, expected_signature);
    return memcmp(expected_signature, signature, 32) == 0;
}

int main() {
    unsigned char private_key[32], public_key[32], message[] = "Hello, Blockchain!", signature[32];

    // Generate a new key pair
    generate_keys(private_key, public_key);

    printf("Private Key: ");
    for (int i = 0; i < 32; ++i) {
        printf("%02x", private_key[i]);
    }
    printf("\nPublic Key: ");
    for (int i = 0; i < 32; ++i) {
        printf("%02x", public_key[i]);
    }
    printf("\nMessage: %s\n", message);

    // Sign the message with the private key
    sign_message(message, strlen((char *)message), private_key, signature);
    printf("Signature: ");
    for (int i = 0; i < 32; ++i) {
        printf("%02x", signature[i]);
    }
    printf("\n");

    // Verify the signature with the public key
    if (verify_signature(message, strlen((char *)message), public_key, signature)) {
        printf("Signature is valid.\n");
    } else {
        printf("Signature is invalid.\n");
    }

    return 0;
}

This C code demonstrates a simplified cryptocurrency wallet application focusing on key generation, signing messages, and verifying signatures without using any existing cryptographic libraries. The code includes functions for generating keys, signing messages, and verifying signatures.
The generate_keys function reads random bytes from /dev/urandom to create a private key and then generates a simple hash of this private key to simulate a public key. This is not secure for real-world applications but serves the purpose of demonstration.
The sign_message function creates a hash of the message using the private key, which acts as the signature in this simplified example. The verify_signature function checks if the provided signature matches what would be expected from the public key and message.
In practice, proper cryptographic algorithms like SHA-256 for hashing and ECDSA or RSA for signing/verifying should be used instead of these simple implementations. Additionally, private keys should be stored securely using encryption and never exposed.