Bitcoin Forum
September 26, 2023, 01:45:17 AM *
News: Latest Bitcoin Core release: 25.0 [Torrent]
 
  Home Help Search Login Register More  
  Show Posts
Pages: [1] 2 »
1  Bitcoin / Armory / libbitcoin vulnerability and armory on: August 18, 2023, 09:13:45 AM
Are wallets created with Armory after 2016 actually affected by libbitcoin vulnerability ?

sounds like I ought to check if Armory's use of libbitcoin could be affected. I didn't create any new Armory wallets since the date (late 2016) of the libbitcoin-system pull request, but possibly others did. Armory previously used Crypto++, which I guess was subject to a little more scrutiny (guessing isn't good enough however, I feel compelled now to check)
2  Bitcoin / Armory / used addresses marked as unused on: January 17, 2020, 05:27:09 PM
I'm taking your advice

Quote
It is good practice to not reveal your wallet's private keys, regardless of the derivation scheme. Consider the wallet compromised if you did, and move the funds out.

and I'm moving my funds out from the old wallet into a new one.

So far I have moved some (non all) UTXO's from the old wallet to 3 addresses in the new wallet (with 3 different transactions)

There is a strange thing:

New Wallet: I clik on "Wallet Properties" and I get the correct balance but:

Used Addresses :
P2PKH : None
P2SH-P2PK : None
P2SH-P2WPKH : None

Change Addresses:
P2PKH : None
P2SH-P2PK : None
P2SH-P2WPKH : None

Unused Addresses:
P2PKH :
Address   Tx Count   Balance
1...            0              0.00
1....           0              x.xx
1.....          0              y.yy
1....           0              z.zzz
1....           0              0.00
1....           0              0.00
1....           0              0.00
.....        .....        ......
P2SH-P2PK : None
P2SH-P2WPKH : None


Any idea?

I'm using 0.96.5 on Ubuntu. The wallet is 'watching only'.

EDIT:

In the same window I see:

Version: 1.35
Addresses Used: 3
Security: Offline
Belongs to: You own this wallet
3  Bitcoin / Development & Technical Discussion / validation rules on: December 31, 2019, 02:13:48 PM
I was reading this page:

https://en.bitcoin.it/wiki/Protocol_documentation

in particular this sentence caught my attention:

Quote
The Bitcoin protocol is specified by the behavior of the reference client, not by this page. In particular, while this page is quite complete in describing the network protocol, it does not attempt to list all of the rules for block or transaction validity.

All the rules we know (21 million btc, ...) come from the first implementations of the Satoshi client? There is not a white paper for all the validation rules?

The Satoshi's paper lacks of many details.

4  Local / Discussioni avanzate e sviluppo / ECDSA parte 2: firma di un messaggio e di una transazione bitcoin on: December 31, 2018, 11:32:47 AM
Continuo il thread iniziato qui:

https://bitcointalk.org/index.php?topic=1339031.0


Vediamo come firmare un messaggio qualsiasi con la chiave privata di un indirizzo bitcoin.

Esempio pratico di firma di un messaggio e verifica utilizzando l'algoritmo ECDSA applicato alla curva secp256k1


Firma di un messaggio

Ricordo brevemente l'algoritmo di firma:

Let (r,s) be the signature, m the message, e = H(m) the message digest, G the curve generator, d the private key, P=d*G the public key.

ECDSA works this way:
1) pick a random nonce k (a private key you use once) in [1,n-1]
2) k -> k*G = Q(xq,yq)   then r = xq mod n (r is more or less like the x coordinate of Q)
3) s = k^-1 * (r*d + e)  mod n

----------------------------------------------------------------------------------------------------------------
Premessa tecnica:
1) utilizzo per iniziare python 2 in modalità interattiva, poi passeremo allo script
quindi
>>> prompt python
~$ prompt shell

2) python è in grado di gestire operazioni tra numeri molto grandi senza problemi, anche modulo n
per quanto riguarda invece il calcolo tra punti della curva è necessario avvalersi di una libreria, in questa prima parte ci avvaliamo di una libreria "mini_ecdsa" (non scritta da me) ad uso didattico, in seguito ne scriveremo una da zero
per scaricarla : git clone https://github.com/qubd/mini_ecdsa.git
per utilizzarla : quando si è entrati in modalità interattiva, execfile('mini_ecdsa.py') (con il percorso relativo corretto)

3) la parte più rognosa per me è stata la manipolazione delle stringhe e le varie codifiche, per usare correttamente sha256 e le varie conversioni tra ascii e altri formati binari bisogna importare 2 altre librerie, "hashlib" e "binascii"
-------------------------------------------------------------------------------------------------------------------
Dati iniziali:

MESSAGGIO DA FIRMARE
Code:
>>>import hashlib
>>>import binascii
>>>
>>>msg = 'Ciao oggi 31 dicembre sto provando a firmare un messaggio'
>>>
>>>msg_formattato = "\x18Bitcoin Signed Message:\n" + chr( len(msg) ) + msg
>>>
>>>e = hashlib.sha256(hashlib.sha256(msg_formattato).digest()).digest()
>>>print binascii.b2a_hex(e)
5ae332695b7d534336b1245b720a771cb4eeaefd3d53583aad108327de30a38c


PARAMETRI DELLA CURVA SECP256K1
Code:
>>>execfile('mini_ecdsa.py')
>>>
>>>p = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F  #caratteristica del campo
>>>n = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141  #ordine della curva

>>>C = CurveOverFp(0, 0, 7, p)
y^2 = x^3 + 7 over F_115792089237316195423570985008687907853269984665640564039457584007908834671663

>>>G = Point(0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798, 0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8) #generatore del gruppo dei punti della curva


GENERAZIONE CHIAVE PRIVATA - CHIAVE PUBBLICA - INDIRIZZO
Code:
~$ hexdump -n 32 -e '8/4 "%08X" 1 "\n"' /dev/urandom
D02E0EB2EF0CE08168FE746B58A91D485BE97E71D2E2061F7807248A739F68D2

>>>d = 0xd02e0eb2ef0ce08168fe746b58a91d485be97e71d2e2061f7807248a739f68d2 (la chiave privata generata mediante urandom)

>>>P = C.mult(G,d)   # P = d*G
>>> print P
(56648515016038393520262952982723707918005872252984079682254662011250519474519,34439720842813318822435587706376241065257505597204067160331538221043835853710)

>>>xp = 56648515016038393520262952982723707918005872252984079682254662011250519474519
>>>yp = 34439720842813318822435587706376241065257505597204067160331538221043835853710

>>> print hex(xp)
0x7d3dec5b3f7bda2eacaa48dfadee6922c741771463b60ce5586371842afe8157L

>>> print hex(yp)
0x4c2430f3c7fd57de7ede4e2723558e804f59c4930ac9023afa0c816fe5c5db8eL

>>>address_compressed = '1FWBBmKhoPu3f6EZPhA6QiqTKoyz7Gj5CC'


GENERAZIONE CHIAVE PRIVATA USA E GETTA - CHIAVE PUBBLICA
Code:
~$ hexdump -n 32 -e '8/4 "%08X" 1 "\n"' /dev/urandom
890E92FAEF7387295984ABE9D583EB269BBA942077F29B227C825788E13FE9BE

>>>k = 0x890e92faef7387295984abe9d583eb269bba942077f29b227c825788e13fe9be (chiave privata usa e getta)

>>> Q = C.mult(G,k)   # Q = k*G
>>> print Q
(84999791795797315190007927603153314605480098556488635859498606522553519770078,13375324783711542103436223255037217772249325984154197258846945690589726740778)

>>> xq = 84999791795797315190007927603153314605480098556488635859498606522553519770078

>>> print hex(xq)
0xbbec2d615c78aa43815c618648897518ca36904e2bcd1b7950da9819c53709de


Riassumendo i dati fondamentali:

Code:
e = 0x5ae332695b7d534336b1245b720a771cb4eeaefd3d53583aad108327de30a38c  (doppio hash del messaggio)

d = 0xd02e0eb2ef0ce08168fe746b58a91d485be97e71d2e2061f7807248a739f68d2  (chiave privata)
P = (0x7d3dec5b3f7bda2eacaa48dfadee6922c741771463b60ce5586371842afe8157, 0x4c2430f3c7fd57de7ede4e2723558e804f59c4930ac9023afa0c816fe5c5db8e)

k = 0x890e92faef7387295984abe9d583eb269bba942077f29b227c825788e13fe9be (chiave privata usa e getta)
Q = (0xbbec2d615c78aa43815c618648897518ca36904e2bcd1b7950da9819c53709de, 0x1d922a618d45e1ba97a4cc0bb53598b73ad408c9cb728d302b2987dab2cf912a)

La firma di questo messaggio consiste in una coppia di valori 'r' e 's', entrambi devono essere compresi tra 1 e n-1.

r è uguale a xq mod n, e poichè in questo caso xq < n, i due valori coincidono:
Code:
r = 0xbbec2d615c78aa43815c618648897518ca36904e2bcd1b7950da9819c53709de

s è uguale a  k^-1 * (r*d + e)  mod n
Code:
>>>k_inv = pow(k, n-2, n)   #qui si sfrutta il teorema di Fermat per il quale se n è primo allora a^n = a -->  a^(n-1) = 1 --> a^(n-2) = 1/a  mod n
>>>
>>>s = k_inv * (r * d + e)  % n
>>>print hex(s)
0x5c40b6ed461d4c1856595432f126050fde4eefd7ab6135bbc2edaf536abe237dL
piccolo teorema di Fermat


Abbiamo ottenuto quindi la firma:

r =  0xbbec2d615c78aa43815c618648897518ca36904e2bcd1b7950da9819c53709de
s =  0x5c40b6ed461d4c1856595432f126050fde4eefd7ab6135bbc2edaf536abe237d


Questi valori vanno codificati in base64:

Code:
>>>r_string = hex(r)[2:-1]  #eliminiamo 0x iniziale e L (long) finale
>>>s_string = hex(r)[2:-1]
>>>
>>>print r_string  #di per sè bisognerebbe anche controllare che il numero di caratteri sia sempre 64
bbec2d615c78aa43815c618648897518ca36904e2bcd1b7950da9819c53709de
>>>
>>> s_string = hex(s)[2:-1]
>>> print s_string
5c40b6ed461d4c1856595432f126050fde4eefd7ab6135bbc2edaf536abe237d
>>>
>>>i=0
#questo parametro i è 0 se xq < n e yq è pari, è 1 se xq < n e e yq è dispari, è 2 se xq >= n e yq è pari, è 3 se xq >= n e yq è dispari
#l'unico carattere da premettere a r e s nella firma finale è chr(27+i) se si sta usando un address non compresso,
#chr(31+i) se invece si sta usando un address compresso
>>>sig = binascii.b2a_base64( chr(31+i) + binascii.a2b_hex(r_string) + binascii.a2b_hex(s_string) )
>>> print sig
H7vsLWFceKpDgVxhhkiJdRjKNpBOK80beVDamBnFNwneXEC27UYdTBhWWVQy8SYFD95O79erYTW7wu2vU2q+I30=


Verifica


Ottenuta la firma codificata in base 64

H7vsLWFceKpDgVxhhkiJdRjKNpBOK80beVDamBnFNwneXEC27UYdTBhWWVQy8SYFD95O79erYTW7wu2 vU2q+I30=

se vogliamo verificare online la correttezza di questo messaggio possiamo farlo così:

Code:
-----BEGIN BITCOIN SIGNED MESSAGE-----
Ciao oggi 31 dicembre sto provando a firmare un messaggio
-----BEGIN SIGNATURE-----
1FWBBmKhoPu3f6EZPhA6QiqTKoyz7Gj5CC
H7vsLWFceKpDgVxhhkiJdRjKNpBOK80beVDamBnFNwneXEC27UYdTBhWWVQy8SYFD95O79erYTW7wu2vU2q+I30=
-----END BITCOIN SIGNED MESSAGE-----

Effettivamente risulta verificato!

Se non siamo soddisfatti da questo tipo di verifica esterna e ne vogliamo realizzare una interna possiamo procedere così:

innanzitutto ricordiamo la teoria:

poichè s = k^-1 * (r*d + e) mod n  si ha che

k = s^-1*r*d + s^-1*e
k*G = s^-1*r*d*G + s^-1*e*G

Q = s^-1*r*P + s^-1*e*G  (poichè k*G = Q e d*G = P, P è la chiave pubblica)

di solito questa è la verifica che si fa quando si invia la chiave pubblica P.

Quando si invia invece l'address come nel nostro caso si ricava invece autonomamente la chiave pubblica dalla firma e dal messaggio, supponendo valida la relazione precedente si ha che:

s*Q = r*P + e*G

da cui si ottiene che P = r^-1 * (s*Q - e*G)

quindi una volta ottenuto la chiave pubblica P possiamo controllare che l'address generato sia effettivamente quello proposto (ovvero la chiave pubblica sia quella giusta)

Code:
>>> A = C.mult(Q,s)  #s*Q
>>> B = C.mult(G,n-e)  #-e*G
>>> R = C.add(A,B) #s*Q - e*G
>>> P = C.mult(R,pow(r,n-2,n)) #r^-1 * (s*Q - e*G)
>>> print P
(56648515016038393520262952982723707918005872252984079682254662011250519474519,34439720842813318822435587706376241065257505597204067160331538221043835853710)

effettivamente abbiamo ritrovato la chiave pubblica di partenza, se generiamo l'address compresso da questa chiave pubblica si ottiene il nostro indirizzo di partenza.


SCRIPT PYTHON
(funziona solo con python2 e mancano diversi controlli sulla lunghezza delle stringhe ma più avanti
c'è una versione più completa che funziona anche con python3)

Riassumendo l'intero discorso, condensiamo tutto in uno script sign_msg.py :

Code:
#!/usr/bin/env python

execfile('mini_ecdsa.py')  #https://github.com/qubd/mini_ecdsa
import hashlib, binascii
import subprocess #se si vuole generare k casualmente con /dev/urandom

#DATI DA IMPOSTARE MANUALMENTE
msg = 'Ciao oggi 31 dicembre sto provando a firmare un messaggio'  #inserire qui il messaggio scelto

d = 0xd02e0eb2ef0ce08168fe746b58a91d485be97e71d2e2061f7807248a739f68d2 #inserire qui la propria chiave privata

address = '1FWBBmKhoPu3f6EZPhA6QiqTKoyz7Gj5CC'
compressed = 1 #se e' compresso segnare 1, altrimenti 0
########################################################################################################################

#DATI CURVA SECP256K1
p = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F  #caratteristica del campo
n = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141  #ordine della curva

print
C = CurveOverFp(0, 0, 7, p)

G = Point(0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798, 0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8) #generatore del gruppo dei punti della curva

#CHIAVE PUBBLICA
P = C.mult(G,d)   # P = d*G (P serve solo per la verifica, non per la firma in se')


#CHIAVE PRIVATA USA E GETTA E RELATIVA CHIAVE PUBBLICA (qui si setta la prima parte della firma, r)
#k deve essere diverso da 0 e minore di n, qui diamo per scontato che sia cosi'
#k = 0x890e92faef7387295984abe9d583eb269bba942077f29b227c825788e13fe9be
k = subprocess.Popen(['hexdump', '-n', '32', '-e','8/4 "%08X"', '/dev/urandom'], stdout=subprocess.PIPE).communicate()[0]
k = int(k,16)  #trasforma una stringa in un numero, se si vuole si puo' inserire qui a mano un altro valore


Q = C.mult(G,k)   # Q = k*G
if (Q.x < n):
r = Q.x
i = 0;
else:
r = Q.x - n;
i = 2;
if (Q.y%2 == 1):
i = i+1;
if (compressed == 0):
i = i + 27
else:
i = i + 31


#FORMATTAZIONE MESSAGGIO
msg_formattato = "\x18Bitcoin Signed Message:\n" + chr( len(msg) ) + msg
e = hashlib.sha256(hashlib.sha256(msg_formattato).digest()).digest()
e = int(binascii.b2a_hex(e),16)  #trasforma una stringa di byte in un numero


#FIRMA DEL MESSAGGIO
#(firmare vuol dire trovare a partire da r casuale un valore s che dimostri di possedere la chiave privata d;
#il valore s dipende ovviamente sia dalla chiave privata d che dal messaggio e)
k_inv = pow(k, n-2, n)
s = k_inv * (r * d + e) % n


#CODIFICA DELLA FIRMA IN BASE 64
#per fare le cose seriamente qui bisognerebbe controllare che sia r che s siano formati da 64 cifre esadecimali,
#in caso contrario bisognerebbe aggiungere degli zeri all'inizio del numero;
#qui questo controllo NON viene fatto
sig = binascii.b2a_base64( chr(i) + binascii.a2b_hex(hex(r)[2:-1]) + binascii.a2b_hex(hex(s)[2:-1]) )
sig = sig[:-1]

print
print '-----BEGIN BITCOIN SIGNED MESSAGE-----'
print msg
print '-----BEGIN SIGNATURE-----'
print address
print sig
print '-----END BITCOIN SIGNED MESSAGE-----'


#VERIFICA ONLINE
print
print 'Verifica qui --> '
p1 = subprocess.Popen(["echo", msg], stdout=subprocess.PIPE)
msg2 = subprocess.Popen(["sed", "s/ /%20/g"], stdin=p1.stdout, stdout=subprocess.PIPE).communicate()[0]
p1.stdout.close()
print 'http://brainwalletx.github.io/#verify?vrAddr=' + address + '&vrMsg=' + msg2[:-1] + '&vrSig=' + sig
print

Proviamolo:

Code:
~/src2/mini_ecdsa$ python sign_msg.py
y^2 = x^3 + 7 over F_115792089237316195423570985008687907853269984665640564039457584007908834671663

-----BEGIN BITCOIN SIGNED MESSAGE-----
Ciao oggi 31 dicembre sto provando a firmare un messaggio
-----BEGIN SIGNATURE-----
1FWBBmKhoPu3f6EZPhA6QiqTKoyz7Gj5CC
H7vsLWFceKpDgVxhhkiJdRjKNpBOK80beVDamBnFNwneXEC27UYdTBhWWVQy8SYFD95O79erYTW7wu2vU2q+I30=
-----END BITCOIN SIGNED MESSAGE-----

Verifica qui -->
http://brainwalletx.github.io/#verify?vrAddr=1FWBBmKhoPu3f6EZPhA6QiqTKoyz7Gj5CC&vrMsg=Ciao%20oggi%2031%20dicembre%20sto%20provando%20a%20firmare%20un%20messaggio&vrSig=H7vsLWFceKpDgVxhhkiJdRjKNpBOK80beVDamBnFNwneXEC27UYdTBhWWVQy8SYFD95O79erYTW7wu2vU2q+I30=
5  Local / Discussioni avanzate e sviluppo / Decentralizzazione mining funzionamento economico sistema bitcoin on: December 20, 2018, 09:55:44 PM
Apro questo thread perchè si sta sviluppando una discussione interessante ma off topic nel thread sul consumo energetico.

La discussione ha preso una strada diversa dal tema energetico
da questo post https://bitcointalk.org/index.php?topic=2957043.msg48749013#msg48749013
fino a questo https://bitcointalk.org/index.php?topic=2957043.msg48789905#msg48789905

Direi quindi di continuare qui per non inquinare ulteriormente l'altro thread.

Per rispondere a duesoldi e a Plutosky:

1) certo che non mi farebbe affatto piacere che l'attività di mining si concentrasse nelle mani di una sola persona;

non è questione però del fatto che gli utenti si disinteressano del mining delegando questa attività ad altri, la questione è che non vedo (per ora) come sia possibile costruire un sistema aperto nel quale tutti possano scrivere in un registro pubblico liberamente (cioè senza sforzo) senza che questo automaticamente diventi un enorme problema di sicurezza. Accessibilità a chiunque senza difficoltà non fa rima con sicurezza.

Il Proof of Work è il metodo migliore trovato finora per garantire alla comunità che chi scrive nella blockchain (nota bene: solo uno alla volta può scrivere un blocco!) lo faccia solo dopo aver dato ampia dimostrazione di non avere altro interesse che quello di far funzionare correttamente la rete.

Il momento della scrittura di un blocco e quindi dell'aggiornamento della catena determina potenzialmente più versioni della blockchain e ci vuole un qualche criterio per passare dalle molte possibili versioni a una sola; come fa questo passaggio a essere gestito in modo efficiente (anche dal punto di vista della sicurezza) da molti?

Ribadisco che l'atto di scrivere un blocco costituisce di per sè un momento di inevitabile accentramento (almeno momentaneo), non si può scrivere un blocco in due (anche se si può minare in molti attraverso le pool). Purtroppo non vi è alcun modo che io sappia di contare il numero di persone che realmente sostengono un blocco o meno, si può misurare invece solo l'HP che supporta quel dato blocco.

L'HP (o meglio la difficulty) è l'unico dato certo sul quale si può costruire un consenso che converga su un'unica catena. E l'HP ha a che fare con la capacità dei miner, c'è poco da fare, non con la democrazia. Altri sistemi come il PoS sono peggiori.


2) riguardo al discorso fungibilità è sicuramente una questione aperta e potenzialmente limitante lo sviluppo di bitcoin.


A ben vedere nel primo caso il problema nasce dal fatto che il sistema non può associare agli indirizzi in modo univoco un'identità, se così fosse avremmo risolto il problema della decentralizzazione del mining perchè al posto della proof of work si potrebbe far votare agli utenti ogni blocco in modo da essere sicuri che la maggioranza effettiva degli utenti abbia sempre il controllo della scrittura dei blocchi.

Nel secondo caso il problema è quasi l'opposto, comunque la blockchain è pubblica ed è possibile ricostruire la storia di quasi ogni utxo, e appena vi è un contatto con il mondo esterno alla blockchain si può risalire a un'identità e quindi potenzialmente censurare delle transazioni.
6  Local / Italiano (Italian) / Immagini animazioni simulazioni per capire meglio on: November 07, 2018, 01:13:40 PM
Le immagini e le animazioni spesso aiutano molto a comprendere il funzionamento di meccanismi altrimenti complessi da comprendere solo da un testo scritto.

Ispirato anche da questo thread https://bitcointalk.org/index.php?topic=5063889.0 in sezione internazionale, provo a raccogliere in questo post del materiale che possa risultare efficace per comprendere meglio i meccanismi di bitcoin.


https://www.youtube.com/watch?v=bBC-nXj3Ng4
miglior video che ho trovato su che cos'è bitcoin e come funziona

https://www.youtube.com/watch?v=S9JGmA5_unY&t=20s
quanto è sicura la cifratura a 256 bit


http://www.yogh.io/#block:last
illustra bene come è costruito un blocco. C'è anche un simulatore di mining.
Mi sembra fatto bene, le informazioni in hex sono suddivise per colori e passandoci sopra con il mouse si vede ogni campo a cosa serve.


https://andersbrownworth.com/blockchain/blockchain
illustra funzionamento dei blocchi e della blockchain



Se avete anche voi qualcosa di interessante da segnalare, magari lo aggiungo. Non sto cercando delle guide, ma modi "visivi" di illustrare il funzionamento di bitcoin. Cerco materiale di alta qualità didattica, non video che sono stati realizzati con mezz'ora di lavoro alle spalle.
7  Local / Off-Topic (Italiano) / sito web on: October 11, 2018, 11:57:12 AM
Sto pensando di mettere su una pagina web tipo questa http://gobittest.appspot.com/Address .

L'idea sarebbe però quella di far girare sul server qualche programma in C che ho scritto, ed utilizzare i campi della pagina web semplicemente come input e output del programma.

Qualche consiglio su come iniziare?  Conviene installare un server LAMP? O basta meno?
8  Local / Discussioni avanzate e sviluppo / ricavare la chiave privata dalla chiave pubblica in casi particolari on: October 03, 2018, 03:42:31 PM
Come tutti ben sapete non è possibile ricavare in tempi umani da una chiave pubblica la sua chiave privata.

L'associazione chiave pubblica - chiave privata appare del tutto casuale se vista dal punto di vista della chiave pubblica, e quindi l'unico modo per ricavare la chiave privata sembrerebbe quello di provare tutte le chiavi private da 1 in poi finchè non si ottiene quella corretta. Poichè nella curva ellittica usata da bitcoin quel numero è dell'ordine di 2^256, questo è anche l'ordine di grandezza dei tentativi necessari con un attacco brute force.

Esistono però algoritmi che migliorano la situazione, essi permettono infatti di ricavare la chiave privata in 2^128 step invece che in 2^256. Per questo si dice di solito che la sicurezza di bitcoin è quantificabile in 128 bit. Alcuni di questi algoritmi (Pollard Rho) si basano sul paradosso dei compleanni; questo paradosso (paradosso solo in apparenza) mette insieme i seguenti fatti:

1) utilizzando tutte le 2^256 chiavi pubbliche, si possono costruire in tutto 2^512 coppie distinte di chiavi pubbliche
2) tra quelle 2^512 coppie ci sono 2^256 coppie formate da 2 chiavi pubbliche identiche tra loro

Dal punto 1) e dal punto 2) si evince come in media ci sia 1 coppia di chiavi pubbliche identiche tra loro ogni 2^256 coppie di chiavi (2^256/2^512 = 1/2^256).
Ora osserviamo che

3) sono sufficienti 2^128 chiavi pubbliche distinte per costruire (all'incirca) 2^256 coppie distinte di chiavi pubbliche

Il risultato finale è che se genero 2^128 chiavi pubbliche, ho di fatto anche generato 2^256 coppie di chiavi, e in media ho ottenuto 1 coppia di chiavi identiche, cioè ho generato almeno 2 volte la stessa chiave.

Sfruttando questo fatto e una opportuna "random walk" simulata, si riesce in soli 2^128 step a generare 2 volte una stessa chiave pubblica, e questa particolare collisione permette di ricavare la chiave privata che si stava cercando.

Altri algoritmi, come "Baby Step Giant Step" si basano invece solo sul fatto che per generare 2^256 chiavi pubbliche basta calcolare solo 2 liste di 2^128 chiavi e poi confrontarle (qui si utilizzano le proprietà algebriche della curva per cui ogni chiave P=d*G si può decomporre in P  = P1+P2.), per i dettagli vedere http://andrea.corbellini.name/2015/06/08/elliptic-curve-cryptography-breaking-security-and-a-comparison-with-rsa/

Utilizzando quest'ultimo approccio (che non è di natura probabilistica a differenza di Pollard Rho) è possibile ricavare da una chiave pubblica la chiave privata sempre in 2^128 step. Il vantaggio di questo metodo è che è possibile fare una ricerca anche solo su un sottospazio di tutte le chiavi pubbliche possibili, a patto ovviamente di avere delle informazioni approssimative riguardo la chiave privata (cioè se si sa già dove si trova più o meno la chiave privata).

Nei mesi scorsi ho scritto un picccolo programma in C (modificandone uno trovato in rete) che mi permette di ricavare la chiave privata in pochissimo tempo se si conosce la posizione della chiave privata all'interno di un range di valori dell'ordine di 2^60 - 2^70.

In pratica, per fare un esempio, se una persona sceglie una chiave privata tra 1 e 2^70 (oppure tra x  e  x + 2^70) e fornisce la chiave pubblica corrispondente, il programma riesce a ricavare la chiave privata corretta. Il programma deve conoscere però l'intervallo dove cercare.

Ovviamente 2^70 è una piccolissima frazione di 2^256, lo so che non ho scoperto nulla, ma è molto interessante verificare che, mentre per generare anche solo  2^60 chiavi pubbliche sarebbero necessari molti anni anche con la scheda video più potente, basta invece una semplice cpu per ricavare in pochi minuti la chiave cercata.
9  Local / Off-Topic (Italiano) / dimostrata la congettura di Riemann ? on: September 23, 2018, 05:52:20 AM
Pare che il famoso matematico Atiyah (già vincitore della medaglia Fields e del premio Abel), ormai sulla soglia dei 90 anni, sia riuscito a dimostrare la celebre congettura di Riemann:

http://www.newscientist.com/article/2180406-famed-mathematician-claims-proof-of-160-year-old-riemann-hypothesis/

https://m.youtube.com/watch?v=oV6TTXJgMt0

https://www.crypto-news.in/news/riemann-hypothesis-may-proved-septmeber-24-impact-crypto-may-huge/


Domani 24 settembre si terrà la presentazione della sua dimostrazione. Sarebbe un enorme risultato per la matematica e non solo.

https://it.quora.com/Il-matematico-britannico-Michael-Atiyah-dice-di-aver-dimostrato-lipotesi-di-Riemann-Che-ne-pensi
10  Bitcoin / Development & Technical Discussion / How to use properly secp256k1 library on: April 18, 2017, 02:10:40 PM
Hi,
I want to exploit the speed of the field operations in libsecp256k1 to make faster operations modulo p (p=0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F).

I wrote a simple program to compute a multiplication of two 256-bit numbers. My code performs 100M times the mult: Gx*Gy mod p.

There are 2 versions: A (gmp library), B (secp256k1 library)

The problem is that at the moment I can get better results with gmp library than libsecp256k1 (at least +10%):

Program A (gmp library):  

Code:
---@ubuntu:~/src/var/mul$ time ./a.out

Result: fd3dc529c6eb60fb 9d166034cf3c1a5a 72324aa9dfd3428a 56d7e1ce0179fd9b

real 0m5.399s
user 0m5.324s
sys 0m0.012s


Program B (secp256k1 library):
Code:
---@ubuntu:~/src/var/mul$ time ./a.out

Result: fd 3d c5 29 c6 eb 60 fb 9d 16 60 34 cf 3c 1a 5a 72 32 4a a9 df d3 42 8a 56 d7 e1 ce 1 79 fd 9b

real 0m6.076s
user 0m5.988s
sys 0m0.004s


Shouldn't it be the other way around?  Is there something wrong in my code?




Program A (gmp library) :
Code:
#include <stdio.h>
#include <stdlib.h>
#include <gmp.h>

inline void red(unsigned long int* a) {

...> performs "a mod p"

}

int main(){

unsigned long int i;
unsigned long int a[8];

unsigned long int Gx[4] = {0x59f2815b16f81798, 0x029bfcdb2dce28d9, 0x55a06295ce870b07, 0x79be667ef9dcbbac};
unsigned long int Gy[4] = {0x9c47d08ffb10d4b8, 0xfd17b448a6855419, 0x5da4fbfc0e1108a8, 0x483ada7726a3c465};


for(i=0;i<100000000;i++) {

mpn_mul_n(a, Gx, Gy, 4); // #1M
red(a);
}

printf("Result: %lx %lx %lx %lx\n", a[3], a[2], a[1], a[0]);

return 0;
}

Program B (libsecp256k1 library) :
Code:
//Compile with:                                                    
//gcc -O2 -I secp256k1/src/ -I secp256k1/  mul.c   -lgmp

#include <stdio.h>
#include <stdlib.h>
#include "libsecp256k1-config.h"
#include "include/secp256k1.h"
#include "secp256k1.c"

int main(){


        const unsigned char Gx[32]={0x79,0xBE,0x66,0x7E,0xF9,0xDC,0xBB,0xAC,0x55,0xA0,0x62,0x95,0xCE,//
                            0x87,0x0B,0x07,0x02,0x9B,0xFC,0xDB,0x2D,0xCE,0x28,0xD9,0x59,0xF2, //
                                             0x81,0x5B,0x16,0xF8,0x17,0x98};

        const unsigned char Gy[32]={0x48,0x3A,0xDA,0x77,0x26,0xA3,0xC4,0x65,0x5D,0xA4,//
                      0xFB,0xFC,0x0E,0x11,0x08,0xA8,0xFD,0x17,0xB4,//
                                               0x48,0xA6,0x85,0x54,0x19,0x9C,0x47,0xD0,0x8F,0xFB,0x10,0xD4,0xB8};


       secp256k1_fe a,b,r;
       unsigned char c[32];

       secp256k1_fe_set_b32(&a, Gx);
       secp256k1_fe_set_b32(&b, Gy);


       for(i=0;i<100000000;i++) { //100 000 000

    secp256k1_fe_mul(&r, &a, &b);
    //secp256k1_fe_normalize_var(&r);


       }

       secp256k1_fe_get_b32(c, &r);

       printf("Result: %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x\n", //
       c[0],c[1],c[2],c[3],c[4],c[5],c[6],c[7],c[8],c[9],c[10],c[11],c[12],//
       c[13],c[14],c[15],c[16],c[17],c[18],c[19],c[20],c[21],c[22],c[23],c[24],//
       c[25],c[26],c[27],c[28],c[29],c[30],c[31]);

       return 0;
}

11  Bitcoin / Development & Technical Discussion / how many addresses from a single private key on: April 14, 2017, 09:11:55 AM
I have a doubt about the use of:

Quote
Pay to Pubkey Hash address (P2PKH):  17VZNX1SN5NtKa8UQFxwQbFeFc3iqRYhem

Pay to script hash address (P2SH) : 3EktnHQD7RiAE6uzMj2ZifT9YgRrkSgzQX  

I know that the starting "1" and "3" are added after sha256 + ripemd160, to get "1" I have to add a "00" prefix and to get "3" a "05" prefix before the Base58 encoding.


So, let's imagine I have a private key k, then I compute the public key kG : (x,y), then I perform
 sha256(ripemd160(x,y)). Now I have a 160bit string s.

My question is: if i made a Base58 encoding of "05+s" instead of "00+s" and I got the address  3EktnHQD7RiAE6uzMj2ZifT9YgRrkSgzQX, I could spend the bitcoin of that address?

In other words: from a single private key k, how many different addresses can we get?

Surely there are at least 2 pubkey hash addresses (compressed and uncompressed public key), but in theory is it possible to get a pay to script address too from a single private key?

12  Bitcoin / Development & Technical Discussion / secp256k1 library and Intel cpu on: January 05, 2017, 11:37:48 PM
Does secp256k1 library exploit the new instructions on Intel cpu for large integer arithmetic?

https://software.intel.com/en-us/blogs/2014/06/11/optimizing-big-data-processing-with-haswell-256-bit-integer-simd-instructions

http://www.intel.com/content/dam/www/public/us/en/documents/white-papers/ia-large-integer-arithmetic-paper.pdf

13  Bitcoin / Development & Technical Discussion / block reward that can never be spent on: December 27, 2016, 11:49:36 AM
This article claims that the block immediately following every halving can never be spent.
(I knew that only genesis block reward cannot be spent)

Is that true?
14  Bitcoin / Development & Technical Discussion / Is the output of hash function evenly distributed? on: November 29, 2016, 03:45:05 PM
Hash function (sha256) is used to mine and identify a block. The digest is a 256 bit string.

We don't know whether this function is surjective or not (whether there is an input-block header for each output-digest).

But we assume that the output of the hash function is evenly distributed (so we can calculate target and difficulty for proof-of-work algorithm).

How can we know for sure the output is evenly distributed?
15  Local / Discussioni avanzate e sviluppo / API per ricavare statistiche da una blockchain "esterna" on: November 22, 2016, 07:40:58 PM
Dopo aver calcolato la distribuzione teorica dei tempi di produzione dei blocchi :  
https://bitcointalk.org/index.php?topic=1665779.msg16858506#msg16858506 mi sono un po' appassionato alla cosa e stavo cercando di verificare come nella storia della blockchain siano andate effettivamente le cose.

Cosa voglio fare? In sostanza aggiornare i dati di questo post --> https://www.reddit.com/r/Bitcoin/comments/1vkp1x/what_is_the_longest_time_between_blocks_in_the/ di due anni fa, dove si dà questa tabella:

21445-21446     23574
74637-74638     24676
19725-19726     24907
15047-15048     25376
19564-19565     25996
21388-21389     28124
20348-20349     29325
20363-20364     30013
20431-20432     30425
16489-16490     30682
27-28                 30884
19721-19722     37536
21437-21438     38219
19723-19724     47127
20188-20189     60203
16591-16592     73782
14-15                 87157
16563-16564     90390
15323-15324     90532
0-1                    463160

A sinistra il numero dei blocchi, nella colonna di destra l'intervallo di tempo tra le apparizioni di due blocchi consecutivi (in secondi).
Ovviamente i dati riguardanti blocchi così vecchi sono poco significativi, nei primi tempi non c'era quasi nessuno che minava, ecc.

Il più delle volte il retarget ha aumentato la difficoltà poichè la capacità computazionale della rete è stata quasi sempre tale da permettere di minare un blocco in media in meno di 10 minuti.  Se si va qui -> http://www.wolframalpha.com/input/?i=seconds+between+January+3,+2009+and+November+21,+2016 si può notare che la blockchain ha una vita (in secondi) di 2.487x10^8s, mentre ha una vita in blocchi di 439943. Quindi il valor medio reale finora è 248,7 milioni di secondi / 439944 = 565 secondi, tempo medio reale per minare un blocco finora, ovvero ben 35 secondi di media in meno rispetto al valor medio prefissato.

Ora che dati guardare? Il timestamp dei blocchi non è per niente affidabile, i miner possono scriverci quello che vogliono, quindi il meglio che si possa fare è affidarsi a un servizio esterno che sia sempre o quasi up e che registri in modo autonomo il tempo di arrivo di ogni blocco  (non esiste un tempo univoco in un sistema decentralizzato - per questo esiste la blockchain - ma almeno l'intervallo di tempo tra due arrivi in un punto preciso della rete ha più senso del timestamp dell'header dei blocchi).

Ho scritto allora un piccolo script in python che funziona appoggiandosi alla API di blockcypher --> https://www.blockcypher.com/dev/bitcoin/

Ho iniziato a scansionare i blocchi dal numero  336257, perchè è da quel momento che verosimilmente blockcypher ha iniziato a registrare il tempo effettivo di arrivo (il numero 336257 corrisponde al 28 dicembre 2014, ore 6.06.50, prima di quella data ci sono solo i classici valori dell'header del blocco).

Al momento ho scansionato 26000 blocchi (6 mesi circa, fino al 22 giugno 2015), questi sono i 20 più lenti:

Quote
blocco  secondi
338698  6493   -->  corrisponde a 1 ora e 48 minuti e 13 secondi
346929  5300           --> corrisponde a 1 ora e 28 minuti e 20 secondi
355724  5081           --> corrisponde a 1 ora e 24 minuti e 41  secondi
360879  4804
343509  4796
345547  4748
357081  4725
336778  4640
340450  4588
359663  4420
352793  4407
358362  4404
357685  4400
336525  4371
342012  4290
343173  4271
351642  4262
352180  4245
340200  4179
350125  4127     --> corrisponde a 1 ora e 08 minuti e 47 secondi

In particolare  solo lo 0,19% ha superato l'ora, contro lo 0,25% previsto dalla teoria.
     
    L' 1,585% ha superato i 40 minuti, contro il 1,83% previsto dalla teoria.

Ricordo infatti che la distribuzione teorica era:

P(di minare un blocco entro t secondi) = 1 - e^(-1/600*t); facendo due calcoli si ottiene:

(minuti)   secondi            probabilità
   -              1                 0,001665279
   -             10                0,016528546
   -             20                0,0327839
   -             30                0,048770575
   1            60                0,095162582
   2            120              0,181269247
   3            180              0,259181779
   4            240              0,329679954
   5            300              0,39346934
   6            360              0,451188364
   7            420              0,503414696
   8            480              0,550671036
   9            540              0,59343034
  10           600              0,632120559
  20           1200            0,864664717
  40           2400            0,981684361
  60          3600            0,997521248
 120          7200            0,999993856




Perchè ne ho scansionati così pochi?
Il problema è che c'è un limite di 200 richieste/ora e 2000 richieste/giorno al loro server  Angry

Per poter fare la scansione degli oltre 100k blocchi che mi mancano ad arrivare a oggi (gli ultimi 2 anni) mi ci vorrebbero almeno 50 giorni! Se però pago un bel po' di soldi mi aumentano il limite, peccato, mi sarebbe piaciuto verificare la distribuzione dei tempi.

Qualcuno conosce delle API fornite da qualche servizio affidabile che permettano quindi un'interrogazione "esterna" (ovviamente in questo caso non ha senso lavorare con la mia personale blockchain in locale, in quanto non vi sono presenti i dati che mi interessano) di queste dimensioni senza far pagare nulla o quasi nulla?

16  Local / Discussioni avanzate e sviluppo / bitcoin e numeri grandi on: October 31, 2016, 06:34:17 PM
Vorrei fare qualche considerazione sui numeri grandi relativi al bitcoin. Una delle cose che sconcerta maggiormente chi si avvicina a questo mondo e cerca di capirlo è il fatto di dover ragionare con numeri il cui ordine di grandezza è assolutamente fuori dall'ordinario. Lavoriamo qui nel "finitamente" grande.


La dimensione dello spazio delle chiavi possibili (2^256) e la potenza (in hash/s) necessaria a minare i blocchi sono solo due esempi estremamente significativi di cosa significa lavorare con grandezze che sembrano infinite (ma non lo sono) e di probabilità che vengono approssimate a 0 (ma non sono 0). Non è affatto scontata la capacità di stimare in modo adeguato queste quantità (e di conseguenza capire realmente di che tipo di sicurezza si parla in relazione alle transazioni e alla blockchain, per esempio);ancor più difficile diventa quindi fare discorsi quantitativi ragionevoli legati alle prospettive di crescita della rete e del valore del bitcoin (non parlerò qui del prezzo del bitcoin, ci sono già troppi thread al riguardo).  


EDIT: facciamo un esempio pratico: in questo articolo http://motherboard.vice.com/read/bitcoin-could-consume-as-much-electricity-as-denmark-by-2020 si prevede, nello scenario più pessimistico, che il consumo elettrico mondiale del mining diventerà nel 2020 equivalente a quello di una piccola nazione come la Danimarca  Shocked


Proviamo allora a fare un semplice collegamento tra potenza e numero di chiavi, giusto per chiarire il concetto.

Al momento la potenza computazionale complessiva di tutti i miner del mondo è di circa 2 exahash/sec, cioè vengono effettuate circa 2*(10^18) operazioni al secondo (in sostanza hash dei blocchi per minarli), ovvero 2^61 operazioni al secondo.

Supponendo per semplicità che queste operazioni siano equiparabili (non lo sono) a quelle necessarie per craccare una chiave privata, in questo momento una chiave di 61 bit potrebbe essere individuata in 1 secondo con un attacco mondiale brute force, mentre per una chiave di 80 bit sarebbero necessari 2^19 secondi, ovvero soli 6 giorni.

Per una chiave di 128 bit invece bisognerebbe impiegare 2^48 * 6 giorni, ovvero 4600 miliardi di anni.

Se la potenza computazionale dovesse però continuare a raddoppiare ogni anno (cosa alquanto improbabile), ogni anno il tempo necessario per craccare una chiave dimezzerebbe.
Tra 20 anni ci vorrebbero 2^28 * 6 giorni = 4,4 milioni di anni per craccare la chiave di 128 bit  e solo mezzo secondo per craccare una chiave da 80 bit.
Tra 48 anni teoricamente sarebbero necessari soli 6 giorni per craccare una chiave di 128 bit.

A parte le ovvie considerazioni sull'impossibilità di una crescita esponenziale sostenuta per così tanto tempo, c'è un limite teorico alla crescita della potenza computazionale della rete? Sì.
E' vero che all'aumentare della potenza complessiva aumenta anche la sicurezza? Solo fino a un certo punto.

Esiste una difficoltà massima prevista dall'algoritmo che fa il retarget della difficoltà ogni 2016 blocchi:

Quote
 difficulty = hashrate / (2^256 / max_target / intended_time_per_block)
             = hashrate / (2^256 / (2^208*65535) / 600)
             = hashrate / (2^48 / 65535 / 600)
             = hashrate / 7158388.055

Infatti il target minimo (cioè quello che si raggiunge con la difficoltà massima, vedi https://en.bitcoin.it/wiki/Target) che si può avere è la stringa di 256 bit **:

                                                    00000.....001

(cioè per minare un blocco bisogna modificarlo in modo che il suo hash non superi una stringa di tutti 0 più un 1 finale).
Se vogliamo che in media la rete raggiunga questo risultato 1 volta ogni 10 minuti, la potenza complessiva dovrebbe essere  di 2^256/10 minuti, ovvero circa 2^247 hash/secondo. In pratica si dovrebbe raggiungere una potenza complessiva che permetta di fare un brute force attack di una chiave di 256 bit in 10 minuti, ma a quel punto il sistema sarebbe già divenuto insicuro da un pezzo!


**Per curiosità aggiungo che non si può ottenere come hash di un blocco una stringa di 256 zeri poichè questo hash è riservato per identificare il blocco (virtuale) che precede il blocco 0 --> https://blockchain.info/block/000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f


Questo mio ragionamento vuole solo evidenziare come al momento lavoriamo con un sistema dagli ampi margini di crescita, ma che lo spazio di manovra apparentemente infinito non lo è affatto, ci sono dei limiti intrinseci che apparentemente sembrano non esserci perchè troppo lontani al momento ma in realtà di cui bisogna tener conto per poter fare dei ragionamenti che abbiano una base.  


17  Local / Discussioni avanzate e sviluppo / Approximate Bitcoin mining on: March 23, 2016, 03:12:45 PM
Segnalo questo interessante articolo

http://rakeshk.crhc.illinois.edu/dac_16_cam.pdf

nel quale si dimostra che rinunciando al vincolo di fare solo calcoli privi di errori, è possibile aumentare anche del 30% i profitti derivanti dall'attività di mining.

Se riuscissero a implementare questo tipo di proposta l'efficienza degli Asic aumenterebbe quindi notevolmente.
18  Local / Discussioni avanzate e sviluppo / Head first mining on: March 09, 2016, 02:24:01 PM
Gavin Andresen ha proposto una modifica nel modo di minare i blocchi, qui la sua proposta:

https://github.com/bitcoinclassic/bitcoinclassic/pull/138

e qui i commenti relativi su reddit:

https://www.reddit.com/r/btc/comments/49ktb5/headfirst_mining_by_gavinandresen_pull_request

La proposta ha ricevuto molti apprezzamenti positivi; qualcuno che l'ha capita bene sarebbe così gentile da riassumerla e spiegarla un attimo? Ho capito che i miner dovrebbero iniziare a lavorare su un nuovo blocco prima di avere la possibilità di controllare la validità delle transazioni dell'ultimo blocco minato nella rete, transazioni che andrebbero recuperate in un secondo tempo (dopo 30 secondi?) ma non ci ho capito molto di più  Smiley  

Tutto ciò dovrebbe rendere più veloce il passaggio dal momento in cui un blocco viene minato in qualche punto della rete al momento in cui tutti gli altri miner della rete sono in grado di iniziare il tentativo di costruire un proprio nuovo blocco che segue il precedente?
19  Local / Off-Topic (Italiano) / sicurezza vs privacy: ad esempio i dati del cellulare on: February 17, 2016, 07:17:15 PM
Ho letto appena adesso questa notizia riguardo al rifiuto di Apple di forzare il codice criptato dell'iPhone 5 di un attentatore:

http://www.corriere.it/tecnologia/economia-digitale/16_febbraio_17/strage-san-bernardino-apple-iphone-tim-cook-syed-farook-fbi-66f4ae62-d554-11e5-bbd0-dbbf7f226638.shtml

Mi raccomando: Non mi interessa assolutamente aprire una discussione su Apple, è solo un esempio su cui riflettere.

Il punto interessante è: fino a che punto la privacy dei dati personali rimane un diritto inviolabile?

È chiaro che nel caso specifico nessuno si dovrebbe far problemi a ledere il diritto di un attentatore, ma il rischio di creare precedenti e soprattutto certificare in questo modo che è sempre possibile tecnicamente accedere ai dati personali di un utente rende la questione complessa (a me il solo fatto che comunque un'azienda se vuole è in grado tecnicamente di accedere ai miei dati criptati mi da fastidio)

Fino a che punto lo Stato (che rappresenta in teoria gli interessi della comunità) può controllare i propri cittadini inducendo aziende private a creare software con backdoor per sfruttare quest'ultime in caso di "necessità"?

Fino a che punto viceversa una qualsiasi azienda privata può opporsi invece alla richiesta di uno Stato?
20  Local / Discussioni avanzate e sviluppo / curve ellittiche e algoritmo ECDSA on: January 24, 2016, 07:18:13 AM
Indice:






Curve ellittiche: punti, coordinate, scalari:

Vediamo una breve trattazione matematica delle curva secp256k1 (così chiamata, secondo la classicazione "Standards for Efficient Cryptography" (SEC), vedi http://www.secg.org/sec2-v2.pdf a pagina 9), la curva impiegata nel protocollo Bitcoin.

Le curve ellittiche in generale hanno equazione ,  e poco hanno a che fare con l'ellisse, nonostante il loro nome.  

In particolare la curva ellittica secp256k1 utilizzata nel mondo Bitcoin è la curva di equazione:


cioè è l'insieme dei punti P(x,y) del "piano cartesiano" le cui coordinate x e y soddisfano quell'equazione particolare.  


Le coordinate dei punti delle curve ellittiche

I valori che può assumere la coordinata x (e di conseguenza anche la coordinata y) non sono però tutti gli infiniti valori reali (come succede invece a scuola quando si studiano le rette o le parabole ) ma sono solo i valori che corrispondono a elementi di un insieme molto particolare, detto campo, che indicheremo con . Quindi quando parliamo di "piano cartesiano" intendiamo in realtà i punti (coppie di coordinate) che appartengono al prodotto cartesiano .
Anche i numeri reali costituiscono un campo, nel caso della secp256k1 "ovviamente" è un sottoinsieme finito di , ma rimane sempre un campo ("ovviamente" nel senso che applicazioni pratiche e infinito non vanno d'accordo!)

Quindi i punti della curva secp256k1 hanno come coordinate possibili solo gli elementi del campo finito .


I punti della curva secp256k1


I punti della curva costituiscono a loro volta un insieme finito (ovviamente, visto che le coordinate possibili di questi punti sono in numero finito) detto gruppo, che indicheremo con o . Per quanto detto prima è un sottoinsieme di .
Si dimostra che E(Fp) è un gruppo ciclico; inoltre il numero di elementi di questo gruppo è a sua volta un numero primo che è all'incirca simile al numero totale degli elementi del campo (ma non è uguale, sono 2 numeri primi diversi, vedi approfondimenti)


Oltre alle coordinate (campo K) e ai punti della curva (gruppo ciclico E(K)), è presente una terza tipologia di elementi, che non hanno dietro una struttura algebrica a differenza degli elementi citati finora: gli scalari.

Gli scalari

Dove intervengono gli scalari?

Esempio: quando sommiamo un punto A con se stesso 7 volte:

A+A+A+A+A+A+A

possiamo indicare questa somma come 7*A.
Gli scalari quindi in questo contesto sono sostanzialmente dei semplici numeri interi che servono solo come contatori e che non hanno alcuna struttura algebrica dietro.  Gli scalari in questo caso sono importantissimi però poichè è proprio su quest'ultimi che lavora in gran parte l'algoritmo di firma digitale. In sostanza gli scalari tengono conto di quanti "movimenti" abbiamo fatto nello spazio dei punti del gruppo ciclico E(K).

Le chiavi private sono esse stesse degli scalari! (mentre le chiavi pubbliche sono punti della curva).


Nel nostro caso, i punti della secp256k1 costituiscono quindi un gruppo ciclico formato da un numero primo di elementi, da ciò si ottiene che partendo da un punto qualsiasi della curva (diverso dallo 0) si possono ottenere tutti gli altri punti della curva (vedere il post 2 sulle considerazioni matematiche).

Nella secp256k1 si è deciso di partire dal punto G = (Gx, Gy):

G = (55066263022277343669578718895168534326250603453777594175500187360389116729240,
      32670510020758816978083085130507043184471273380659243275938904335757337482424)

Si osservi innanzitutto che entrambe le coordinate sono minori di p=115792089237316195423570985008687907853269984665640564039457584007908834671663

Facciamo un rapido controllo per verificare che G appartenga veramente alla curva seckp256k1, ovvero che Gx^3+7-Gy^2 sia uguale a 0 modulo p:



tutto ok!

Da G è possibile raggiungere tutti gli altri punti della curva moltiplicando il punto G stesso per uno scalare qualsiasi che va da 1 a n
(n = 115792089237316195423570985008687907852837564279074904382605163141518161494337)

G                              = 1*G              
G+G                          = 2*G
G+G+G                     =  3*G
G+G+G+G                 =  4*G
............
G+G+G+......+G        = (n-1)*G
G+G+G+.....+G+G    =  n*G  = 0  

L'espressione "moltiplicare G per uno scalare s" è solo un altro modo di dire "sommare il punto base G a se stesso s volte"

s è la chiave privata che il vostro software wallet pesca random tra 1 e n-1, s*G è la chiave pubblica relativa

NB: le chiavi private "0" o "n" non sono valori consentiti nell'ECDSA, quindi se inviate bitcoin all'indirizzo che si ottiene facendo l'hash del punto all'infinito che è associato a quegli scalari (punto che per pura convenzione si rappresenta mediante le coordinate (0,0)), nessuno sarà in grado di spendere quei bitcoin, poichè la chiave privata "0" (oppure "n") nonostante matematicamente sia associata al punto all'infinito non è considerata valida per firmare le transazioni.
Pages: [1] 2 »
Powered by MySQL Powered by PHP Powered by SMF 1.1.19 | SMF © 2006-2009, Simple Machines Valid XHTML 1.0! Valid CSS!