react-native-secreton 2.2.1 → 2.3.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 +31 -6
- package/android/secreton.gradle +12 -4
- package/android/src/main/java/com/secreton/SecretonModule.kt +39 -6
- package/android/src/main/java/com/secreton/SecretonPackage.kt +1 -1
- package/dist/NodeSecreton.js +5 -1
- package/ios/Secreton.mm +63 -8
- package/lib/module/NativeSecreton.js.map +1 -1
- package/lib/module/NodeSecreton.js +5 -1
- package/lib/module/NodeSecreton.js.map +1 -1
- package/lib/module/index.js +5 -2
- package/lib/module/index.js.map +1 -1
- package/lib/typescript/src/NativeSecreton.d.ts +2 -1
- package/lib/typescript/src/NativeSecreton.d.ts.map +1 -1
- package/lib/typescript/src/NodeSecreton.d.ts +1 -0
- package/lib/typescript/src/NodeSecreton.d.ts.map +1 -1
- package/lib/typescript/src/index.d.ts +2 -1
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/package.json +5 -2
- package/react-native-secreton.podspec +2 -0
- package/src/NativeSecreton.ts +2 -1
- package/src/NodeSecreton.ts +6 -1
- package/src/index.tsx +6 -2
package/README.md
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
# react-native-secreton
|
|
2
|
-
|
|
2
|
+
A library for managing **secret environment variables** in React Native apps.
|
|
3
|
+
Supports integration with **Consul** and **Vault** to securely retrieve configurations.
|
|
3
4
|
|
|
4
5
|
## Installation
|
|
5
|
-
```
|
|
6
|
+
```bash
|
|
6
7
|
npm install react-native-secreton
|
|
8
|
+
# or
|
|
9
|
+
yarn add react-native-secreton
|
|
7
10
|
```
|
|
8
11
|
|
|
9
12
|
## Generate secret key
|
|
@@ -15,7 +18,7 @@ openssl rand -hex 32
|
|
|
15
18
|
## Setup
|
|
16
19
|
Link the library:
|
|
17
20
|
```
|
|
18
|
-
$ react-native link react-native-
|
|
21
|
+
$ react-native link react-native-secreton
|
|
19
22
|
```
|
|
20
23
|
|
|
21
24
|
- Manual Link (Android)
|
|
@@ -39,6 +42,30 @@ $ react-native link react-native-config
|
|
|
39
42
|
+ pod 'react-native-secreton', :path => '../node_modules/react-native-secreton'
|
|
40
43
|
```
|
|
41
44
|
|
|
45
|
+
## Usage Examples
|
|
46
|
+
|
|
47
|
+
### Using Consul
|
|
48
|
+
```bash
|
|
49
|
+
export ENV_SECRET_KEY=my-secret
|
|
50
|
+
export FETCH_ENV=consul
|
|
51
|
+
export CONSUL_ADDR=http://consul.mycompany.com:8500
|
|
52
|
+
export CONSUL_PATH=mobile/myapp
|
|
53
|
+
export CONSUL_TOKEN=abcd1234
|
|
54
|
+
|
|
55
|
+
rn-secreton-cli .env
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### Using Vault
|
|
59
|
+
```bash
|
|
60
|
+
export ENV_SECRET_KEY=my-secret
|
|
61
|
+
export FETCH_ENV=vault
|
|
62
|
+
export VAULT_ADDR=http://vault.mycompany.com:8200
|
|
63
|
+
export VAULT_PATH=secret/data/mobile/myapp
|
|
64
|
+
export VAULT_TOKEN=abcd1234
|
|
65
|
+
|
|
66
|
+
rn-secreton-cli .env
|
|
67
|
+
```
|
|
68
|
+
|
|
42
69
|
## Native Usage
|
|
43
70
|
|
|
44
71
|
### Android
|
|
@@ -63,8 +90,6 @@ Then in Xcode build settings:
|
|
|
63
90
|
2. Use on native iOS (Objective‑C/Swift)
|
|
64
91
|
```objective‑c
|
|
65
92
|
let apiKey = ProcessInfo.processInfo.environment["GEO_APK_API_KEY"]
|
|
66
|
-
|
|
67
|
-
or
|
|
68
|
-
|
|
93
|
+
# or
|
|
69
94
|
let apiKey = Bundle.main.object(forInfoDictionaryKey: "GEO_APK_API_KEY") as? String
|
|
70
95
|
```
|
package/android/secreton.gradle
CHANGED
|
@@ -72,10 +72,15 @@ ext.decryptValue = { String encrypted, String secretKey ->
|
|
|
72
72
|
proc.waitFor()
|
|
73
73
|
|
|
74
74
|
if (proc.exitValue() != 0) {
|
|
75
|
-
throw new RuntimeException(proc.err.text)
|
|
75
|
+
throw new RuntimeException("❌ OpenSSL decrypt failed: ${proc.err.text}")
|
|
76
76
|
}
|
|
77
77
|
|
|
78
|
-
|
|
78
|
+
def output = proc.in.text.trim()
|
|
79
|
+
if (!output) {
|
|
80
|
+
throw new RuntimeException("❌ Decryption returned empty value")
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return output
|
|
79
84
|
}
|
|
80
85
|
|
|
81
86
|
ext.loadAndDecryptEnv = { appProject ->
|
|
@@ -97,8 +102,11 @@ ext.loadAndDecryptEnv = { appProject ->
|
|
|
97
102
|
def envMap = loadEnvFile(envFile)
|
|
98
103
|
envMap.each { k, v ->
|
|
99
104
|
def value = v
|
|
100
|
-
if (v instanceof String && v.startsWith("
|
|
101
|
-
value = decryptValue(v.substring(
|
|
105
|
+
if (v instanceof String && v.startsWith("secreton:")) {
|
|
106
|
+
value = decryptValue(v.substring(9), secretKey)
|
|
107
|
+
}
|
|
108
|
+
if (value == null) {
|
|
109
|
+
throw new RuntimeException("❌ Failed to resolve env ${k}")
|
|
102
110
|
}
|
|
103
111
|
appProject.ext.env[k] = value
|
|
104
112
|
}
|
|
@@ -3,21 +3,54 @@ package com.secreton
|
|
|
3
3
|
import com.facebook.react.bridge.ReactApplicationContext
|
|
4
4
|
import com.facebook.react.module.annotations.ReactModule
|
|
5
5
|
|
|
6
|
+
import android.util.Base64
|
|
7
|
+
import javax.crypto.Cipher
|
|
8
|
+
import javax.crypto.SecretKeyFactory
|
|
9
|
+
import javax.crypto.spec.IvParameterSpec
|
|
10
|
+
import javax.crypto.spec.PBEKeySpec
|
|
11
|
+
import javax.crypto.spec.SecretKeySpec
|
|
12
|
+
|
|
6
13
|
@ReactModule(name = SecretonModule.NAME)
|
|
7
14
|
class SecretonModule(reactContext: ReactApplicationContext) :
|
|
8
15
|
NativeSecretonSpec(reactContext) {
|
|
9
16
|
|
|
17
|
+
companion object {
|
|
18
|
+
const val NAME = "Secreton"
|
|
19
|
+
}
|
|
20
|
+
|
|
10
21
|
override fun getName(): String {
|
|
11
22
|
return NAME
|
|
12
23
|
}
|
|
13
24
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
25
|
+
override fun encrypt(value: String, key: String): String {
|
|
26
|
+
val salt = ByteArray(16)
|
|
27
|
+
val iv = ByteArray(16)
|
|
28
|
+
|
|
29
|
+
val factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256")
|
|
30
|
+
val spec = PBEKeySpec(key.toCharArray(), salt, 100000, 256)
|
|
31
|
+
val tmp = factory.generateSecret(spec)
|
|
32
|
+
val secretKey = SecretKeySpec(tmp.encoded, "AES")
|
|
33
|
+
|
|
34
|
+
val cipher = Cipher.getInstance("AES/CBC/PKCS7Padding")
|
|
35
|
+
cipher.init(Cipher.ENCRYPT_MODE, secretKey, IvParameterSpec(iv))
|
|
36
|
+
|
|
37
|
+
val encrypted = cipher.doFinal(value.toByteArray())
|
|
38
|
+
return Base64.encodeToString(encrypted, Base64.NO_WRAP)
|
|
18
39
|
}
|
|
19
40
|
|
|
20
|
-
|
|
21
|
-
|
|
41
|
+
override fun decrypt(encrypted: String, key: String): String {
|
|
42
|
+
val salt = ByteArray(16)
|
|
43
|
+
val iv = ByteArray(16)
|
|
44
|
+
|
|
45
|
+
val factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256")
|
|
46
|
+
val spec = PBEKeySpec(key.toCharArray(), salt, 100000, 256)
|
|
47
|
+
val tmp = factory.generateSecret(spec)
|
|
48
|
+
val secretKey = SecretKeySpec(tmp.encoded, "AES")
|
|
49
|
+
|
|
50
|
+
val cipher = Cipher.getInstance("AES/CBC/PKCS7Padding")
|
|
51
|
+
cipher.init(Cipher.DECRYPT_MODE, secretKey, IvParameterSpec(iv))
|
|
52
|
+
|
|
53
|
+
val decoded = Base64.decode(encrypted, Base64.NO_WRAP)
|
|
54
|
+
return String(cipher.doFinal(decoded))
|
|
22
55
|
}
|
|
23
56
|
}
|
package/dist/NodeSecreton.js
CHANGED
|
@@ -5,6 +5,10 @@ export function encrypt(value, key) {
|
|
|
5
5
|
const cmd = `printf "%s" "${value}" | openssl enc -aes-256-cbc -a -A -salt -pbkdf2 -iter 100000 -pass pass:${key}`;
|
|
6
6
|
return execSync(cmd).toString().trim();
|
|
7
7
|
}
|
|
8
|
+
export function decrypt(encrypted, key) {
|
|
9
|
+
const cmd = `printf "%s" "${encrypted}" | openssl enc -aes-256-cbc -a -A -d -salt -pbkdf2 -iter 100000 -pass pass:${key}`;
|
|
10
|
+
return execSync(cmd).toString().trim();
|
|
11
|
+
}
|
|
8
12
|
export function readExistingEnv(envFile) {
|
|
9
13
|
if (!fs.existsSync(envFile))
|
|
10
14
|
return new Set();
|
|
@@ -60,7 +64,7 @@ export async function generateEnv(options) {
|
|
|
60
64
|
}
|
|
61
65
|
const newLines = entries
|
|
62
66
|
.filter(({ key }) => !existingKeys.has(key))
|
|
63
|
-
.map(({ key, value }) => `${key}=
|
|
67
|
+
.map(({ key, value }) => `${key}=secreton:${encrypt(value, secretKey)}`);
|
|
64
68
|
if (newLines.length === 0) {
|
|
65
69
|
console.log('ℹ️ [Node] Secreton no new env keys to add');
|
|
66
70
|
return;
|
package/ios/Secreton.mm
CHANGED
|
@@ -1,21 +1,76 @@
|
|
|
1
1
|
#import "Secreton.h"
|
|
2
2
|
|
|
3
|
+
#import <CommonCrypto/CommonCrypto.h>
|
|
4
|
+
|
|
3
5
|
@implementation Secreton
|
|
4
|
-
- (NSNumber *)multiply:(double)a b:(double)b {
|
|
5
|
-
NSNumber *result = @(a * b);
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
+ (NSString *)moduleName
|
|
8
|
+
{
|
|
9
|
+
return @"Secreton";
|
|
8
10
|
}
|
|
9
11
|
|
|
10
|
-
-
|
|
11
|
-
|
|
12
|
+
#pragma mark - TurboModule methods
|
|
13
|
+
|
|
14
|
+
- (NSString *)encrypt:(NSString *)value key:(NSString *)key
|
|
12
15
|
{
|
|
13
|
-
return
|
|
16
|
+
return [self aes:kCCEncrypt value:value key:key];
|
|
14
17
|
}
|
|
15
18
|
|
|
16
|
-
|
|
19
|
+
- (NSString *)decrypt:(NSString *)value key:(NSString *)key
|
|
17
20
|
{
|
|
18
|
-
|
|
21
|
+
return [self aes:kCCDecrypt value:value key:key];
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
#pragma mark - AES core
|
|
25
|
+
|
|
26
|
+
- (NSString *)aes:(CCOperation)operation
|
|
27
|
+
value:(NSString *)value
|
|
28
|
+
key:(NSString *)key
|
|
29
|
+
{
|
|
30
|
+
NSData *data = [value dataUsingEncoding:NSUTF8StringEncoding];
|
|
31
|
+
|
|
32
|
+
// FIX: key 32 byte (AES-256)
|
|
33
|
+
NSMutableData *keyData = [NSMutableData dataWithLength:kCCKeySizeAES256];
|
|
34
|
+
NSData *rawKey = [key dataUsingEncoding:NSUTF8StringEncoding];
|
|
35
|
+
NSUInteger copyLen = MIN(rawKey.length, kCCKeySizeAES256);
|
|
36
|
+
memcpy(keyData.mutableBytes, rawKey.bytes, copyLen);
|
|
37
|
+
|
|
38
|
+
size_t outLength = 0;
|
|
39
|
+
NSMutableData *outData = [NSMutableData dataWithLength:data.length + kCCBlockSizeAES128];
|
|
40
|
+
|
|
41
|
+
CCCryptorStatus status = CCCrypt(
|
|
42
|
+
operation,
|
|
43
|
+
kCCAlgorithmAES,
|
|
44
|
+
kCCOptionPKCS7Padding,
|
|
45
|
+
keyData.bytes,
|
|
46
|
+
kCCKeySizeAES256,
|
|
47
|
+
NULL, // IV = zero (compat Swift)
|
|
48
|
+
data.bytes,
|
|
49
|
+
data.length,
|
|
50
|
+
outData.mutableBytes,
|
|
51
|
+
outData.length,
|
|
52
|
+
&outLength
|
|
53
|
+
);
|
|
54
|
+
|
|
55
|
+
if (status != kCCSuccess) {
|
|
56
|
+
return nil;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
outData.length = outLength;
|
|
60
|
+
|
|
61
|
+
if (operation == kCCEncrypt) {
|
|
62
|
+
return [outData base64EncodedStringWithOptions:0];
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return [[NSString alloc] initWithData:outData encoding:NSUTF8StringEncoding];
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
#pragma mark - TurboModule binding
|
|
69
|
+
|
|
70
|
+
- (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:
|
|
71
|
+
(const facebook::react::ObjCTurboModule::InitParams &)params
|
|
72
|
+
{
|
|
73
|
+
return std::make_shared<facebook::react::NativeSecretonSpecJSI>(params);
|
|
19
74
|
}
|
|
20
75
|
|
|
21
76
|
@end
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["TurboModuleRegistry","getEnforcing"],"sourceRoot":"../../src","sources":["NativeSecreton.ts"],"mappings":";;AAAA,SAASA,mBAAmB,QAA0B,cAAc;
|
|
1
|
+
{"version":3,"names":["TurboModuleRegistry","getEnforcing"],"sourceRoot":"../../src","sources":["NativeSecreton.ts"],"mappings":";;AAAA,SAASA,mBAAmB,QAA0B,cAAc;AAOpE,eAAeA,mBAAmB,CAACC,YAAY,CAAO,UAAU,CAAC","ignoreList":[]}
|
|
@@ -7,6 +7,10 @@ export function encrypt(value, key) {
|
|
|
7
7
|
const cmd = `printf "%s" "${value}" | openssl enc -aes-256-cbc -a -A -salt -pbkdf2 -iter 100000 -pass pass:${key}`;
|
|
8
8
|
return execSync(cmd).toString().trim();
|
|
9
9
|
}
|
|
10
|
+
export function decrypt(encrypted, key) {
|
|
11
|
+
const cmd = `printf "%s" "${encrypted}" | openssl enc -aes-256-cbc -a -A -d -salt -pbkdf2 -iter 100000 -pass pass:${key}`;
|
|
12
|
+
return execSync(cmd).toString().trim();
|
|
13
|
+
}
|
|
10
14
|
export function readExistingEnv(envFile) {
|
|
11
15
|
if (!fs.existsSync(envFile)) return new Set();
|
|
12
16
|
const content = fs.readFileSync(envFile, 'utf8');
|
|
@@ -67,7 +71,7 @@ export async function generateEnv(options) {
|
|
|
67
71
|
}) => !existingKeys.has(key)).map(({
|
|
68
72
|
key,
|
|
69
73
|
value
|
|
70
|
-
}) => `${key}=
|
|
74
|
+
}) => `${key}=secreton:${encrypt(value, secretKey)}`);
|
|
71
75
|
if (newLines.length === 0) {
|
|
72
76
|
console.log('ℹ️ [Node] Secreton no new env keys to add');
|
|
73
77
|
return;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["path","fs","execSync","encrypt","value","key","cmd","toString","trim","readExistingEnv","envFile","existsSync","Set","content","readFileSync","split","map","line","filter","Boolean","startsWith","length","fetchConsul","addr","token","headers","res","fetch","ok","Error","data","json","item","Value","Key","replace","Buffer","from","fetchVault","Object","entries","String","generateEnv","options","secretKey","fetchEnv","fileName","basename","existingKeys","vault","consul","newLines","has","console","log","appendFileSync","join"],"sourceRoot":"../../src","sources":["NodeSecreton.ts"],"mappings":";;AAAA,OAAOA,IAAI,MAAM,WAAW;AAC5B,OAAOC,EAAE,MAAM,SAAS;AACxB,SAASC,QAAQ,QAAQ,oBAAoB;AAgC7C,OAAO,SAASC,OAAOA,CAACC,KAAa,EAAEC,GAAW,EAAE;EAClD,MAAMC,GAAG,GAAG,gBAAgBF,KAAK,4EAA4EC,GAAG,EAAE;EAClH,OAAOH,QAAQ,CAACI,GAAG,CAAC,CAACC,QAAQ,CAAC,CAAC,CAACC,IAAI,CAAC,CAAC;AACxC;AAEA,OAAO,SAASC,eAAeA,CAACC,OAAe,EAAe;EAC5D,IAAI,
|
|
1
|
+
{"version":3,"names":["path","fs","execSync","encrypt","value","key","cmd","toString","trim","decrypt","encrypted","readExistingEnv","envFile","existsSync","Set","content","readFileSync","split","map","line","filter","Boolean","startsWith","length","fetchConsul","addr","token","headers","res","fetch","ok","Error","data","json","item","Value","Key","replace","Buffer","from","fetchVault","Object","entries","String","generateEnv","options","secretKey","fetchEnv","fileName","basename","existingKeys","vault","consul","newLines","has","console","log","appendFileSync","join"],"sourceRoot":"../../src","sources":["NodeSecreton.ts"],"mappings":"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","ignoreList":[]}
|
package/lib/module/index.js
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
3
|
import Secreton from "./NativeSecreton.js";
|
|
4
|
-
export function
|
|
5
|
-
return Secreton.
|
|
4
|
+
export function encrypt(value, key) {
|
|
5
|
+
return Secreton.encrypt(value, key);
|
|
6
|
+
}
|
|
7
|
+
export function decrypt(encrypted, key) {
|
|
8
|
+
return Secreton.decrypt(encrypted, key);
|
|
6
9
|
}
|
|
7
10
|
//# sourceMappingURL=index.js.map
|
package/lib/module/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["Secreton","
|
|
1
|
+
{"version":3,"names":["Secreton","encrypt","value","key","decrypt","encrypted"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":";;AAAA,OAAOA,QAAQ,MAAM,qBAAkB;AAEvC,OAAO,SAASC,OAAOA,CAACC,KAAa,EAAEC,GAAW,EAAU;EAC1D,OAAOH,QAAQ,CAACC,OAAO,CAACC,KAAK,EAAEC,GAAG,CAAC;AACrC;AAEA,OAAO,SAASC,OAAOA,CAACC,SAAiB,EAAEF,GAAW,EAAU;EAC9D,OAAOH,QAAQ,CAACI,OAAO,CAACC,SAAS,EAAEF,GAAG,CAAC;AACzC","ignoreList":[]}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { type TurboModule } from 'react-native';
|
|
2
2
|
export interface Spec extends TurboModule {
|
|
3
|
-
|
|
3
|
+
encrypt(value: string, key: string): string;
|
|
4
|
+
decrypt(encrypted: string, key: string): string;
|
|
4
5
|
}
|
|
5
6
|
declare const _default: Spec;
|
|
6
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,
|
|
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,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAAC;IAC5C,OAAO,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAAC;CACjD;;AAED,wBAAkE"}
|
|
@@ -24,6 +24,7 @@ export interface GenerateEnvOptions {
|
|
|
24
24
|
fetchEnv?: 'consul' | 'vault';
|
|
25
25
|
}
|
|
26
26
|
export declare function encrypt(value: string, key: string): string;
|
|
27
|
+
export declare function decrypt(encrypted: string, key: string): string;
|
|
27
28
|
export declare function readExistingEnv(envFile: string): Set<string>;
|
|
28
29
|
export declare function generateEnv(options: GenerateEnvOptions): Promise<void>;
|
|
29
30
|
//# sourceMappingURL=NodeSecreton.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NodeSecreton.d.ts","sourceRoot":"","sources":["../../../src/NodeSecreton.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,QAAQ;IACvB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,MAAM,QAAQ,GAAG;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB,CAAC;AAEF,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,QAAQ,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC;CAC/B;AAED,wBAAgB,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,UAGjD;AAED,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,CAc5D;AAwCD,wBAAsB,WAAW,CAAC,OAAO,EAAE,kBAAkB,iBAgC5D"}
|
|
1
|
+
{"version":3,"file":"NodeSecreton.d.ts","sourceRoot":"","sources":["../../../src/NodeSecreton.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,QAAQ;IACvB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,MAAM,QAAQ,GAAG;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB,CAAC;AAEF,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,QAAQ,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC;CAC/B;AAED,wBAAgB,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,UAGjD;AAED,wBAAgB,OAAO,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,UAGrD;AAED,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,CAc5D;AAwCD,wBAAsB,WAAW,CAAC,OAAO,EAAE,kBAAkB,iBAgC5D"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.tsx"],"names":[],"mappings":"AAEA,wBAAgB,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.tsx"],"names":[],"mappings":"AAEA,wBAAgB,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAE1D;AAED,wBAAgB,OAAO,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAE9D"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native-secreton",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.3.0",
|
|
4
4
|
"description": "Config secret variables for React Native apps",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"react-native",
|
|
@@ -48,7 +48,8 @@
|
|
|
48
48
|
"nitrogen": "nitrogen",
|
|
49
49
|
"typecheck": "tsc",
|
|
50
50
|
"lint": "eslint \"src/**/*.{js,ts,tsx}\"",
|
|
51
|
-
"test": "jest",
|
|
51
|
+
"test": "jest -c jest.config.cjs",
|
|
52
|
+
"test:coverage": "jest -c jest.config.cjs --coverage --coverageDirectory=.coverage",
|
|
52
53
|
"release": "release-it --only-version"
|
|
53
54
|
},
|
|
54
55
|
"bin": {
|
|
@@ -76,6 +77,7 @@
|
|
|
76
77
|
"@react-native/eslint-config": "0.83.0",
|
|
77
78
|
"@release-it/conventional-changelog": "^10.0.1",
|
|
78
79
|
"@types/jest": "^29.5.14",
|
|
80
|
+
"@types/node": "^25.0.5",
|
|
79
81
|
"@types/react": "^19.2.0",
|
|
80
82
|
"commitlint": "^19.8.1",
|
|
81
83
|
"del-cli": "^6.0.0",
|
|
@@ -90,6 +92,7 @@
|
|
|
90
92
|
"react-native": "0.83.0",
|
|
91
93
|
"react-native-builder-bob": "^0.40.17",
|
|
92
94
|
"release-it": "^19.0.4",
|
|
95
|
+
"ts-jest": "^29.4.6",
|
|
93
96
|
"turbo": "^2.5.6",
|
|
94
97
|
"typescript": "^5.9.2"
|
|
95
98
|
},
|
package/src/NativeSecreton.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { TurboModuleRegistry, type TurboModule } from 'react-native';
|
|
2
2
|
|
|
3
3
|
export interface Spec extends TurboModule {
|
|
4
|
-
|
|
4
|
+
encrypt(value: string, key: string): string;
|
|
5
|
+
decrypt(encrypted: string, key: string): string;
|
|
5
6
|
}
|
|
6
7
|
|
|
7
8
|
export default TurboModuleRegistry.getEnforcing<Spec>('Secreton');
|
package/src/NodeSecreton.ts
CHANGED
|
@@ -37,6 +37,11 @@ export function encrypt(value: string, key: string) {
|
|
|
37
37
|
return execSync(cmd).toString().trim();
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
+
export function decrypt(encrypted: string, key: string) {
|
|
41
|
+
const cmd = `printf "%s" "${encrypted}" | openssl enc -aes-256-cbc -a -A -d -salt -pbkdf2 -iter 100000 -pass pass:${key}`;
|
|
42
|
+
return execSync(cmd).toString().trim();
|
|
43
|
+
}
|
|
44
|
+
|
|
40
45
|
export function readExistingEnv(envFile: string): Set<string> {
|
|
41
46
|
if (!fs.existsSync(envFile)) return new Set();
|
|
42
47
|
|
|
@@ -113,7 +118,7 @@ export async function generateEnv(options: GenerateEnvOptions) {
|
|
|
113
118
|
|
|
114
119
|
const newLines = entries
|
|
115
120
|
.filter(({ key }) => !existingKeys.has(key))
|
|
116
|
-
.map(({ key, value }) => `${key}=
|
|
121
|
+
.map(({ key, value }) => `${key}=secreton:${encrypt(value, secretKey)}`);
|
|
117
122
|
|
|
118
123
|
if (newLines.length === 0) {
|
|
119
124
|
console.log('ℹ️ [Node] Secreton no new env keys to add');
|
package/src/index.tsx
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import Secreton from './NativeSecreton';
|
|
2
2
|
|
|
3
|
-
export function
|
|
4
|
-
return Secreton.
|
|
3
|
+
export function encrypt(value: string, key: string): string {
|
|
4
|
+
return Secreton.encrypt(value, key);
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export function decrypt(encrypted: string, key: string): string {
|
|
8
|
+
return Secreton.decrypt(encrypted, key);
|
|
5
9
|
}
|