gradido/database/integrity/0013-test.ts.keep

86 lines
2.9 KiB
Plaintext

/* MIGRATION TO CLEAN PRODUCTION DATA
*
* the way the passphrases are stored in login_user_backups is inconsistent.
* we need to try to detect which word list was used and transform it accordingly
*/
import fs from 'fs'
// eslint-disable-next-line @typescript-eslint/no-var-requires
const sodium = require('sodium-native')
const PHRASE_WORD_COUNT = 24
const WORDS = fs
.readFileSync('src/config/mnemonic.uncompressed_buffer13116.txt')
.toString()
.split(',')
const KeyPairEd25519Create = (passphrase: string[]): Buffer[] => {
if (!passphrase.length || passphrase.length < PHRASE_WORD_COUNT) {
throw new Error('passphrase empty or to short')
}
const state = Buffer.alloc(sodium.crypto_hash_sha512_STATEBYTES)
sodium.crypto_hash_sha512_init(state)
for (let i = 0; i < PHRASE_WORD_COUNT; i++) {
const value = Buffer.alloc(8)
const wordIndex = WORDS.indexOf(passphrase[i])
value.writeBigInt64LE(BigInt(wordIndex))
sodium.crypto_hash_sha512_update(state, value)
}
// trailing space is part of the login_server implementation
const clearPassphrase = passphrase.slice(0, PHRASE_WORD_COUNT).join(' ') + ' '
sodium.crypto_hash_sha512_update(state, Buffer.from(clearPassphrase))
const outputHashBuffer = Buffer.alloc(sodium.crypto_hash_sha512_BYTES)
sodium.crypto_hash_sha512_final(state, outputHashBuffer)
const pubKey = Buffer.alloc(sodium.crypto_sign_PUBLICKEYBYTES)
const privKey = Buffer.alloc(sodium.crypto_sign_SECRETKEYBYTES)
sodium.crypto_sign_seed_keypair(
pubKey,
privKey,
outputHashBuffer.slice(0, sodium.crypto_sign_SEEDBYTES),
)
return [pubKey, privKey]
}
export async function upgrade(queryFn: (query: string, values?: any[]) => Promise<Array<any>>) {
// Delete data with no reference in login_users table
// eslint-disable-next-line no-console
// 663 affected rows
const userBackups = await queryFn(
`SELECT passphrase, LOWER(HEX(pubkey)) as pubkey, user_id
FROM login_user_backups
LEFT JOIN login_users ON login_user_backups.user_id = login_users.id
WHERE user_id=1503`,
// WHERE pubkey is not null`, // todo fix this condition and regenerate
)
let i = 0
// eslint-disable-next-line no-console
userBackups.forEach(async (userBackup) => {
const passphrase = userBackup.passphrase.split(' ')
const keyPair = KeyPairEd25519Create(passphrase)
if (keyPair[0].toString('hex') !== userBackup.pubkey) {
i++
// eslint-disable-next-line no-console
console.log(
'Missmatch Pubkey',
i,
userBackup.user_id,
`"${userBackup.passphrase}"`,
`"${keyPair[0].toString('hex')}`,
`"${userBackup.pubkey}"`,
)
} else {
// eslint-disable-next-line no-console
// console.log('SUCCESS: ', `"${keyPair[0].toString('hex')}`, `"${userBackup.pubkey}"`)
}
})
}
export async function downgrade(queryFn: (query: string, values?: any[]) => Promise<Array<any>>) {
return [] // cannot transform things back
}