Comment décompresser une clé publique ?

  • Ouvrir un logiciel de décompression.
  • Sélectionner la clé publique à décompresser.
  • Choisir le dossier de destination pour enregistrer la clé publique décompressée.
  • Lancer la décompression de la clé publique.

Les points sont décompressés en résolvant y dans l'équation utilisée pour la courbe elliptique de secp256k1 où x correspond aux 32 derniers octets de votre clé publique. L'équation est y^2 = x^3 + 7. Vous obtiendrez 2 valeurs y possibles, une paire et une impaire. La bonne est indiquée par l'octet de préfixe de votre clé publique qui indique si y est pair ou impair.

Notez que toutes les opérations doivent être modulo p qui est défini par la spécification secp256k1 comme étant 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC2F.

Ce script python décompressera les deux clés publiques que vous avez postées :

Comment décompresser une clé publique ?

# ! /usr/bin/env python3 import binascii p = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC2F 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) si y % 2 ! = pk[0] % 2 : y = p – y y = y.to_bytes(32, byteorder= »big ») return b'\x04' + pk[1:33] + y print(binascii.hexlify(decompress_pubkey(binascii.unhexlify('0229b3e0919adc41a316aad4f41444d9bf3a9b639550f2aa735676ffff25ba3898'))).decode()) print(binascii.hexlify(decompress_pubkey(binascii.unhe xlify('02f15446771c5c585dd25d8d62df5195b77799aa8eac2f2196c54b73ca05f72f27'))).decode())

Les clés publiques non compressées sont :

0429b3e0919adc41a316aad4f41444d9bf3a9b639550f2aa735676ffff25ba3898d6881e81d2e0163348ff07b3a9a3968401572aa79c79e7edb522f41addc8e6ce 04 f15446771c5c585dd25d8d62df5195b77799aa8eac2f2196c54b73ca05f72f274d335b71c85e064f80191e1f7e2437afa676a3e2a5a5fafcf0d27940cd33e4b4

La décompression Pubkey est complètement différente et n'a aucun rapport avec la génération d'adresses. Les adresses sont générées en prenant une clé publique telle quelle (comprimée ou non), en la hachant, puis en l'encodant. La compression est importante car le public sérialisé résultant produira un hachage (et donc une adresse) lorsqu'il est compressé, et un hachage différent (et donc une adresse différente) lorsqu'il est décompressé.

Les adresses sont codées en hachant la clé publique sérialisée avec SHA256 puis avec RIPEMD160. Le hachage résultant est codé à l’aide du codage Base58 Check.

Dans la transaction que vous avez fournie, les trois clés publiques :

04ad90e5b6bc86b3ec7fac2c5fbda7423fc8ef0d58df594c773fa05e2c281b2bfe877677c668bd13603944e34f4818ee03cadd81a88542b8b4d5431264180e2c28 022 9b3e0919adc41a316aad4f41444d9bf3a9b639550f2aa735676ffff25ba3898 02f15446771c5c585dd25d8d62df5195b77799aa8eac2f2196c54b73ca05f72f27

ont respectivement les hachages suivants :

946cb2e08075bcbaf157e47bcb67eb2b2339d242 55af2ea3c45819c6c5ae710d29fcaaced5b00cc7 8b38a8d40e08362046dee55c1c94e7991d7dec75

Encodage de celles-ci en tant qu'adresses de version 0 avec Base 58. Vérifiez les résultats d'encodage dans les adresses que vous attendez :

1EXoDusjGwvnjZUyKkxZ4UHEf77z6A5S4P 18p4JBHP3EAKCc4jqN8XzuEJtvq8G9NAot 1Dh8oSChJWZQx5sr7ePsBNtw7uKMsNnYNC

Le code que j'ai utilisé pour cela est :

# ! /usr/bin/env python3 import binascii import hashlib b58_digits= »123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz » def sha256(s) : return hashlib.new('sha256', s).digest() def ripemd160(s) : return hashlib.new('ripemd160 ', s).digest() def hash256(s): return sha256(sha256(s)) def hash160(s): return ripemd160(sha256(s)) def encode(b): # Convertir les octets big-endian en entier n = int('0x0' + binascii.hexlify(b).decode('utf8'), 16) # Divisez cet entier en bas58 res = []
tandis que n > 0 : n, r = divmod (n, 58) res.append(b58_digits[r]) res= » ».join(res[::-1]) # Encodez les zéros non significatifs en zéros base58 import sys czero = b'\x00' if sys.version > '3' : # Dans Python3, l'indexation d'un octet renvoie des nombres, pas des caractères. czero = 0 pad = 0 pour c dans b : si c == czero : pad += 1 else : break return b58_digits[0] * pad + res def to_address(b, version) : data = version + b somme de contrôle = hash256(data)[0:4]
data + = somme de contrôle return encode(data) pk1 = binascii.unhexlify(« 0229b3e0919adc41a316aad4f41444d9bf3a9b639550f2aa735676ffff25ba3898 ») pk2 = binascii.unhexlify(« 02f15446771c5c585dd25d 8d62df5195b77799aa8eac2f2196c54b73ca05f72f27 ») pk3 = binascii.unhexlify(« 04ad90e5b6bc86b3ec7fac2c5fbda7423fc8ef0d58df594c773fa05e2c281b2bfe877677c66 8bd13603944e34f4818ee03cadd81a88542b8b4d5431264180e2c28 ») h1 = hachage160 (pk1) h2 = hachage160 (pk2 ) h3 = hash160(pk3) print(to_address(h3, b'\x00')) print(to_address(h1, b'\x00')) print(to_address(h2, b'\x00'))

(Fonction d'encodage Base58 de https://github.com/bitcoin-core/HWI/blob/master/hwilib/base58.py)

Comme vous pouvez le voir, cela n’effectue aucune compression ou décompression ponctuelle. Au lieu de cela, il prend la clé publique telle quelle et la code.