比特币--通过公钥生成地址全过程

Posted justin_jia_92

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了比特币--通过公钥生成地址全过程相关的知识,希望对你有一定的参考价值。

import org.ethereum.util.ByteUtil;

public class AddressUtil 
	
	public static String generateAddressFromHexPub(String hexPubKeyStr, String version) 
		//公钥sha256得到a
		String a = SHAEncrypt.SHA256WithHex(hexPubKeyStr);
		//a进行ripemd160计算后转hexString得到b
		String b = ByteUtil.toHexString(Ripemd160.getHashWithHex(a));
		//两次sha256, sha256(sha256(version + b))得到c
		String c = SHAEncrypt.SHA256WithHex(SHAEncrypt.SHA256WithHex(version + b));
		//(version + b + c的前4个字节,十六进制前八位) 得到十六进制字符串d
		String d = version + b + c.substring(0, 8);
		//对d进行base58编码得到地址
		String address = Base58.encode(ByteUtil.hexStringToBytes(d));
		return address;
	

	public static void main(String[] args) 
		String version = "00";
		String hexPubKeyStr = "026d9a6baec4d380091b9881400dbd99ca90bae0f61e171df121dd2ff0e2ac9517";
		System.out.println(generateAddressFromHexPub(hexPubKeyStr, version));
		//1Po8pvaAHE3V9twnSGXZwEXEkwctcCtWDe
	
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

import org.ethereum.util.ByteUtil;

public class SHAEncrypt 
	public static String SHA256(final String strText)
	
		return SHA(strText.getBytes(), "SHA-256");
	
	public static String SHA256WithHex(final String hexStr)
	
		return SHA(ByteUtil.hexStringToBytes(hexStr), "SHA-256");
	

	public static String SHA512(final String strText)
	
		return SHA(strText.getBytes(), "SHA-512");
	

	public static String SHA512WithHex(final String hexStr)
	
		return SHA(ByteUtil.hexStringToBytes(hexStr), "SHA-512");
	

	private static String SHA(final byte[] text, final String strType)
	
		String strResult = null;

		if (text != null && text.length > 0)
		
			try
			
				MessageDigest messageDigest = MessageDigest.getInstance(strType);
				messageDigest.update(text);
				byte byteBuffer[] = messageDigest.digest();

				StringBuffer strHexString = new StringBuffer();
				for (int i = 0; i < byteBuffer.length; i++)
				
					String hex = Integer.toHexString(0xff & byteBuffer[i]);
					if (hex.length() == 1)
					
						strHexString.append('0');
					
					strHexString.append(hex);
				
				strResult = strHexString.toString();
			
			catch (NoSuchAlgorithmException e)
			
				e.printStackTrace();
			
		

		return strResult;
	
import static java.lang.Integer.rotateLeft;
import java.util.Arrays;
import java.util.Objects;

import org.ethereum.util.ByteUtil;


public final class Ripemd160 

	private static final int BLOCK_LEN = 64;  // In bytes

	public static byte[] getHashWithHex(String hexMsg) 
		return getHash(ByteUtil.hexStringToBytes(hexMsg));
	

	public static byte[] getHash(byte[] msg) 
		Objects.requireNonNull(msg);
		int[] state = 0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0;
		int off = msg.length / BLOCK_LEN * BLOCK_LEN;
		compress(state, msg, off);

		byte[] block = new byte[BLOCK_LEN];
		System.arraycopy(msg, off, block, 0, msg.length - off);
		off = msg.length % block.length;
		block[off] = (byte)0x80;
		off++;
		if (off + 8 > block.length) 
			compress(state, block, block.length);
			Arrays.fill(block, (byte)0);
		
		long len = (long)msg.length << 3;
		for (int i = 0; i < 8; i++)
			block[block.length - 8 + i] = (byte)(len >>> (i * 8));
		compress(state, block, block.length);

		byte[] result = new byte[state.length * 4];
		for (int i = 0; i < result.length; i++)
			result[i] = (byte)(state[i / 4] >>> (i % 4 * 8));
		return result;
	

	private static void compress(int[] state, byte[] blocks, int len) 
		if (len % BLOCK_LEN != 0)
			throw new IllegalArgumentException();
		for (int i = 0; i < len; i += BLOCK_LEN) 
			int[] schedule = new int[16];
			for (int j = 0; j < BLOCK_LEN; j++)
				schedule[j / 4] |= (blocks[i + j] & 0xFF) << (j % 4 * 8);
			int al = state[0], ar = state[0];
			int bl = state[1], br = state[1];
			int cl = state[2], cr = state[2];
			int dl = state[3], dr = state[3];
			int el = state[4], er = state[4];
			for (int j = 0; j < 80; j++) 
				int temp;
				temp = rotateLeft(al + f(j, bl, cl, dl) + schedule[RL[j]] + KL[j / 16], SL[j]) + el;
				al = el;
				el = dl;
				dl = rotateLeft(cl, 10);
				cl = bl;
				bl = temp;
				temp = rotateLeft(ar + f(79 - j, br, cr, dr) + schedule[RR[j]] + KR[j / 16], SR[j]) + er;
				ar = er;
				er = dr;
				dr = rotateLeft(cr, 10);
				cr = br;
				br = temp;
			
			int temp = state[1] + cl + dr;
			state[1] = state[2] + dl + er;
			state[2] = state[3] + el + ar;
			state[3] = state[4] + al + br;
			state[4] = state[0] + bl + cr;
			state[0] = temp;
		
	


	private static int f(int i, int x, int y, int z) 
		assert 0 <= i && i < 80;
		if (i < 16) return x ^ y ^ z;
		if (i < 32) return (x & y) | (~x & z);
		if (i < 48) return (x | ~y) ^ z;
		if (i < 64) return (x & z) | (y & ~z);
		return x ^ (y | ~z);
	

	private static final int[] KL = 0x00000000, 0x5A827999, 0x6ED9EBA1, 0x8F1BBCDC, 0xA953FD4E;  // Round constants for left line
	private static final int[] KR = 0x50A28BE6, 0x5C4DD124, 0x6D703EF3, 0x7A6D76E9, 0x00000000;  // Round constants for right line

	private static final int[] RL =   // Message schedule for left line
			0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,
			7,  4, 13,  1, 10,  6, 15,  3, 12,  0,  9,  5,  2, 14, 11,  8,
			3, 10, 14,  4,  9, 15,  8,  1,  2,  7,  0,  6, 13, 11,  5, 12,
			1,  9, 11, 10,  0,  8, 12,  4, 13,  3,  7, 15, 14,  5,  6,  2,
			4,  0,  5,  9,  7, 12,  2, 10, 14,  1,  3,  8, 11,  6, 15, 13;

	private static final int[] RR =   // Message schedule for right line
			5, 14,  7,  0,  9,  2, 11,  4, 13,  6, 15,  8,  1, 10,  3, 12,
			6, 11,  3,  7,  0, 13,  5, 10, 14, 15,  8, 12,  4,  9,  1,  2,
			15,  5,  1,  3,  7, 14,  6,  9, 11,  8, 12,  2, 10,  0,  4, 13,
			8,  6,  4,  1,  3, 11, 15,  0,  5, 12,  2, 13,  9,  7, 10, 14,
			12, 15, 10,  4,  1,  5,  8,  7,  6,  2, 13, 14,  0,  3,  9, 11;

	private static final int[] SL =   // Left-rotation for left line
			11, 14, 15, 12,  5,  8,  7,  9, 11, 13, 14, 15,  6,  7,  9,  8,
			7,  6,  8, 13, 11,  9,  7, 15,  7, 12, 15,  9, 11,  7, 13, 12,
			11, 13,  6,  7, 14,  9, 13, 15, 14,  8, 13,  6,  5, 12,  7,  5,
			11, 12, 14, 15, 14, 15,  9,  8,  9, 14,  5,  6,  8,  6,  5, 12,
			9, 15,  5, 11,  6,  8, 13, 12,  5, 12, 13, 14, 11,  8,  5,  6;

	private static final int[] SR =   // Left-rotation for right line
			8,  9,  9, 11, 13, 15, 15,  5,  7,  7,  8, 11, 14, 14, 12,  6,
			9, 13, 15,  7, 12,  8,  9, 11,  7,  7, 12,  7,  6, 15, 13, 11,
			9,  7, 15, 11,  8,  6,  6, 14, 12, 13,  5, 14, 13, 13,  7,  5,
			15,  5,  8, 11, 14, 14,  6, 14,  6,  9, 12,  9, 12,  5, 15,  8,
			8,  5, 12,  9, 12,  5, 14,  6,  8, 13,  6,  5, 15, 13, 11, 11;



	private Ripemd160()   // Not instantiable

import java.math.BigInteger;
import java.util.Arrays;

public class Base58 
	public static final char[] ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz".toCharArray();
	private static final char ENCODED_ZERO = ALPHABET[0];
	private static final int[] INDEXES = new int[128];
	static 
		Arrays.fill(INDEXES, -1);
		for (int i = 0; i < ALPHABET.length; i++) 
			INDEXES[ALPHABET[i]] = i;
		
	

	public static String encode(byte[] input) 
		if (input.length == 0) 
			return "";
		
		int zeros = 0;
		while (zeros < input.length && input[zeros] == 0) 
			++zeros;
		
		input = Arrays.copyOf(input, input.length); // since we modify it in-place
		char[] encoded = new char[input.length * 2]; // upper bound
		int outputStart = encoded.length;
		for (int inputStart = zeros; inputStart < input.length; ) 
			encoded[--outputStart] = ALPHABET[divmod(input, inputStart, 256, 58)];
			if (input[inputStart] == 0) 
				++inputStart; // optimization - skip leading zeros
			
		
		while (outputStart < encoded.length && encoded[outputStart] == ENCODED_ZERO) 
			++outputStart;
		
		while (--zeros >= 0) 
			encoded[--outputStart] = ENCODED_ZERO;
		
		return new String(encoded, outputStart, encoded.length - outputStart);
	

	public static byte[] decode(String input) 
		if (input.length() == 0) 
			return new byte[0];
		
		byte[] input58 = new byte[input.length()];
		for (int i = 0; i < input.length(); ++i) 
			char c = input.charAt(i);
			int digit = c < 128 ? INDEXES[c] : -1;
			if (digit < 0) 
				throw new IllegalStateException("InvalidCharacter in base 58");
			
			input58[i] = (byte) digit;
		
		int zeros = 0;
		while (zeros < input58.length && input58[zeros] == 0) 
			++zeros;
		
		byte[] decoded = new byte[input.length()];
		int outputStart = decoded.length;
		for (int inputStart = zeros; inputStart < input58.length; ) 
			decoded[--outputStart] = divmod(input58, inputStart, 58, 256);
			if (input58[inputStart] == 0) 
				++inputStart; // optimization - skip leading zeros
			
		
		while (outputStart < decoded.length && decoded[outputStart] == 0) 
			++outputStart;
		
		return Arrays.copyOfRange(decoded, outputStart - zeros, decoded.length);
	

	public static BigInteger decodeToBigInteger(String input) 
		return new BigInteger(1, decode(input));
	

	private static byte divmod(byte[] number, int firstDigit, int base, int divisor) 
		int remainder = 0;
		for (int i = firstDigit; i < number.length; i++) 
			int digit = (int) number[i] & 0xFF;
			int temp = remainder * base + digit;
			number[i] = (byte) (temp / divisor);
			remainder = temp % divisor;
		
		return (byte) remainder;
	

以上是关于比特币--通过公钥生成地址全过程的主要内容,如果未能解决你的问题,请参考以下文章

从 ECDSA 公钥生成比特币地址

密钥和地址

比特币『私钥』『公钥』『钱包地址』间的关系

比特币如何防止伪造交易记录?

Bitcoin 地址原理公钥地址到比特币地址

比特币隔离见证钱包地址计算