Bitcoin’in Genesis Block’unu İnceleyelim


Bitcoin’in kaynak kodları https://github.com/bitcoin/bitcoin adresindedir. Bu repository altında src dizininde chainparams.cpp adında bir dosya vardır.

Öncelikle belirtelim Bitcoin C++ ile yazılmıştır. chainparams.cpp altında Genesis Block’u oluşturan iki adet statik fonksiyon tanımlanmıştır. Bunların kodları aşağıdadır:

static CBlock CreateGenesisBlock(const char* pszTimestamp, const CScript& genesisOutputScript, uint32_t nTime, uint32_t nNonce, uint32_t nBits, int32_t nVersion, const CAmount& genesisReward)
{
    CMutableTransaction txNew;
    txNew.nVersion = 1;
    txNew.vin.resize(1);
    txNew.vout.resize(1);
    txNew.vin[0].scriptSig = CScript() << 486604799 << CScriptNum(4) << std::vector<unsigned char>((const unsigned char*)pszTimestamp, (const unsigned char*)pszTimestamp + strlen(pszTimestamp));
    txNew.vout[0].nValue = genesisReward;
    txNew.vout[0].scriptPubKey = genesisOutputScript;

    CBlock genesis;
    genesis.nTime    = nTime;
    genesis.nBits    = nBits;
    genesis.nNonce   = nNonce;
    genesis.nVersion = nVersion;
    genesis.vtx.push_back(MakeTransactionRef(std::move(txNew)));
    genesis.hashPrevBlock.SetNull();
    genesis.hashMerkleRoot = BlockMerkleRoot(genesis);
    return genesis;
}

/**
 * Build the genesis block. Note that the output of its generation
 * transaction cannot be spent since it did not originally exist in the
 * database.
 *
 * CBlock(hash=000000000019d6, ver=1, hashPrevBlock=00000000000000, hashMerkleRoot=4a5e1e, nTime=1231006505, nBits=1d00ffff, nNonce=2083236893, vtx=1)
 *   CTransaction(hash=4a5e1e, ver=1, vin.size=1, vout.size=1, nLockTime=0)
 *     CTxIn(COutPoint(000000, -1), coinbase 04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73)
 *     CTxOut(nValue=50.00000000, scriptPubKey=0x5F1DF16B2B704C8A578D0B)
 *   vMerkleTree: 4a5e1e
 */
static CBlock CreateGenesisBlock(uint32_t nTime, uint32_t nNonce, uint32_t nBits, int32_t nVersion, const CAmount& genesisReward)
{
    const char* pszTimestamp = "The Times 03/Jan/2009 Chancellor on brink of second bailout for banks";
    const CScript genesisOutputScript = CScript() << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f") << OP_CHECKSIG;
    return CreateGenesisBlock(pszTimestamp, genesisOutputScript, nTime, nNonce, nBits, nVersion, genesisReward);
}

Daha önceki yıllarda incelediğimde Unique Genesis Block’u oluşturan bir kod vardı, Unique Genesis Block’u oluşturmak için 6 elemanlı bir rastgele sayısı dizisi private hash olarak üretilip kullanılıyordu. Deploy edilmiş Bitcoin hala böyle olması gerekiyor, çünkü Blockchain’in değiştirilmemesi lazım. Ancak şimdi incelediğimde Genesis Block üretiminin değiştirildiğini ve PubKey’in CScript ile üretildiğini görüyorum. Bu kaynak kod geliştiricilere özel sunulmuş olabilir halen production’daki Bitcoin 6 elemanlı rastgele sayı dizisini Genesis block’un private key’i olarak kullanıyor olabilir. Bunu bilmiyoruz. Ancak eğer öyleyse productionda bir güvenlik zayıflığı var demektir.

Şu anki sürümde CScript’te Hexadecimal bir sayı gönderiliyor ve araştırma yaptığımızda bu CScript’ten PubKey’in extract edilmesinin mümkün olduğunu anlaşılıyor. CScript’ten PubKey’i extract etmek için şu adrese bakabilirsiniz. https://www.programcreek.com/cpp/?CodeExample=extract+pub+key

Ayrıca bu adreste coinbase’deki PubKey ortaya çıkartılmış durumda: https://ma.ttias.be/retrieving-the-genesis-block-in-bitcoin-with-bitcoin-cli/ Yani bitcoin merkezinin Coinbase olduğunu anlıyoruz.

Evet yukarıdaki fonksiyonlar haricinde Main fonksiyonu içerisinde aşağıdaki kodları görmek mümkün:

genesis = CreateGenesisBlock(1231006505, 2083236893, 0x1d00ffff, 1, 50 * COIN);
        consensus.hashGenesisBlock = genesis.GetHash();
        assert(consensus.hashGenesisBlock == uint256S("0x000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f"));
        assert(genesis.hashMerkleRoot == uint256S("0x4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b"));

Bu kodlardaki assert’lerden sanki Genesis Block’un ve Merkle Root’un Bitcoine özel sabit bir hashi olduğunu anlamak mümkün.

Bu durumda 0. block yani Genesis Block’u ile ilgili bilinmeyen bir şey yok gibi duruyor, bu durumda 1. block’a bakmamız lazım. 1. block’ta da muhtemelen cüzdandan alınan private key’i gizli parametre olarak kullanılıyor, bu durumda güvenlik maksimize edilmiş görünüyor.

Sonuç:

Bitcoin’in önceki sürümlerinde bir güvenlik zayıflığı vardı. Çünkü 6 elemanlı rastgele sayısı dizisi Genesis Block’un private key’i olarak kullanılıyordu. Şimdi ise Genesis block açıkça statik ve sabit bir hashe kavuşmuş. Cüzdanların private key’leri ile bir güvenlik sağlanmış. Bu durumda Satoshi Nakamoto’nun gizli bir cüzdanı olduğu sonucuna varabiliriz. Bu durumda Satoshi Nakamoto (minimum) ilk iki block’la ilgili tüm bilgilere sahip özel biri oluyor. Ve bitcoin ekibi, kurucuları ilk blocklardaki tüm detayları biliyorlar. Private key’leri de biliyorlar. Peki bu ona ve onlara ne avantaj sağlar?

Buradan yola çıkarak diğer block’lardaki private key’leri tespit edebilirler mi? Bunun için SHA256 hash algoritmasını decrypt etmeyi çözmeleri lazım. Olası bir teorimi paylaşmak istiyorum.

  1. cüzdan private key’ini SHA256 ile şifreleyelim.
  2. PreviousHash+Block+SHA256(PrivateKey) tekrar SHA256 ile şifreleyip Public Key hashini üretelim

Diğer kodları incelemediğim için teorik olarak Bitcoin’in güvenli olduğunu, SHA256 hashi kırılmadığı sürece bir sıkıntı olmadığını söyleyebilirim. Ancak aşağıdaki makalede 1500 qubitlik bir kuantum bilgisayar ile SHA256 güvenlik algoritmasının kırılabileceği tahmin edilmiş.

https://www.forbes.com/sites/billybambrough/2019/10/02/could-google-be-about-to-break-bitcoin/

Ve uzun zamandır 2000 qubitten fazla quantum bilgisayarlar çıkmış durumda. SHA256’nın kırılmak üzere olduğunu anlaşıldığı için SHA3 çıkartıldı.

Ve NIST kuantum bilgisayarlara dirençli güvenlik algoritmaları üzerinde bir taraftan çalışıyor: https://csrc.nist.gov/Projects/post-quantum-cryptography

SHA256 kırılmak üzere olduğundan post-kuantum güvenlik algoritmalarına geçmeye öncelik vermeliyiz.

Mutlu kodlamalar 🙂

Yazılım Güvenliği: Neden Veri ve Kodları açık kaydediyoruz?


Veri ve Smart Contract’lar açık kaydediliyorsa BlockChain güvenli değildir. Şifreli kaydediliyorsa BlockChain’e gerek var mıdır?

Yazılım güvenliği için yapmadığımız şey yok; antivirüsler, güvenlik duvarları, internet güvenliği, yedekleme, blockchain derken.. güvenlik için sürekli yeni çözümler geliştiriyoruz.

Ancak gelişmelere bakacak olursak; GitHub’ta ve Devops’ta kodlar varsayılan olarak açıktır. SQL Server’da ve MongoDB’de veriler varsayılan olarak okunabilir kaydedilir.

Böylece kullanıcı adı ve şifremizi ele geçiren hackerler, ya da işletim sistemini ele geçiren hackler verileri ve kodları alabilir ve kullanabilir. Kişisel verileri kolaylıkla satışa çıkarabilir ve kodlarımızdaki güvenlik açıklarını tespit edebilir.

Madem ki güvenlikten bahsediyoruz, neden kodlar ve veriler varsayılan olarak şifreli kaydedilmiyor? SQL sorgularımız ve işletim sistemlerimiz neden Encrypt/Decrypt gömülü olarak çalışmıyorlar?

Sizce verilerin ve kodların kurumumuza özel algoritmalarla şifreli olarak kaydedilmesi, sızıntı durumlarında güvende olmamızı sağlamaz mı?

İsterseniz Şifreleyebiliyorsunuz

Encryption At Rest ve BitLocker gibi özellikler var. Evet. Ama bunlar by default pasif olarak geliyorlar. Ayrıca kullanıcı adı-şifre ele geçirilince sistem hala açık. Sistemin çalışırken de kapalı ve şifreli olarak çalışması gerekmez mi?

Yani SQL Server’da Encrytion At Rest yaptınız diyelim ama Management Studio ile SQL Server’a bağlandığınızda verilerin yine açık olduğunu göreceksiniz. SELECT * FROM TableName dediğinizde veriler açık olarak gelir.

Veya GitHub’ta kodlarınız açık olarak kaydedildiğinden GitHub’ın sahibi Microsoft’la tüm kodlarımızı paylaşmış oluruz. GitHub şifremiz ele geçirilirse bir hacker’ın (ya da yapay zekanın) sessiz sedasız yazılımımızdaki güvenlik açıkları tespit edip etmediğinden emin olamayız.

Halbuki by default herşey şifreli olarak kaydedilseydi ve sadece izin verdiğim kullanıcılar decrypt edebilseydi, ortam daha güvenli olacaktı. Şifreleme algoritmaları pluggable olsaydı ve ben kurumuma özel algoritma kullanabilseydim, kurumumun verileri ve kodları daha güvende olacaktı. Güveniyorum çünkü güvenlik algoritmam sağlam diyebilecektim.

İnternette güven kırıldı, bozuldu. Telefonlar ve bilgisayarlar kolaylıkla hacklenebiliyorlar. Blockchain’in ve kriptoparaların sıcak cüzdanları da bu yüzden güvenli değil. Ama işletim sistemleri, veritabanları, depolama cihazları ve kod depolama sistemleri varsayılan şifreli kaydetse ve sadece izin verdiğim kullanıcılar decrypt edilmiş veriye hatta o verinin de sadece bir kısmına ulaşabilseler daha güvenli bir dijital dünya geliştirebiliriz.

Standart blockchain tanımında da veri açık kaydedilir, açık veri sızıntılara davetiye çıkarır unutmayın. HyperLedger Fabric’te olduğu gibi pluggable güvenlik algoritmalarını kullanarak blockchain üzerindeki veriyi, ayrı olarak kaydettiğimiz big datayı, storageları, geliştirme kodlarını ve smart contractlarımızı kurumumuza özel şifreleme algoritmalarıyla şifrelemediğimiz sürece sızıntılara karşı güvende değiliz.

Mutlu kodlamalar 🙂