Saturday, August 9, 2014

Kriptirani privatni ključevi (BIP38)


Privatne ključeve moguće je kriptirati tako da su zaštićeni lozinkom. Takav ključ može vidjti bilo tko, no samo osoba koja zna lozinku može ga dešifrirati. Takva zaštita pogodna je za kreiranje papirnatih novčanika i fizičkih bitcoina.


Postoje dva načina kriptiranja. Prvi omogućuje da se bilo koji privatni ključ zaštiti bilo kojom lozinkom. Drugi omogućuje dijeljeni ključ gdje jedna strana derivira međuključ iz lozinke, a druga strana derivira konačni ključ i adresu iz međuključa. Trošenje bitcoina moguće je jedino onome tko zna lozinku.


Uz svaki se kriptirani ključ sprema i hash rezultirajuće adrese koji služi za provjeru ispravnosti adrese.

Korištene funkcije


AES256Encrypt, AES256Decrpyt – šifriranje i dešifriranje pomoću AES šifre. Prima ključ od 256 bitova te 16 bajtova ulaza i deterministički daje 16 bajtova izlaza.
SHA256 – Algoritam za hashitanje koji uzima ulaz proizvoljne duljine te daje fiksni izlaz od 256 bitova (32 bajta).
Scrypt – Algoritam za deriviranje ključeva (engl. key derivation algorithm). Parametri: lozinka, salt, n, r, p, duljina. Kao izlaz daje niz znakova dužine parametra "duljina".
ECMultiply – množenje na krivulji secp256k1.
G, N – generator i red generatora eliptičke krivulje secp256k1.
Base58Check – alfanumerička baza 58 koja se koristi za enkodiranje bitcoin adresa.

Format kriptiranog ključa

  1. Ključ počinje prefiksom 0x0142 ili 0x0143 ovisno o tome je li korišteno množenje na eliptičkoj krivulji. Kad se na to primijeni Base58Check, korisnik će vidjeti 6P. Svaki kriptirani ključ počinje znakovima 6P. 6 zato da se razlikuje od normalnog privatnog ključa koji uvijek počinju brojem 5. Broj 6 znači da se radi o kriptiranom ključu koji se dekriptira pomoću metode P. P u ovom slučaju označuje lozinku (engl. Passphrase).
     
  2. 37 bajtova sadržaja:
    1. zastavica (1 bajt) označuje koristi li se množenje na krivulji ili ne
    2. zaštitna suma (4 bajta) SHA256(SHA256(očekivana_bitcoin_adresa))[0..3]
    3. 16 bajtova ovisno o množenju
    4. 16 bajtova AES šifrirani sadržaj (ovisi o množenju)

 Enkripcija bez množenja na eliptičkoj krivulji

 

Enkripcija:
  1. Izračunati bitcoin adresu i uzeti prva četiri bajta od SHA256(SHA256(adresa)). To je hash_adrese.
  2. Derivirati ključ iz lozinke pomoću funkcije scrypt s parametrima n=16384, r=8, p=8, duljina=64. Salt je hash_adrese. Podijeliti dobivena 64 bajta na dva dijela: polovica1 i polovica2.
  3. Napraviti AES256Encrypt(privatni_ključ[0..15] xor polovica1[0..15], polovica2). Rezultat je enkriptirana_polovica1.
  4. Napraviti AES256Encrypt(privatni_ključ[16..31] xor polovica1[16..31], polovica2). Rezultat je enkriptirana_polovica2.

Konačan je rezultat: Base58Check(0x01 0x42 + zastavica + salt + enkriptirana_polovica1 + enkriptirana_polovica2).

 Dekripcija:

  1. Uzeti enkriptirani ključ i lozinku.
  2. Izračunati polovica1 i polovica2 korištenjem algoritma scrypt predajući mu lozinku i hash_adrese.
  3. Izračunati enkriptirana_polovica1 i enkriptirana_polovica2 korištenjem AES256Decrypt.
  4. Iz privatnog ključa izračunati bitcoin adresu.
  5. Hashirati bitcoin adresu i provjeriti odgovara li hash_adrese.

Enkripcija s množenjem na eliptičkoj krivulji


Ovakav način enkripcije omogućuje da se kriptirani ključ generira poznavajući samo točku na eliptičkoj krivulji i salt koji je korisnik generirao bez poznavanja lozinke. Osoba koja zna lozinku naziva se vlasnik i ona generira jedan ili više međuključeva te i predaje osobi, pisaču, koja će generirati enkriptirani privatni ključ.
Enkriptirani privatni ključ može sadržavati broj čestice i redni broj. Zajedno su duljine 32 bita. Broj čestice je duljine 20 bitova, a redni broj 12 bitova.


Algoritam kojim vlasnik generira međuključ:

  1. Generirati 4 nasumična bajta salt_vlasnika
  2. Kodirati broj čestice i redni broj u big-endian formatu: čestica * 4096 + redni_broj. Ta se četiri bajta nazivaju čestica_redni broj.
  3. Konkatenirati salt_vlasnika i čestica_redni_broj. To se naziva entropija_vlasnika. Ako se ne koriste čestica i redni broj, entropija_vlasnika = salt_vlasnika.
  4. Generirati ključ iz lozinke pomoću algoritma scrypt duljine 32 bajta. Ti se bajtovi nazivaju predfaktor. Napraviti SHA256(SHA256(predfaktor + entropija_vlasnika)). To se naziva faktor_lozinke. Ako se ne koriste čestica i redni broj, faktor_lozinke je rezultat izvođenja algoritma scrypt.
  5. Pomnožiti faktor_lozinke s generatorom eliptičke krivulje te zapisati u kompresiranom formatu (33 bajta).
  6. Proslijediti rezultat množenja i salt_vlasnika pisaču.


Nakon što dobije međuključ od vlasnika, pisač provodi algoritam:

  1. Postavi zastavicu.
  2. Generira 24 nasumična bajta zvana sjemeb te napravi SHA256(SHA256()) nad njima. Rezultat se naziva faktorb.
  3. Pomnoži točku dobivenu od vlasnika sa faktoromb. Rezltat koristit kao javni ključ iz kojeg se izvede bitcoin adresa. To se zove generirana_adresa.
  4. SHA256(SHA256(generirana_adresa))[0..3] = hash_adrese
  5. scrypt(sjemeb) duljine 64 bajta, salt je hash_adrese + entropija_vlasnika
  6. Podijeliti dobivena 64 bajta na dva dijela: polovica1 i polovica2.
  7. Napraviti AES256Encrypt(sjemeb[0..15] xor polovica1[0..15], polovica2). Rezultat je enkriptirana_polovica1.
  8. Napraviti AES256Encrypt(enkriptirana_polovica1[8..15] + sjemeb[16..23] xor polovica1[16..235], polovica2). Rezultat je enkriptirana_polovica2.

Za konačan rezultat potrebno je napraviti Base58Check od 0x01 0x43 + zastavica + hash_adrese + entropija_vlasnika + enkriptirana_polovica1[0..7] + enkriptirana_polovica2.

Dekripcija:

  1. Prikupiti enkriptirani privatni ključ i lozinku od korisnika.
  2. Dobiti faktor_lozinke pomoću algoritma scrypt koristeći salt_vlasnika i lozinku.
  3. Dobiti ključ za dekripciju za sjemeb koristeći scrypt sa hash_adrese, entropija_vlasnika i rezultatom iz prethodnog koraka.
  4. Dekriptirati enkriptirana_polovica2 pomoću AES256Decrpyt da se dobije početnih 8 bajtova sjemeb i završnih 8 bajtova za enkriptirana_polovica1.
  5. Dekriptirati enkriptirana_polovica1 da se dobije ostatak sjemeb.
  6. Iz sjemeb izvesti faktorb.
  7. Pomnožiti faktor_lozinke i faktorb da se dobije privatni ključ povezan s generirana_adresa.
  8. Iz privatnog ključa izvesti bitcoin adresu.
  9. Provjeriti odgovara li hash_adrese.