Introduce
Curve secp256k1
The elliptic curve domain parameters over associated with a Koblitz curve
secp256k1
are specified by the sextuple
where the finite field
is defined by:
p = FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE FFFFFC2F
=
The curve over
is defined by:
a = 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
b = 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000007
The base point in compressed form is:
G = 02 79BE667E F9DCBBAC 55A06295 CE870B07 029BFCDB 2DCE28D9 59F2815B 16F81798
and in uncompressed form is:
G = 04 79BE667E F9DCBBAC 55A06295 CE870B07 029BFCDB 2DCE28D9 59F2815B 16F81798
483ADA77 26A3C465 5DA4FBFC 0E1108A8 FD17B448 A6855419 9C47D08F FB10D4B8
Finally the order of
and the cofactor are:
n = FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE BAAEDCE6 AF48A03B BFD25E8C D0364141
h = 01
Pub key to Addr

Private key to Addr
Java Code
public class BTCAddressGenerator { public static void main(String[] args) { String keyHex = "F1A679C2DFF382267856E40066F083ED8A78D6F02DDD6CA8C30B27AC691F0109"; ECNamedCurveParameterSpec ecn = ECNamedCurveTable.getParameterSpec("secp256k1"); BigInteger k = new BigInteger(1, Bytes.fromHex(keyHex).bytes()); ECPoint pubK = ecn.getG().multiply(k).normalize(); System.out.println("X: " + Bytes.from(pubK.getAffineXCoord().getEncoded()).asHex()); System.out.println("Y: " + Bytes.from(pubK.getAffineYCoord().getEncoded()).asHex()); Bytes ripemd160sha256 = Bytes.from(pubK.getEncoded(false)).digest(Digests.sha256()).digest(Digests.ripemd160()); Bytes addr1 = Bytes.fromHex("00").concat(ripemd160sha256); Bytes addr1sha256sha256 = addr1.digest(Digests.sha256()).digest(Digests.sha256()); Bytes finalAddr = addr1.concat(addr1sha256sha256.head(4)); System.out.println("ADDR: " + finalAddr.asBase58()); { Bytes extended = Bytes.fromHex("80").concat(Bytes.fromHex(keyHex)); Bytes checksum = extended.digest(Digests.sha256()).digest(Digests.sha256()).head(4); System.out.println("WIF: " + extended.concat(checksum).asBase58()); } { Bytes extended = Bytes.fromHex("80").concat(Bytes.fromHex(keyHex)).concat(Bytes.fromHex("01")); Bytes checksum = extended.digest(Digests.sha256()).digest(Digests.sha256()).head(4); System.out.println("WIF (compressed): " + extended.concat(checksum).asBase58()); } } }
Outputs:
X: 71e035f316b8bd48071060c397c1aa3c916a63f0ad6250f1250e03b7864bd8d4
Y: de40c5becb54be8ea34b0b7579c2b1e1ec9e4d987561cdce871798a9975ccfa4
ADDR: 1JxtdVzeksoDDLBtcRSdsuDGBrKWptdSmc
WIF: 5KeiDN58eVgkn9BoeTemHeHC32hFDf8pmCP2UGkVu5UaPaPabhk
WIF (compressed): L5KSua1EkVcUEF8gtLdgUTYThxUdksKXp5EDVNWzYrkiNCwqu2P8
Rust Code
BTC address implemention in Rust: h
ETH Address
和比特币类似,一个以太坊账户就是一个公钥哈希后得到的地址,它是由一个私钥推导出对应的公钥,然后再计算出地址。其中,私钥与公钥算法与比特币完全相同,均为 secp256k1
椭圆曲线,但和比特币不同的是,以太坊采用非压缩公钥,然后直接对公钥做
keccak256
哈希,得到32字节的哈希值,取后20字节加上
0x
前缀即为地址:

通过规范 ERC-55 可以对 ETH 地址进行校验。