File size: 4,202 Bytes
373c769
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
// Secure encryption utility for API key storage
// Uses device-specific salt and multiple encryption layers

class ApiKeyEncryption {
  constructor() {
    // Generate a device-specific salt based on browser fingerprint
    this.salt = this.generateDeviceSalt();
    this.additionalSalt = 'Luna-OCR-2025-Security-Salt';
  }

  // Generate a consistent salt based on device characteristics
  generateDeviceSalt() {
    const canvas = document.createElement('canvas');
    const ctx = canvas.getContext('2d');
    ctx.textBaseline = 'top';
    ctx.font = '14px Arial';
    ctx.fillText('Luna OCR Device Salt', 2, 2);
    
    const fingerprint = [
      navigator.userAgent,
      navigator.language,
      window.screen.width + 'x' + window.screen.height,
      new Date().getTimezoneOffset(),
      canvas.toDataURL()
    ].join('|');
    
    return this.simpleHash(fingerprint);
  }

  // Simple hash function
  simpleHash(str) {
    let hash = 0;
    for (let i = 0; i < str.length; i++) {
      const char = str.charCodeAt(i);
      hash = ((hash << 5) - hash) + char;
      hash = hash & hash; // Convert to 32-bit integer
    }
    return Math.abs(hash).toString(36);
  }

  // Multi-layer encryption with salt and additional security
  encrypt(text) {
    if (!text || text.trim() === '') return '';
    
    // Layer 1: Add timestamp and random padding
    const timestamp = Date.now().toString(36);
    const randomPadding = Math.random().toString(36).substring(2);
    const paddedText = `${timestamp}:${text}:${randomPadding}`;
    
    // Layer 2: XOR with device salt
    const saltKey = this.salt + this.additionalSalt;
    let encrypted = '';
    
    for (let i = 0; i < paddedText.length; i++) {
      const textChar = paddedText.charCodeAt(i);
      const saltChar = saltKey.charCodeAt(i % saltKey.length);
      const encryptedChar = textChar ^ saltChar;
      encrypted += String.fromCharCode(encryptedChar);
    }
    
    // Layer 3: Base64 encode with additional obfuscation
    const base64 = btoa(encrypted);
    const obfuscated = base64.split('').reverse().join('');
    
    return obfuscated;
  }

  // Multi-layer decryption
  decrypt(encryptedText) {
    if (!encryptedText || encryptedText.trim() === '') return '';
    
    try {
      // Layer 1: Reverse obfuscation and Base64 decode
      const deobfuscated = encryptedText.split('').reverse().join('');
      const encrypted = atob(deobfuscated);
      
      // Layer 2: XOR decryption with device salt
      const saltKey = this.salt + this.additionalSalt;
      let decrypted = '';
      
      for (let i = 0; i < encrypted.length; i++) {
        const encryptedChar = encrypted.charCodeAt(i);
        const saltChar = saltKey.charCodeAt(i % saltKey.length);
        const decryptedChar = encryptedChar ^ saltChar;
        decrypted += String.fromCharCode(decryptedChar);
      }
      
      // Layer 3: Extract original text from padded format
      const parts = decrypted.split(':');
      if (parts.length >= 3) {
        // Remove timestamp and random padding, return original text
        return parts.slice(1, -1).join(':');
      }
      
      return decrypted; // Fallback for old format
    } catch (error) {
      console.warn('Failed to decrypt API key:', error);
      return '';
    }
  }

  // Store encrypted API key with obfuscated key name
  storeApiKey(apiKey) {
    if (!apiKey || apiKey.trim() === '') {
      localStorage.removeItem('luna_secure_config_v2');
      return;
    }
    
    const encrypted = this.encrypt(apiKey);
    localStorage.setItem('luna_secure_config_v2', encrypted);
  }

  // Retrieve and decrypt API key
  retrieveApiKey() {
    const encrypted = localStorage.getItem('luna_secure_config_v2');
    if (!encrypted) return '';
    
    return this.decrypt(encrypted);
  }

  // Clear stored API key
  clearApiKey() {
    localStorage.removeItem('luna_secure_config_v2');
  }

  // Check if API key exists
  hasStoredApiKey() {
    return !!localStorage.getItem('luna_secure_config_v2');
  }
}

export default new ApiKeyEncryption();