Skip to content

Commit

Permalink
feat: ✨ add encryptKeystore compatible with xchain
Browse files Browse the repository at this point in the history
  • Loading branch information
jojobyte committed Dec 30, 2023
1 parent 46b90fc commit e99ba77
Show file tree
Hide file tree
Showing 4 changed files with 167 additions and 11 deletions.
11 changes: 11 additions & 0 deletions public/libs/blake2b.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 12 additions & 0 deletions public/libs/sha3.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

152 changes: 142 additions & 10 deletions src/helpers/wallet.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ import {

// @ts-ignore
import blake from 'blakejs'
// @ts-ignore
import { keccak_256 } from '@noble/hashes/sha3'

// @ts-ignore
let dashsight = DashSight.create({
Expand Down Expand Up @@ -235,19 +237,23 @@ export async function decryptPhraseFromKeystore(

// console.log('decryptPhrase derivedBits', derivedBytes)

const calculatedMAC = blake256([
const bMAC = blake256([
...new Uint8Array(derivedBytes.slice(16, 32)),
...Cryptic.toBytes(ciphertext),
])
const kMAC = Cryptic.toHex(keccak_256(new Uint8Array([
...new Uint8Array(derivedBytes.slice(16, 32)),
...Cryptic.toBytes(ciphertext),
])));

// console.log(
// 'decryptPhrase mac === calculatedMAC',
// 'decryptPhrase mac === bMAC',
// // mac,
// // calculatedMAC,
// mac === calculatedMAC
// // bMAC,
// mac === bMAC
// )

if (mac !== calculatedMAC) {
if (mac && ![bMAC, kMAC].includes(mac)) {
throw new Error('Invalid password')
}

Expand Down Expand Up @@ -313,19 +319,23 @@ export async function decryptPhraseFromKeystoreBytes(

// console.log('decryptPhrase derivedBits', derivedBytes)

const calculatedMAC = blake256([
const bMAC = blake256([
...new Uint8Array(derivedBytes.slice(16, 32)),
...Cryptic.toBytes(ciphertext),
])
const kMAC = Cryptic.toHex(keccak_256(new Uint8Array([
...new Uint8Array(derivedBytes.slice(16, 32)),
...Cryptic.toBytes(ciphertext),
])));

// console.log(
// 'decryptPhrase mac === calculatedMAC',
// 'decryptPhrase mac === bMAC',
// // mac,
// // calculatedMAC,
// mac === calculatedMAC
// // bMAC,
// mac === bMAC
// )

if (mac !== calculatedMAC) {
if (mac && ![bMAC, kMAC].includes(mac)) {
throw new Error('Invalid password')
}

Expand Down Expand Up @@ -355,6 +365,128 @@ export async function decryptPhraseFromKeystoreBytes(
}
}

export async function encryptKeystore(
encryptionPassword,
recoveryPhrase,
) {
let ks = {
crypto: {
cipher: "aes-128-ctr",
ciphertext: '',
cipherparams: {
iv: '',
},
kdf: "pbkdf2",
kdfparams: {
c: 262144,
dklen: 32,
prf: "hmac-sha256",
salt: '',
},
mac: '',
},
id: crypto.randomUUID(),
meta: 'dash-incubator-keystore',
version: 3,
}
// const {
// ciphertext, cipherLength, cipherAlgorithm,
// derivationAlgorithm, hashingAlgorithm, // iv,
// mac, iterations, ivBuffer, salt, numBits,
// } = getKeystoreData(ks)

const [
cipherAlgorithm,
cipherLength,
] = KS_CIPHER[ks.crypto.cipher]

// Cryptic.setConfig('name', cipherAlgorithm)
// Cryptic.setConfig('length', cipherLength)
// Cryptic.setConfig('pbkdfName', 'PBKDF2')
// Cryptic.setConfig(
// 'iterations',
// // @ts-ignore
// ks.crypto.kdfparams.c,
// )

const salt = Cryptic.randomBytes(32)
const iv = Cryptic.randomBytes(16)

ks.crypto.kdfparams.salt = Cryptic.bufferToHex(salt)
ks.crypto.cipherparams.iv = Cryptic.bufferToHex(iv)

const keyMaterial = await crypto.subtle.importKey(
'raw',
Cryptic.stringToBuffer(encryptionPassword),
ks.crypto.kdf.toUpperCase(),
false,
['deriveBits', 'deriveKey'],
)

const keyLength = ks.crypto.kdfparams.dklen / 2
// const numBits = (keyLength + Cryptic.bufferToHex(iv).length) * 8
const numBits = (keyLength + iv.length) * 8

const derivedBytes = await crypto.subtle.deriveBits(
{
name: ks.crypto.kdf.toUpperCase(),
salt,
iterations: ks.crypto.kdfparams.c,
hash: KS_PRF[ks.crypto.kdfparams.prf],
},
keyMaterial,
numBits,
);

const derivedKey = await crypto.subtle.deriveKey(
{
name: ks.crypto.kdf.toUpperCase(),
salt,
iterations: ks.crypto.kdfparams.c,
hash: KS_PRF[ks.crypto.kdfparams.prf],
},
keyMaterial,
{
name: cipherAlgorithm,
length: cipherLength
},
true,
['encrypt', 'decrypt'],
)

let enc = await crypto.subtle.encrypt(
{
name: cipherAlgorithm,
counter: iv,
length: cipherLength,
},
derivedKey,
Cryptic.stringToBuffer(recoveryPhrase),
)
ks.crypto.ciphertext = Cryptic.bufferToHex(enc)

const bMAC = blake256([
...new Uint8Array(derivedBytes.slice(16, 32)),
...Cryptic.toBytes(ks.crypto.ciphertext),
])
const kMAC = Cryptic.toHex(keccak_256(new Uint8Array([
...new Uint8Array(derivedBytes.slice(16, 32)),
...Cryptic.toBytes(ks.crypto.ciphertext),
])));

ks.crypto.mac = bMAC

// console.log(
// 'encrypted keystore', ks,
// [
// bMAC,
// kMAC,
// ]
// )

return ks
}

export async function initWallet(
encryptionPassword,
wallet,
Expand Down
3 changes: 2 additions & 1 deletion src/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,8 @@
<script type="importmap">
{
"imports": {
"blakejs": "./public/libs/blake2b.js"
"blakejs": "./public/libs/blake2b.js",
"@noble/hashes/sha3": "./public/libs/sha3.js"
}
}
</script>
Expand Down

0 comments on commit e99ba77

Please sign in to comment.