Spaces:
Sleeping
Sleeping
Download src/crypto/password.ts from relv-dev/relv-space3: direct link, hf CLI and curl.
- Browser
- Download file 2.1 kB
-
https://huggingface.co/spaces/relv-dev/relv-space3/resolve/main/src/crypto/password.ts
- Command line
-
hf download hf://spaces/relv-dev/relv-space3/src/crypto/password.ts
-
curl -L -o password.ts https://huggingface.co/spaces/relv-dev/relv-space3/resolve/main/src/crypto/password.ts
2.1 kB
| import * as crypto from 'crypto'; | |
| import { config } from '../config'; | |
| const ALGORITHM = 'aes-256-gcm'; | |
| const IV_LENGTH = 16; | |
| const AUTH_TAG_LENGTH = 16; | |
| /** | |
| * Derive a 32-byte key from the encryption key string. | |
| * Uses SHA-256 so any length passphrase works. | |
| */ | |
| function deriveKey(): Buffer { | |
| return crypto.createHash('sha256').update(config.credentialEncryptionKey).digest(); | |
| } | |
| /** | |
| * Encrypt a plaintext password. | |
| * Returns base64 string: iv(16) + authTag(16) + ciphertext | |
| */ | |
| export function encryptPassword(plaintext: string): string { | |
| const key = deriveKey(); | |
| const iv = crypto.randomBytes(IV_LENGTH); | |
| const cipher = crypto.createCipheriv(ALGORITHM, key, iv); | |
| const encrypted = Buffer.concat([ | |
| cipher.update(plaintext, 'utf8'), | |
| cipher.final(), | |
| ]); | |
| const authTag = cipher.getAuthTag(); | |
| // Format: iv + authTag + ciphertext | |
| const combined = Buffer.concat([iv, authTag, encrypted]); | |
| return combined.toString('base64'); | |
| } | |
| /** | |
| * Decrypt an encrypted password string. | |
| * Input is base64 string: iv(16) + authTag(16) + ciphertext | |
| */ | |
| export function decryptPassword(encrypted: string): string { | |
| const key = deriveKey(); | |
| const combined = Buffer.from(encrypted, 'base64'); | |
| const iv = combined.subarray(0, IV_LENGTH); | |
| const authTag = combined.subarray(IV_LENGTH, IV_LENGTH + AUTH_TAG_LENGTH); | |
| const ciphertext = combined.subarray(IV_LENGTH + AUTH_TAG_LENGTH); | |
| const decipher = crypto.createDecipheriv(ALGORITHM, key, iv); | |
| decipher.setAuthTag(authTag); | |
| const decrypted = Buffer.concat([ | |
| decipher.update(ciphertext), | |
| decipher.final(), | |
| ]); | |
| return decrypted.toString('utf8'); | |
| } | |
| /** | |
| * Get the Turnitin password for an account. | |
| * If encryption key is set, tries to decrypt. Otherwise uses shared password. | |
| */ | |
| export function getAccountPassword(encryptedPassword?: string | null): string { | |
| if (encryptedPassword && config.credentialEncryptionKey) { | |
| try { | |
| return decryptPassword(encryptedPassword); | |
| } catch { | |
| // Fallback to shared password if decryption fails | |
| } | |
| } | |
| return config.turnitinSharedPassword; | |
| } | |