Beispiel #1
0
bool verify_signature(const ec_point& public_key, hash_digest hash,
    const endorsement& signature)
{
    init.init();
    return 1 == secp256k1_ecdsa_verify(hash.data(), hash.size(),
        signature.data(), signature.size(), public_key.data(),
        public_key.size()
    );
}
Beispiel #2
0
bool verify_signature(const ec_point& public_key, hash_digest hash,
    const data_chunk& signature)
{
    std::reverse(hash.begin(), hash.end());
    init.init();
    return 1 == secp256k1_ecdsa_verify(
        hash.data(), hash.size(),
        signature.data(), signature.size(),
        public_key.data(), public_key.size()
    );
}
Beispiel #3
0
compact_signature sign_compact(ec_secret secret, hash_digest hash,
    ec_secret nonce)
{
    init.init();

    compact_signature out;
    if (0 < secp256k1_ecdsa_sign_compact(hash.data(), hash.size(),
        out.signature.data(), secret.data(), nonce.data(), &out.recid))
    {
        return out;
    }

    // Error case:
    return compact_signature{{{0}}, 0};
}
Beispiel #4
0
compact_signature sign_compact(ec_secret secret, hash_digest hash)
{
    init.init();

    compact_signature out;

    ec_secret nonce;
    unsigned index = 0;
    do {
        nonce = create_nonce(secret, hash, index++);
    } while (secp256k1_ecdsa_sign_compact(hash.data(), hash.size(),
        out.signature.data(), secret.data(), nonce.data(), &out.recid) <= 0);

    return out;
}
Beispiel #5
0
endorsement sign(ec_secret secret, hash_digest hash, ec_secret nonce)
{
    init.init();

    int out_size = max_endorsement_size;
    endorsement signature(out_size);
    if (0 < secp256k1_ecdsa_sign(hash.data(), hash.size(), signature.data(),
        &out_size, secret.data(), nonce.data()))
    {
        signature.resize(out_size);
        return signature;
    }

    // Error case:
    return endorsement();
}
Beispiel #6
0
ec_point secret_to_public_key(const ec_secret& secret,
    bool compressed)
{
    init.init();
    size_t size = ec_uncompressed_size;
    if (compressed)
        size = ec_compressed_size;

    ec_point out(size);
    int out_size;
    if (!secp256k1_ecdsa_pubkey_create(out.data(), &out_size, secret.data(),
            compressed))
        return ec_point();
    BITCOIN_ASSERT(size == static_cast<size_t>(out_size));
    return out;
}
Beispiel #7
0
endorsement sign(ec_secret secret, hash_digest hash)
{
    init.init();

    int out_size = max_endorsement_size;
    endorsement signature(out_size);

    ec_secret nonce;
    unsigned index = 0;
    do {
        nonce = create_nonce(secret, hash, index++);
    } while (secp256k1_ecdsa_sign(hash.data(), hash.size(), signature.data(),
        &out_size, secret.data(), nonce.data()) <= 0);

    signature.resize(out_size);
    return signature;
}
Beispiel #8
0
data_chunk sign(ec_secret secret, hash_digest hash, ec_secret nonce)
{
    std::reverse(hash.begin(), hash.end());
    init.init();
    int out_size = 72;
    data_chunk signature(out_size);

    if (!verify_private_key(nonce)) // Needed because of upstream bug
        return data_chunk();
    bool valid = secp256k1_ecdsa_sign(hash.data(), hash.size(),
        signature.data(), &out_size, secret.data(), nonce.data()) == 1;
    if (!valid)
        return data_chunk();

    signature.resize(out_size);
    return signature;
}
Beispiel #9
0
ec_point recover_compact(compact_signature signature,
    hash_digest hash, bool compressed)
{
    init.init();

    size_t public_key_size = ec_uncompressed_size;
    if (compressed)
        public_key_size = ec_compressed_size;

    ec_point out(public_key_size);
    int out_size;
    if (0 < secp256k1_ecdsa_recover_compact(hash.data(), hash.size(),
        signature.signature.data(), out.data(), &out_size, compressed,
        signature.recid))
    {
        BITCOIN_ASSERT(public_key_size == static_cast<size_t>(out_size));
        return out;
    }

    // Error case:
    return ec_point();
}
Beispiel #10
0
ec_secret create_nonce(ec_secret secret, hash_digest hash, unsigned index)
{
    init.init();

    hash_digest K
    {{
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
    }};
    hash_digest V
    {{
        0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
        0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
        0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
        0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01
    }};

    K = hmac_sha256_hash(build_data({V, to_byte(0x00), secret, hash}), K);
    V = hmac_sha256_hash(V, K);
    K = hmac_sha256_hash(build_data({V, to_byte(0x01), secret, hash}), K);
    V = hmac_sha256_hash(V, K);

    while (true)
    {
        V = hmac_sha256_hash(V, K);

        if (0 == index)
            return V;
        --index;

        K = hmac_sha256_hash(build_data({V, to_byte(0x00)}), K);
        V = hmac_sha256_hash(V, K);
    }
}
Beispiel #11
0
BC_API ec_secret create_nonce(ec_secret secret, hash_digest hash)
{
    std::reverse(hash.begin(), hash.end());
    init.init();

    hash_digest K
    {{
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
    }};
    hash_digest V
    {{
        0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
        0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
        0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
        0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01
    }};

    K = hmac_sha256_hash(V + byte_array<1>{{0x00}} + secret + hash, K);
    V = hmac_sha256_hash(V, K);
    K = hmac_sha256_hash(V + byte_array<1>{{0x01}} + secret + hash, K);
    V = hmac_sha256_hash(V, K);

    while (true)
    {
        V = hmac_sha256_hash(V, K);

        if (verify_private_key(V))
            return V;

        K = hmac_sha256_hash(V + byte_array<1>{{0x00}}, K);
        V = hmac_sha256_hash(V, K);
    }
}
Beispiel #12
0
bool ec_multiply(ec_point& a, const ec_secret& b)
{
    init.init();
    return secp256k1_ec_pubkey_tweak_mul(a.data(), a.size(), b.data()) == 1;
}
Beispiel #13
0
namespace libbitcoin {

/**
 * Internal class to start and stop the secp256k1 library.
 */
class init_singleton
{
public:
    init_singleton()
      : init_done_(false)
    {}
    ~init_singleton()
    {
        if (init_done_)
            secp256k1_stop();
    }
    void init()
    {
        if (init_done_)
            return;
        secp256k1_start();
        init_done_ = true;
    }

private:
    bool init_done_;
};

static init_singleton init;

ec_point secret_to_public_key(const ec_secret& secret,
    bool compressed)
{
    init.init();
    size_t size = ec_uncompressed_size;
    if (compressed)
        size = ec_compressed_size;

    ec_point out(size);
    int out_size;
    if (!secp256k1_ecdsa_pubkey_create(out.data(), &out_size, secret.data(),
            compressed))
        return ec_point();
    BITCOIN_ASSERT(size == static_cast<size_t>(out_size));
    return out;
}

bool verify_public_key(const ec_point& public_key)
{
    init.init();
    return secp256k1_ecdsa_pubkey_verify(public_key.data(), public_key.size())
        == 1;
}

bool verify_public_key_fast(const ec_point& public_key)
{
    if (public_key.size() == ec_compressed_size)
        return public_key[0] == 0x02 || public_key[0] == 0x03;
    if (public_key.size() == ec_uncompressed_size)
        return public_key[0] == 0x04;
    return false;
}

bool verify_private_key(const ec_secret& private_key)
{
    init.init();
    return secp256k1_ecdsa_seckey_verify(private_key.data()) == 1;
}

inline data_chunk operator +(data_slice a, data_slice b)
{
    data_chunk out;
    out.reserve(a.size() + b.size());
    out.insert(out.end(), a.begin(), a.end());
    out.insert(out.end(), b.begin(), b.end());
    return out;
}

BC_API ec_secret create_nonce(ec_secret secret, hash_digest hash)
{
    std::reverse(hash.begin(), hash.end());
    init.init();

    hash_digest K
    {{
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
    }};
    hash_digest V
    {{
        0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
        0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
        0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
        0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01
    }};

    K = hmac_sha256_hash(V + byte_array<1>{{0x00}} + secret + hash, K);
    V = hmac_sha256_hash(V, K);
    K = hmac_sha256_hash(V + byte_array<1>{{0x01}} + secret + hash, K);
    V = hmac_sha256_hash(V, K);

    while (true)
    {
        V = hmac_sha256_hash(V, K);

        if (verify_private_key(V))
            return V;

        K = hmac_sha256_hash(V + byte_array<1>{{0x00}}, K);
        V = hmac_sha256_hash(V, K);
    }
}

data_chunk sign(ec_secret secret, hash_digest hash, ec_secret nonce)
{
    std::reverse(hash.begin(), hash.end());
    init.init();
    int out_size = 72;
    data_chunk signature(out_size);

    if (!verify_private_key(nonce)) // Needed because of upstream bug
        return data_chunk();
    bool valid = secp256k1_ecdsa_sign(hash.data(), hash.size(),
        signature.data(), &out_size, secret.data(), nonce.data()) == 1;
    if (!valid)
        return data_chunk();

    signature.resize(out_size);
    return signature;
}

bool verify_signature(const ec_point& public_key, hash_digest hash,
    const data_chunk& signature)
{
    std::reverse(hash.begin(), hash.end());
    init.init();
    return 1 == secp256k1_ecdsa_verify(
        hash.data(), hash.size(),
        signature.data(), signature.size(),
        public_key.data(), public_key.size()
    );
}

bool ec_tweak_add(ec_point& a, const ec_secret& b)
{
    init.init();
    return secp256k1_ecdsa_pubkey_tweak_add(a.data(), a.size(), b.data()) == 1;
}

bool ec_multiply(ec_point& a, const ec_secret& b)
{
    init.init();
    return secp256k1_ecdsa_pubkey_tweak_mul(a.data(), a.size(), b.data()) == 1;
}

bool ec_add(ec_secret& a, const ec_secret& b)
{
    init.init();
    return secp256k1_ecdsa_privkey_tweak_add(a.data(), b.data()) == 1;
}

bool ec_multiply(ec_secret& a, const ec_secret& b)
{
    init.init();
    return secp256k1_ecdsa_privkey_tweak_mul(a.data(), b.data()) == 1;
}

} // namespace libbitcoin
Beispiel #14
0
bool ec_multiply(ec_secret& a, const ec_secret& b)
{
    init.init();
    return secp256k1_ecdsa_privkey_tweak_mul(a.data(), b.data()) == 1;
}
Beispiel #15
0
bool ec_tweak_add(ec_point& a, const ec_secret& b)
{
    init.init();
    return secp256k1_ecdsa_pubkey_tweak_add(a.data(), a.size(), b.data()) == 1;
}
Beispiel #16
0
bool verify_public_key(const ec_point& public_key)
{
    init.init();
    return secp256k1_ecdsa_pubkey_verify(public_key.data(), public_key.size())
        == 1;
}
Beispiel #17
0
bool ec_add(ec_secret& a, const ec_secret& b)
{
    init.init();
    return secp256k1_ec_privkey_tweak_add(a.data(), b.data()) == 1;
}
Beispiel #18
0
bool verify_private_key(const ec_secret& private_key)
{
    init.init();
    return secp256k1_ecdsa_seckey_verify(private_key.data()) == 1;
}
Beispiel #19
0
namespace libbitcoin {

/**
 * Internal class to start and stop the secp256k1 library.
 */
class init_singleton
{
public:
    init_singleton()
      : init_done_(false)
    {
    }
    ~init_singleton()
    {
        if (init_done_)
            secp256k1_stop();
    }
    void init()
    {
        if (init_done_)
            return;

        // It may be more efficient on a per-call basis to pass these
        // individually via init(), however since we are caching the init
        // we must set both flags here.
        secp256k1_start(SECP256K1_START_VERIFY | SECP256K1_START_SIGN);

        init_done_ = true;
    }

private:
    bool init_done_;
};

static init_singleton init;

ec_point secret_to_public_key(const ec_secret& secret,
    bool compressed)
{
    init.init();
    size_t public_key_size = ec_uncompressed_size;
    if (compressed)
        public_key_size = ec_compressed_size;

    ec_point out(public_key_size);
    int out_size;
    if (!secp256k1_ec_pubkey_create(out.data(), &out_size, secret.data(),
            compressed))
        return ec_point();
    BITCOIN_ASSERT(public_key_size == static_cast<size_t>(out_size));
    return out;
}

bool verify_public_key(const ec_point& public_key)
{
    init.init();
    return secp256k1_ec_pubkey_verify(public_key.data(), public_key.size())
        == 1;
}

bool verify_public_key_fast(const ec_point& public_key)
{
    if (public_key.size() == ec_compressed_size)
        return public_key[0] == 0x02 || public_key[0] == 0x03;
    if (public_key.size() == ec_uncompressed_size)
        return public_key[0] == 0x04;
    return false;
}

bool verify_private_key(const ec_secret& private_key)
{
    init.init();
    return secp256k1_ec_seckey_verify(private_key.data()) == 1;
}

endorsement sign(ec_secret secret, hash_digest hash)
{
    init.init();

    int out_size = max_endorsement_size;
    endorsement signature(out_size);

    ec_secret nonce;
    unsigned index = 0;
    do {
        nonce = create_nonce(secret, hash, index++);
    } while (secp256k1_ecdsa_sign(hash.data(), hash.size(), signature.data(),
        &out_size, secret.data(), nonce.data()) <= 0);

    signature.resize(out_size);
    return signature;
}

compact_signature sign_compact(ec_secret secret, hash_digest hash)
{
    init.init();

    compact_signature out;

    ec_secret nonce;
    unsigned index = 0;
    do {
        nonce = create_nonce(secret, hash, index++);
    } while (secp256k1_ecdsa_sign_compact(hash.data(), hash.size(),
        out.signature.data(), secret.data(), nonce.data(), &out.recid) <= 0);

    return out;
}

ec_secret create_nonce(ec_secret secret, hash_digest hash, unsigned index)
{
    init.init();

    hash_digest K
    {{
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
    }};
    hash_digest V
    {{
        0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
        0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
        0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
        0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01
    }};

    K = hmac_sha256_hash(build_data({V, to_byte(0x00), secret, hash}), K);
    V = hmac_sha256_hash(V, K);
    K = hmac_sha256_hash(build_data({V, to_byte(0x01), secret, hash}), K);
    V = hmac_sha256_hash(V, K);

    while (true)
    {
        V = hmac_sha256_hash(V, K);

        if (0 == index)
            return V;
        --index;

        K = hmac_sha256_hash(build_data({V, to_byte(0x00)}), K);
        V = hmac_sha256_hash(V, K);
    }
}

endorsement sign(ec_secret secret, hash_digest hash, ec_secret nonce)
{
    init.init();

    int out_size = max_endorsement_size;
    endorsement signature(out_size);
    if (0 < secp256k1_ecdsa_sign(hash.data(), hash.size(), signature.data(),
        &out_size, secret.data(), nonce.data()))
    {
        signature.resize(out_size);
        return signature;
    }

    // Error case:
    return endorsement();
}

compact_signature sign_compact(ec_secret secret, hash_digest hash,
    ec_secret nonce)
{
    init.init();

    compact_signature out;
    if (0 < secp256k1_ecdsa_sign_compact(hash.data(), hash.size(),
        out.signature.data(), secret.data(), nonce.data(), &out.recid))
    {
        return out;
    }

    // Error case:
    return compact_signature{{{0}}, 0};
}

bool verify_signature(const ec_point& public_key, hash_digest hash,
    const endorsement& signature)
{
    init.init();
    return 1 == secp256k1_ecdsa_verify(hash.data(), hash.size(),
        signature.data(), signature.size(), public_key.data(),
        public_key.size()
    );
}

ec_point recover_compact(compact_signature signature,
    hash_digest hash, bool compressed)
{
    init.init();

    size_t public_key_size = ec_uncompressed_size;
    if (compressed)
        public_key_size = ec_compressed_size;

    ec_point out(public_key_size);
    int out_size;
    if (0 < secp256k1_ecdsa_recover_compact(hash.data(), hash.size(),
        signature.signature.data(), out.data(), &out_size, compressed,
        signature.recid))
    {
        BITCOIN_ASSERT(public_key_size == static_cast<size_t>(out_size));
        return out;
    }

    // Error case:
    return ec_point();
}

bool ec_add(ec_point& a, const ec_secret& b)
{
    init.init();
    return secp256k1_ec_pubkey_tweak_add(a.data(), a.size(), b.data()) == 1;
}

bool ec_add(ec_secret& a, const ec_secret& b)
{
    init.init();
    return secp256k1_ec_privkey_tweak_add(a.data(), b.data()) == 1;
}

bool ec_multiply(ec_point& a, const ec_secret& b)
{
    init.init();
    return secp256k1_ec_pubkey_tweak_mul(a.data(), a.size(), b.data()) == 1;
}

bool ec_multiply(ec_secret& a, const ec_secret& b)
{
    init.init();
    return secp256k1_ec_privkey_tweak_mul(a.data(), b.data()) == 1;
}

} // namespace libbitcoin