Hướng dẫn tạo địa chỉ ví Bitcoin từ khóa riêng (Private Key). Nếu bạn chỉ đơn thuần là nhà đầu tư hay trade coin, thì bạn chỉ cần quan tâm cách đăng nhập vào các địa chỉ lưu trữ tài sản số của bạn. Đối với các bạn đam mê bitcoin, cryptos và muốn tìm hiểu sâu hơn về công nghệ blockchain hay mã hóa Bitcoin, bài viết dưới đây sẽ rất thú vị để tìm hiểu.
Mở đầu về tạo ví Bitcoin từ Private Key
Thực tế có nhiều phương pháp khác nhau để tạo khóa riêng. Dù bạn chọn phương pháp nào, bạn sẽ kết thúc với 32 byte dữ liệu. Private Key dưới đây là 1 ví dụ được chúng tôi tạo ra:
60cf347dbc59d31c1358c8e5cf5e45b822ab85b79cb32a9f3d98184779a9efc2
Chúng tôi sẽ sử dụng khóa riêng này trong suốt bài viết để lấy cả khóa công khai (Public Key) và địa chỉ ví Bitcoin (Bitcoin Adress).
Những gì chúng tôi muốn làm là áp dụng một loạt các chuyển đổi cho khóa riêng để lấy khóa chung và sau đó là địa chỉ ví. Hầu hết các chuyển đổi này được gọi là hàm băm. Các hàm băm này là các chuyển đổi một chiều không thể đảo ngược. Chúng tôi sẽ không đi đến cơ chế của các chức năng – có rất nhiều bài viết tuyệt vời bao gồm điều đó. Thay vào đó, chúng tôi sẽ xem xét cách sử dụng các chức năng này theo đúng thứ tự có thể dẫn bạn đến địa chỉ ví Bitcoin mà bạn có thể sử dụng.
Mật mã đường cong Elip
Điều đầu tiên chúng ta cần làm là áp dụng Thuật toán Chữ ký số ECDSA hoặc Elliptic Curve cho khóa riêng của chúng tôi. Đường cong elip là đường cong được xác định bởi phương trình y² = x³ + ax + b
với một lựa chọn a
và b
. Có một gia đình của những đường cong như vậy được biết đến và sử dụng rộng rãi. Bitcoin sử dụng đường cong secp256k1. Nếu bạn muốn tìm hiểu thêm về Mật mã đường cong Elliptic, bạn hãy nghiên cứu chuyên sâu tại bài viết này: Thuật toán đằng sau Bitcoin – mật mã đường cong Elip.
Bằng cách áp dụng ECDSA cho khóa riêng, chúng ta có được số nguyên 64 byte. Điều này bao gồm hai số nguyên 32 byte đại diện cho X và Y của điểm trên đường cong elip, được nối với nhau.
Ví dụ của chúng tôi, chúng tôi đã nhận được:
1e7bcc70c72770dbb72fea022e8a6d07f814d2ebe4de9ae3f7af75bf706902a7b73ff919898c836396a6b0c96812c3213b99372050853bd1678da0ead14487d7
.
Trong Python, nó sẽ trông như thế này:
private_key_bytes = codecs.decode(private_key, ‘hex’)
# Get ECDSA public key
key = ecdsa.SigningKey.from_string(private_key_bytes, curve=ecdsa.SECP256k1).verifying_key
key_bytes = key.to_string()
key_hex = codecs.encode(key_bytes, ‘hex’)
Lưu ý: như bạn có thể thấy từ mã, trước khi tôi sử dụng một phương thức từ ecdsa
mô-đun, tôi đã giải mã khóa riêng bằng cách sử dụng codecs
. Điều này có liên quan nhiều hơn đến Python và ít hơn với chính thuật toán, nhưng tôi sẽ giải thích những gì chúng ta đang làm ở đây để loại bỏ sự nhầm lẫn có thể.
Trong Python, có ít nhất hai lớp có thể giữ các khóa riêng và khóa chung: đó là str str và các byte byte. Đầu tiên là một chuỗi và thứ hai là một mảng byte. Các phương thức mã hóa trong Python hoạt động với một lớp byte byte, lấy nó làm đầu vào và trả về kết quả.
Bây giờ, có một chút bắt: một chuỗi, giả sử, 4f3c
không bằng mảng byte 4f3c
, nó bằng với mảng byte có hai phần tử , O<
. Và đó là codecs.decode
phương thức làm gì : nó chuyển đổi một chuỗi thành một mảng byte. Điều đó sẽ giống nhau cho tất cả các thao tác mã hóa mà chúng ta sẽ làm trong bài viết này.
Tạo Public Key từ Private Key
Khi chúng ta đã hoàn thành với ECDSA, tất cả những gì chúng ta cần làm là thêm các byte 0x04
vào đầu khóa công khai. Kết quả là một khóa công khai đầy đủ Bitcoin, tương đương với:
041e7bcc70c72770dbb72fea022e8a6d07f814d2ebe4de9ae3f7af75bf706902a7b73ff919898c836396a6b0c96812c3213b99372050853bd1678da0ead14487d7
đối với trường hợp của chúng tôi.
Nén khóa công khai Public Key
Nhưng chúng ta có thể làm tốt hơn. Như bạn có thể nhớ, khóa chung là một số điểm (X, Y) trên đường cong. Chúng ta biết đường cong và với mỗi X chỉ có hai Y xác định điểm nằm trên đường cong đó. Vậy tại sao lại giữ Y? Thay vào đó, hãy giữ X và dấu hiệu của Y. Sau đó, chúng ta có thể lấy Y từ đó nếu cần.
Các chi tiết cụ thể như sau: chúng tôi lấy X từ khóa chung ECDSA. Bây giờ, chúng ta thêm 0x02
nếu byte cuối cùng của Y là chẵn và byte 0x03
nếu byte cuối cùng là số lẻ.
Trong trường hợp của chúng tôi, byte cuối cùng là số lẻ, vì vậy chúng tôi thêm 0x03
để lấy khóa chung được nén: 031e7bcc70c72770dbb72fea022e8a6d07f814d2ebe4de9ae3f7af75bf706902a7
. Khóa này chứa cùng một thông tin, nhưng nó ngắn gần gấp đôi so với khóa không nén. Mát mẻ!
Trước đây, phần mềm ví sử dụng các phiên bản dài, đầy đủ của khóa công khai, nhưng bây giờ hầu hết đã chuyển sang khóa nén.
Mã hóa khóa công khai Public Key
Từ bây giờ, chúng ta cần tạo một địa chỉ ví. Bất cứ phương pháp nào để lấy khóa công khai bạn chọn, nó đều trải qua cùng một quy trình. Rõ ràng, các địa chỉ sẽ khác nhau. Trong bài viết này, chúng tôi sẽ đi với phiên bản nén.
Những gì chúng ta cần làm ở đây là áp dụng SHA-256 cho khóa chung và sau đó áp dụng RIPEMD-160 cho kết quả. Thứ tự là quan trọng.
SHA-256 và RIPEMD-160 là hai hàm băm và một lần nữa, chúng ta sẽ không đi sâu vào chi tiết về cách chúng hoạt động. Vấn đề là bây giờ chúng ta có số nguyên 160 bit, sẽ được sử dụng để sửa đổi thêm. Hãy gọi đó là một khóa công khai được mã hóa. Ví dụ của chúng tôi, khóa công khai được mã hóa là 453233600a96384bb8d73d400984117ac84d7e8b
.
Encrypted public key = RIPEMD-160 ( SHA-256 ( Public key ) )
Đây là cách chúng tôi mã hóa khóa công khai trong Python:
public_key_bytes = codecs.decode(public_key, ‘hex’)
# Run SHA-256 for the public key
sha256_bpk = hashlib.sha256(public_key_bytes)
sha256_bpk_digest = sha256_bpk.digest()
# Run RIPEMD-160 for the SHA-256
ripemd160_bpk = hashlib.new(‘ripemd160’)
ripemd160_bpk.update(sha256_bpk_digest)
ripemd160_bpk_digest = ripemd160_bpk.digest()
ripemd160_bpk_hex = codecs.encode(ripemd160_bpk_digest, ‘hex’)
Thêm network Byte
Bitcoin có hai mạng, chính và thử nghiệm. Mạng chính là mạng mà tất cả mọi người sử dụng để chuyển tiền. Mạng thử nghiệm đã được tạo – bạn đoán nó – để kiểm tra các tính năng và phần mềm mới.
Chúng tôi muốn tạo một địa chỉ để sử dụng nó trên mainnet, vì vậy chúng tôi cần thêm 0x00
byte vào khóa công khai được mã hóa. Kết quả là 00453233600a96384bb8d73d400984117ac84d7e8b
. Đối với testnet, đó sẽ là 0x6f
byte.
Checksum
Bây giờ chúng ta cần tính toán tổng kiểm tra của khóa mainnet của chúng tôi. Ý tưởng của tổng kiểm tra là đảm bảo rằng dữ liệu (trong trường hợp của chúng tôi là khóa) không bị hỏng trong quá trình truyền. Phần mềm ví nên xem xét tổng kiểm tra và đánh dấu địa chỉ là không hợp lệ nếu tổng kiểm tra không khớp.
Để tính toán tổng kiểm tra của khóa, chúng ta cần áp dụng SHA-256 hai lần và sau đó lấy 4 byte đầu tiên của kết quả. Ví dụ của chúng tôi, SHA-256 kép là 512f43c48517a75e58a7ec4c554ecd1a8f9603c891b46325006abf39c5c6b995
và do đó tổng kiểm tra là 512f43c4
(lưu ý rằng 4 byte là 8 chữ số hex).
C = SHA256 ( SHA-256 ( Mainnet encrypted public key ) )
Checksum = first 4 bytes of C
Mã để tính toán Checksum địa chỉ như sau:
# Double SHA256 to get checksum
sha256_nbpk = hashlib.sha256(network_bitcoin_public_key_bytes)
sha256_nbpk_digest = sha256_nbpk.digest()
sha256_2_nbpk = hashlib.sha256(sha256_nbpk_digest)
sha256_2_nbpk_digest = sha256_2_nbpk.digest()
sha256_2_hex = codecs.encode(sha256_2_nbpk_digest, ‘hex’)
checksum = sha256_2_hex[:8]
Lấy địa chỉ ví Bitcoin
Cuối cùng, để tạo một địa chỉ, chúng tôi chỉ cần ghép khóa mainnet và tổng kiểm tra. Điều đó làm cho nó 00453233600a96384bb8d73d400984117ac84d7e8b512f43c4
cho ví dụ của chúng tôi.
Đó là nó! Đó là địa chỉ ví cho khóa riêng ở đầu bài viết.
Nhưng bạn có thể nhận thấy rằng một cái gì đó đang tắt. Bạn có thể đã thấy một số địa chỉ Bitcoin và chúng không giống như vậy. Chà, lý do là chúng được mã hóa với Base58 . Đó là một chút kỳ lạ.
Đây là thuật toán để chuyển đổi một địa chỉ hex thành địa chỉ Base58:
def base58(address_hex):
alphabet = ‘123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz’
b58_string = ‘’
# Get the number of leading zeros
leading_zeros = len(address_hex) — len(address_hex.lstrip(‘0’))
# Convert hex to decimal
address_int = int(address_hex, 16)
# Append digits to the start of string
while address_int > 0:
digit = address_int % 58
digit_char = alphabet[digit]
b58_string = digit_char + b58_string
address_int //= 58
# Add ‘1’ for each 2 leading zeros
ones = leading_zeros // 2
for one in range(ones):
b58_string = ‘1’ + b58_string
return b58_string
Những gì chúng tôi nhận được là 17JsmEygbbEUEpvt4PFtYaTeSqfb9ki1F1
, một địa chỉ ví Bitcoin đã được nén.
Hex adress = Mainnet encrypted public key + Checksum
Adress = Base58 (Hex address)
Kết luận
Trên đây chúng tôi đã hướng dẫn các bạn từng bước và ví dụ về cách tạo địa chỉ ví Bitcoin từ Private Key.
Tóm lại, quá trình tạo khóa ví có thể được chia thành bốn bước:
- Tạo khóa chung với ECDSA
- Mã hóa khóa bằng SHA-256 và RIPEMD-160
- Tính toán tổng kiểm tra với gấp đôi SHA-256
- Mã hóa khóa với Base58.
Tùy thuộc vào hình thức của khóa công khai (đầy đủ hoặc được nén), chúng tôi nhận được các địa chỉ khác nhau, nhưng cả hai đều hoàn toàn hợp lệ.
Đây là thuật toán đầy đủ cho khóa công khai không nén:

Hy vọng các bạn đã có được các kiến thức cho riêng mình.