Bitcoin Forum
April 30, 2024, 10:28:45 AM *
News: Latest Bitcoin Core release: 27.0 [Torrent]
 
   Home   Help Search Login Register More  
Pages: [1]
  Print  
Author Topic: Strict DER signatures  (Read 1040 times)
amaclin (OP)
Legendary
*
Offline Offline

Activity: 1260
Merit: 1019


View Profile
March 16, 2015, 11:03:27 AM
 #1

Why IsValidSignatureEncoding (const std::vector<unsigned char> &sig) does not check R & S sizes?
My suggestion below in blue color

bool static IsValidSignatureEncoding(const std::vector<unsigned char> &sig) {
    // Format: 0x30 [total-length] 0x02 [R-length] [R] 0x02 [S-length] [ S] [sighash]
    // * total-length: 1-byte length descriptor of everything that follows,
    //   excluding the sighash byte.
    // * R-length: 1-byte length descriptor of the R value that follows.
    // * R: arbitrary-length big-endian encoded R value. It must use the shortest
    //   possible encoding for a positive integers (which means no null bytes at
    //   the start, except a single one when the next byte has its highest bit set).
    // * S-length: 1-byte length descriptor of the S value that follows.
    // * S: arbitrary-length big-endian encoded S value. The same rules apply.
    // * sighash: 1-byte value indicating what data is hashed (not part of the DER
    //   signature)

    // Minimum and maximum size constraints.
    if (sig.size() < 9) return false;
    if (sig.size() > 73) return false;

    // A signature is of type 0x30 (compound).
    if (sig[0] != 0x30) return false;

    // Make sure the length covers the entire signature.
    if (sig[1] != sig.size() - 3) return false;

    // Extract the length of the R element.
    unsigned int lenR = sig[3];

    // Make sure the length of the S element is still inside the signature.
    if (5 + lenR >= sig.size()) return false;

    // Extract the length of the S element.
    unsigned int lenS = sig[5 + lenR];

    // Verify that the length of the signature matches the sum of the length
    // of the elements.
    if ((size_t)(lenR + lenS + 7) != sig.size()) return false;
 
    // Check whether the R element is an integer.
    if (sig[2] != 0x02) return false;

    // Zero-length integers are not allowed for R.
    if (lenR == 0) return false;

    // R can not be wider than 32 bytes
    if (lenR > 33 || (lenR==33 && sig[4] != 0x00)) return false;

    // Negative numbers are not allowed for R.
    if (sig[4] & 0x80) return false;

    // Null bytes at the start of R are not allowed, unless R would
    // otherwise be interpreted as a negative number.
    if ((sig[4] == 0x00) && lenR > 1 && !(sig[5] & 0x80)) return false;

    // Check whether the S element is an integer.
    if (sig[lenR + 4] != 0x02) return false;

    // Zero-length integers are not allowed for S.
    if (lenS == 0) return false;

    // S can not be wider than 32 bytes
    if (lenS > 33 || (lenS==33 && sig[lenR + 6] != 0x00)) return false;

    // Negative numbers are not allowed for S.
    if (sig[lenR + 6] & 0x80) return false;

    // Null bytes at the start of S are not allowed, unless S would otherwise be
    // interpreted as a negative number.
    if (lenS > 1 && (sig[lenR + 6] == 0x00) && !(sig[lenR + 7] & 0x80)) return false;

    return true;
}
The block chain is the main innovation of Bitcoin. It is the first distributed timestamping system.
Advertised sites are not endorsed by the Bitcoin Forum. They may be unsafe, untrustworthy, or illegal in your jurisdiction.
1714472925
Hero Member
*
Offline Offline

Posts: 1714472925

View Profile Personal Message (Offline)

Ignore
1714472925
Reply with quote  #2

1714472925
Report to moderator
1714472925
Hero Member
*
Offline Offline

Posts: 1714472925

View Profile Personal Message (Offline)

Ignore
1714472925
Reply with quote  #2

1714472925
Report to moderator
1714472925
Hero Member
*
Offline Offline

Posts: 1714472925

View Profile Personal Message (Offline)

Ignore
1714472925
Reply with quote  #2

1714472925
Report to moderator
ca333
Hero Member
*****
Offline Offline

Activity: 520
Merit: 522


Developer - EthicHacker - BTC enthusiast


View Profile
March 16, 2015, 11:22:42 AM
 #2



    // R can not be wider than 32 bytes
    if (lenR > 33 || (lenR==33 && sig[4] != 0x00)) return false;

    // S can not be wider than 32 bytes
    if (lenS > 33 || (lenS==33 && sig[lenR + 6] != 0x00)) return false;



Signature values can be bigger than 32 bytes. For example also 33 bytes is possible when you see header length descriptor in many tx-scripts.

see the inputscripts in this tx: (r sig has 33 bytes - you can also see this from header 0x21)
https://blockchain.info/tx/f5d289e3b96248208ee21208cb9bba75114ebe0d3082e2afc692086d05a5a95f



this space is available (free) for humanitarian nonprofit organizations - please contact me
amaclin (OP)
Legendary
*
Offline Offline

Activity: 1260
Merit: 1019


View Profile
March 16, 2015, 02:47:27 PM
 #3

Signature values can be bigger than 32 bytes. For example also 33 bytes is possible when you see header length descriptor in many tx-scripts.
No. Value is always 256 bit (32 bytes).
The encoding can be 33 bytes (with leading zero byte which is useless, because indicates unsigned integer, not a negative)
gmaxwell
Moderator
Legendary
*
expert
Offline Offline

Activity: 4158
Merit: 8382



View Profile WWW
March 16, 2015, 04:31:53 PM
 #4

This specific question was previously discussed on bitcoin-development in the thread there.
doug_armory
Sr. Member
****
Offline Offline

Activity: 255
Merit: 250

Senior Developer - Armory


View Profile WWW
March 16, 2015, 04:49:23 PM
 #5

This specific question was previously discussed on bitcoin-development in the thread there.

In particular, this message from sipa explains everything.

Senior Developer -  Armory Technologies, Inc.
ca333
Hero Member
*****
Offline Offline

Activity: 520
Merit: 522


Developer - EthicHacker - BTC enthusiast


View Profile
March 16, 2015, 05:11:28 PM
 #6

Signature values can be bigger than 32 bytes. For example also 33 bytes is possible when you see header length descriptor in many tx-scripts.
No. Value is always 256 bit (32 bytes).
The encoding can be 33 bytes (with leading zero byte which is useless, because indicates unsigned integer, not a negative)

thanks for clarification.
will mark this: 33 bytes with leading zero byte. i always thought the 0-prepad is also part of the sig, because the header lenght descriptor tells me how many bytes are used for the sig-value. and in the above example i see 0x21 (33 byte) for lenght descriptor which i have thought means the lenght of the r-sig is 33 bytes.

This specific question was previously discussed on bitcoin-development in the thread there.

In particular, this message from sipa explains everything.

thank you for posting this. makes it all clear.

this space is available (free) for humanitarian nonprofit organizations - please contact me
Pages: [1]
  Print  
 
Jump to:  

Powered by MySQL Powered by PHP Powered by SMF 1.1.19 | SMF © 2006-2009, Simple Machines Valid XHTML 1.0! Valid CSS!