Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
emit(ai.props.output.context.api, 'loginStart', {
username: stashTree.username
})
// Find the appropriate child:
const child = searchTree(stashTree, stash => stash.appId === appId)
if (child == null) {
throw new Error(`Cannot find requested appId: "${appId}"`)
}
// The Airbitz mobile will sometimes send the pin2Key in base58
// instead of base64 due to an unfortunate bug. Fix that:
if (child.pin2Key != null && child.pin2Key.slice(-1) !== '=') {
io.console.warn('Fixing base58 pin2Key')
child.pin2Key = base64.stringify(base58.parse(child.pin2Key))
}
await saveStash(ai, stashTree)
// This is almost guaranteed to blow up spectacularly:
const loginKey = base64.parse(reply.loginKey)
const loginTree = makeLoginTree(stashTree, loginKey, appId)
const login = searchTree(loginTree, login => login.appId === appId)
if (login == null) {
throw new Error(`Cannot find requested appId: "${appId}"`)
}
const newLoginTree = await syncLogin(ai, loginTree, login)
const account = await makeAccount(ai, appId, newLoginTree, 'edgeLogin', opts)
emit(ai.props.output.context.api, 'login', account)
}
if (mnemonicBox != null && rootKeyBox != null) {
const rootKey = decrypt(rootKeyBox, loginKey)
const infoKey = hmacSha256(rootKey, utf8.parse('infoKey'))
const keys = {
mnemonic: utf8.stringify(decrypt(mnemonicBox, infoKey)),
rootKey: base64.stringify(rootKey)
}
legacyKeys.push(makeKeyInfo('wallet:bitid', keys, rootKey))
}
// Account settings:
if (stash.syncKeyBox != null) {
const syncKey = decrypt(stash.syncKeyBox, loginKey)
const type = makeAccountType(login.appId)
const keys = {
syncKey: base64.stringify(syncKey),
dataKey: base64.stringify(loginKey)
}
legacyKeys.push(makeKeyInfo(type, keys, loginKey))
}
// Keys:
const stashKeyBoxes = stash.keyBoxes != null ? stash.keyBoxes : []
const keyInfos = stashKeyBoxes.map(box =>
JSON.parse(utf8.stringify(decrypt(box, loginKey)))
)
login.keyInfos = mergeKeyInfos([...legacyKeys, ...keyInfos]).map(walletInfo =>
fixWalletInfo(walletInfo)
)
// Recurse into children:
const rootKey = decrypt(rootKeyBox, loginKey)
const infoKey = hmacSha256(rootKey, utf8.parse('infoKey'))
const keys = {
mnemonic: utf8.stringify(decrypt(mnemonicBox, infoKey)),
rootKey: base64.stringify(rootKey)
}
legacyKeys.push(makeKeyInfo('wallet:bitid', keys, rootKey))
}
// Account settings:
if (stash.syncKeyBox != null) {
const syncKey = decrypt(stash.syncKeyBox, loginKey)
const type = makeAccountType(login.appId)
const keys = {
syncKey: base64.stringify(syncKey),
dataKey: base64.stringify(loginKey)
}
legacyKeys.push(makeKeyInfo(type, keys, loginKey))
}
// Keys:
const stashKeyBoxes = stash.keyBoxes != null ? stash.keyBoxes : []
const keyInfos = stashKeyBoxes.map(box =>
JSON.parse(utf8.stringify(decrypt(box, loginKey)))
)
login.keyInfos = mergeKeyInfos([...legacyKeys, ...keyInfos]).map(walletInfo =>
fixWalletInfo(walletInfo)
)
// Recurse into children:
const stashChildren = stash.children != null ? stash.children : []
pin: string,
enableLogin: boolean
): LoginKit {
const { io } = ai.props
const pin2TextBox = encrypt(io, utf8.parse(pin), login.loginKey)
if (enableLogin) {
const pin2Key = login.pin2Key || io.random(32)
const pin2Box = encrypt(io, login.loginKey, pin2Key)
const pin2KeyBox = encrypt(io, pin2Key, login.loginKey)
return {
serverPath: '/v2/login/pin2',
server: {
pin2Id: base64.stringify(pin2Id(pin2Key, username)),
pin2Auth: base64.stringify(pin2Auth(pin2Key, pin)),
pin2Box,
pin2KeyBox,
pin2TextBox
},
stash: {
pin2Key: base64.stringify(pin2Key),
pin2TextBox
},
login: {
pin2Key,
pin
},
loginId: login.loginId
}
} else {
return {
username: string,
pin: string,
enableLogin: boolean
): LoginKit {
const { io } = ai.props
const pin2TextBox = encrypt(io, utf8.parse(pin), login.loginKey)
if (enableLogin) {
const pin2Key = login.pin2Key || io.random(32)
const pin2Box = encrypt(io, login.loginKey, pin2Key)
const pin2KeyBox = encrypt(io, pin2Key, login.loginKey)
return {
serverPath: '/v2/login/pin2',
server: {
pin2Id: base64.stringify(pin2Id(pin2Key, username)),
pin2Auth: base64.stringify(pin2Auth(pin2Key, pin)),
pin2Box,
pin2KeyBox,
pin2TextBox
},
stash: {
pin2Key: base64.stringify(pin2Key),
pin2TextBox
},
login: {
pin2Key,
pin
},
loginId: login.loginId
}
} else {
async function fetchLoginKey(
ai: ApiInput,
username: string,
password: string,
otp: string | void
) {
const up = makeHashInput(username, password)
const [userId, passwordAuth] = await Promise.all([
hashUsername(ai, username),
scrypt(ai, up, passwordAuthSnrp)
])
const request = {
userId: base64.stringify(userId),
passwordAuth: base64.stringify(passwordAuth),
otp
}
const reply = await authRequest(ai, 'POST', '/v2/login', request)
if (reply.passwordBox == null || reply.passwordKeySnrp == null) {
throw new Error('Missing data for online password login')
}
const passwordKey = await scrypt(ai, up, reply.passwordKeySnrp)
return {
loginKey: decrypt(reply.passwordBox, passwordKey),
loginReply: reply
}
}
async function fetchLoginKey(
ai: ApiInput,
pin2Key: Uint8Array,
username: string,
pin: string,
otp: string | void
) {
const request = {
pin2Id: base64.stringify(pin2Id(pin2Key, username)),
pin2Auth: base64.stringify(pin2Auth(pin2Key, pin)),
otp
}
const reply = await authRequest(ai, 'POST', '/v2/login', request)
if (reply.pin2Box == null) {
throw new Error('Missing data for PIN v2 login')
}
return {
loginKey: decrypt(reply.pin2Box, pin2Key),
loginReply: reply
}
}
recovery2Key
)
const recovery2Box = encrypt(io, login.loginKey, recovery2Key)
const recovery2KeyBox = encrypt(io, recovery2Key, login.loginKey)
return {
serverPath: '/v2/login/recovery2',
server: {
recovery2Id: base64.stringify(recovery2Id(recovery2Key, username)),
recovery2Auth: recovery2Auth(recovery2Key, answers),
recovery2Box,
recovery2KeyBox,
question2Box
},
stash: {
recovery2Key: base64.stringify(recovery2Key)
},
login: {
recovery2Key
},
loginId: login.loginId
}
}
export function makeStorageKeyInfo(
ai: ApiInput,
type: string,
keys: StorageKeys = {}
) {
const { io } = ai.props
if (keys.dataKey == null) keys.dataKey = base64.stringify(io.random(32))
if (keys.syncKey == null) keys.syncKey = base64.stringify(io.random(20))
return makeKeyInfo(type, keys, base64.parse(keys.dataKey))
}