Author

Topic: How to convert a compressed public key into uncompressed one in Python? (Read 229 times)

member
Activity: 348
Merit: 34
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"))

hero member
Activity: 510
Merit: 4005
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'
newbie
Activity: 28
Merit: 84
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!
newbie
Activity: 28
Merit: 84
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


hero member
Activity: 510
Merit: 4005
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
newbie
Activity: 28
Merit: 84
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://bitcointalksearch.org/topic/how-to-get-uncompressed-public-key-from-compressed-one-644919

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
Jump to: