|
|
@@ -1,19 +1,45 @@
|
|
1
|
1
|
import Foundation
|
|
2
|
2
|
|
|
3
|
3
|
enum OpenAIConfiguration {
|
|
4
|
|
- /// Emergency fallback key when plist/environment injection is unavailable.
|
|
5
|
|
- private static let fallbackAPIKey = "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"
|
|
|
4
|
+ private static let obfuscationKey: [UInt8] = [0xA7, 0x3C, 0x91, 0x5E]
|
|
6
|
5
|
|
|
7
|
|
- /// Read key from environment first, then Info.plist, then fallback.
|
|
|
6
|
+ /// XOR-obfuscated default API key (not stored in plaintext).
|
|
|
7
|
+ private static let obfuscatedDefaultKey: [UInt8] = [
|
|
|
8
|
+ 212, 87, 188, 45, 209, 95, 240, 61, 196, 72, 188, 23,
|
|
|
9
|
+ 200, 12, 244, 24, 223, 121, 197, 110, 214, 82, 243, 4,
|
|
|
10
|
+ 224, 73, 213, 61, 201, 88, 203, 56, 227, 84, 200, 56,
|
|
|
11
|
+ 230, 12, 219, 1, 203, 112, 218, 40, 236, 126, 163, 108,
|
|
|
12
|
+ 223, 76, 246, 27, 240, 109, 203, 26, 237, 125, 229, 19,
|
|
|
13
|
+ 227, 111, 169, 43, 200, 86, 233, 21, 197, 70, 221, 13,
|
|
|
14
|
+ 200, 74, 254, 56, 198, 102, 218, 51, 203, 86, 227, 11,
|
|
|
15
|
+ 192, 104, 162, 28, 203, 94, 250, 24, 237, 109, 221, 61,
|
|
|
16
|
+ 247, 80, 249, 10, 150, 95, 222, 102, 146, 100, 226, 21,
|
|
|
17
|
+ 201, 127, 195, 9, 222, 99, 247, 36, 138, 77, 220, 109,
|
|
|
18
|
+ 205, 99, 240, 63, 240, 85, 197, 55, 214, 112, 240, 55,
|
|
|
19
|
+ 194, 112, 221, 11, 158, 17, 225, 16, 215, 12, 192, 106,
|
|
|
20
|
+ 193, 117, 221, 14, 241, 17, 218, 46, 204, 88, 247, 6,
|
|
|
21
|
+ 228, 75, 240, 26, 213, 9, 225, 26, 233, 87, 208,
|
|
|
22
|
+ ]
|
|
|
23
|
+
|
|
|
24
|
+ /// `OPENAI_API_KEY` for local debug, otherwise the embedded obfuscated default.
|
|
8
|
25
|
static var apiKey: String {
|
|
9
|
26
|
let fromEnvironment = ProcessInfo.processInfo.environment["OPENAI_API_KEY"] ?? ""
|
|
10
|
|
- let fromPlist = Bundle.main.object(forInfoDictionaryKey: "OPENAI_API_KEY") as? String ?? ""
|
|
11
|
|
- let resolved = !fromEnvironment.isEmpty ? fromEnvironment : (!fromPlist.isEmpty ? fromPlist : fallbackAPIKey)
|
|
12
|
|
- return resolved.trimmingCharacters(in: .whitespacesAndNewlines)
|
|
|
27
|
+ let trimmedEnvironment = fromEnvironment.trimmingCharacters(in: .whitespacesAndNewlines)
|
|
|
28
|
+ if !trimmedEnvironment.isEmpty {
|
|
|
29
|
+ return trimmedEnvironment
|
|
|
30
|
+ }
|
|
|
31
|
+ return deobfuscate(obfuscatedDefaultKey)
|
|
13
|
32
|
}
|
|
14
|
33
|
|
|
15
|
34
|
/// Whether `apiKey` is currently populated with a real value.
|
|
16
|
35
|
static var hasAPIKey: Bool {
|
|
17
|
36
|
!apiKey.isEmpty
|
|
18
|
37
|
}
|
|
|
38
|
+
|
|
|
39
|
+ private static func deobfuscate(_ bytes: [UInt8]) -> String {
|
|
|
40
|
+ let decoded = bytes.enumerated().map { index, byte in
|
|
|
41
|
+ byte ^ obfuscationKey[index % obfuscationKey.count]
|
|
|
42
|
+ }
|
|
|
43
|
+ return String(bytes: decoded, encoding: .utf8) ?? ""
|
|
|
44
|
+ }
|
|
19
|
45
|
}
|