react-native-secreton 2.3.0 â 2.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -3
- package/android/build.gradle +3 -1
- package/android/secreton.gradle +22 -17
- package/android/src/main/java/com/secreton/SecretonModule.kt +64 -23
- package/dist/NodeSecreton.js +1 -1
- package/ios/Secreton.mm +33 -9
- package/lib/module/NodeSecreton.js +1 -1
- package/lib/module/index.js +4 -4
- package/lib/module/index.js.map +1 -1
- package/lib/typescript/src/NativeSecreton.d.ts +2 -2
- package/lib/typescript/src/NativeSecreton.d.ts.map +1 -1
- package/lib/typescript/src/index.d.ts +2 -2
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/package.json +1 -1
- package/react-native-secreton.podspec +1 -1
- package/scripts/secreton-ios.sh +26 -12
- package/src/NativeSecreton.ts +2 -2
- package/src/NodeSecreton.ts +1 -1
- package/src/index.tsx +4 -4
package/README.md
CHANGED
|
@@ -46,7 +46,7 @@ $ react-native link react-native-secreton
|
|
|
46
46
|
|
|
47
47
|
### Using Consul
|
|
48
48
|
```bash
|
|
49
|
-
export ENV_SECRET_KEY=
|
|
49
|
+
export ENV_SECRET_KEY=secret-key-32-bytes
|
|
50
50
|
export FETCH_ENV=consul
|
|
51
51
|
export CONSUL_ADDR=http://consul.mycompany.com:8500
|
|
52
52
|
export CONSUL_PATH=mobile/myapp
|
|
@@ -57,10 +57,10 @@ rn-secreton-cli .env
|
|
|
57
57
|
|
|
58
58
|
### Using Vault
|
|
59
59
|
```bash
|
|
60
|
-
export ENV_SECRET_KEY=
|
|
60
|
+
export ENV_SECRET_KEY=secret-key-32-bytes
|
|
61
61
|
export FETCH_ENV=vault
|
|
62
62
|
export VAULT_ADDR=http://vault.mycompany.com:8200
|
|
63
|
-
export VAULT_PATH=
|
|
63
|
+
export VAULT_PATH=myapp/data/local
|
|
64
64
|
export VAULT_TOKEN=abcd1234
|
|
65
65
|
|
|
66
66
|
rn-secreton-cli .env
|
package/android/build.gradle
CHANGED
|
@@ -18,9 +18,10 @@ buildscript {
|
|
|
18
18
|
|
|
19
19
|
apply plugin: "com.android.library"
|
|
20
20
|
apply plugin: "kotlin-android"
|
|
21
|
-
|
|
22
21
|
apply plugin: "com.facebook.react"
|
|
23
22
|
|
|
23
|
+
apply from: "secreton.gradle"
|
|
24
|
+
|
|
24
25
|
def getExtOrIntegerDefault(name) {
|
|
25
26
|
return rootProject.ext.has(name) ? rootProject.ext.get(name) : (project.properties["Secreton_" + name]).toInteger()
|
|
26
27
|
}
|
|
@@ -33,6 +34,7 @@ android {
|
|
|
33
34
|
defaultConfig {
|
|
34
35
|
minSdkVersion getExtOrIntegerDefault("minSdkVersion")
|
|
35
36
|
targetSdkVersion getExtOrIntegerDefault("targetSdkVersion")
|
|
37
|
+
buildConfigField "String", "ENV_SECRET_KEY", "\"${getSecretKeyFromEnv(project)}\""
|
|
36
38
|
}
|
|
37
39
|
|
|
38
40
|
buildFeatures {
|
package/android/secreton.gradle
CHANGED
|
@@ -38,18 +38,30 @@ ext.loadEnvFile = { File file ->
|
|
|
38
38
|
return map
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
+
ext.getEnvFile = { appProject ->
|
|
42
|
+
def androidDir = appProject.rootProject.projectDir
|
|
43
|
+
def workspaceRoot = findWorkspaceRoot(androidDir)
|
|
44
|
+
|
|
45
|
+
def envFileName = appProject.findProperty("ENVFILE") ?: System.getenv("ENVFILE") ?: ".env"
|
|
46
|
+
def envFile = new File(workspaceRoot, envFileName)
|
|
47
|
+
|
|
48
|
+
return envFile
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
ext.getSecretKeyFromEnv = { appProject ->
|
|
52
|
+
def envFile = getEnvFile(appProject)
|
|
53
|
+
def envMap = loadEnvFile(envFile)
|
|
54
|
+
|
|
55
|
+
return envMap["ENV_SECRET_KEY"] ?: ""
|
|
56
|
+
}
|
|
57
|
+
|
|
41
58
|
ext.ensureLocalEnv = { appProject ->
|
|
42
59
|
if (appProject.ext.has("localEnv")) return
|
|
43
60
|
|
|
44
61
|
appProject.ext.localEnv = [:]
|
|
45
62
|
appProject.ext.env = [:]
|
|
46
|
-
|
|
47
|
-
def
|
|
48
|
-
def workspaceRoot = findWorkspaceRoot(androidDir)
|
|
49
|
-
def rootDir = workspaceRoot
|
|
50
|
-
|
|
51
|
-
def envFileName = appProject.findProperty("ENVFILE") ?: System.getenv("ENVFILE") ?: ".env"
|
|
52
|
-
def envFile = new File(rootDir, envFileName)
|
|
63
|
+
|
|
64
|
+
def envFile = getEnvFile(appProject)
|
|
53
65
|
|
|
54
66
|
if (envFile.exists()) {
|
|
55
67
|
appProject.ext.localEnv.putAll(loadEnvFile(envFile))
|
|
@@ -85,15 +97,8 @@ ext.decryptValue = { String encrypted, String secretKey ->
|
|
|
85
97
|
|
|
86
98
|
ext.loadAndDecryptEnv = { appProject ->
|
|
87
99
|
ensureLocalEnv(appProject)
|
|
88
|
-
|
|
89
|
-
def
|
|
90
|
-
def rootDir = findWorkspaceRoot(androidDir)
|
|
91
|
-
|
|
92
|
-
def envFileName =
|
|
93
|
-
appProject.findProperty("ENVFILE")
|
|
94
|
-
?: System.getenv("ENVFILE")
|
|
95
|
-
?: ".env"
|
|
96
|
-
def envFile = new File(rootDir, envFileName)
|
|
100
|
+
|
|
101
|
+
def envFile = getEnvFile(appProject)
|
|
97
102
|
if (!envFile.exists()) return
|
|
98
103
|
|
|
99
104
|
def secretKey = getSecretKey(appProject)
|
|
@@ -102,7 +107,7 @@ ext.loadAndDecryptEnv = { appProject ->
|
|
|
102
107
|
def envMap = loadEnvFile(envFile)
|
|
103
108
|
envMap.each { k, v ->
|
|
104
109
|
def value = v
|
|
105
|
-
if (v instanceof String && v.startsWith("
|
|
110
|
+
if (v instanceof String && v.startsWith("Secreton:")) {
|
|
106
111
|
value = decryptValue(v.substring(9), secretKey)
|
|
107
112
|
}
|
|
108
113
|
if (value == null) {
|
|
@@ -2,8 +2,8 @@ package com.secreton
|
|
|
2
2
|
|
|
3
3
|
import com.facebook.react.bridge.ReactApplicationContext
|
|
4
4
|
import com.facebook.react.module.annotations.ReactModule
|
|
5
|
-
|
|
6
5
|
import android.util.Base64
|
|
6
|
+
import java.security.SecureRandom
|
|
7
7
|
import javax.crypto.Cipher
|
|
8
8
|
import javax.crypto.SecretKeyFactory
|
|
9
9
|
import javax.crypto.spec.IvParameterSpec
|
|
@@ -11,46 +11,87 @@ import javax.crypto.spec.PBEKeySpec
|
|
|
11
11
|
import javax.crypto.spec.SecretKeySpec
|
|
12
12
|
|
|
13
13
|
@ReactModule(name = SecretonModule.NAME)
|
|
14
|
-
class SecretonModule(
|
|
15
|
-
|
|
14
|
+
class SecretonModule(
|
|
15
|
+
reactContext: ReactApplicationContext
|
|
16
|
+
) : NativeSecretonSpec(reactContext) {
|
|
16
17
|
|
|
17
18
|
companion object {
|
|
18
19
|
const val NAME = "Secreton"
|
|
20
|
+
private const val PREFIX = "$NAME:"
|
|
21
|
+
private const val ITERATIONS = 100_000
|
|
19
22
|
}
|
|
20
23
|
|
|
21
|
-
override fun getName()
|
|
22
|
-
|
|
24
|
+
override fun getName() = NAME
|
|
25
|
+
|
|
26
|
+
override fun encrypt(value: String): String {
|
|
27
|
+
val encrypted = encryptOpenSSL(value, getSecretKey())
|
|
28
|
+
return PREFIX + encrypted
|
|
23
29
|
}
|
|
24
30
|
|
|
25
|
-
override fun
|
|
26
|
-
|
|
27
|
-
|
|
31
|
+
override fun decrypt(value: String): String {
|
|
32
|
+
if (!value.startsWith(PREFIX)) return value
|
|
33
|
+
return decryptOpenSSL(value.removePrefix(PREFIX), getSecretKey())
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
private fun getSecretKey(): String {
|
|
37
|
+
return BuildConfig.ENV_SECRET_KEY
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
private fun encryptOpenSSL(value: String, key: String): String {
|
|
41
|
+
val salt = ByteArray(8)
|
|
42
|
+
SecureRandom().nextBytes(salt)
|
|
28
43
|
|
|
29
44
|
val factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256")
|
|
30
|
-
val spec = PBEKeySpec(
|
|
31
|
-
|
|
32
|
-
|
|
45
|
+
val spec = PBEKeySpec(
|
|
46
|
+
key.toCharArray(),
|
|
47
|
+
salt,
|
|
48
|
+
ITERATIONS,
|
|
49
|
+
(32 + 16) * 8 // key + iv in bits
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
val keyIv = factory.generateSecret(spec).encoded
|
|
53
|
+
val aesKey = SecretKeySpec(keyIv.copyOfRange(0, 32), "AES")
|
|
54
|
+
val iv = IvParameterSpec(keyIv.copyOfRange(32, 48))
|
|
33
55
|
|
|
34
56
|
val cipher = Cipher.getInstance("AES/CBC/PKCS7Padding")
|
|
35
|
-
cipher.init(Cipher.ENCRYPT_MODE,
|
|
57
|
+
cipher.init(Cipher.ENCRYPT_MODE, aesKey, iv)
|
|
36
58
|
|
|
37
|
-
val encrypted = cipher.doFinal(value.toByteArray())
|
|
38
|
-
|
|
59
|
+
val encrypted = cipher.doFinal(value.toByteArray(Charsets.UTF_8))
|
|
60
|
+
|
|
61
|
+
val output = ByteArray(16 + encrypted.size)
|
|
62
|
+
System.arraycopy("Salted__".toByteArray(), 0, output, 0, 8)
|
|
63
|
+
System.arraycopy(salt, 0, output, 8, 8)
|
|
64
|
+
System.arraycopy(encrypted, 0, output, 16, encrypted.size)
|
|
65
|
+
|
|
66
|
+
return Base64.encodeToString(output, Base64.NO_WRAP)
|
|
39
67
|
}
|
|
40
68
|
|
|
41
|
-
|
|
42
|
-
val
|
|
43
|
-
|
|
69
|
+
private fun decryptOpenSSL(encrypted: String, key: String): String {
|
|
70
|
+
val decoded = Base64.decode(encrypted, Base64.NO_WRAP)
|
|
71
|
+
|
|
72
|
+
val magic = String(decoded.copyOfRange(0, 8))
|
|
73
|
+
if (magic != "Salted__") {
|
|
74
|
+
throw IllegalArgumentException("Invalid OpenSSL salt header")
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
val salt = decoded.copyOfRange(8, 16)
|
|
78
|
+
val cipherText = decoded.copyOfRange(16, decoded.size)
|
|
44
79
|
|
|
45
80
|
val factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256")
|
|
46
|
-
val spec = PBEKeySpec(
|
|
47
|
-
|
|
48
|
-
|
|
81
|
+
val spec = PBEKeySpec(
|
|
82
|
+
key.toCharArray(),
|
|
83
|
+
salt,
|
|
84
|
+
ITERATIONS,
|
|
85
|
+
(32 + 16) * 8
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
val keyIv = factory.generateSecret(spec).encoded
|
|
89
|
+
val aesKey = SecretKeySpec(keyIv.copyOfRange(0, 32), "AES")
|
|
90
|
+
val iv = IvParameterSpec(keyIv.copyOfRange(32, 48))
|
|
49
91
|
|
|
50
92
|
val cipher = Cipher.getInstance("AES/CBC/PKCS7Padding")
|
|
51
|
-
cipher.init(Cipher.DECRYPT_MODE,
|
|
93
|
+
cipher.init(Cipher.DECRYPT_MODE, aesKey, iv)
|
|
52
94
|
|
|
53
|
-
|
|
54
|
-
return String(cipher.doFinal(decoded))
|
|
95
|
+
return String(cipher.doFinal(cipherText), Charsets.UTF_8)
|
|
55
96
|
}
|
|
56
97
|
}
|
package/dist/NodeSecreton.js
CHANGED
|
@@ -64,7 +64,7 @@ export async function generateEnv(options) {
|
|
|
64
64
|
}
|
|
65
65
|
const newLines = entries
|
|
66
66
|
.filter(({ key }) => !existingKeys.has(key))
|
|
67
|
-
.map(({ key, value }) => `${key}=
|
|
67
|
+
.map(({ key, value }) => `${key}=Secreton:${encrypt(value, secretKey)}`);
|
|
68
68
|
if (newLines.length === 0) {
|
|
69
69
|
console.log('âšī¸ [Node] Secreton no new env keys to add');
|
|
70
70
|
return;
|
package/ios/Secreton.mm
CHANGED
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
|
|
5
5
|
@implementation Secreton
|
|
6
6
|
|
|
7
|
+
static NSString * const kPrefix = @"Secreton:";
|
|
8
|
+
|
|
7
9
|
+ (NSString *)moduleName
|
|
8
10
|
{
|
|
9
11
|
return @"Secreton";
|
|
@@ -11,14 +13,30 @@
|
|
|
11
13
|
|
|
12
14
|
#pragma mark - TurboModule methods
|
|
13
15
|
|
|
14
|
-
- (NSString *)encrypt:(NSString *)value
|
|
16
|
+
- (NSString *)encrypt:(NSString *)value
|
|
15
17
|
{
|
|
16
|
-
|
|
18
|
+
NSString *key = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"ENV_SECRET_KEY"];
|
|
19
|
+
if (!key || key.length == 0) {
|
|
20
|
+
return nil;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
NSString *encrypted = [self aes:kCCEncrypt value:value key:key];
|
|
24
|
+
return [kPrefix stringByAppendingString:encrypted];
|
|
17
25
|
}
|
|
18
26
|
|
|
19
|
-
- (NSString *)decrypt:(NSString *)value
|
|
27
|
+
- (NSString *)decrypt:(NSString *)value
|
|
20
28
|
{
|
|
21
|
-
|
|
29
|
+
if (![value hasPrefix:kPrefix]) {
|
|
30
|
+
return value;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
NSString *key = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"ENV_SECRET_KEY"];
|
|
34
|
+
if (!key || key.length == 0) {
|
|
35
|
+
return nil;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
NSString *raw = [value substringFromIndex:kPrefix.length];
|
|
39
|
+
return [self aes:kCCDecrypt value:raw key:key];
|
|
22
40
|
}
|
|
23
41
|
|
|
24
42
|
#pragma mark - AES core
|
|
@@ -27,13 +45,19 @@
|
|
|
27
45
|
value:(NSString *)value
|
|
28
46
|
key:(NSString *)key
|
|
29
47
|
{
|
|
30
|
-
NSData *data =
|
|
48
|
+
NSData *data = nil;
|
|
49
|
+
|
|
50
|
+
if (operation == kCCEncrypt) {
|
|
51
|
+
data = [value dataUsingEncoding:NSUTF8StringEncoding];
|
|
52
|
+
} else {
|
|
53
|
+
data = [[NSData alloc] initWithBase64EncodedString:value options:0];
|
|
54
|
+
if (!data) return nil;
|
|
55
|
+
}
|
|
31
56
|
|
|
32
|
-
//
|
|
57
|
+
// Key 32 byte (AES-256)
|
|
33
58
|
NSMutableData *keyData = [NSMutableData dataWithLength:kCCKeySizeAES256];
|
|
34
59
|
NSData *rawKey = [key dataUsingEncoding:NSUTF8StringEncoding];
|
|
35
|
-
|
|
36
|
-
memcpy(keyData.mutableBytes, rawKey.bytes, copyLen);
|
|
60
|
+
memcpy(keyData.mutableBytes, rawKey.bytes, MIN(rawKey.length, kCCKeySizeAES256));
|
|
37
61
|
|
|
38
62
|
size_t outLength = 0;
|
|
39
63
|
NSMutableData *outData = [NSMutableData dataWithLength:data.length + kCCBlockSizeAES128];
|
|
@@ -44,7 +68,7 @@
|
|
|
44
68
|
kCCOptionPKCS7Padding,
|
|
45
69
|
keyData.bytes,
|
|
46
70
|
kCCKeySizeAES256,
|
|
47
|
-
NULL, // IV
|
|
71
|
+
NULL, // IV zero
|
|
48
72
|
data.bytes,
|
|
49
73
|
data.length,
|
|
50
74
|
outData.mutableBytes,
|
|
@@ -71,7 +71,7 @@ export async function generateEnv(options) {
|
|
|
71
71
|
}) => !existingKeys.has(key)).map(({
|
|
72
72
|
key,
|
|
73
73
|
value
|
|
74
|
-
}) => `${key}=
|
|
74
|
+
}) => `${key}=Secreton:${encrypt(value, secretKey)}`);
|
|
75
75
|
if (newLines.length === 0) {
|
|
76
76
|
console.log('âšī¸ [Node] Secreton no new env keys to add');
|
|
77
77
|
return;
|
package/lib/module/index.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
3
|
import Secreton from "./NativeSecreton.js";
|
|
4
|
-
export function encrypt(value
|
|
5
|
-
return Secreton.encrypt(value
|
|
4
|
+
export function encrypt(value) {
|
|
5
|
+
return Secreton.encrypt(value);
|
|
6
6
|
}
|
|
7
|
-
export function decrypt(encrypted
|
|
8
|
-
return Secreton.decrypt(encrypted
|
|
7
|
+
export function decrypt(encrypted) {
|
|
8
|
+
return Secreton.decrypt(encrypted);
|
|
9
9
|
}
|
|
10
10
|
//# sourceMappingURL=index.js.map
|
package/lib/module/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["Secreton","encrypt","value","
|
|
1
|
+
{"version":3,"names":["Secreton","encrypt","value","decrypt","encrypted"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":";;AAAA,OAAOA,QAAQ,MAAM,qBAAkB;AAEvC,OAAO,SAASC,OAAOA,CAACC,KAAa,EAAU;EAC7C,OAAOF,QAAQ,CAACC,OAAO,CAACC,KAAK,CAAC;AAChC;AAEA,OAAO,SAASC,OAAOA,CAACC,SAAiB,EAAU;EACjD,OAAOJ,QAAQ,CAACG,OAAO,CAACC,SAAS,CAAC;AACpC","ignoreList":[]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { type TurboModule } from 'react-native';
|
|
2
2
|
export interface Spec extends TurboModule {
|
|
3
|
-
encrypt(value: string
|
|
4
|
-
decrypt(encrypted: string
|
|
3
|
+
encrypt(value: string): string;
|
|
4
|
+
decrypt(encrypted: string): string;
|
|
5
5
|
}
|
|
6
6
|
declare const _default: Spec;
|
|
7
7
|
export default _default;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NativeSecreton.d.ts","sourceRoot":"","sources":["../../../src/NativeSecreton.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuB,KAAK,WAAW,EAAE,MAAM,cAAc,CAAC;AAErE,MAAM,WAAW,IAAK,SAAQ,WAAW;IACvC,OAAO,CAAC,KAAK,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"NativeSecreton.d.ts","sourceRoot":"","sources":["../../../src/NativeSecreton.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuB,KAAK,WAAW,EAAE,MAAM,cAAc,CAAC;AAErE,MAAM,WAAW,IAAK,SAAQ,WAAW;IACvC,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC;IAC/B,OAAO,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAAC;CACpC;;AAED,wBAAkE"}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export declare function encrypt(value: string
|
|
2
|
-
export declare function decrypt(encrypted: string
|
|
1
|
+
export declare function encrypt(value: string): string;
|
|
2
|
+
export declare function decrypt(encrypted: string): string;
|
|
3
3
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.tsx"],"names":[],"mappings":"AAEA,wBAAgB,OAAO,CAAC,KAAK,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.tsx"],"names":[],"mappings":"AAEA,wBAAgB,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAE7C;AAED,wBAAgB,OAAO,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAEjD"}
|
package/package.json
CHANGED
|
@@ -19,7 +19,7 @@ Pod::Spec.new do |s|
|
|
|
19
19
|
|
|
20
20
|
s.script_phase = {
|
|
21
21
|
:name => 'Secreton Env',
|
|
22
|
-
:script => 'bash "${PODS_TARGET_SRCROOT}
|
|
22
|
+
:script => 'bash "${PODS_TARGET_SRCROOT}/scripts/secreton-ios.sh"',
|
|
23
23
|
:execution_position => :before_compile
|
|
24
24
|
}
|
|
25
25
|
|
package/scripts/secreton-ios.sh
CHANGED
|
@@ -3,33 +3,47 @@ set -e
|
|
|
3
3
|
|
|
4
4
|
echo "đ [Secreton] iOS script phase running..."
|
|
5
5
|
|
|
6
|
-
WORKSPACE_ROOT="$
|
|
6
|
+
WORKSPACE_ROOT="${SRCROOT}/../.."
|
|
7
7
|
ENVFILE="${ENVFILE:-.env}"
|
|
8
|
+
|
|
9
|
+
ENV_PATH="$WORKSPACE_ROOT/$ENVFILE"
|
|
8
10
|
CLI_BIN="$WORKSPACE_ROOT/node_modules/.bin/rn-secreton-cli"
|
|
9
11
|
GENERATED_FILE="$WORKSPACE_ROOT/Secreton.xcconfig"
|
|
10
12
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
+
echo "đ WORKSPACE_ROOT = $WORKSPACE_ROOT"
|
|
14
|
+
echo "đ ENVFILE = $ENV_PATH"
|
|
15
|
+
|
|
16
|
+
if [ ! -f "$ENV_PATH" ]; then
|
|
17
|
+
echo "â ENV file not found: $ENV_PATH"
|
|
13
18
|
exit 1
|
|
14
19
|
fi
|
|
15
20
|
|
|
21
|
+
echo "đ Loading env vars"
|
|
22
|
+
set -a
|
|
23
|
+
source "$ENV_PATH"
|
|
24
|
+
set +a
|
|
25
|
+
|
|
26
|
+
: "${ENV_SECRET_KEY:?â ENV_SECRET_KEY not set in $ENVFILE}"
|
|
27
|
+
|
|
16
28
|
if [ ! -f "$CLI_BIN" ]; then
|
|
17
29
|
echo "â rn-secreton-cli not found at $CLI_BIN"
|
|
18
30
|
exit 1
|
|
19
31
|
fi
|
|
20
32
|
|
|
21
33
|
echo "đ rn-secreton generating env (iOS)..."
|
|
22
|
-
|
|
34
|
+
"$CLI_BIN" "$ENV_PATH" --out "$GENERATED_FILE"
|
|
35
|
+
|
|
36
|
+
touch "$GENERATED_FILE"
|
|
23
37
|
|
|
24
|
-
"
|
|
38
|
+
echo "// Generated by rn-secreton-cli" > "$GENERATED_FILE"
|
|
39
|
+
while IFS='=' read -r key value || [ -n "$key" ]; do
|
|
40
|
+
[[ -z "$key" ]] && continue
|
|
41
|
+
[[ "$key" =~ ^# ]] && continue
|
|
25
42
|
|
|
26
|
-
if
|
|
27
|
-
|
|
28
|
-
while IFS='=' read -r key value; do
|
|
29
|
-
[ -z "$key" ] && continue
|
|
30
|
-
[[ "$key" =~ ^# ]] && continue
|
|
43
|
+
if ! grep -q "^${key}=" "$GENERATED_FILE"; then
|
|
44
|
+
echo "â adding missing key: $key"
|
|
31
45
|
echo "$key=$value" >> "$GENERATED_FILE"
|
|
32
|
-
|
|
33
|
-
|
|
46
|
+
fi
|
|
47
|
+
done < "$ENV_PATH"
|
|
34
48
|
|
|
35
49
|
echo "â
Secreton.xcconfig generated at $GENERATED_FILE"
|
package/src/NativeSecreton.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { TurboModuleRegistry, type TurboModule } from 'react-native';
|
|
2
2
|
|
|
3
3
|
export interface Spec extends TurboModule {
|
|
4
|
-
encrypt(value: string
|
|
5
|
-
decrypt(encrypted: string
|
|
4
|
+
encrypt(value: string): string;
|
|
5
|
+
decrypt(encrypted: string): string;
|
|
6
6
|
}
|
|
7
7
|
|
|
8
8
|
export default TurboModuleRegistry.getEnforcing<Spec>('Secreton');
|
package/src/NodeSecreton.ts
CHANGED
|
@@ -118,7 +118,7 @@ export async function generateEnv(options: GenerateEnvOptions) {
|
|
|
118
118
|
|
|
119
119
|
const newLines = entries
|
|
120
120
|
.filter(({ key }) => !existingKeys.has(key))
|
|
121
|
-
.map(({ key, value }) => `${key}=
|
|
121
|
+
.map(({ key, value }) => `${key}=Secreton:${encrypt(value, secretKey)}`);
|
|
122
122
|
|
|
123
123
|
if (newLines.length === 0) {
|
|
124
124
|
console.log('âšī¸ [Node] Secreton no new env keys to add');
|
package/src/index.tsx
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import Secreton from './NativeSecreton';
|
|
2
2
|
|
|
3
|
-
export function encrypt(value: string
|
|
4
|
-
return Secreton.encrypt(value
|
|
3
|
+
export function encrypt(value: string): string {
|
|
4
|
+
return Secreton.encrypt(value);
|
|
5
5
|
}
|
|
6
6
|
|
|
7
|
-
export function decrypt(encrypted: string
|
|
8
|
-
return Secreton.decrypt(encrypted
|
|
7
|
+
export function decrypt(encrypted: string): string {
|
|
8
|
+
return Secreton.decrypt(encrypted);
|
|
9
9
|
}
|