將任意檔案寫入以太坊區塊的方法
以太坊除數字貨幣方面的應用外,還可以儲存無法被篡改/刪除的資料(51%雙花攻擊或者區塊回滾除外)。
一段文字,一張照片,或者一首歌曲,只需寫入以太坊區塊中,即可真正做到 “恆久遠 永流傳” ,不會出現網盤、郵箱、網站上儲存的資料丟失的情況。
以下介紹將資料寫入以太坊區塊的方法。
由於以太坊轉賬的gas存在上限,所以可傳送的資料也存在限制,大約只能傳送不超過44KB的資料。參考:https://blog.csdn.net/shebao3333/article/details/80112436
過大的檔案,可以採取分塊寫入的方式。需注意,轉賬的gas手續費與寫入的資料大小存在正比關係,即寫入的越多,手續費越高,區塊確認速度相對也比較慢。
前置步驟:安裝chrome錢包外掛METAMASK,匯入錢包,試用主網購入ETH或者使用測試網路獲取免費ETH,參考:https://blog.csdn.net/kaitiren/article/details/79299394
一. 將文字寫入以太坊區塊
步驟:1.將文字轉為UTF-8格式,可使用線上工具轉換http://tool.chinaz.com/Tools/UTF-8.aspx
2.將utf-8編碼轉為16進位制編碼,可使用線上轉換http://www.5ixuexiwang.com/str/hex.php
3.開啟METAMASK錢包,使用send選項,傳送的錢包地址可隨意,傳送數量為0即可
完成傳送ETH後,在交易記錄裡檢視區塊資訊即可:
等待交易確認完畢後,在區塊交易頁面下方,可以查詢到剛才寫入區塊的文字:
這時候,這篇文章就寫入了以太坊區塊中,任何人無法修改與刪除
區塊檢視:https://ropsten.etherscan.io/tx/0x5af3ba0973b6c4663730be8ef701accadea12fc6e9b0485f8974c139d4d8fe3c
二.將檔案寫入以太坊區塊
1.將檔案轉為byte陣列:(java實現)
public static byte[] getBytes(String filePath){
byte[] buffer = null;
try {
File file = new File(filePath);
FileInputStream fis = new FileInputStream(file);
ByteArrayOutputStream bos = new ByteArrayOutputStream(1000);
byte[] b = new byte[1000];
int n;
while ((n = fis.read(b)) != -1) {
bos.write(b, 0, n);
}
fis.close();
bos.close();
buffer = bos.toByteArray();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return buffer;
}
2.將byte陣列轉為16進位制字串:(java實現)
public static String bytesToHexFun1(byte[] bytes) {
// 一個byte為8位,可用兩個十六進位制位標識
char[] HEX_CHAR = {'0', '1', '2', '3', '4', '5',
'6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
char[] buf = new char[bytes.length * 2];
int a = 0;
int index = 0;
for(byte b : bytes) { // 使用除與取餘進行轉換
if(b < 0) {
a = 256 + b;
} else {
a = b;
}
buf[index++] = HEX_CHAR[a / 16];
buf[index++] = HEX_CHAR[a % 16];
}
return new String(buf);
}
傳送到以太坊區塊的方法,與傳送文字相同,只需將16進位制編碼填入交易資訊即可。
從區塊中還原出文件的方法,將16進位制編碼還原為byte陣列:
public static byte[] toBytes(String str) {
if(str == null || str.trim().equals("")) {
return new byte[0];
}
byte[] bytes = new byte[str.length() / 2];
for(int i = 0; i < str.length() / 2; i++) {
String subStr = str.substring(i * 2, i * 2 + 2);
bytes[i] = (byte) Integer.parseInt(subStr, 16);
}
return bytes;
}
byte陣列轉為檔案輸出到本地:
public static void writeFile(byte[] bfile, String filePath) {
BufferedOutputStream bos = null;
FileOutputStream fos = null;
File file = null;
try {
File dir = new File(filePath);
if(!dir.exists()&&dir.isDirectory()){//判斷檔案目錄是否存在
dir.mkdirs();
}
file = new File(filePath);
fos = new FileOutputStream(file);
bos = new BufferedOutputStream(fos);
bos.write(bfile);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (bos != null) {
try {
bos.close();
} catch (IOException e1) {
e1.printStackTrace();
}
}
if (fos != null) {
try {
fos.close();
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
}