Trong ví blockchain đầu tiên (hiện nay được gọi là Bitcoin Core), ví là tập hợp các khóa bí mật được tạo ngẫu nhiên. Ví dụ, phần mềm Bitcoin Core
gốc tạo sẵn 100 khóa bí mật ngẫu nhiên khi khởi động lần đầu tiên và tạo ra thêm các khóa khi cần thiết, mỗi khóa chỉ sử dụng một lần. Việc quản lý, sao lưu và nhập các ví này rất phiền phức vì vậy chúng đang bị thay thế bởi các ví tất định. Điểm bất lợi của các khóa ngẫu nhiên là nếu tạo nhiều khóa, người dùng sẽ phải giữ bản sao của tất cả các khóa đó, điều này đồng nghĩa với việc phải sao lưu ví thường xuyên. Phải sao lưu từng khóa, nếu không số tiền do các khóa kiểm soát sẽ bị mất vĩnh viễn nếu không truy cập được ví. Điều này xung đột trực tiếp với nguyên tắc tránh dùng lại địa chỉ thông qua việc sử dụng mỗi địa chỉ bitcoin cho riêng một giao dịch. Việc dùng lại địa chỉ làm giảm đi tính bảo mật do liên kết nhiều giao dịch và địa chỉ lại với nhau. Hình 2-1 minh họa một ví bất định, chứa mộ tập hợp các khóa ngẫu nhiên không liên quan đến nhau.
Hình 2.1. Ví bất định 2.1.2. Ví tất định
Ví tất định, hay ví “được gieo hạt”, là ví chứa các khóa bí mật được tạo ra từ hạt giống chung bằng hàm băm một chiều. Hạt giống này là một số được
tạo ngẫu nhiên sau đó kết hợp với các dữ liệu khác, ví dụ như một chỉ số hay một “mã chuỗi” (chain code) để tạo ra các khóa bí mật. Trong ví tất định, chỉ cần hạt giống này là có thể khôi phục lại tất cả các khóa được tạo ra, do đó chỉ cần một bản sao lưu vào thời điểm khởi tạo là đủ. Hạt giống này cũng có thể xuất và nhập ví, cho phép dễ dàng di chuyển qua lại tất cả các khóa của người dùng giữa các bản thực thi ví khác nhau. Hình 2.2 là biểu đồ logic của một ví tất định.
Hình 2.2. Ví tất định (được gieo hạt): một chuỗi khóa tất định được tạo ra từ
một hạt giống 0’/0/2.
2.2. MỘT SỐ CÁCH LƯU TRỮ CỦA VÍ ĐIỆN TỬ BLOCKCHAIN
Thời gian gần đây đã xảy ra rất nhiều vụ tấn công đến ví tiền điện tử Blockchain, ví dụ điển hình như vụ tấn công sàn giao dịch Coincheck vào tháng 1/2018 đã bị đánh cắp token có giá trị lên tới 530 triệu USD. Đây là vụ tấn công lớn nhất cho tới thời điểm hiện tại. Chính vì vậy nên quan tâm tới
cách lưu trữ tiền điện tử một cách an toàn hơn. Có hai loại lưu trữ chính là ví lạnh và ví nóng. Ví nóng thì được kết nối với Internet còn ví lạnh thì không.
2.2.1. Ví nóng
Ví nóng là ví dễ dàng tạo nhất sau khi thực hiện mua tiền điện tử trên sàn. Coinbase và một số sàn giao dịch khác đều cung cấp ví miễn phí nhưng tiền điện tử của người dùng vẫn có nguy cơ bị tấn công. Ví nóng có thể dễ dàng chi tiêu, giao dịch một cách nhanh chóng với việc kết nối trực tiếp tới Internet. Tuy nhiên, hacker có thể tấn công mật khẩu trên ví nóng.
Ví nóng là miễn phí và nói chung khá dễ dàng để thiết lập. Chúng có nhiều định dạng khác nhau như phần mềm máy tính, thiết bị di động hoặc trưc tuyến. Các ví khác nhau hỗ trợ các loại tiền điện tử khác nhau, vì vậy nên chọn phù hợp với mục tiêu đầu tư ban đầu. Dưới đây là bốn tùy chọn ví nóng phổ biến:
Blockchain.info
Blockchain.info có một ví trực tuyến lưu trữ Bitcoin và Ethereum. Ví cho BTC hoặc ETH là một lựa chọn tốt cho người dùng vì dễ sử dụng và có giao diện rõ ràng.
Myetherwallet.com
MyEtherWallet (MEW) tích hợp tốt với Trezor, một ví trữ lạnh sẽ được đề cập ở phần sau. Với một số người dùng, việc thiết lập ví MEW trở nên khó khăn nhưng nó hoạt động tốt trên nhiều thiết bị và hỗ trợ Etherum, các ERC- 20 token.
Electrum
Electrum đã có mặt từ những ngày đầu (2011) và cung cấp một phần mềm ví với nhiều tính năng an toàn mới. Có thể tích hợp với kho lưu trữ lạnh và khôi phục mật khẩu của mình nếu cần. Electrum chỉ hỗ trợ lưu trữ Bitcoin, vì vậy sẽ phải tạo một ví khác nếu muốn lưu trữ các loại tiền điện tử khác.
Exodus Wallet
Với giao diện biểu đồ hình tròn tuyệt đẹp thể hiện tất cả các khoản đầu tư, Exodus là một ví tiền hấp dẫn, dễ sử dụng cho những người đầu từ vào tiền điện tử.
Vì vậy nếu như thường xuyên giao dịch, nên cần một ví nóng. Nếu như chỉ lưu trữ và đầu tư dài hạn nên mua ví lưu trữ lạnh để đảm bảo an toàn hơn các lựa chọn ở trên.
2.2.2. Ví trữ lạnh
Ví lạnh là cách an toàn nhất để lưu trữ coin vì coin sẽ được lưu trữ ngoại tuyến. Nếu không cần truy cập nhiều, ví lạnh là lựa chọn an toàn nhất miễn là chúng được sử dụng đúng cách. Có hai lựa chọn khi nói đến ví lạnh là ví giấy và ví phần cứng.
Ví giấy
Ví giấy dễ thiết lập và rất an toàn nếu sử dụng đúng cách. Không giống như ví nóng hay ví phần cứng, không có cách nào truy xuất khóa bí mật nếu ví giấy bị mất. Hoặc nếu ví giấy bị phá hủy, ví dụ như trong một vụ hỏa hoạn, sẽ mất hoàn toàn tiền được lưu trong ví. Ví giấy tốt cho việc lưu trữ tiền dài hạn.
Ví phần cứng
Ví phần cứng mạnh hơn và tiện lợi hơn ví giấy. Cả hai tùy chọn này đều tích hợp tốt với ví nóng, cho phép bạn kết nối và chuyển tiền khi cần giao dịch.
Trezor và Ledger Nano S là cả hai tùy chọn lưu trữ dài hạn với việc kết nối tới máy tính thông qua USB. Những lợi thế chính cho các ví phần cứng này là khả năng sử dụng, hỗ trợ nhiều coin và bảo mật.
2.3. VÍ ĐIỆN TỬ BLOCKCHAIN
Blockchain được lưu trữ trong “địa chỉ” dựa trên cặp khóa ECDSA công khai/bí mật. Hầu hết mỗi địa chỉ được tạo ra bởi một khóa bí mật duy nhất.
Những địa chỉ này (còn gọi là “địa chỉ tiêu chuẩn”), có thể được nhận ra dễ dàng bởi thực tế chúng luôn bắt đầu bằng “0” hoặc “1”. Bất kỳ ai biết khóa bí mật tương ứng với địa chỉ này đều có thể chi tiêu lượng bitcoin của địa chỉ. Giao dịch thành công không thể đảo ngược. Cách lưu trữ này chỉ yêu cầu một chữ ký khi giao dịch vì vậy dẫn đến một số vấn đề quan trọng đối với Bitcoin.
2.3.1. Bảo mật
Ở mức độ đơn giản nhất, một ví Blockchain đơn giản chỉ có một khóa cho phép người dùng ký và giao dịch bitcoin của mình, các khóa này thường được tạo ra và lưu trữ trên một thiết bị. Mặc dù có thể thực hiện các biện pháp bảo mật tốt thì bất kỳ thiết bị nào lưu trữ một khóa như vậy rất dễ trở thành điểm yếu. Nếu tập tin lưu trữ khóa bị đánh cắp, hacker hoặc phần mềm độc hại tấn công thì người dùng coi như đã mất kiểm soát ví của mình. Hiện nay Bitcoin đã phát triển và có giá trị rất lớn, đi kèm theo đó là mục tiêu nhắm tới của các hacker. Đó là nguy cơ bảo mật cơ bản của lưu trữ một khóa dẫn đến việc phát triển các giao thức phức tạp hơn như lưu trữ ngoại tuyến, lưu trữ lạnh.
2.3.2. Kiểm soát truy cập
Làm cách nào để các doanh nghiệp có thể sử dụng Blockchain hiệu quả? Thông thường các doanh nghiệp thường ủy thác trách nhiệm tích hợp công nghệ cho nhân viên CNTT của họ. Nhưng việc giảm tải trách nhiệm cho một chiếc Ví Blockchain như để lại một đống hóa đơn trị giá 100 USD trên một cái bàn ở giữa văn phòng. Vì bất kỳ ai có quyền truy cập vào các khóa đều có thể chuyển tiền mà không để lại dấu vết, nếu nhiều người có quyền truy cập vào một khóa duy nhất, không có cách nào thực sự đạt được trách nhiệm hoặc để ngăn chặn hành vi trộm cắp nội bộ. Vấn đề đặt ra là làm sao kiểm soát truy cập cho những người được ủy thác giao dịch.
Để tạo giao dịch có chữ ký, trước tiên cần tạo một giao dịch thô chưa ký có input là đầu ra chưa chi tiêu UTXO trước đó. Giao dịch này sẽ băm với hàm băm SHA256 làm đầu vào sử dụng thuật toán chữ ký số ECDSA. Sơ đồ tạo chữ ký được mô tả như hình 2.3.
Hình 2.3. Tạo chữ ký cho giao dịch
Các bước thực hiện:
a. Unsigned TX sẽ được băm với SHA256 tạo ra bản tóm lược làm đầu vào để ký
b. Dùng khóa bí mật của A để ký lên đầu vào bản tóm lược với thuật toán ECDSA.
c. Kết quả sẽ là một giá trị chữ ký của A
ra bản tóm lược. Với giá trị chữ ký A sẽ được giải mã bằng khóa công khai A tạo ra bản tóm lược 1. So sánh hai giá trị này nếu giống nhau thì là chữ ký đúng. Ngược lại, nếu hai giá trị khác nhau nghĩa là chữ ký không đúng. Sơ đồ kiểm tra chữ ký được mô tả như hình 2-4.
Hình 2.4. Quá trình kiểm tra chữ ký 2.4. TẠO VÍ BLOCKCHAIN
Trong các loại tiền tệ kĩ thuật số, quyền sở hữu đồng tiền được chuyển giao trên Blockchain như các giao dịch, người tham gia có địa chỉ ví mà đồng tiền có thể được gửi đến và đi. Trong ví dụ cơ bản, ví của họ có thể lưu trữ các địa chỉ này, hầu hết các ví đều có thể thực hiện các giao dịch mới trên Blockchain.
Hình 2.5. Ví Blockchain
Trong ví nắm giữ Public key (khóa công khai) và Private keys (khóa bí mật) được thể hiện qua đoạn code sau:
package NoobChain; import java.security.*; public class Wallet {
public PrivateKey privateKey; public PublicKey publicKey; }
Đối với đồng tiền kĩ thuật số của chúng ta, Public key (khóa công khai) sẽ hoạt động như địa chỉ. Ta có thể chia sẻ khóa công khai này với những người khác để nhận thanh toán. Private key (khóa bí mật) được sử dụng để ký các giao dịch, để không ai có thể chi tiêu đồng tiền ngoài chủ sở hữu của chúng. Người dùng sẽ phải giữ bí mật Private key (khóa bí mật) của họ! Chúng ta cũng gửi khóa công khai cùng với giao dịch và nó có thể sử dụng để xác minh rằng chữ ký hợp lệ và dữ liệu không bị giả mạo.
Hình 2.6. Xác minh chữ ký
Thuật toán sinh ra cặp khóa qua đoạn code như sau: package NoobChain;
import java.security.*;
import java.security.spec.ECGenParameterSpec; public class Wallet {
public PrivateKey privateKey; public PublicKey publicKey; public Wallet() {
generateKeyPair();
}
public void generateKeyPair() {
try {
KeyPairGenerator keyGen =
KeyPairGenerator.getInstance("ECDSA", "BC");
SecureRandom random =
SecureRandom.getInstance("SHA1PRNG");
ECGenParameterSpec ecSpec = new
ECGenParameterSpec("prime192v1");
KeyPair keyPair = keyGen.generateKeyPair();
privateKey = keyPair.getPrivate();
publicKey = keyPair.getPublic();
} catch (Exception e) {
throw new RuntimeException(e);
}
} }
Kết quả của thuật toán này là một chuỗi ký tự khóa có dạng:
2.4.1. Cách tạo các giao dịch
Mỗi giao dịch sẽ mang một lượng dữ liệu nhất định: Khóa công khai (địa chỉ) của người gửi tiền.
Khóa công khai (địa chỉ) của người nhận tiền. Giá trị / số tiền cần chuyển.
Đầu vào, là các tham chiếu đến các giao dịch trước đó chứng minh người gửi có tiền để gửi.
Kết quả, cho thấy số lượng địa chỉ liên quan nhận được trong giao dịch. (Những đầu ra này được tham chiếu như đầu vào trong các giao dịch mới)
Một chữ ký mã hoá, chứng minh chủ sở hữu địa chỉ là người gửi giao dịch này và dữ liệu không bị thay đổi. (ví dụ: ngăn cản một bên thứ ba thay đổi số tiền đã gửi)
Thuật toán giao dịch trong ví Blockchain bằng đoạn code như sau: package NoobChain;
import java.security.*; import java.util.ArrayList; public class Transaction { public String transactionId;
public PublicKey sender; public PublicKey reciepient; public float value;
public byte[] signature;
public ArrayList<TransactionInput> inputs = new ArrayList<TransactionInput>();
public ArrayList<TransactionOutput> outputs = new ArrayList<TransactionOutput>();
private static int sequence = 0
public Transaction(PublicKey from, PublicKey to, float value, ArrayList<TransactionInput> inputs) { this.sender = from; this.reciepient = to; this.value = value; this.inputs = inputs; }
private String calulateHash() {
sequence++;
return StringUtil.applySha256(StringUtil.getStringFromKey(sender) + StringUtil.getStringFromKey(reciepient)
+ Float.toString(value) + sequence); }
public void generateSignature(PrivateKey privateKey) { String data = StringUtil.getStringFromKey(sender) + StringUtil.getStringFromKey(reciepient)
+ Float.toString(value);
signature = StringUtil.applyECDSASig(privateKey, data); }
String data = StringUtil.getStringFromKey(sender) + StringUtil.getStringFromKey(reciepient)
+ Float.toString(value);
return StringUtil.verifyECDSASig(sender, data, signature); }
public boolean processTransaction() { if (verifiySignature() == false) {
System.out.println("#Transaction Signature failed to verify"); return false;
}
for (TransactionInput i : inputs) {
i.UTXO = NoobChain.UTXOs.get(i.transactionOutputId); }
if (getInputsValue() < NoobChain.minimumTransaction) { System.out.println("#Transaction Inputs to small: " + getInputsValue());
return false; }
float leftOver = getInputsValue() - value; transactionId = calulateHash();
outputs.add(new TransactionOutput(this.reciepient, value, transactionId)); outputs.add(new TransactionOutput(this.sender, leftOver, transactionId)); for (TransactionOutput o : outputs) {
NoobChain.UTXOs.put(o.id, o); }
for (TransactionInput i : inputs) { if (i.UTXO == null)
continue;
NoobChain.UTXOs.remove(i.UTXO.id); }
return true; }
public float getInputsValue() { float total = 0;
for (TransactionInput i : inputs) { if (i.UTXO == null) continue; total += i.UTXO.value; } return total; }
public float getOutputsValue() { float total = 0;
for (TransactionOutput o : outputs) { total += o.value; } return total; } } 2.4.2. Xác thực chữ ký
Chữ ký thực hiện hai nhiệm vụ rất quan trọng trên Blockchain: Thứ nhất, nó chỉ cho phép chủ sở hữu chi tiêu tiền của họ, thứ hai, nó ngăn chặn người khác can thiệp vào giao dịch trước khi một Block mới được khai thác.
Ví dụ: Tú muốn gửi 2 coin đến Minh, do đó ví của họ tạo ra giao dịch và gửi cho người khai thác mỏ để thêm dữ liệu vào trong block tiếp theo. Một thợ mỏ cố gắng để thay đổi người nhận của 2 đồng tiền là Hoa. Tuy nhiên, may mắn thay, Tú đã ký kết dữ liệu giao dịch với khóa riêng của mình, cho phép bất cứ ai kiểm tra xem dữ liệu giao dịch đã được thay đổi bằng khóa công khai của Tú hay không.
Thuật toán ký và kiểm tra chữ ký vào lớp chữ ký StringUtil như sau: // Applies ECDSA Signature and returns the result ( as bytes ).
public static byte[] applyECDSASig(PrivateKey privateKey, String input) {
Signature dsa;
byte[] output = new byte[0]; try {
dsa = Signature.getInstance("ECDSA", "BC"); dsa.initSign(privateKey);
byte[] strByte = input.getBytes(); dsa.update(strByte);
byte[] realSig = dsa.sign(); output = realSig;
} catch (Exception e) {
throw new RuntimeException(e); }
return output; }
// Verifies a String signature
public static boolean verifyECDSASig(PublicKey publicKey, String data, byte[] signature) {
try {
Signature ecdsaVerify = Signature.getInstance("ECDSA", "BC"); ecdsaVerify.initVerify(publicKey);
ecdsaVerify.update(data.getBytes()); return ecdsaVerify.verify(signature); } catch (Exception e) {
throw new RuntimeException(e); }
2.4.3. Sở hữu tiền điện tử
Để bạn sở hữu một Bitcoin, bạn phải nhận được một Bitcoin. Sổ cái không thực sự thêm một Bitcoin cho bạn và trừ đi một Bitcoin từ người gửi, người gửi phải tham chiếu rằng trước đây họ đã nhận được một Bitcoin, sau đó một giao dịch được tạo ra cho thấy một Bitcoin được gửi đến địa chỉ của bạn. ( Đầu vào của giao dịch tham chiếu đến kết quả các giao dịch trước đó).
Số dư ví của bạn là tổng của tất cả các kết quả giao dịch chưa được chi tiêu được gửi cho bạn.
Hình 2.7. Ví dụ tập UTXO
Thuật toán chuyển tiền được thực hiện qua đoạn code sau: Lớp này sẽ được sử dụng để tham chiếu đến TransactionOutputs chưa được chi tiêu. TransactionOutputId sẽ được sử dụng để tìm các TransactionOutput có liên quan, cho phép các thợ mỏ kiểm tra quyền sở hữu của bạn.
Package NoobChain;
public String transactionOutputId; public TransactionOutput UTXO;
public TransactionInput(String transactionOutputId) { this.transactionOutputId = transactionOutputId; }
}
Tạo TransactionOutput class: package NoobChain;
import java.security.PublicKey; public class TransactionOutput {
public String id;
public PublicKey reciepient; public float value;
public String parentTransactionId; //Constructor
public TransactionOutput(PublicKey reciepient, float value, String parentTransactionId) { this.reciepient = reciepient; this.value = value; this.parentTransactionId = parentTransactionId; this.id=StringUtil.applySha256(StringUtil.getStringFromKey(reciepient)+Floa t.toString(value)+parentTransactionId); }
public boolean isMine(PublicKey publicKey) { return (publicKey == reciepient);
} }
Kết quả giao dịch sẽ hiển thị số tiền cuối cùng được gửi cho mỗi bên từ giao dịch. Nó được tham chiếu là đầu vào trong các giao dịch mới, hoạt động
như bằng chứng cho thấy bạn có tiền để gửi.
2.4.4. Xử lý giao dịch
Các khối trong chuỗi có thể nhận được nhiều giao dịch và Blockchain có thể rất dài, có thể mất thời gian để xử lý một giao dịch mới vì chúng ta phải tìm và kiểm tra đầu vào của nó. Để giải quyết vấn đề này, chúng ta sẽ giữ thêm một tập hợp tất cả các giao dịch chưa được chi tiêu được sử dụng làm đầu vào.
Chúng ta thực hiện một số kiểm tra để đảm bảo rằng giao dịch hợp lệ,