Author

Topic: Determining the positivity or negativity of a Bitcoin public key (Read 217 times)

jr. member
Activity: 40
Merit: 3
@odolvlobo
@kTimesG

I would like to apologize to both of you.
The part you pointed out as an error was indeed an error.
I was wrong to think that as long as the result was correct, it would be fine.
Thank you to everyone who showed interest.
The issue has been resolved. Thank you!
member
Activity: 165
Merit: 26
Code:
   # Determine the first byte of the compressed public key based on the private key's sign
    if private_key_int < 0:
        public_key_bytes_compressed = (
            b"\x03" + vk.to_string()[:32] if vk.to_string()[-1] % 2 == 0 else b"\x02" + vk.to_string()[:32]
        )
    else:
        public_key_bytes_compressed = (
            b"\x02" + vk.to_string()[:32] if vk.to_string()[-1] % 2 == 0 else b"\x03" + vk.to_string()[:32]
        )

You code is incorrect. The 0x02, 0x03 prefixes are based only on the value of the public key.

Furthermore, a valid secp256k1 private key is an integer in the range 1 to FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364140, so testing if it is less than 0 should always return false. If your test returns true, then the private key is invalid or there is a bug in your code.


Since the program itself knows the private key, the public key output result is 100% accurate.
There are no errors in the program.
Please check the private key and the outputted public key.

So you've been told twice already that you're doing things incorrectly, but you insist on it being 100% correct and error-free. Why do you need our opinion in that case?

Public keys for private keys "-1" and N-1 are identical, while your code messes up their compressed representation (since you have a logical contradiction at the reasoning layer, since private keys don't have a sign, since a modular interval doesn't have negative values). So before all else, if your code was Windows 95, this would become a BSOD of the brain.
jr. member
Activity: 40
Merit: 3
Code:
   # Determine the first byte of the compressed public key based on the private key's sign
    if private_key_int < 0:
        public_key_bytes_compressed = (
            b"\x03" + vk.to_string()[:32] if vk.to_string()[-1] % 2 == 0 else b"\x02" + vk.to_string()[:32]
        )
    else:
        public_key_bytes_compressed = (
            b"\x02" + vk.to_string()[:32] if vk.to_string()[-1] % 2 == 0 else b"\x03" + vk.to_string()[:32]
        )

You code is incorrect. The 0x02, 0x03 prefixes are based only on the value of the public key.

Furthermore, a valid secp256k1 private key is an integer in the range 1 to FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364140, so testing if it is less than 0 should always return false. If your test returns true, then the private key is invalid or there is a bug in your code.


Since the program itself knows the private key, the public key output result is 100% accurate.
There are no errors in the program.
Please check the private key and the outputted public key.
legendary
Activity: 4466
Merit: 3391
Code:
   # Determine the first byte of the compressed public key based on the private key's sign
    if private_key_int < 0:
        public_key_bytes_compressed = (
            b"\x03" + vk.to_string()[:32] if vk.to_string()[-1] % 2 == 0 else b"\x02" + vk.to_string()[:32]
        )
    else:
        public_key_bytes_compressed = (
            b"\x02" + vk.to_string()[:32] if vk.to_string()[-1] % 2 == 0 else b"\x03" + vk.to_string()[:32]
        )

You code is incorrect. The 0x02, 0x03 prefixes are based only on the value of the public key.

Furthermore, a valid secp256k1 private key is an integer in the range 1 to FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364140, so testing if it is less than 0 should always return false. If your test returns true, then the private key is invalid or there is a bug in your code.
newbie
Activity: 3
Merit: 168
Quote
It is possible to determine the positivity or negativity if the final output values of pma and pmb from the current program are provided.

When |pma| > |pmb|, the positivity or negativity can be determined with 100% accuracy, but when |pma| < |pmb|, errors occur in determining positivity or negativity. I am looking for someone to collaborate on this issue.


You can easily do it using power of two values. They are the key factor here.
Here is how.

2^10...2^11 (1024...2048) for example

1288:2=644 1288+0.5=1288.5
1288-1024=264
264+(256+64+32+16+8+4)=644
644+644=1288 POINT IS EVEN

1289:2=644,5 1289+0.5=1289.5
1289-1024=265
265+(256+64+32+16+8+2+1)=644
644,5+644+1=1289,5 POINT IS ODD

This requires bruteforcing the correct sequence of powers of two.
And for high-tier ranges like 2^250...2^256 will be pretty hard to find.
And moreover if that sequence is found you can directly get the privatekey.
(256+64+32+16+8+4)=380
512-380=132
132*2=264
1024+264=1288

(256+64+32+16+8+2+1)=379
512-379=133
133*2-1=265
1024+265=1289
member
Activity: 165
Merit: 26
When |pma| > |pmb|, the positivity or negativity can be determined with 100% accuracy, but when |pma| < |pmb|, errors occur in determining positivity or negativity. I am looking for someone to collaborate on this issue.

1. There's no such thing as a negative public key or negative private key.
2. There's no relation between the bits of a private key and the bits of a public key, otherwise ECC would be broken. Your code fails the very fundamentals of how ECC works.
3. You have errors because you wrote that bunch of code without understanding what ECC is all about, and so of course you get errors, since it doesn't make sense even before you would write it on paper as pseudo-code, let alone as a Python script.
4. It works when |pma| > |pmb| because this is how you created it to work (as it doesn't really respect ECC fundamentals, rather some dubious creation of strings which are definitely not respecting the correct private key to public key relation); hence, since it is written in such a way to produce results based on what you wanted it to do, what else would you expect in the other cases? Magic?
5. Good luck on finding a collaborator to help you fix the "errors".
6. Public key prefixes indicate the Y parity (the least significant bit value), not the private key being in the lower or upper half of the scalar field. Else it would be a backdoor/leak in the ECC system. See point 2.
jr. member
Activity: 40
Merit: 3
Due to the nature of elliptic curves over finite fields, (when using secure parameters) it is not possible (or at least, no one knows how) to take the public key and infer any information about the private key.

===>
I am not trying to find out the private key; I want a program that can distinguish the positivity or negativity of the public key.
newbie
Activity: 7
Merit: 0
This program generates public keys from randomly created private keys using elliptic curve cryptography, specifically the secp256k1 curve used in Bitcoin. The private keys (pma and pmb) are set with the same sign, either both positive or both negative. Based on the sign of each private key, the program outputs corresponding compressed and uncompressed public keys. The compressed public keys’ prefixes (0x02 or 0x03) are adjusted according to whether the private key is positive or negative.

There is a program that determines whether the private key is positive or negative based solely on the generated public key output.

program

import random
import ecdsa
import binascii

# Define the range
a = random.randint(2**134, 2**135)
am = 10**37
b = a - am

# Set pma and pmb: both values should have the same sign
sign = random.choice([1, -1])  # Set both as either positive or negative
pma = sign * a
pmb = sign * b

# Function to generate a public key from a private key
def generate_public_key(private_key_int):
    # Convert the private key to a 32-byte format
    private_key_bytes = abs(private_key_int).to_bytes(32, byteorder="big", signed=True)
    
    # Generate the elliptic curve public key (secp256k1)
    sk = ecdsa.SigningKey.from_string(private_key_bytes, curve=ecdsa.SECP256k1)
    vk = sk.verifying_key
    
    # Create uncompressed public key format
    public_key_bytes_uncompressed = b"\x04" + vk.to_string()
    
    # Determine the compressed public key's prefix based on the private key's sign
    if private_key_int < 0:
        public_key_bytes_compressed = (
            b"\x03" + vk.to_string()[:32] if vk.to_string()[-1] % 2 == 0 else b"\x02" + vk.to_string()[:32]
        )
    else:
        public_key_bytes_compressed = (
            b"\x02" + vk.to_string()[:32] if vk.to_string()[-1] % 2 == 0 else b"\x03" + vk.to_string()[:32]
        )
    
    # Convert the public keys to hexadecimal strings
    public_key_uncompressed = binascii.hexlify(public_key_bytes_uncompressed).decode()
    public_key_compressed = binascii.hexlify(public_key_bytes_compressed).decode()
    
    return public_key_uncompressed, public_key_compressed

# Generate public keys using pma and pmb as private keys
public_key_a_uncompressed, public_key_a_compressed = generate_public_key(pma)
public_key_b_uncompressed, public_key_b_compressed = generate_public_key(pmb)

# Output the results
print("a:", a)
print("b:", b)
print("am:", am)
print("pma (Private Key a):", pma)
print("pmb (Private Key b):", pmb)
print("public_key_a (Uncompressed Public Key a):", public_key_a_uncompressed)
print("public_key_a (Compressed Public Key a):", public_key_a_compressed)
print("public_key_b (Uncompressed Public Key b):", public_key_b_uncompressed)
print("public_key_b (Compressed Public Key b):", public_key_b_compressed)

It is possible to determine the positivity or negativity if the final output values of pma and pmb from the current program are provided.

When |pma| > |pmb|, the positivity or negativity can be determined with 100% accuracy, but when |pma| < |pmb|, errors occur in determining positivity or negativity. I am looking for someone to collaborate on this issue.


Due to the nature of elliptic curves over finite fields, (when using secure parameters) it is not possible (or at least, no one knows how) to take the public key and infer any information about the private key.
jr. member
Activity: 40
Merit: 3
This program generates public keys from randomly created private keys using elliptic curve cryptography, specifically the secp256k1 curve used in Bitcoin. The private keys (pma and pmb) are set with the same sign, either both positive or both negative. Based on the sign of each private key, the program outputs corresponding compressed and uncompressed public keys. The compressed public keys’ prefixes (0x02 or 0x03) are adjusted according to whether the private key is positive or negative.

There is a program that determines whether the private key is positive or negative based solely on the generated public key output.

program

import random
import ecdsa
import binascii

# Define the range
a = random.randint(2**134, 2**135)
am = 10**37
b = a - am

# Set pma and pmb: both values should have the same sign
sign = random.choice([1, -1])  # Set both as either positive or negative
pma = sign * a
pmb = sign * b

# Function to generate a public key from a private key
def generate_public_key(private_key_int):
    # Convert the private key to a 32-byte format
    private_key_bytes = abs(private_key_int).to_bytes(32, byteorder="big", signed=True)
    
    # Generate the elliptic curve public key (secp256k1)
    sk = ecdsa.SigningKey.from_string(private_key_bytes, curve=ecdsa.SECP256k1)
    vk = sk.verifying_key
    
    # Create uncompressed public key format
    public_key_bytes_uncompressed = b"\x04" + vk.to_string()
    
    # Determine the compressed public key's prefix based on the private key's sign
    if private_key_int < 0:
        public_key_bytes_compressed = (
            b"\x03" + vk.to_string()[:32] if vk.to_string()[-1] % 2 == 0 else b"\x02" + vk.to_string()[:32]
        )
    else:
        public_key_bytes_compressed = (
            b"\x02" + vk.to_string()[:32] if vk.to_string()[-1] % 2 == 0 else b"\x03" + vk.to_string()[:32]
        )
    
    # Convert the public keys to hexadecimal strings
    public_key_uncompressed = binascii.hexlify(public_key_bytes_uncompressed).decode()
    public_key_compressed = binascii.hexlify(public_key_bytes_compressed).decode()
    
    return public_key_uncompressed, public_key_compressed

# Generate public keys using pma and pmb as private keys
public_key_a_uncompressed, public_key_a_compressed = generate_public_key(pma)
public_key_b_uncompressed, public_key_b_compressed = generate_public_key(pmb)

# Output the results
print("a:", a)
print("b:", b)
print("am:", am)
print("pma (Private Key a):", pma)
print("pmb (Private Key b):", pmb)
print("public_key_a (Uncompressed Public Key a):", public_key_a_uncompressed)
print("public_key_a (Compressed Public Key a):", public_key_a_compressed)
print("public_key_b (Uncompressed Public Key b):", public_key_b_uncompressed)
print("public_key_b (Compressed Public Key b):", public_key_b_compressed)

It is possible to determine the positivity or negativity if the final output values of pma and pmb from the current program are provided.

When |pma| > |pmb|, the positivity or negativity can be determined with 100% accuracy, but when |pma| < |pmb|, errors occur in determining positivity or negativity. I am looking for someone to collaborate on this issue.
Jump to: