mirror of
https://github.com/sussy-code/smov.git
synced 2025-01-17 01:51:24 +01:00
Fix seed generation, add code signing and fix Base64
This commit is contained in:
parent
df85861cf2
commit
791923e78c
5 changed files with 32 additions and 32 deletions
|
@ -7,6 +7,7 @@
|
||||||
"@formkit/auto-animate": "^0.7.0",
|
"@formkit/auto-animate": "^0.7.0",
|
||||||
"@headlessui/react": "^1.5.0",
|
"@headlessui/react": "^1.5.0",
|
||||||
"@movie-web/providers": "^1.0.4",
|
"@movie-web/providers": "^1.0.4",
|
||||||
|
"@noble/hashes": "^1.3.2",
|
||||||
"@react-spring/web": "^9.7.1",
|
"@react-spring/web": "^9.7.1",
|
||||||
"@scure/bip39": "^1.2.1",
|
"@scure/bip39": "^1.2.1",
|
||||||
"@sozialhelden/ietf-language-tags": "^5.4.2",
|
"@sozialhelden/ietf-language-tags": "^5.4.2",
|
||||||
|
@ -33,7 +34,6 @@
|
||||||
"react-use": "^17.4.0",
|
"react-use": "^17.4.0",
|
||||||
"slugify": "^1.6.6",
|
"slugify": "^1.6.6",
|
||||||
"subsrt-ts": "^2.1.1",
|
"subsrt-ts": "^2.1.1",
|
||||||
"universal-base64url": "^1.1.0",
|
|
||||||
"unzipit": "^1.4.3",
|
"unzipit": "^1.4.3",
|
||||||
"zustand": "^4.3.9"
|
"zustand": "^4.3.9"
|
||||||
},
|
},
|
||||||
|
|
|
@ -20,6 +20,9 @@ dependencies:
|
||||||
'@movie-web/providers':
|
'@movie-web/providers':
|
||||||
specifier: ^1.0.4
|
specifier: ^1.0.4
|
||||||
version: 1.0.4
|
version: 1.0.4
|
||||||
|
'@noble/hashes':
|
||||||
|
specifier: ^1.3.2
|
||||||
|
version: 1.3.2
|
||||||
'@react-spring/web':
|
'@react-spring/web':
|
||||||
specifier: ^9.7.1
|
specifier: ^9.7.1
|
||||||
version: 9.7.3(react-dom@17.0.2)(react@17.0.2)
|
version: 9.7.3(react-dom@17.0.2)(react@17.0.2)
|
||||||
|
@ -98,9 +101,6 @@ dependencies:
|
||||||
subsrt-ts:
|
subsrt-ts:
|
||||||
specifier: ^2.1.1
|
specifier: ^2.1.1
|
||||||
version: 2.1.1
|
version: 2.1.1
|
||||||
universal-base64url:
|
|
||||||
specifier: ^1.1.0
|
|
||||||
version: 1.1.0
|
|
||||||
unzipit:
|
unzipit:
|
||||||
specifier: ^1.4.3
|
specifier: ^1.4.3
|
||||||
version: 1.4.3
|
version: 1.4.3
|
||||||
|
@ -6150,16 +6150,6 @@ packages:
|
||||||
crypto-random-string: 2.0.0
|
crypto-random-string: 2.0.0
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/universal-base64@2.1.0:
|
|
||||||
resolution: {integrity: sha512-WeOkACVnIXJZr/qlv7++Rl1zuZOHN96v2yS5oleUuv8eJOs5j9M5U3xQEIoWqn1OzIuIcgw0fswxWnUVGDfW6g==}
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/universal-base64url@1.1.0:
|
|
||||||
resolution: {integrity: sha512-qWv2+8KCaAWdpqqXwU8W0Yj9pflYDXP37/a3kec6Y4Je7bYzgIfxEVRjZWeLR67be7iot1lGCy5Nuo+xB0fojA==}
|
|
||||||
dependencies:
|
|
||||||
universal-base64: 2.1.0
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/universalify@0.2.0:
|
/universalify@0.2.0:
|
||||||
resolution: {integrity: sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==}
|
resolution: {integrity: sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==}
|
||||||
engines: {node: '>= 4.0.0'}
|
engines: {node: '>= 4.0.0'}
|
||||||
|
|
|
@ -1,13 +1,14 @@
|
||||||
|
import { pbkdf2Async } from "@noble/hashes/pbkdf2";
|
||||||
|
import { sha256 } from "@noble/hashes/sha256";
|
||||||
import { generateMnemonic } from "@scure/bip39";
|
import { generateMnemonic } from "@scure/bip39";
|
||||||
import { wordlist } from "@scure/bip39/wordlists/english";
|
import { wordlist } from "@scure/bip39/wordlists/english";
|
||||||
import forge from "node-forge";
|
import forge from "node-forge";
|
||||||
import { encode } from "universal-base64url";
|
|
||||||
|
|
||||||
async function seedFromMnemonic(mnemonic: string) {
|
async function seedFromMnemonic(mnemonic: string) {
|
||||||
const md = forge.md.sha256.create();
|
return pbkdf2Async(sha256, mnemonic, "mnemonic", {
|
||||||
md.update(mnemonic);
|
c: 2048,
|
||||||
// TODO this is probably not correct
|
dkLen: 32,
|
||||||
return md.digest().toHex();
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function keysFromMenmonic(mnemonic: string) {
|
export async function keysFromMenmonic(mnemonic: string) {
|
||||||
|
@ -28,13 +29,19 @@ export function genMnemonic(): string {
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function signCode(
|
export async function signCode(
|
||||||
_code: string,
|
code: string,
|
||||||
_privateKey: forge.pki.ed25519.NativeBuffer
|
privateKey: forge.pki.ed25519.NativeBuffer
|
||||||
): Promise<Uint8Array> {
|
): Promise<forge.pki.ed25519.NativeBuffer> {
|
||||||
// TODO add real signature
|
return forge.pki.ed25519.sign({
|
||||||
return new Uint8Array();
|
encoding: "utf8",
|
||||||
|
message: code,
|
||||||
|
privateKey,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function bytesToBase64Url(bytes: Uint8Array): string {
|
export function bytesToBase64Url(bytes: Uint8Array): string {
|
||||||
return encode(String.fromCodePoint(...bytes));
|
return btoa(String.fromCodePoint(...bytes))
|
||||||
|
.replace(/\//g, "_")
|
||||||
|
.replace(/\+/g, "-")
|
||||||
|
.replace(/=+$/, "");
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,11 @@
|
||||||
import { ofetch } from "ofetch";
|
import { ofetch } from "ofetch";
|
||||||
|
|
||||||
import { SessionResponse, UserResponse } from "@/backend/accounts/auth";
|
import { SessionResponse, UserResponse } from "@/backend/accounts/auth";
|
||||||
import { keysFromMenmonic, signCode } from "@/backend/accounts/crypto";
|
import {
|
||||||
|
bytesToBase64Url,
|
||||||
|
keysFromMenmonic as keysFromMnemonic,
|
||||||
|
signCode,
|
||||||
|
} from "@/backend/accounts/crypto";
|
||||||
|
|
||||||
export interface ChallengeTokenResponse {
|
export interface ChallengeTokenResponse {
|
||||||
challenge: string;
|
challenge: string;
|
||||||
|
@ -55,10 +59,10 @@ export async function registerAccount(
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function signChallenge(mnemonic: string, challengeCode: string) {
|
export async function signChallenge(mnemonic: string, challengeCode: string) {
|
||||||
const keys = await keysFromMenmonic(mnemonic);
|
const keys = await keysFromMnemonic(mnemonic);
|
||||||
const signature = await signCode(challengeCode, keys.privateKey);
|
const signature = await signCode(challengeCode, keys.privateKey);
|
||||||
return {
|
return {
|
||||||
publicKey: keys.publicKey,
|
publicKey: bytesToBase64Url(keys.publicKey),
|
||||||
signature,
|
signature: bytesToBase64Url(signature),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { useAsyncFn } from "react-use";
|
import { useAsyncFn } from "react-use";
|
||||||
|
|
||||||
import { bytesToBase64Url } from "@/backend/accounts/crypto";
|
|
||||||
import {
|
import {
|
||||||
getRegisterChallengeToken,
|
getRegisterChallengeToken,
|
||||||
registerAccount,
|
registerAccount,
|
||||||
|
@ -37,9 +36,9 @@ export function VerifyPassphrase(props: VerifyPassphraseProps) {
|
||||||
const registerResult = await registerAccount(url, {
|
const registerResult = await registerAccount(url, {
|
||||||
challenge: {
|
challenge: {
|
||||||
code: challenge,
|
code: challenge,
|
||||||
signature: bytesToBase64Url(keys.signature),
|
signature: keys.signature,
|
||||||
},
|
},
|
||||||
publicKey: bytesToBase64Url(keys.publicKey),
|
publicKey: keys.publicKey,
|
||||||
device: props.profile.device,
|
device: props.profile.device,
|
||||||
profile: props.profile.profile,
|
profile: props.profile.profile,
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in a new issue