數(shù)字錢包私鑰與助記詞的相互轉(zhuǎn)化

參考:助記詞(Mnemonics)生成種子,以及Public Key, Private key?https://my.oschina.net/gavinzheng731/blog/1847838

【區(qū)塊鏈 | ETH】Web3j創(chuàng)建錢包的2種方式的對(duì)比https://blog.csdn.net/qq_28505809/article/details/99857208

基本大意,根據(jù)BIP39,11位二進(jìn)制數(shù)轉(zhuǎn)化成一個(gè)單詞,如果有不足的位數(shù),使用私鑰hash的結(jié)果來填充,于是助記詞和私鑰之間就可以相互轉(zhuǎn)換了。

貼上代碼

/**

* pk is 256 bits, the mn words will be 24

*/

@Override

public List<String> getWords(byte[] pk) throws Exception {

ArrayList<String> ret = new ArrayList<String>();

byte[] out = CreateCredentialsUtil.pk2mn("SHA-256", "", pk);

int n;

n = (out[0] & 0xff) << 3 | (out[1] & 0xff) >> 5;

ret.add(words.get(n));

n = (out[1] & 0x1f) << 6 | (out[2] & 0xff) >> 2;

ret.add(words.get(n));

n = (out[2] & 0x03) << 9 | (out[3] & 0xff) << 1 | (out[4] & 0xff) >> 7;

ret.add(words.get(n));

n = (out[4] & 0x7f) << 4 | (out[5] & 0xff) >> 4;

ret.add(words.get(n));

n = (out[5] & 0x0f) << 7 | (out[6] & 0xff) >> 1;

ret.add(words.get(n));

n = (out[6] & 0x01) << 10 | (out[7] & 0xff) << 2 | (out[8] & 0xff) >> 6;

ret.add(words.get(n));

n = (out[8] & 0x3f) << 5 | (out[9] & 0xff) >> 3;

ret.add(words.get(n));

n = (out[9] & 0x07) << 8 | (out[10] & 0xff) ;

ret.add(words.get(n));

// round 2

n = (out[11] & 0xff) << 3 | (out[12] & 0xff) >> 5;

ret.add(words.get(n));

n = (out[12] & 0x1f) << 6 | (out[13] & 0xff) >> 2;

ret.add(words.get(n));

n = (out[13] & 0x03) << 9 | (out[14] & 0xff) << 1 | (out[15] & 0xff) >> 7;

ret.add(words.get(n));

n = (out[15] & 0x7f) << 4 | (out[16] & 0xff) >> 4;

ret.add(words.get(n));

n = (out[16] & 0x0f) << 7 | (out[17] & 0xff) >> 1;

ret.add(words.get(n));

n = (out[17] & 0x01) << 10 | (out[18] & 0xff) << 2 | (out[19] & 0xff) >> 6;

ret.add(words.get(n));

n = (out[19] & 0x3f) << 5 | (out[20] & 0xff) >> 3;

ret.add(words.get(n));

n = (out[20] & 0x07) << 8 | (out[21] & 0xff) ;

ret.add(words.get(n));

// round 3

n = (out[22] & 0xff) << 3 | (out[23] & 0xff) >> 5;

ret.add(words.get(n));

n = (out[23] & 0x1f) << 6 | (out[24] & 0xff) >> 2;

ret.add(words.get(n));

n = (out[24] & 0x03) << 9 | (out[25] & 0xff) << 1 | (out[26] & 0xff) >> 7;

ret.add(words.get(n));

n = (out[26] & 0x7f) << 4 | (out[27] & 0xff) >> 4;

ret.add(words.get(n));

n = (out[27] & 0x0f) << 7 | (out[28] & 0xff) >> 1;

ret.add(words.get(n));

n = (out[28] & 0x01) << 10 | (out[29] & 0xff) << 2 | (out[30] & 0xff) >> 6;

ret.add(words.get(n));

n = (out[30] & 0x3f) << 5 | (out[31] & 0xff) >> 3;

ret.add(words.get(n));

n = (out[31] & 0x07) << 8 | (out[32] & 0xff) ;

ret.add(words.get(n));

return ret;

}

@Override

public byte[] getPk(List<String> input) {

byte[] ret = new byte[32];

int[] in = new int[24];

for (int i = 0; i < 24; ++i) {

in[i] = words.indexOf(input.get(i));

}

// round 1

ret[0] = (byte) ((in[0] & 0x7ff) >> 3);

ret[1] = (byte) ((in[0] & 0x07) << 5 | (in[1] & 0x7ff) >> 6);

ret[2] = (byte) ((in[1] & 0x3f) << 2 | (in[2] & 0x7ff) >> 9);

ret[3] = (byte) ((in[2] & 0x1ff) >> 1);

ret[4] = (byte) ((in[2] & 0x1) << 7 | (in[3] & 0x7ff) >> 4);

ret[5] = (byte) ((in[3] & 0xf) << 4 | (in[4] & 0x7ff) >> 7);

ret[6] = (byte) ((in[4] & 0x7f) << 1 | (in[5] & 0x7ff) >> 10);

ret[7] = (byte) ((in[5] & 0x3ff) >> 2);

ret[8] = (byte) ((in[5] & 0x3) << 6 | (in[6] & 0x7ff) >> 5);

ret[9] = (byte) ((in[6] & 0x1f) << 3 | (in[7] & 0x7ff) >> 8);

ret[10] = (byte) ((in[7] & 0xff));

// round 2

ret[11] = (byte) ((in[8] & 0x7ff) >> 3);

ret[12] = (byte) ((in[8] & 0x07) << 5 | (in[9] & 0x7ff) >> 6);

ret[13] = (byte) ((in[9] & 0x3f) << 2 | (in[10] & 0x7ff) >> 9);

ret[14] = (byte) ((in[10] & 0x1ff) >> 1);

ret[15] = (byte) ((in[10] & 0x1) << 7 | (in[11] & 0x7ff) >> 4);

ret[16] = (byte) ((in[11] & 0xf) << 4 | (in[12] & 0x7ff) >> 7);

ret[17] = (byte) ((in[12] & 0x7f) << 1 | (in[13] & 0x7ff) >> 10);

ret[18] = (byte) ((in[13] & 0x3ff) >> 2);

ret[19] = (byte) ((in[13] & 0x3) << 6 | (in[14] & 0x7ff) >> 5);

ret[20] = (byte) ((in[14] & 0x1f) << 3 | (in[15] & 0x7ff) >> 8);

ret[21] = (byte) ((in[15] & 0xff));

// round 3

ret[22] = (byte) ((in[16] & 0x7ff) >> 3);

ret[23] = (byte) ((in[16] & 0x07) << 5 | (in[17] & 0x7ff) >> 6);

ret[24] = (byte) ((in[17] & 0x3f) << 2 | (in[18] & 0x7ff) >> 9);

ret[25] = (byte) ((in[18] & 0x1ff) >> 1);

ret[26] = (byte) ((in[18] & 0x1) << 7 | (in[19] & 0x7ff) >> 4);

ret[27] = (byte) ((in[19] & 0xf) << 4 | (in[20] & 0x7ff) >> 7);

ret[28] = (byte) ((in[20] & 0x7f) << 1 | (in[21] & 0x7ff) >> 10);

ret[29] = (byte) ((in[21] & 0x3ff) >> 2);

ret[30] = (byte) ((in[21] & 0x3) << 6 | (in[22] & 0x7ff) >> 5);

ret[31] = (byte) ((in[22] & 0x1f) << 3 | (in[23] & 0x7ff) >> 8);

// ret[32] = (byte) ((in[23] & 0xff));

return ret;

}

單詞文件,請(qǐng)到https://github.com/bitcoin/bips/tree/master/bip-0039自行尋找。

最后寫點(diǎn)小收獲,java的BigInteger, 轉(zhuǎn)成byte[]時(shí),如果第一個(gè)byte是負(fù)數(shù),那么會(huì)在其前加上一個(gè)byte,值是0。這樣,256位的私鑰,本來應(yīng)該變成32個(gè)byte,卻變成了33個(gè)byte,這樣處理,是因?yàn)槿绻胋yte數(shù)組生成大整數(shù),如果最高位為1,那么生成的整數(shù)是負(fù)的。但如果這些byte變成字串,則沒關(guān)系。比如BigInteger(“FFF”,16)并不會(huì)變成一個(gè)負(fù)數(shù)。

以上方法,助記詞和私鑰可以相互轉(zhuǎn)化,另有一種從助記詞生成私鑰的方法,(但反向不行)

參考 java使用bip39創(chuàng)建以太坊錢包http://www.itdecent.cn/p/14b9d2908a66

區(qū)塊鏈知識(shí)普及之 BIP39 助記詞生成過程詳解http://www.itdecent.cn/p/3db04e987a6c

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容