ruby 以太坊将私钥转换为地址(公钥)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ruby 以太坊将私钥转换为地址(公钥)相关的知识,希望对你有一定的参考价值。

// Go Version
// openssl rand 32 -hex > ~/priv_key.txt
// go run main.go ~/priv_key.txt

package main

import (
	"crypto/ecdsa"
	"crypto/elliptic"
	"encoding/hex"
	"fmt"
	"io"
	"math/big"
	"os"

	"github.com/ethereum/go-ethereum/crypto/secp256k1"
	"github.com/ethereum/go-ethereum/crypto/sha3"
)

func main() {
	if len(os.Args) > 1 {
		path := os.Args[1]
		fileBuf, err := loadFile(path)
		fmt.Println("Read private Key:", string(fileBuf))
		if err != nil {
			fmt.Println("load keyfile error!")
			os.Exit(1)
		}
		hexBuf, _ := decodeHexString(fileBuf)
		priv := ToECDSA(hexBuf)
		pub := priv.PublicKey

		ecdsaPubBytes := elliptic.Marshal(secp256k1.S256(), pub.X, pub.Y)
		fmt.Println("public key string:", hex.EncodeToString(ecdsaPubBytes))
		fmt.Println("public key bytes:", ecdsaPubBytes)
		fmt.Println("public.X:", pub.X)
		fmt.Println("public.Y:", pub.Y)

		// byteLen := (secp256k1.S256().Params().BitSize + 7) >> 3
		// fmt.Println(byteLen)

		addressBytes := Keccak256(ecdsaPubBytes[1:])[12:]
		fmt.Println("address bytes:", addressBytes)
		fmt.Println("sha3 string:", hex.EncodeToString(Keccak256(ecdsaPubBytes[1:])))
		fmt.Println("address string:", hex.EncodeToString(addressBytes))
	} else {
		fmt.Println("keyfile must be given as argument")
	}
}

func decodeHexString(data []byte) ([]byte, error) {
	return hex.DecodeString(string(data))
}

func loadFile(file string) ([]byte, error) {
	buf := make([]byte, 64)
	fd, err := os.Open(file)
	if err != nil {
		return nil, err
	}
	defer fd.Close()
	if _, err := io.ReadFull(fd, buf); err != nil {
		return nil, err
	}

	return buf, nil
}

func BytesToBig(data []byte) *big.Int {
	n := new(big.Int)
	n.SetBytes(data)

	return n
}

func ToECDSA(prv []byte) *ecdsa.PrivateKey {
	priv := new(ecdsa.PrivateKey)
	priv.PublicKey.Curve = secp256k1.S256()
	priv.D = BytesToBig(prv)
	priv.PublicKey.X, priv.PublicKey.Y = secp256k1.S256().ScalarBaseMult(prv)

	return priv
}

func Keccak256(data ...[]byte) []byte {
	d := sha3.NewKeccak256()
	for _, b := range data {
		d.Write(b)
	}
	return d.Sum(nil)
}
// NodeJS version
// npm install keccakjs
// npm install secp256k1

const SHA3 = require('keccakjs')

let pubKeyHex = "046B8A6CC271D62F45301A3C6C443DC1879193CA1E4A8DF6CCFA8A82525F5A027C1333C132A93EA35857A30CB486BEF3045A4E33B29F18BC128A8EFF6C44074268"
let pubKeyBuf = new Buffer(pubKeyHex, 'hex')
let h = new SHA3(256)
h.update(pubKeyBuf.slice(1)) // 130 => 128

let address = h.digest('hex').slice(-40)

console.log(address)
# geth version
openssl rand 32 -hex > ~/priv_key.txt
geth account import ~/priv_key.txt
# Ruby version
# gem install digest-sha3

require 'openssl'
require 'digest/sha3'

curve = OpenSSL::PKey::EC.new('secp256k1')
curve.generate_key
prv = curve.private_key.to_s(16)
pub = curve.public_key.to_bn.to_s(16)

puts "Private Key: #{prv}"
puts "Public Key: #{pub}"

def decode(s, base)
  syms = '0123456789abcdef'.freeze
  s = s.downcase if base == 16

  result = 0
  while s.size > 0
    result *= base
    result += syms.index(s[0])
    s = s[1..-1]
  end

  result
end

def encode(v, base)
  syms = 256.times.map {|i| i.chr }.join.freeze

  result = ''
  while v > 0
    result = syms[v % base] + result
    v /= base
  end

  result
end

def public_to_address(str)
  str = str[2, 128]
  Digest::SHA3.hexdigest(encode(decode(str, 16), 256), 256)[-40..-1]
end

puts "Address: #{public_to_address(pub)}"

以上是关于ruby 以太坊将私钥转换为地址(公钥)的主要内容,如果未能解决你的问题,请参考以下文章

如何将私钥证书 (.pfx)、公钥证书 (.cer) 上传到 Azure WebApp

如何将私钥转换为 RSA 私钥?

5、以太坊名词解析

如何使用 python 将私钥编码为 RS256 格式的 JSON WEB TOKEN

从零开发区块链应用--以太坊地址生成

将私钥与 .net 中的 X509Certificate2 类关联