In creating a scriptSig, how do I sign the hash of a raw transaction?

1

I have created a raw transaction, added the hash code, and Double-sha256 this result. Now I should sign this hash with the private key, which would give me the DER encoded signature, but I'm not clear on what exactly I should be doing. How do I SIGN this hash with the private key? What exactly would I be doing? I am not using any crypto library, except for SHA256, and I have implemented secp256k1 my self, so I guess in relation to that, what should I be doing with the private key and the hash? I am specifically aimed at step 15. If I were to guess, this and this are essentially my answer, unless I am mistaken, and if I am, I would like to know why. Otherwise, the caveat with those answers is the introduction of a random nonce. Why could I not just have the private key = "k" (since you shouldn't reuse addresses anyway, right?), calculate "s", and concatenate "r" and "s"? Or is this how it IS done?

doffing81

Posted 2017-01-11T17:16:05.710

Reputation: 474

This seems relatively close to what I am looking for, however, in this example, wouldn't "k" simply be the private key, and "p1" simply be the public key generated from this private key (code I already have), leaving "s" as the only added calculation I would need to implement in order to sign the hash?doffing81 2017-01-11T18:54:14.093

use k=priv would comprimize your private key if you try to use it more than onceamaclin 2017-01-11T19:23:27.667

Indeed, that is why I assume address reuse is not recommended in Bitcoin. Still, k=priv is essentially what is done, no?doffing81 2017-01-11T19:25:13.933

I mean, what good is the private key if you introduce a random nonce? I believe the answer is related to my first comment here. If all I have to do is calculate "s", and concatenate it with a public key derived from the private key (without a random nonce)... game on. If this is not the case, I would like to know how, or why?doffing81 2017-01-11T21:26:10.103

you must keep the 'k' value secret.amaclin 2017-01-11T22:06:14.780

My question would be how the private key is not secret, but I'm assuming you'll go down the path of address reuse, which is fine. I guess I have to assume that a random nonce is necessary, even though I question it when you don't reuse an address. Looks like I'll have to read up on this

doffing81 2017-01-11T23:19:08.517

Do not use k=privkey. Doing so will instantly reveal the private key to everyone. The standard algorithm for choosing k is RFC6979.Pieter Wuille 2017-01-12T22:07:52.183

Thank you Mr. Sir Pieter Wuille :). I haven't actually worked past this point yet in the transaction signing process, which is where my ignorance comes into play, but have indeed discovered that RFC6979 is the standard, as per the link in my answer, and am currently looking into that standard.doffing81 2017-01-12T22:14:31.583

Answers

1

This would be the answer I am looking for, with a helper link for the first function (signature generation algorithm), and a helper link for the second function (rfc6979 standard for generating "k"):

def ecdsa_sign(val, secret_exponent):
    """Return a signature for the provided hash, using the provided
    random nonce. It is absolutely vital that random_k be an unpredictable
    number in the range [1, self.public_key.point.order()-1].  If
    an attacker can guess random_k, he can compute our private key from a
    single signature. Also, if an attacker knows a few high-order
    bits (or a few low-order bits) of random_k, he can compute our private
    key from many signatures. The generation of nonces with adequate
    cryptographic strength is very difficult and far beyond the scope
    of this comment.

    May raise RuntimeError, in which case retrying with a new
    random value k is in order.
    """
    G = ecdsa.SECP256k1
    n = G.order()
    k = deterministic_generate_k(n, secret_exponent, val)
    p1 = k * G
    r = p1.x()
    if r == 0: raise RuntimeError("amazingly unlucky random number r")
    s = ( ecdsa.numbertheory.inverse_mod( k, n ) * ( val + ( secret_exponent * r ) % n ) ) % n
    if s == 0: raise RuntimeError("amazingly unlucky random number s")

    return signature_to_der(r, s)

def deterministic_generate_k(generator_order, secret_exponent, val, hash_f=hashlib.sha256):
    """
    Generate K value according to https://tools.ietf.org/html/rfc6979
    """
    n = generator_order
    order_size = (bit_length(n) + 7) // 8
    hash_size = hash_f().digest_size
    v = b'\x01' * hash_size
    k = b'\x00' * hash_size
    priv = intbytes.to_bytes(secret_exponent, length=order_size)
    shift = 8 * hash_size - bit_length(n)
    if shift > 0:
        val >>= shift
    if val > n:
        val -= n
    h1 = intbytes.to_bytes(val, length=order_size)
    k = hmac.new(k, v + b'\x00' + priv + h1, hash_f).digest()
    v = hmac.new(k, v, hash_f).digest()
    k = hmac.new(k, v + b'\x01' + priv + h1, hash_f).digest()
    v = hmac.new(k, v, hash_f).digest()

    while 1:
        t = bytearray()

        while len(t) < order_size:
             v = hmac.new(k, v, hash_f).digest()
             t.extend(v)

        k1 = intbytes.from_bytes(bytes(t))

        k1 >>= (len(t)*8 - bit_length(n))
        if k1 >= 1 and k1 < n:
            return k1

        k = hmac.new(k, v + b'\x00', hash_f).digest()
        v = hmac.new(k, v, hash_f).digest()

doffing81

Posted 2017-01-11T17:16:05.710

Reputation: 474

1

It is not the sha256(sha256(tx_bytes)) that needs to be signed. You need to follow the specific algorithm defined inside of Bitcoin core to produce a proper digital signature. Here is where the signature encoding algorithm is defined. Notice, that this algorithm changes slightly based on the hash type you provide. This allows us functionality to include (or prevent inclusion) of extra inputs/outputs on a transaction.

Chris Stewart

Posted 2017-01-11T17:16:05.710

Reputation: 865

A little hard for me to read, but I'll see what I can make of it. Interesting you say that it is not the doublesha256 that needs to be signed. I was simply following this, step 15

doffing81 2017-01-11T19:45:39.057

It is using sha256(sha256()) what it isn't is the transaction's bytes. The signature serialization modifies your transaction by replacing some data in it, and then signs it.Chris Stewart 2017-01-11T20:50:09.703

I think I get what you're saying here, in regard to the entire algorithm, but I am specifically aimed at a certain point, and you seem to suggest signing takes place at a different point from what I understand. Perhaps my naive terminology throws one off, or perhaps I'm not understanding you entirely. Step 15 is my specific problem; signing the hash of the initial raw transaction.

doffing81 2017-01-11T21:20:05.053

0

what should I be doing with the private key and the hash?

sign :)

there is such method in any crypto-lib

for more information refer to Redeeming a raw transaction step by step example required step #15

amaclin

Posted 2017-01-11T17:16:05.710

Reputation: 5 763

Indeed, I have seen this post, but as I have said in my post, I am not using any crypto library, so in relation to ECDSA, or secp256k1, what should I be doing with the private key and hash?doffing81 2017-01-11T19:24:04.237

the math operations in EC are complicated. how did you get the public key from your private key without crypto-library?amaclin 2017-01-11T19:26:26.083

like I said, I have implemented the math operations myself, and they seem to be working just fine.doffing81 2017-01-11T19:27:28.573

Nice link. It may help clarify the code I linked todoffing81 2017-01-11T19:40:14.190