mirror of
https://github.com/Myzel394/kleckrelay-website.git
synced 2025-06-21 00:30:31 +02:00
improved cryptography
This commit is contained in:
parent
ee0682a8b6
commit
b828f75332
@ -1,13 +1,12 @@
|
||||
import {AliasNote} from "~/server-types"
|
||||
|
||||
export const MASTER_PASSWORD_LENGTH = 1024
|
||||
export const LOCAL_REGEX = /^[a-zA-Z0-9!#$%&‘*+–/=?^_`.{|}~-]{1,64}$/g
|
||||
export const URL_REGEX =
|
||||
/((http[s]*:\/\/)?[a-z0-9-%\/\&=?\.]+\.[a-z]{2,4}\/?([^\s<>\#%"\,\{\}\\|\\\^\[\]`]+)?)/gi
|
||||
export const DEFAULT_ALIAS_NOTE: AliasNote = {
|
||||
version: "1.0",
|
||||
data: {
|
||||
createdOn: "instance",
|
||||
createdOn: "/aliases",
|
||||
createdAt: null,
|
||||
creationContext: "web",
|
||||
personalNotes: "",
|
||||
|
@ -37,6 +37,9 @@ export function CreateAliasButton(): ReactElement {
|
||||
JSON.stringify(
|
||||
update(DEFAULT_ALIAS_NOTE, {
|
||||
data: {
|
||||
createdOn: {
|
||||
$set: window.location.origin + window.location.pathname,
|
||||
},
|
||||
createdAt: {
|
||||
$set: new Date(),
|
||||
},
|
||||
|
@ -5,19 +5,16 @@ import {readKey} from "openpgp"
|
||||
import {AxiosError} from "axios"
|
||||
import {useTranslation} from "react-i18next"
|
||||
import {useLoaderData} from "react-router-dom"
|
||||
import React, {ReactElement, useCallback, useContext, useMemo, useRef} from "react"
|
||||
import passwordGenerator from "secure-random-password"
|
||||
import React, {ReactElement, useCallback, useContext, useRef} from "react"
|
||||
|
||||
import {Box, InputAdornment} from "@mui/material"
|
||||
import {useMutation} from "@tanstack/react-query"
|
||||
|
||||
import {AuthContext, PasswordField, SimpleForm} from "~/components"
|
||||
import {encryptString, generateKeys, getEncryptionPassword, getUserSalt} from "~/utils"
|
||||
import {setupEncryptionForUser} from "~/utils"
|
||||
import {useExtensionHandler, useNavigateToNext, useSystemPreferredTheme, useUser} from "~/hooks"
|
||||
import {MASTER_PASSWORD_LENGTH} from "~/constants/values"
|
||||
import {AuthenticationDetails, ServerSettings, UserNote} from "~/server-types"
|
||||
import {AuthenticationDetails, ServerSettings} from "~/server-types"
|
||||
import {UpdateAccountData, updateAccount} from "~/apis"
|
||||
import {encryptUserNote} from "~/utils/encrypt-user-note"
|
||||
|
||||
export interface PasswordFormProps {
|
||||
onDone: () => void
|
||||
@ -54,7 +51,6 @@ export default function PasswordForm({onDone}: PasswordFormProps): ReactElement
|
||||
|
||||
const {_setEncryptionPassword, login} = useContext(AuthContext)
|
||||
|
||||
const waitForKeyGeneration = useMemo(generateKeys, [])
|
||||
const {mutateAsync} = useMutation<AuthenticationDetails, AxiosError, UpdateAccountData>(
|
||||
updateAccount,
|
||||
)
|
||||
@ -66,32 +62,20 @@ export default function PasswordForm({onDone}: PasswordFormProps): ReactElement
|
||||
},
|
||||
onSubmit: async ({password}, {setErrors}) => {
|
||||
try {
|
||||
const keyPair = await waitForKeyGeneration
|
||||
|
||||
const masterPassword = passwordGenerator.randomPassword({
|
||||
length: MASTER_PASSWORD_LENGTH,
|
||||
})
|
||||
|
||||
const salt = getUserSalt(user, serverSettings)
|
||||
const encryptionKey = await getEncryptionPassword(
|
||||
user.email.address,
|
||||
password,
|
||||
salt,
|
||||
)
|
||||
const encryptedMasterPassword = encryptString(masterPassword, encryptionKey)
|
||||
|
||||
const note: UserNote = {
|
||||
theme,
|
||||
privateKey: keyPair.privateKey,
|
||||
}
|
||||
const encryptedNotes = encryptUserNote(note, masterPassword)
|
||||
const {encryptionPassword, encryptedPassword, encryptedNotes, publicKey} =
|
||||
await setupEncryptionForUser({
|
||||
password,
|
||||
user,
|
||||
serverSettings,
|
||||
theme,
|
||||
})
|
||||
|
||||
await mutateAsync(
|
||||
{
|
||||
encryptedPassword: encryptedMasterPassword,
|
||||
encryptedPassword,
|
||||
publicKey: (
|
||||
await readKey({
|
||||
armoredKey: keyPair.publicKey,
|
||||
armoredKey: publicKey,
|
||||
})
|
||||
)
|
||||
.toPublic()
|
||||
@ -101,7 +85,7 @@ export default function PasswordForm({onDone}: PasswordFormProps): ReactElement
|
||||
{
|
||||
onSuccess: ({user: newUser}) => {
|
||||
login(newUser)
|
||||
_setEncryptionPassword(masterPassword)
|
||||
_setEncryptionPassword(encryptionPassword)
|
||||
navigateToNext()
|
||||
},
|
||||
},
|
||||
|
9
src/utils/crypto/generate-encryption-password.ts
Normal file
9
src/utils/crypto/generate-encryption-password.ts
Normal file
@ -0,0 +1,9 @@
|
||||
import passwordGenerator from "secure-random-password"
|
||||
|
||||
export default function generateEncryptionPassword(): string {
|
||||
// 16 characters ^ 64 combinations results in an entropy of 256 bits
|
||||
return passwordGenerator.randomPassword({
|
||||
length: 64,
|
||||
characters: "0123456789ABCDEF",
|
||||
})
|
||||
}
|
@ -12,3 +12,7 @@ export * from "./generate-keys"
|
||||
export {default as generateKeys} from "./generate-keys"
|
||||
export * from "./extract-cleartext-from-signed-message"
|
||||
export {default as extractCleartextFromSignedMessage} from "./extract-cleartext-from-signed-message"
|
||||
export * from "./generate-encryption-password"
|
||||
export {default as generateEncryptionPassword} from "./generate-encryption-password"
|
||||
export * from "./setup-encryption-for-user"
|
||||
export {default as setupEncryptionForUser} from "./setup-encryption-for-user"
|
||||
|
50
src/utils/crypto/setup-encryption-for-user.ts
Normal file
50
src/utils/crypto/setup-encryption-for-user.ts
Normal file
@ -0,0 +1,50 @@
|
||||
import {ServerSettings, ServerUser, Theme, User, UserNote} from "~/server-types"
|
||||
import {encryptUserNote} from "~/utils/encrypt-user-note"
|
||||
|
||||
import encryptString from "./encrypt-string"
|
||||
import generateEncryptionPassword from "./generate-encryption-password"
|
||||
import generateKeys from "./generate-keys"
|
||||
import getEncryptionPassword from "./get-encryption-password"
|
||||
import getUserSalt from "./get-user-salt"
|
||||
|
||||
export interface SetupEncryptionForUserData {
|
||||
password: string
|
||||
user: ServerUser | User
|
||||
serverSettings: ServerSettings
|
||||
theme: Theme
|
||||
}
|
||||
|
||||
export interface SetupEncryptionForUserResult {
|
||||
encryptedPassword: string
|
||||
encryptedNotes: string
|
||||
encryptionPassword: string
|
||||
publicKey: string
|
||||
}
|
||||
|
||||
export default async function setupEncryptionForUser({
|
||||
user,
|
||||
serverSettings,
|
||||
password,
|
||||
theme,
|
||||
}: SetupEncryptionForUserData): Promise<SetupEncryptionForUserResult> {
|
||||
const keyPair = await generateKeys()
|
||||
const masterPassword = generateEncryptionPassword()
|
||||
|
||||
const salt = getUserSalt(user, serverSettings)
|
||||
const encryptionKey = await getEncryptionPassword(user.email.address, password, salt)
|
||||
|
||||
const encryptedMasterPassword = encryptString(masterPassword, encryptionKey)
|
||||
|
||||
const note: UserNote = {
|
||||
theme,
|
||||
privateKey: keyPair.privateKey,
|
||||
}
|
||||
const encryptedNotes = encryptUserNote(note, masterPassword)
|
||||
|
||||
return {
|
||||
encryptedPassword: encryptedMasterPassword,
|
||||
encryptedNotes,
|
||||
encryptionPassword: masterPassword,
|
||||
publicKey: keyPair.publicKey,
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user