60 lines
1.6 KiB
TypeScript
60 lines
1.6 KiB
TypeScript
|
|
import type { PasswordPublicKeyResponse } from '@geo/shared-types'
|
||
|
|
|
||
|
|
const textEncoder = new TextEncoder()
|
||
|
|
|
||
|
|
export function browserSupportsPasswordCipher(): boolean {
|
||
|
|
return typeof window !== 'undefined' && Boolean(window.crypto?.subtle)
|
||
|
|
}
|
||
|
|
|
||
|
|
export async function encryptPasswordForLogin(
|
||
|
|
password: string,
|
||
|
|
key: PasswordPublicKeyResponse,
|
||
|
|
): Promise<{ encrypted_password: string; password_key_id: string }> {
|
||
|
|
const cryptoKey = await importRSAOAEPKey(key.public_key)
|
||
|
|
const encrypted = await window.crypto.subtle.encrypt(
|
||
|
|
{ name: 'RSA-OAEP' },
|
||
|
|
cryptoKey,
|
||
|
|
textEncoder.encode(password),
|
||
|
|
)
|
||
|
|
return {
|
||
|
|
encrypted_password: arrayBufferToBase64(encrypted),
|
||
|
|
password_key_id: key.key_id,
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
async function importRSAOAEPKey(publicKeyPEM: string): Promise<CryptoKey> {
|
||
|
|
const binaryDER = pemToArrayBuffer(publicKeyPEM)
|
||
|
|
return window.crypto.subtle.importKey(
|
||
|
|
'spki',
|
||
|
|
binaryDER,
|
||
|
|
{
|
||
|
|
name: 'RSA-OAEP',
|
||
|
|
hash: 'SHA-256',
|
||
|
|
},
|
||
|
|
false,
|
||
|
|
['encrypt'],
|
||
|
|
)
|
||
|
|
}
|
||
|
|
|
||
|
|
function pemToArrayBuffer(pem: string): ArrayBuffer {
|
||
|
|
const base64 = pem
|
||
|
|
.replace(/-----BEGIN PUBLIC KEY-----/g, '')
|
||
|
|
.replace(/-----END PUBLIC KEY-----/g, '')
|
||
|
|
.replace(/\s/g, '')
|
||
|
|
const binary = window.atob(base64)
|
||
|
|
const bytes = new Uint8Array(binary.length)
|
||
|
|
for (let i = 0; i < binary.length; i += 1) {
|
||
|
|
bytes[i] = binary.charCodeAt(i)
|
||
|
|
}
|
||
|
|
return bytes.buffer
|
||
|
|
}
|
||
|
|
|
||
|
|
function arrayBufferToBase64(buffer: ArrayBuffer): string {
|
||
|
|
const bytes = new Uint8Array(buffer)
|
||
|
|
let binary = ''
|
||
|
|
for (const byte of bytes) {
|
||
|
|
binary += String.fromCharCode(byte)
|
||
|
|
}
|
||
|
|
return window.btoa(binary)
|
||
|
|
}
|