Questions about Duplicate R and S

13 replies 264 views
Posts: 23 · Reputation: 192
#1Jul 23, 2021, 03:08 PM
Hey everyone. I’m having trouble verifying the signature in this process. When I calculate the Z value, it seems like the Kx value of point K (which is R) doesn’t check out. Am I messing up the message calculation or something? Also, the verification process seems pretty tricky. You might notice that there are repeated S and R values in the signatures. Check out this transaction: https://www.blockchain.com/explorer/transactions/btc/bd17bfb7051bef5ca916931f06493a0af0db080b4df21ee9768fa0f3d775070a Does anyone have a clue about how to do the signature verification mathematically for this transaction? Thanks!
6 Reply Quote Share
RogueMoonFull Member
Posts: 110 · Reputation: 789
#2Jul 24, 2021, 07:51 PM
The signature verification process is the same for all transactions (TX). If you want a comprehensive explanation, I recommend checking out this detailed resource: https://cryptobook.nakov.com/digital-signatures/ecdsa-sign-verify-messages But in short you need to calculate the Proof of signature s In short, the proof of signature involves verifying the mathematical relationship between the transaction message, the public key, and the provided signature. Here's a simplified breakdown of the process: Calculate z is the double SHA-256 hash of the transaction message. Use the nonce k is a randomly generated ephemeral private key that ensures uniqueness for each signature. There is a z = double sha256 of the message There is a Nonce K (like another ephemeral private key) Compute R and extract r: R = k * G (where G is the curve's generator point). Take the x-coordinate of R to get r. Calculate s (the proof of signature) s= k^-1 * (z + r * privatekey) mod N It's important to note that in cryptography, we use s (the computed part of the signature) to ensure the validity of the private key's influence on the signed message. Occasionally, you'll see -s (negative s) in verification contexts. This happens because ECDSA signatures are valid in both positive and negative forms due to the symmetry of elliptic curves. Verification software typically normalizes the signature by ensuring that s is the smaller of the two possible values (s or -s mod N) The critical takeaway is that the process guarantees that only the holder of the correct private key could have generated the signature, ensuring authenticity. If you'd like me to expand on any specific step or provide further details, feel free to ask! Edit, NOW i got you that is really a weird case not only R is duplicated it is also S... WTF how are those signatures valid, even if all of them has different Z value?
2 Reply Quote Share
Posts: 23 · Reputation: 192
#3Jul 24, 2021, 08:39 PM
Hello Albert Thank you for the valuable information. I will review it again. I have been familiar with this information for a long time. I would like to explain it through a signature example from the above Operations. I will share sagemath log for this. As you can see, the signature is not verified with these values, I tried both manually and with various scripts to see if I calculated the Z value incorrectly. also the signature type is “pubkeyhash” This value of R_int (53263660719217912605226701691521450355210418686441457516777995068762774452686) The x value of this ECpoint must be the same. (19829164371494234377691210117539544104487361239120201118967338701656141495058 : 32604581094205453339388830956426246807569685087240405477122130035957072641097 : 1)
3 Reply Quote Share
fox_pixelMember
Posts: 6 · Reputation: 63
#4Jul 26, 2021, 09:06 PM
Hi, before diving into deep math, check your message hashes. Those are definitely wrong.
1 Reply Quote Share
RogueMoonFull Member
Posts: 110 · Reputation: 789
#5Jul 26, 2021, 09:16 PM
Well that is the point of this topic, according to the math having the same same R and S is only possible if the hash is the same for all the message as long they belong to the same publickey. I already checked the Signaures and all of them has the same R and S But the values of each those utxo are different. This only should mean that such Transaction is invalid.
4 Reply Quote Share
omega_bearFull Member
Posts: 116 · Reputation: 780
#6Jul 27, 2021, 01:50 AM
I think this is bitcoin mixer transaction, and maybe sach transactions will  more
2 Reply Quote Share
gr3g.0rbitHero Member
Posts: 1025 · Reputation: 2646
#7Jul 27, 2021, 06:32 AM
Yes. All inputs, together with those with the same R and S are signed with [SINGLE|ANYONECANPAY] (0x83) sighash flag. (can also be the reason for the same R,S) But you've calculated the message hash for SIGHASH_ALL (0x01). Problem is, I cannot find a single "RSZ tool" that can check for the sighash_flag then switch the z-value calculation algorithm accordingly. With that; DYOR, I'll just leave you some references: https://static.learnmeabitcoin.com/diagrams/png/keys-signature-hash-types.pnghttps://raghavsood.com/blog/2018/06/10/bitcoin-signature-types-sighash/
0 Reply Quote Share
RogueMoonFull Member
Posts: 110 · Reputation: 789
#8Jul 27, 2021, 07:15 AM
Thank you for this direct direct and well done explanation. This will point me in the right direction. Regards
0 Reply Quote Share
Posts: 23 · Reputation: 192
#9Jul 27, 2021, 12:52 PM
Hello, thank you very much for your explanation. I hope I can verify manually. I am trying to understand validation thoroughly.  I have separated this process as an example. https://blockchain.info/rawtx/bd17bfb7051bef5ca916931f06493a0af0db080b4df21ee9768fa0f3d775070a?format=hex It can be considered as a challenge open to members who have time and interest. I really want to understand the algorithm of verification. I hope it will help those who want to work for verification. Thank you very much.
1 Reply Quote Share
Posts: 23 · Reputation: 192
#10Jul 27, 2021, 03:49 PM
Hello , I think I solved the this problem. the problem is “SIGHASH_SINGLE bug” after the first signature, all other signatures all have a hash value of “0100000000000000000000000000000000000000000000000000000000000000”. i tried it and was able to verify.
0 Reply Quote Share
im_apeHero Member
Posts: 629 · Reputation: 3824
#11Jul 27, 2021, 07:59 PM
It is not a bug, that is the only way SIGHASH_SINGLE can be defined. That sighash flag says you have to sign output at the same index as your input but in Bitcoin protocol there is no rule saying the transaction has to have same number of inputs and outputs meaning there may not be any output at the same index but you still have to sign something if that sighash is used, therefore a fixed value is used.
3 Reply Quote Share
byte2019Senior Member
Posts: 270 · Reputation: 1836
#12Jul 29, 2021, 09:43 PM
It is definitely a bug. Normally, the whole transaction should be just marked as invalid. Not really, because if you compare for example legacy with Segwit, then it is defined differently. And for "bc1q" address, you won't have just the SHA-256 of "1", but you would have more complex way of computing transaction hash instead. Not to mention, that there are many other ways to define it, because if somebody would really mean "z=1", then the endianness should be reversed. It would be much better, if that specific case would be just marked as invalid, and rejected. Also because if you use "z=endian(1)", then you can move coins, where the ECDSA signature would be valid, but nobody would know the private key. For example: https://mempool.space/testnet/tx/3952b35bde53eb3f4871824f0b6b8c5ad25ca84ce83f04eb1c1d69b83ad6e448 Here, you have this innocently looking public key: https://mempool.space/testnet/address/032baf163f5e27261ab3228e61fb86dc98054abd514751fce93d7444e8fbc6a293 As you can see, those coins were successfully moved in testnet. And in general, if you start picking different "(r,s)" signatures, then you can use public key recovery, and move coins, even if you don't know the private key. Fortunately, this "z-value" is just "endian(1)", and not something weaker, because then, it could be possible to exploit it, and move someone else's coins, for example by using "r=target_public_key".
1 Reply Quote Share
im_apeHero Member
Posts: 629 · Reputation: 3824
#13Jul 30, 2021, 01:08 AM
It would only be a bug if the code were unintentionally signing 1, but it can't be a bug when the developer knowingly wrote that in the code to intentionally sign 1 in that particular scenario. If we do that we would be enforcing an unreasonable rule to force any transaction using SIGHASH_SINGLE to have same number or more outputs than inputs. If the user doesn't want to sign 1 then they can change their tx and if they want to sign 1 they have that option. The current way can come in handy in a multisig scenario that also provides security (eg. in 2-of-2 where 1 cosigner uses SIGHASH_SINGLE and the other uses SIGHASH_ALL). Fair point but that wasn't what I was talking about. Even in SegWit when we sign outputs we still have to have a corresponding output to sign with SIGHASH_SINGLE and if there is none we still sign a fixed value. So in that regard that is the only way that it can be defined. To be specific in SegWit both hashSequence and hashOutputs are going to be zero in our scenario. No you can't. If you could do that, then everyone would have just gone around and spend every single coin in any P2PK output that's on chain. The example you posted is a special case created with a special public key that would produce a valid signature with (r,s,z)=(1,1,1). If you are the one creating that public key then you can no longer claim the "key is unknown" when you created the signature as well. Have you noticed that the source and destination of the coins were the same? From tb1qft...h7jw to that pubkey then from that pubkey to tb1qft...h7jw. Meaning the same person who intentionally created that special public key also spent the coins. ECDSA is just math, you can find weird ways of producing weird but valid signatures as long as you control all the variables in it. But if you don't, like when you don't have the private key or when you are not the one creating the public key (that received the coins) assuming the key is randomly generated, you won't be able to produce a valid signature to spend those coins regardless of what the sighash is.
0 Reply Quote Share
byte2019Senior Member
Posts: 270 · Reputation: 1836
#14Jul 30, 2021, 05:00 AM
Looks like a bug. This "printf" doesn't look like "let's put 1 intentionally", but rather "let's report an error, and mark it as invalid". However, in this specific case, the whole function was supposed to return z-value, so when it returned "1", the rest of the code was executed normally, and treated it like every other value. It is unknown. The public key is known, but the private key is completely unknown. If anyone could get a private key out of it, then it would be possible to use the same method, and get a private key for any other public key as well. Here, nobody knows d-value or k-value, which means that nobody knows the private key. Because if it would be known, then people could just use "R=some_public_key", solve it, and get a private key out of it. Also, the same tricks cannot be replicated on Taproot, because it was designed to block public key recovery, so you cannot get a matching public key, out of some signature. Yes, but it is just P2WSH for OP_TRUE. And it doesn't matter, if you want to test out of bounds SIGHASH_SINGLE, the first input and output can be anything.
1 Reply Quote Share
?Reply
Sign in to reply to this topic

Related topics