mirror of
https://github.com/LBRYFoundation/Watch-on-LBRY.git
synced 2025-08-23 17:47:26 +00:00
🍣 crypto changes
This commit is contained in:
parent
deed10423a
commit
f86affc093
3 changed files with 68 additions and 67 deletions
|
@ -1,14 +1,15 @@
|
||||||
import { getExtensionSettingsAsync } from "./settings"
|
import { getExtensionSettingsAsync, ytUrlResolversSettings } from "./settings"
|
||||||
import { setSetting } from "./useSettings"
|
import { setSetting } from "./useSettings"
|
||||||
|
import path from 'path'
|
||||||
|
|
||||||
async function generateKeys() {
|
async function generateKeys() {
|
||||||
const keys = await window.crypto.subtle.generateKey(
|
const keys = await window.crypto.subtle.generateKey(
|
||||||
{
|
{
|
||||||
name: "RSASSA-PKCS1-v1_5",
|
name: "RSASSA-PKCS1-v1_5",
|
||||||
// Consider using a 4096-bit key for systems that require long-term security
|
// Consider using a 4096-bit key for systems that require long-term security
|
||||||
modulusLength: 2048,
|
modulusLength: 384,
|
||||||
publicExponent: new Uint8Array([1, 0, 1]),
|
publicExponent: new Uint8Array([1, 0, 1]),
|
||||||
hash: "SHA-256",
|
hash: "SHA-1",
|
||||||
},
|
},
|
||||||
true,
|
true,
|
||||||
["sign", "verify"]
|
["sign", "verify"]
|
||||||
|
@ -28,22 +29,26 @@ async function exportPrivateKey(key: CryptoKey) {
|
||||||
return Buffer.from(exported).toString('base64')
|
return Buffer.from(exported).toString('base64')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const publicKeyPrefix = `MEwwDQYJKoZIhvcNAQEBBQADOwAwOAIxA`
|
||||||
|
const publicKeySuffix = `IDAQAB` //`wIDAQAB` `WIDAQAB`
|
||||||
|
const publicKeyLength = 65
|
||||||
async function exportPublicKey(key: CryptoKey) {
|
async function exportPublicKey(key: CryptoKey) {
|
||||||
const exported = await window.crypto.subtle.exportKey(
|
const exported = await window.crypto.subtle.exportKey(
|
||||||
"spki",
|
"spki",
|
||||||
key
|
key
|
||||||
)
|
)
|
||||||
return Buffer.from(exported).toString('base64')
|
const publicKey = Buffer.from(exported).toString('base64')
|
||||||
|
console.log(publicKey)
|
||||||
|
return publicKey.substring(publicKeyPrefix.length, publicKeyPrefix.length + publicKeyLength)
|
||||||
}
|
}
|
||||||
|
|
||||||
function importPrivateKey(base64: string) {
|
function importPrivateKey(base64: string) {
|
||||||
|
|
||||||
return window.crypto.subtle.importKey(
|
return window.crypto.subtle.importKey(
|
||||||
"pkcs8",
|
"pkcs8",
|
||||||
Buffer.from(base64, 'base64'),
|
Buffer.from(base64, 'base64'),
|
||||||
{
|
{
|
||||||
name: "RSASSA-PKCS1-v1_5",
|
name: "RSASSA-PKCS1-v1_5",
|
||||||
hash: "SHA-256",
|
hash: "SHA-1",
|
||||||
},
|
},
|
||||||
true,
|
true,
|
||||||
["sign"]
|
["sign"]
|
||||||
|
@ -54,7 +59,7 @@ export async function sign(data: string, privateKey: string) {
|
||||||
return Buffer.from(await window.crypto.subtle.sign(
|
return Buffer.from(await window.crypto.subtle.sign(
|
||||||
{ name: "RSASSA-PKCS1-v1_5" },
|
{ name: "RSASSA-PKCS1-v1_5" },
|
||||||
await importPrivateKey(privateKey),
|
await importPrivateKey(privateKey),
|
||||||
Buffer.from(data)
|
await crypto.subtle.digest({ name: 'SHA-1' }, Buffer.from(data))
|
||||||
)).toString('base64')
|
)).toString('base64')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -63,6 +68,33 @@ export function resetProfileSettings() {
|
||||||
setSetting('privateKey', null)
|
setSetting('privateKey', null)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function apiRequest<T extends object>(method: 'GET' | 'POST', pathname: string, data: T) {
|
||||||
|
const settings = await getExtensionSettingsAsync()
|
||||||
|
/* const urlResolverSettings = ytUrlResolversSettings[settings.urlResolver]
|
||||||
|
if (!urlResolverSettings.signRequest) throw new Error() */
|
||||||
|
|
||||||
|
console.log(ytUrlResolversSettings)
|
||||||
|
const url = new URL(ytUrlResolversSettings.madiatorFinder.href/* urlResolverSettings.href */)
|
||||||
|
console.log(url)
|
||||||
|
url.pathname = path.join(url.pathname, pathname)
|
||||||
|
url.searchParams.set('data', JSON.stringify(data))
|
||||||
|
|
||||||
|
if (true/* requiresSignature */) {
|
||||||
|
if (!settings.privateKey || !settings.publicKey)
|
||||||
|
throw new Error('There is no profile.')
|
||||||
|
|
||||||
|
url.searchParams.set('keys', JSON.stringify({
|
||||||
|
signature: await sign(url.searchParams.toString(), settings.privateKey!),
|
||||||
|
publicKey: settings.publicKey
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
const respond = await fetch(url.href, { method })
|
||||||
|
|
||||||
|
if (respond.ok) return respond.json()
|
||||||
|
throw new Error((await respond.json()).message)
|
||||||
|
}
|
||||||
|
|
||||||
export async function generateProfileAndSetNickname(overwrite = false) {
|
export async function generateProfileAndSetNickname(overwrite = false) {
|
||||||
let { publicKey, privateKey } = await getExtensionSettingsAsync()
|
let { publicKey, privateKey } = await getExtensionSettingsAsync()
|
||||||
|
|
||||||
|
@ -74,80 +106,43 @@ export async function generateProfileAndSetNickname(overwrite = false) {
|
||||||
alert("Invalid nickname")
|
alert("Invalid nickname")
|
||||||
}
|
}
|
||||||
|
|
||||||
if (overwrite || !privateKey || !publicKey) {
|
try {
|
||||||
resetProfileSettings()
|
if (overwrite || !privateKey || !publicKey) {
|
||||||
await generateKeys().then((keys) => {
|
resetProfileSettings()
|
||||||
publicKey = keys.publicKey
|
await generateKeys().then((keys) => {
|
||||||
privateKey = keys.privateKey
|
publicKey = keys.publicKey
|
||||||
})
|
privateKey = keys.privateKey
|
||||||
}
|
})
|
||||||
|
setSetting('publicKey', publicKey)
|
||||||
const url = new URL('https://finder.madiator.com/api/v1/profile')
|
setSetting('privateKey', privateKey)
|
||||||
url.searchParams.set('data', JSON.stringify({ nickname }))
|
}
|
||||||
url.searchParams.set('keys', JSON.stringify({
|
await apiRequest('POST', '/profile', { nickname })
|
||||||
signature: await sign(url.searchParams.toString(), privateKey!),
|
|
||||||
publicKey
|
|
||||||
}))
|
|
||||||
const respond = await fetch(url.href, { method: "POST" })
|
|
||||||
if (respond.ok) {
|
|
||||||
setSetting('publicKey', publicKey)
|
|
||||||
setSetting('privateKey', privateKey)
|
|
||||||
alert(`Your nickname has been set to ${nickname}`)
|
alert(`Your nickname has been set to ${nickname}`)
|
||||||
|
} catch (error: any) {
|
||||||
|
resetProfileSettings()
|
||||||
|
alert(error.message)
|
||||||
}
|
}
|
||||||
else alert((await respond.json()).message)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function purgeProfile() {
|
export async function purgeProfile() {
|
||||||
try {
|
try {
|
||||||
if (!confirm("This will purge all of your online and offline profile data.\nStill wanna continue?")) return
|
if (!confirm("This will purge all of your online and offline profile data.\nStill wanna continue?")) return
|
||||||
const settings = await getExtensionSettingsAsync()
|
await apiRequest('POST', '/profile/purge', {})
|
||||||
|
resetProfileSettings()
|
||||||
if (!settings.privateKey || !settings.publicKey)
|
alert(`Your profile has been purged`)
|
||||||
throw new Error('There is no profile to be purged.')
|
|
||||||
|
|
||||||
const url = new URL('https://finder.madiator.com/api/v1/profile/purge')
|
|
||||||
url.searchParams.set('keys', JSON.stringify({
|
|
||||||
signature: await sign(url.searchParams.toString(), settings.privateKey!),
|
|
||||||
publicKey: settings.publicKey
|
|
||||||
}))
|
|
||||||
const respond = await fetch(url.href, { method: "POST" })
|
|
||||||
if (respond.ok) {
|
|
||||||
resetProfileSettings()
|
|
||||||
alert(`Your profile has been purged`)
|
|
||||||
}
|
|
||||||
else throw new Error((await respond.json()).message)
|
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
alert(error.message)
|
alert(error.message)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getProfile() {
|
export async function getProfile() {
|
||||||
try {
|
let { publicKey, privateKey } = await getExtensionSettingsAsync()
|
||||||
const settings = await getExtensionSettingsAsync()
|
return (await apiRequest('GET', '/profile', { publicKey })) as { nickname: string, score: number, publickKey: string }
|
||||||
|
|
||||||
if (!settings.privateKey || !settings.publicKey)
|
|
||||||
throw new Error('There is no profile.')
|
|
||||||
|
|
||||||
const url = new URL('https://finder.madiator.com/api/v1/profile')
|
|
||||||
url.searchParams.set('data', JSON.stringify({ publicKey: settings.publicKey }))
|
|
||||||
url.searchParams.set('keys', JSON.stringify({
|
|
||||||
signature: await sign(url.searchParams.toString(), settings.privateKey!),
|
|
||||||
publicKey: settings.publicKey
|
|
||||||
}))
|
|
||||||
const respond = await fetch(url.href, { method: "GET" })
|
|
||||||
if (respond.ok) {
|
|
||||||
const profile = await respond.json() as { nickname: string, score: number, publickKey: string }
|
|
||||||
return profile
|
|
||||||
}
|
|
||||||
else throw new Error((await respond.json()).message)
|
|
||||||
} catch (error: any) {
|
|
||||||
console.error(error)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function friendlyPublicKey(publicKey: string | null) {
|
export function friendlyPublicKey(publicKey: string | null) {
|
||||||
// This is copy paste of Madiator Finder's friendly public key
|
// This is copy paste of Madiator Finder's friendly public key
|
||||||
return publicKey?.substring(publicKey.length - 64, publicKey.length - 32)
|
return `${publicKey?.substring(0, 32)}...`
|
||||||
}
|
}
|
||||||
|
|
||||||
function download(data: string, filename: string, type: string) {
|
function download(data: string, filename: string, type: string) {
|
||||||
|
|
|
@ -118,12 +118,17 @@ export const getYtUrlResolversSettingsEntiries = () => Object.entries(ytUrlResol
|
||||||
export const ytUrlResolversSettings = {
|
export const ytUrlResolversSettings = {
|
||||||
odyseeApi: ytUrlResolver({
|
odyseeApi: ytUrlResolver({
|
||||||
name: "Odysee",
|
name: "Odysee",
|
||||||
href: "https://api.odysee.com/yt/resolve",
|
href: "https://api.odysee.com/yt",
|
||||||
signRequest: false
|
signRequest: false
|
||||||
}),
|
}),
|
||||||
madiatorFinder: ytUrlResolver({
|
madiatorFinder: ytUrlResolver({
|
||||||
name: "Madiator Finder",
|
name: "Madiator Finder",
|
||||||
href: "https://finder.madiator.com/api/v1/resolve",
|
href: "https://finder.madiator.com/api/v1",
|
||||||
signRequest: true
|
signRequest: true
|
||||||
})
|
}),
|
||||||
|
/* madiatorFinderLocal: ytUrlResolver({
|
||||||
|
name: "Madiator Finder Local",
|
||||||
|
href: "http://127.0.0.1:3001/api/v1",
|
||||||
|
signRequest: true
|
||||||
|
}) */
|
||||||
}
|
}
|
|
@ -41,6 +41,7 @@ export async function resolveById(params: Paramaters, progressCallback?: (progre
|
||||||
if (params.length === 0) return results
|
if (params.length === 0) return results
|
||||||
|
|
||||||
const url = new URL(`${urlResolverSetting.href}`)
|
const url = new URL(`${urlResolverSetting.href}`)
|
||||||
|
url.pathname = '/resolve'
|
||||||
url.searchParams.set('video_ids', params.filter((item) => item.type === 'video').map((item) => item.id).join(','))
|
url.searchParams.set('video_ids', params.filter((item) => item.type === 'video').map((item) => item.id).join(','))
|
||||||
url.searchParams.set('channel_ids', params.filter((item) => item.type === 'channel').map((item) => item.id).join(','))
|
url.searchParams.set('channel_ids', params.filter((item) => item.type === 'channel').map((item) => item.id).join(','))
|
||||||
if (urlResolverSetting.signRequest && publicKey && privateKey)
|
if (urlResolverSetting.signRequest && publicKey && privateKey)
|
||||||
|
|
Loading…
Add table
Reference in a new issue