Bitcoin Forum
May 08, 2024, 01:25:30 PM *
News: Latest Bitcoin Core release: 27.0 [Torrent]
 
   Home   Help Search Login Register More  
Pages: [1]
  Print  
Author Topic: How to convert a compressed public key into uncompressed one in Python?  (Read 195 times)
SamYezi (OP)
Newbie
*
Offline Offline

Activity: 25
Merit: 79


View Profile
August 30, 2022, 10:05:16 AM
Merited by PowerGlove (2)
 #1

I've searched really hard for a Python script that coverts a compressed public key into uncompressed one, since I don't know how to code this. I stumbled upon these links:

https://stackoverflow.com/questions/43629265/deriving-an-ecdsa-uncompressed-public-key-from-a-compressed-one
https://bitcoin.stackexchange.com/questions/86234/how-to-uncompress-a-public-key
https://bitcointalk.org/index.php?topic=644919.0

but all python scripts/functions either don't work or outputting incorrect values. I tried to debug them and failed. Could you point out how to code something like this in Python or give an example of the working code? Here are the values to play with (HEX):

Code:
#Test case 1
#Compressed Pubkey: 025A2146590B80D1F0D97CC7104E702011AFFF21BFAF817F5C7002446369BA9DDC
'''
Right Uncompressed Pubkey:
045A2146590B80D1F0D97CC7104E702011AFFF21BFAF817F5C7002446369BA9DDC9BD5DCD1B4A737244D6BB7B96E256391B8597D3A7972A6F8CA9096D4AEA1F37E
'''

#Test case 2
#Compressed Pubkey: 035728F4692D85D411DF3643CD69FE05C411A0D507C7D814008F56C8F260AD7ED9
'''
Right Uncompressed Pubkey:
045728F4692D85D411DF3643CD69FE05C411A0D507C7D814008F56C8F260AD7ED99E2DF8D9CB1A575D55264692629AE22E518BC14AD02592941C13BE6755C72973
'''

#Test case 3
#Compressed Pubkey:039E87EB177890FDD788B95843ED53AD4FB6E877E3F730EF1E73593964C2AB9D15
'''
Right Uncompressed Pubkey:
049E87EB177890FDD788B95843ED53AD4FB6E877E3F730EF1E73593964C2AB9D15A3B647C8C4A0766420917B7B445CDCD6BFEC2900175C5534C6113954F3FF00D9
1715174730
Hero Member
*
Offline Offline

Posts: 1715174730

View Profile Personal Message (Offline)

Ignore
1715174730
Reply with quote  #2

1715174730
Report to moderator
1715174730
Hero Member
*
Offline Offline

Posts: 1715174730

View Profile Personal Message (Offline)

Ignore
1715174730
Reply with quote  #2

1715174730
Report to moderator
The Bitcoin software, network, and concept is called "Bitcoin" with a capitalized "B". Bitcoin currency units are called "bitcoins" with a lowercase "b" -- this is often abbreviated BTC.
Advertised sites are not endorsed by the Bitcoin Forum. They may be unsafe, untrustworthy, or illegal in your jurisdiction.
1715174730
Hero Member
*
Offline Offline

Posts: 1715174730

View Profile Personal Message (Offline)

Ignore
1715174730
Reply with quote  #2

1715174730
Report to moderator
1715174730
Hero Member
*
Offline Offline

Posts: 1715174730

View Profile Personal Message (Offline)

Ignore
1715174730
Reply with quote  #2

1715174730
Report to moderator
1715174730
Hero Member
*
Offline Offline

Posts: 1715174730

View Profile Personal Message (Offline)

Ignore
1715174730
Reply with quote  #2

1715174730
Report to moderator
PowerGlove
Hero Member
*****
hacker
Offline Offline

Activity: 510
Merit: 4005



View Profile
August 30, 2022, 03:22:56 PM
Merited by SamYezi (4), Welsh (3), odolvlobo (1)
 #2

The Python script you've already discovered, over here works correctly as far as I can tell.

Substituting your example keys into the "compressed_key" variable on line 12 and running the script three times produced the following results:

compressed_key = '025A2146590B80D1F0D97CC7104E702011AFFF21BFAF817F5C7002446369BA9DDC'
Code:
045a2146590b80d1f0d97cc7104e702011afff21bfaf817f5c7002446369ba9ddc9bd5dcd1b4a737244d6bb7b96e256391b8597d3a7972a6f8ca9096d4aea1f37e

compressed_key = '035728F4692D85D411DF3643CD69FE05C411A0D507C7D814008F56C8F260AD7ED9'
Code:
045728f4692d85d411df3643cd69fe05c411a0d507c7d814008f56c8f260ad7ed99e2df8d9cb1a575d55264692629ae22e518bc14ad02592941c13be6755c72973

compressed_key = '039E87EB177890FDD788B95843ED53AD4FB6E877E3F730EF1E73593964C2AB9D15'
Code:
049e87eb177890fdd788b95843ed53ad4fb6e877e3f730ef1e73593964c2ab9d15a3b647c8c4a0766420917b7b445cdcd6bfec2900175c5534c6113954f3ff00d9
SamYezi (OP)
Newbie
*
Offline Offline

Activity: 25
Merit: 79


View Profile
August 30, 2022, 06:20:46 PM
 #3

The Python script you've already discovered, over here works correctly as far as I can tell.

Substituting your example keys into the "compressed_key" variable on line 12 and running the script three times produced the following results:

compressed_key = '025A2146590B80D1F0D97CC7104E702011AFFF21BFAF817F5C7002446369BA9DDC'
Code:
045a2146590b80d1f0d97cc7104e702011afff21bfaf817f5c7002446369ba9ddc9bd5dcd1b4a737244d6bb7b96e256391b8597d3a7972a6f8ca9096d4aea1f37e

compressed_key = '035728F4692D85D411DF3643CD69FE05C411A0D507C7D814008F56C8F260AD7ED9'
Code:
045728f4692d85d411df3643cd69fe05c411a0d507c7d814008f56c8f260ad7ed99e2df8d9cb1a575d55264692629ae22e518bc14ad02592941c13be6755c72973

compressed_key = '039E87EB177890FDD788B95843ED53AD4FB6E877E3F730EF1E73593964C2AB9D15'
Code:
049e87eb177890fdd788b95843ed53ad4fb6e877e3f730ef1e73593964c2ab9d15a3b647c8c4a0766420917b7b445cdcd6bfec2900175c5534c6113954f3ff00d9

Unfortunatelly in my case it outputs incorrect values (Pycharm Python 3.10.5)
Here's the rundown of the cases:
https://i.stack.imgur.com/VgZhr.png
https://i.stack.imgur.com/VgZhr.png

Test 1:
Code:
042351126323155009915566305515988222562668831973356296881287277305661165837788ee29766cfd677f845e830bea820e1ef951b86fdc335247a8aa697e6baf1ef78
Test 2:
Code:
046799846282981021315422058923075594964980219729412475060169781627609169100505f87b4bda8ed8b93cff4207e66c65b4909a48a3b54076aac6d6ba7626e15ba875
Test 3:
Code:
049081844685017147717691639198226214703337765349173402524026447080150572702997d7b2db226c460a5e7167c150fab386c8688dd4170d3d453a2c3efad529c73e75


SamYezi (OP)
Newbie
*
Offline Offline

Activity: 25
Merit: 79


View Profile
August 30, 2022, 06:51:39 PM
 #4

The Python script you've already discovered, over here works correctly as far as I can tell.

Substituting your example keys into the "compressed_key" variable on line 12 and running the script three times produced the following results:

compressed_key = '025A2146590B80D1F0D97CC7104E702011AFFF21BFAF817F5C7002446369BA9DDC'
Code:
045a2146590b80d1f0d97cc7104e702011afff21bfaf817f5c7002446369ba9ddc9bd5dcd1b4a737244d6bb7b96e256391b8597d3a7972a6f8ca9096d4aea1f37e

compressed_key = '035728F4692D85D411DF3643CD69FE05C411A0D507C7D814008F56C8F260AD7ED9'
Code:
045728f4692d85d411df3643cd69fe05c411a0d507c7d814008f56c8f260ad7ed99e2df8d9cb1a575d55264692629ae22e518bc14ad02592941c13be6755c72973

compressed_key = '039E87EB177890FDD788B95843ED53AD4FB6E877E3F730EF1E73593964C2AB9D15'
Code:
049e87eb177890fdd788b95843ed53ad4fb6e877e3f730ef1e73593964c2ab9d15a3b647c8c4a0766420917b7b445cdcd6bfec2900175c5534c6113954f3ff00d9

I found the error. If inputting 0x... hex values with str() conversion into the function, it is going to output incorrect values. So it requires the compressed inputting public key to be a string with ' ' single quotes like:
https://i.stack.imgur.com/AdY3o.png
New test results:
Test 1:
Code:
045a2146590b80d1f0d97cc7104e702011afff21bfaf817f5c7002446369ba9ddc9bd5dcd1b4a737244d6bb7b96e256391b8597d3a7972a6f8ca9096d4aea1f37e
Test 2:
Code:
045728f4692d85d411df3643cd69fe05c411a0d507c7d814008f56c8f260ad7ed99e2df8d9cb1a575d55264692629ae22e518bc14ad02592941c13be6755c72973
Test 3:
Code:
049e87eb177890fdd788b95843ed53ad4fb6e877e3f730ef1e73593964c2ab9d15a3b647c8c4a0766420917b7b445cdcd6bfec2900175c5534c6113954f3ff00d9
So, thanks!
PowerGlove
Hero Member
*****
hacker
Offline Offline

Activity: 510
Merit: 4005



View Profile
August 30, 2022, 07:23:16 PM
Merited by nc50lc (1), NotATether (1)
 #5

I found the error. If inputting 0x... hex values with str() conversion into the function, it is going to output incorrect values.
Yup, you were accidentally passing '272351126323155009915566305515988222562668831973356296881287277305661165837788' into the function instead of '025A2146590B80D1F0D97CC7104E702011AFFF21BFAF817F5C7002446369BA9DDC'. Smiley

I'm glad it's working now. You can make the script a little shorter by getting rid of the "pow_mod" definition and using the built-in "pow", like so (code taken from your PNG):

Code:
def compressedToUncompressed(compressed_key):
    p = 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f
    y_parity = int(compressed_key[:2]) - 2
    x = int(compressed_key[2:], 16)
    a = (pow(x, 3, p) + 7) % p
    y = pow(a, (p+1)//4, p)
    if y % 2 != y_parity:
        y = -y % p
    uncompressed_key = '04{:x}{:x}'.format(x, y)
    return uncompressed_key

assert compressedToUncompressed('025A2146590B80D1F0D97CC7104E702011AFFF21BFAF817F5C7002446369BA9DDC') == '045a2146590b80d1f0d97cc7104e702011afff21bfaf817f5c7002446369ba9ddc9bd5dcd1b4a737244d6bb7b96e256391b8597d3a7972a6f8ca9096d4aea1f37e'
assert compressedToUncompressed('035728F4692D85D411DF3643CD69FE05C411A0D507C7D814008F56C8F260AD7ED9') == '045728f4692d85d411df3643cd69fe05c411a0d507c7d814008f56c8f260ad7ed99e2df8d9cb1a575d55264692629ae22e518bc14ad02592941c13be6755c72973'
assert compressedToUncompressed('039E87EB177890FDD788B95843ED53AD4FB6E877E3F730EF1E73593964C2AB9D15') == '049e87eb177890fdd788b95843ed53ad4fb6e877e3f730ef1e73593964c2ab9d15a3b647c8c4a0766420917b7b445cdcd6bfec2900175c5534c6113954f3ff00d9'
brainless
Member
**
Offline Offline

Activity: 316
Merit: 34


View Profile
August 31, 2022, 04:04:04 AM
 #6

compress to uncompress
Code:
import binascii

p = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F

def decompress_pubkey(pk):
    x = int.from_bytes(pk[1:33], byteorder='big')
    y_sq = (pow(x, 3, p) + 7) % p
    y = pow(y_sq, (p + 1) // 4, p)
    if y % 2 != pk[0] % 2:
        y = p - y
    y = y.to_bytes(32, byteorder='big')
    return b'\x04' + pk[1:33] + y

with open('add.txt') as f:
  for line in f:
    line=line.strip()
    print(binascii.hexlify(decompress_pubkey(binascii.unhexlify(line))).decode(),file=open("uncomp.txt", "a"))

uncompress to compress

Code:
def cpub(x,y):
 prefix = '02' if y % 2 == 0 else '03'
 c = prefix+ hex(x)[2:].zfill(64)
 return c
with open('add.txt') as f:
  for line in f:
    line=line.strip()
    x = int(line[2:66], 16)
    y = int(line[66:], 16)
    pub04=cpub(x,y)

    print(pub04,file=open("comp.txt", "a"))


13sXkWqtivcMtNGQpskD78iqsgVy9hcHLF
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!