酸饼博客
关注区块链技术应用与数字货币

区块链入门100问(12) :比特币地址是如何生成的?

比特币地址类似于银行的收款账户,用来接收来自他人的转账。
地址对应的密钥对,决定了该地址上的比特币的所有权。掌握了密钥,就掌握了地址上的比特币资产。

比特币钱包里有一系列的密钥对。每个密钥对包括公钥和私钥。私钥是一个数字,通常是随机选出来的。有了私钥,可以通过单向加密啊函数生成一个公钥。注意这里是单向,即是可以通过私钥生成公钥,但很难通过公钥逆向计算出私钥。

利用私钥生成公钥之后,再经过一系列的计算、转换、编码,生成密钥对所对应的比特币地址。这里面,私钥是最为关键的,私钥泄露,则会被他人很容易就偷走自己的比特币资产,因此要保护好自己的私钥。

本文将通过代码,演示在比特币系统中是如何生成密钥对及比特币地址。

首先第一步是利用操作系统底层的随机数生成器产生一个256位二进制的随机数,然后使用椭圆形加密算法从私钥计算出公钥。上面说过,私钥计算出公钥,这是一个不可逆的计算过程。

(1)生成密钥对的过程是:

        KeyPairGenerator keyGen = KeyPairGenerator.getInstance("EC");
        ECGenParameterSpec ecSpec = new ECGenParameterSpec("secp256k1");
        keyGen.initialize(ecSpec);

        KeyPair kp = keyGen.generateKeyPair();

(2)私钥的随机生成:

        PrivateKey pvt = kp.getPrivate();
        ECPrivateKey epvt = (ECPrivateKey)pvt;
        String sepvt = adjustTo64(epvt.getS().toString(16)).toUpperCase();
        System.out.println("s[" + sepvt.length() + "]: " + sepvt);

(3)计算出公钥:

        PublicKey pub=kp.getPublic();
        ECPublicKey epub = (ECPublicKey)pub;
        ECPoint pt = epub.getW();
        String sx = adjustTo64(pt.getAffineX().toString(16)).toUpperCase();
        String sy = adjustTo64(pt.getAffineY().toString(16)).toUpperCase();
        String bcPub = "04" + sx + sy;
        System.out.println("bcPub: " + bcPub);

        return bcPub;

(4)计算公钥的哈希值(SHA-256算法):

        MessageDigest sha = MessageDigest.getInstance("SHA-256");
        byte[] s1 = sha.digest(bcPub.getBytes("UTF-8"));
        System.out.println("  sha: " + bytesToHex(s1).toUpperCase());

(5)对上一步的哈希值,通过RIPEMD-160算法再次取哈希值:

        Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());

        MessageDigest rmd = MessageDigest.getInstance("RipeMD160", "BC");
        byte[] r1 = rmd.digest(s1);

(6)对上一步的结果,加入地址版本号(比特币主网的版本号是“0x00”):

        byte[] r2 = new byte[r1.length + 1];
        r2[0] = 0;
        for (int i = 0 ; i 

(7)对上一步结果连续两次SHA-256取哈希:

        byte[] s2 = sha.digest(r2);
        System.out.println("  sha: " + bytesToHex(s2).toUpperCase());
        byte[] s3 = sha.digest(s2);
        System.out.println("  sha: " + bytesToHex(s3).toUpperCase());

(8) 取第7步的结果的前4个字节,作为校验码加在第5步结果的后面:

        byte[] a1 = new byte[25];
        for (int i = 0 ; i 

(9)最后,用Base58变换一下上一步的结果,得到最常见形态的比特币地址:

        String address =Base58.encode(a1);
        System.out.println("  adr: " + address);
未经允许不得转载:酸饼 » 区块链入门100问(12) :比特币地址是如何生成的?
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

留言联系关于酸饼