Skip to content

Commit

Permalink
from same mnemonic, to generate key is the same of the libra cli gene…
Browse files Browse the repository at this point in the history
…rate
  • Loading branch information
wenshenjun committed Jul 9, 2019
1 parent 18a61ac commit 7292cb6
Show file tree
Hide file tree
Showing 5 changed files with 50 additions and 9 deletions.
1 change: 1 addition & 0 deletions .gitignore
Expand Up @@ -2,3 +2,4 @@ build
node_modules
.DS_Store
.idea
libra-web.iml
19 changes: 13 additions & 6 deletions packages/libra-web-account/KeyFactory.ts
Expand Up @@ -12,10 +12,12 @@ import { Mnemonic } from './Mnemonic'
export class Seed {
public static fromMnemonic(words: string[] | Mnemonic, salt: string = 'LIBRA'): Seed {
const mnemonic: Mnemonic = Array.isArray(words) ? new Mnemonic(words) : words
const mnemonicBytes = mnemonic.toBytes()
const parsedSalt = `${KeyPrefixes.MnemonicSalt}${salt}`

const bytes = new Pbkdf('sha256').extract(mnemonicBytes, parsedSalt, 2048, 32)
const bytes = new Pbkdf('sha3-256').pbkdf2(
mnemonic.toBytes(),
Buffer.from(`${KeyPrefixes.MnemonicSalt}${salt}`),
2048,
32,
)
return new Seed(bytes)
}
public readonly data: Uint8Array
Expand All @@ -38,7 +40,7 @@ export class KeyFactory {

constructor(seed: Seed) {
this.seed = seed
this.hkdf = new Hkdf('sha256')
this.hkdf = new Hkdf('sha3-256')
this.masterPrk = this.hkdf.extract(this.seed.data, KeyPrefixes.MasterKeySalt)
}

Expand All @@ -47,7 +49,12 @@ export class KeyFactory {
*
*/
public generateKey(childDepth: number): KeyPair {
const info = `${KeyPrefixes.DerivedKey}${childDepth}`
const childDepthBuffer = Buffer.alloc(8)
childDepthBuffer.writeBigUInt64LE(BigInt(childDepth))
const info = Buffer.concat([
Uint8Array.from(Buffer.from(KeyPrefixes.DerivedKey)),
Uint8Array.from(childDepthBuffer),
]);
const secretKey = this.hkdf.expand(this.masterPrk, info, 32)

return KeyPair.fromSecretKey(secretKey)
Expand Down
3 changes: 2 additions & 1 deletion packages/libra-web-core-utils/crypto/Hkdf.ts
@@ -1,6 +1,7 @@
/* tslint:disable */
const hkdf = require('futoin-hkdf')
/* tslint:enable */
type BuffString = Buffer | string;

// Todo: Update implementation to work not only with Node
export class Hkdf {
Expand All @@ -16,7 +17,7 @@ export class Hkdf {
return new Uint8Array(prk)
}

public expand(prk: Uint8Array, info: string, outputLen: number): Uint8Array {
public expand(prk: Uint8Array, info: BuffString, outputLen: number): Uint8Array {
const prkBuffer = Buffer.from(prk)
const okm = hkdf.expand(this.hashAlgorithm, this.hashLength, prkBuffer, outputLen, info)
return new Uint8Array(okm)
Expand Down
34 changes: 33 additions & 1 deletion packages/libra-web-core-utils/crypto/Pbkdf.ts
@@ -1,4 +1,4 @@
import crypto from 'crypto'
import crypto, {BinaryLike} from 'crypto'

export class Pbkdf {
private readonly digestAlgorithm: string
Expand All @@ -9,4 +9,36 @@ export class Pbkdf {
public extract(password: Uint8Array, salt: string, iterations: number, outputLen: number) {
return new Uint8Array(crypto.pbkdf2Sync(Buffer.from(password), salt, iterations, outputLen, this.digestAlgorithm))
}

public pbkdf2(password: BinaryLike, salt: Buffer, iterations: number, outputLen: number) {
const hmacLength = crypto.createHmac(this.digestAlgorithm, 'test').digest().length;
const outputBuffer = Buffer.alloc(outputLen);
const hmacOutput = Buffer.alloc(hmacLength);
const block = Buffer.alloc(salt.length + 4);
const leftLength = Math.ceil(outputLen / hmacLength);
const rightLength = outputLen - (leftLength - 1) * hmacLength;
salt.copy(block, 0, 0, salt.length);
for (let i = 1; i <= leftLength; i++) {
block.writeUInt32BE(i, salt.length);
let hmac = crypto
.createHmac(this.digestAlgorithm, password)
.update(block)
.digest();
hmac.copy(hmacOutput, 0, 0, hmacLength);
for (let j = 1; j < iterations; j++) {
hmac = crypto
.createHmac(this.digestAlgorithm, password)
.update(hmac)
.digest();
for (let k = 0; k < hmacLength; k++) {
// tslint:disable-next-line:no-bitwise
hmacOutput[k] ^= hmac[k];
}
}
const destPos = (i - 1) * hmacLength;
const len = i === leftLength ? rightLength : hmacLength;
hmacOutput.copy(outputBuffer, destPos, 0, len);
}
return outputBuffer;
}
}
2 changes: 1 addition & 1 deletion test/query.test.ts
Expand Up @@ -15,7 +15,7 @@ describe('LibraClient.query*()', () => {
console.log('User 1 address is', account1Address.toHex())
let account1State = await client.getAccountState(account1Address)

const account2 = wallet.getAccount(0)
const account2 = wallet.getAccount(1)
const account2Address = account2.getAddress()
console.log('User 2 address is', account2Address.toHex())
let account2State = await client.getAccountState(account2Address)
Expand Down

0 comments on commit 7292cb6

Please sign in to comment.