比特币地址算法生成

本文讲解比特币地址的生成,并且重点解释老地址和新地址

首先看看所需的依赖包

const randomBytes         = require('randombytes')
const BigInteger          = require('bigi')
const ecurve              = require('ecurve')
const Crypto              = require('crypto')
const cs                  = require('coinstring')

生成方法:

首先是随机生成一个32字节的数(范围是1~2^256-1),而这个数就是真正的私钥

var secp256k1 = ecurve.getCurveByName('secp256k1')
var randombytes = randomBytes(32).toString('hex')
var privatekey = new Buffer(randombytes, 'hex')
var privateKey=privatekey;

但是大家会发现随机数私钥和大家常见的私钥有所不同,这是因为比特币对它进行了一些操作换了种表示方式,表示方式有两种,也就是上面提到的新地址和老地址,接下来介绍老地址(也称非压缩式)的生成方法

首先是老地址的私钥,在随机数私钥前添加0x80表示版本号,然后对其进行base58编码,即可得到WIF(Wallet Import Format)格式的私钥,下面是使用了模块直接生成

//非压缩类 
console.log("老地址私钥5开头"+cs.encode(privateKey, 0x80))

接下来是地址了,首先由随机数私钥通过secp256k1椭圆曲线算法计算出其对应的x和y值,拼接x值和y值并加上前缀0x04压缩标识,将拼接的结果先进行一遍sha256运算,再将运算结果进行rmd160运算,将运算结果加上0x00前缀并进行base58编码得到即可得到老地址

var ecparams = ecurve.getCurveByName('secp256k1')
var curvePt = ecparams.G.multiply(BigInteger.fromBuffer(privatekey))
var x = curvePt.affineX.toBuffer(32)
var y = curvePt.affineY.toBuffer(32)
var publicKey = Buffer.concat([new Buffer([0x04]), x, y])
var sha = Crypto.createHash('sha256').update(publicKey).digest()
var pubkeyHash = Crypto.createHash('rmd160').update(sha).digest()
console.log("老地址:" + cs.encode(pubkeyHash, 0x0)) 

然后是新地址即压缩地址的生成,首先新地址的私钥是随机数私钥添加前缀0x80(版本号)和后缀0x01(压缩标识),然后进行base58编码得到

privateKey = Buffer.concat([privateKey, new Buffer([0x01])]); 
console.log("新地址私钥"+cs.encode(privateKey, 0x80)); 

新地址的生成主要区别于老地址的地方是,新地址不是直接拼接secp256k1椭圆曲线算法的x值和y值,而是仅保留x,前缀变为0x02(y值是偶数时)和0x03(y值是奇数时),后面的步骤和老地址一样,先sha256再rmd160加上前缀,最后base58得到

var ecparams = ecurve.getCurveByName('secp256k1')
var curvePt = ecparams.G.multiply(BigInteger.fromBuffer(privatekey))
var x = curvePt.affineX.toBuffer(32)
var y = curvePt.affineY.toBuffer(32)
var publicKey = Buffer.concat([new Buffer([0x04]), x, y])
publicKey = curvePt.getEncoded(true) //true forces compressed public key
var sha = Crypto.createHash('sha256').update(publicKey).digest()
var pubkeyHash = Crypto.createHash('rmd160').update(sha).digest()
console.log("新地址" + cs.encode(pubkeyHash, 0x0)) 

总结一下比特币地址生成

源头一个32字节的随机数,大家所见的私钥也是它加上标识再经过编码后的结果

而账户地址有两种表示方式,一种是老地址(非压缩)和新地址(压缩),分别对应了一对运算过后的私钥和地址

它们有几个特征:

地址都是1开头(新老都是)

非压缩类私钥是5开头

压缩类私钥是L或者K开头



猜你喜欢

转载自blog.csdn.net/qq_35513792/article/details/80939490