react-native-des-machine 0.1.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.
@@ -0,0 +1,20 @@
1
+ require "json"
2
+
3
+ package = JSON.parse(File.read(File.join(__dir__, "package.json")))
4
+
5
+ Pod::Spec.new do |s|
6
+ s.name = "DesMachine"
7
+ s.version = package["version"]
8
+ s.summary = package["description"]
9
+ s.homepage = package["homepage"]
10
+ s.license = package["license"]
11
+ s.authors = package["author"]
12
+
13
+ s.platforms = { :ios => min_ios_version_supported }
14
+ s.source = { :git => "https://github.com/NeRo8/react-native-des-machine.git", :tag => "#{s.version}" }
15
+
16
+ s.source_files = "ios/**/*.{h,m,mm,swift,cpp}"
17
+ s.private_header_files = "ios/**/*.h"
18
+
19
+ install_modules_dependencies(s)
20
+ end
package/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Artur Duchenko
4
+ Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ of this software and associated documentation files (the "Software"), to deal
6
+ in the Software without restriction, including without limitation the rights
7
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ copies of the Software, and to permit persons to whom the Software is
9
+ furnished to do so, subject to the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be included in all
12
+ copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,190 @@
1
+ # react-native-des-machine
2
+
3
+ A React Native TurboModule that provides DES (Data Encryption Standard) encryption and decryption with support for multiple cipher modes, padding schemes, and output formats.
4
+
5
+ ## Features
6
+
7
+ - DES encryption and decryption
8
+ - Multiple cipher modes: ECB, CBC, CFB, OFB, CTR
9
+ - Multiple padding schemes: PKCS7, ISO10126, Zero, None
10
+ - Output formats: Base64, Hexadecimal
11
+ - Native implementation for both iOS and Android
12
+ - TurboModule support for improved performance
13
+
14
+ ## Installation
15
+
16
+ Using npm:
17
+
18
+ ```sh
19
+ npm install react-native-des-machine
20
+ ```
21
+
22
+ Using yarn:
23
+
24
+ ```sh
25
+ yarn add react-native-des-machine
26
+ ```
27
+
28
+ ### iOS Setup
29
+
30
+ After installing, run pod install:
31
+
32
+ ```sh
33
+ cd ios && pod install
34
+ ```
35
+
36
+ ### Android Setup
37
+
38
+ No additional setup required. The library auto-links on Android.
39
+
40
+ ## Usage
41
+
42
+ ### Basic Example
43
+
44
+ ```typescript
45
+ import {
46
+ setMachineParams,
47
+ encrypt,
48
+ decrypt,
49
+ Mode,
50
+ Padding,
51
+ Format,
52
+ } from 'react-native-des-machine';
53
+
54
+ // Initialize the DES machine with your encryption key
55
+ setMachineParams({
56
+ key: 'mySecretKey123', // minimum 8 characters
57
+ });
58
+
59
+ // Encrypt text
60
+ const encrypted = encrypt('Hello World!');
61
+ console.log('Encrypted:', encrypted);
62
+ // Output: "Encrypted: 2jmj7l5rSw0yVb/vlWAYkK/YBwk="
63
+
64
+ // Decrypt text
65
+ const decrypted = decrypt(encrypted);
66
+ console.log('Decrypted:', decrypted);
67
+ // Output: "Decrypted: Hello World!"
68
+ ```
69
+
70
+ ### Advanced Configuration
71
+
72
+ ```typescript
73
+ import {
74
+ setMachineParams,
75
+ encrypt,
76
+ decrypt,
77
+ Mode,
78
+ Padding,
79
+ Format,
80
+ } from 'react-native-des-machine';
81
+
82
+ // Configure with custom mode, padding, and output format
83
+ setMachineParams({
84
+ key: 'mySecretKey123',
85
+ mode: Mode.CBC, // Cipher Block Chaining mode
86
+ padding: Padding.PKCS7, // PKCS7 padding
87
+ outputFormat: Format.HEX, // Hexadecimal output
88
+ });
89
+
90
+ const encrypted = encrypt('Sensitive data');
91
+ console.log('Encrypted (hex):', encrypted);
92
+ // Output: "Encrypted (hex): 4a6f686e446f65..."
93
+
94
+ const decrypted = decrypt(encrypted);
95
+ console.log('Decrypted:', decrypted);
96
+ ```
97
+
98
+ ## API Reference
99
+
100
+ ### `setMachineParams(params: DesMachineParams): void`
101
+
102
+ Initialize the DES machine with encryption parameters.
103
+
104
+ #### Parameters
105
+
106
+ | Parameter | Type | Required | Default | Description |
107
+ | -------------- | ----------------------- | -------- | ---------- | ------------------------------------- |
108
+ | `key` | `string` | Yes | - | Encryption key (minimum 8 characters) |
109
+ | `mode` | `ModeEncryptionType` | No | `'ECB'` | Cipher mode |
110
+ | `padding` | `PaddingEncryptionType` | No | `'PKCS7'` | Padding scheme |
111
+ | `outputFormat` | `OutputFormatType` | No | `'BASE64'` | Output encoding format |
112
+
113
+ ### `encrypt(text: string): string`
114
+
115
+ Encrypt plaintext using the configured DES parameters.
116
+
117
+ - **Parameters:** `text` - The plaintext string to encrypt
118
+ - **Returns:** Encrypted string in the configured output format
119
+ - **Throws:** Error if `setMachineParams()` has not been called
120
+
121
+ ### `decrypt(text: string): string`
122
+
123
+ Decrypt ciphertext using the configured DES parameters.
124
+
125
+ - **Parameters:** `text` - The encrypted string to decrypt
126
+ - **Returns:** Decrypted plaintext string
127
+ - **Throws:** Error if `setMachineParams()` has not been called
128
+
129
+ ## Constants
130
+
131
+ ### Mode
132
+
133
+ | Constant | Value | Description |
134
+ | ---------- | ------- | ----------------------------- |
135
+ | `Mode.ECB` | `'ECB'` | Electronic Codebook (default) |
136
+ | `Mode.CBC` | `'CBC'` | Cipher Block Chaining |
137
+ | `Mode.CFB` | `'CFB'` | Cipher Feedback |
138
+ | `Mode.OFB` | `'OFB'` | Output Feedback |
139
+ | `Mode.CTR` | `'CTR'` | Counter |
140
+
141
+ ### Padding
142
+
143
+ | Constant | Value | Description |
144
+ | ------------------ | ------------ | ------------------------ |
145
+ | `Padding.PKCS7` | `'PKCS7'` | PKCS#7 padding (default) |
146
+ | `Padding.ISO10126` | `'ISO10126'` | ISO 10126 padding |
147
+ | `Padding.ZERO` | `'ZERO'` | Zero padding |
148
+ | `Padding.NONE` | `'NONE'` | No padding |
149
+
150
+ ### Format
151
+
152
+ | Constant | Value | Description |
153
+ | --------------- | ---------- | ------------------------- |
154
+ | `Format.BASE64` | `'BASE64'` | Base64 encoding (default) |
155
+ | `Format.HEX` | `'HEX'` | Hexadecimal encoding |
156
+
157
+ ## TypeScript Support
158
+
159
+ The library includes full TypeScript definitions:
160
+
161
+ ```typescript
162
+ import type {
163
+ DesMachineParams,
164
+ ModeEncryptionType,
165
+ PaddingEncryptionType,
166
+ OutputFormatType,
167
+ } from 'react-native-des-machine';
168
+ ```
169
+
170
+ ## Security Notice
171
+
172
+ DES is considered cryptographically weak by modern standards due to its 56-bit key size. For production applications requiring strong encryption, consider using AES or other modern algorithms. This library is suitable for:
173
+
174
+ - Legacy system compatibility
175
+ - Educational purposes
176
+ - Low-security applications
177
+
178
+ ## Contributing
179
+
180
+ - [Development workflow](CONTRIBUTING.md#development-workflow)
181
+ - [Sending a pull request](CONTRIBUTING.md#sending-a-pull-request)
182
+ - [Code of conduct](CODE_OF_CONDUCT.md)
183
+
184
+ ## License
185
+
186
+ MIT
187
+
188
+ ---
189
+
190
+ Made with [create-react-native-library](https://github.com/callstack/react-native-builder-bob)
@@ -0,0 +1,67 @@
1
+ buildscript {
2
+ ext.DesMachine = [
3
+ kotlinVersion: "2.0.21",
4
+ minSdkVersion: 24,
5
+ compileSdkVersion: 36,
6
+ targetSdkVersion: 36
7
+ ]
8
+
9
+ ext.getExtOrDefault = { prop ->
10
+ if (rootProject.ext.has(prop)) {
11
+ return rootProject.ext.get(prop)
12
+ }
13
+
14
+ return DesMachine[prop]
15
+ }
16
+
17
+ repositories {
18
+ google()
19
+ mavenCentral()
20
+ }
21
+
22
+ dependencies {
23
+ classpath "com.android.tools.build:gradle:8.7.2"
24
+ // noinspection DifferentKotlinGradleVersion
25
+ classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${getExtOrDefault('kotlinVersion')}"
26
+ }
27
+ }
28
+
29
+
30
+ apply plugin: "com.android.library"
31
+ apply plugin: "kotlin-android"
32
+
33
+ apply plugin: "com.facebook.react"
34
+
35
+ android {
36
+ namespace "com.desmachine"
37
+
38
+ compileSdkVersion getExtOrDefault("compileSdkVersion")
39
+
40
+ defaultConfig {
41
+ minSdkVersion getExtOrDefault("minSdkVersion")
42
+ targetSdkVersion getExtOrDefault("targetSdkVersion")
43
+ }
44
+
45
+ buildFeatures {
46
+ buildConfig true
47
+ }
48
+
49
+ buildTypes {
50
+ release {
51
+ minifyEnabled false
52
+ }
53
+ }
54
+
55
+ lint {
56
+ disable "GradleCompatible"
57
+ }
58
+
59
+ compileOptions {
60
+ sourceCompatibility JavaVersion.VERSION_1_8
61
+ targetCompatibility JavaVersion.VERSION_1_8
62
+ }
63
+ }
64
+
65
+ dependencies {
66
+ implementation "com.facebook.react:react-android"
67
+ }
@@ -0,0 +1,2 @@
1
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android">
2
+ </manifest>
@@ -0,0 +1,193 @@
1
+ package com.desmachine
2
+
3
+ import android.util.Base64
4
+ import com.facebook.react.bridge.ReactApplicationContext
5
+ import com.facebook.react.bridge.ReadableMap
6
+ import javax.crypto.Cipher
7
+ import javax.crypto.SecretKey
8
+ import javax.crypto.SecretKeyFactory
9
+ import javax.crypto.spec.DESKeySpec
10
+ import javax.crypto.spec.IvParameterSpec
11
+
12
+ class DesMachineModule(reactContext: ReactApplicationContext) :
13
+ NativeDesMachineSpec(reactContext) {
14
+
15
+ private var secretKey: SecretKey? = null
16
+ private var mode: String = MODE_ECB
17
+ private var padding: String = PADDING_PKCS7
18
+ private var outputFormat: String = FORMAT_BASE64
19
+ private var ivSpec: IvParameterSpec? = null
20
+
21
+ /**
22
+ * Set the DES machine parameters including key, mode, padding, and output format.
23
+ * @param params ReadableMap containing:
24
+ * - key: String (required, minimum 8 characters)
25
+ * - mode: String (optional, default: ECB) - ECB, CBC, CFB, OFB, CTR
26
+ * - padding: String (optional, default: PKCS7) - PKCS7, ISO10126, ZERO, NONE
27
+ * - outputFormat: String (optional, default: BASE64) - BASE64, HEX
28
+ */
29
+ override fun setMachineParams(params: ReadableMap) {
30
+ // Extract and validate key
31
+ val key = params.getString("key")
32
+ ?: throw IllegalArgumentException("Key is required")
33
+ require(key.length >= 8) { "DES key must be at least 8 characters long" }
34
+
35
+ // Extract optional parameters with defaults
36
+ mode = params.getString("mode") ?: MODE_ECB
37
+ padding = params.getString("padding") ?: PADDING_PKCS7
38
+ outputFormat = params.getString("outputFormat") ?: FORMAT_BASE64
39
+
40
+ // Initialize secret key
41
+ val keyBytes = key.toByteArray(Charsets.UTF_8)
42
+ val desKeySpec = DESKeySpec(keyBytes)
43
+ val keyFactory = SecretKeyFactory.getInstance(DES_ALGORITHM)
44
+ secretKey = keyFactory.generateSecret(desKeySpec)
45
+
46
+ // Initialize IV for modes that require it (CBC, CFB, OFB, CTR)
47
+ if (mode != MODE_ECB) {
48
+ // Use first 8 bytes of key as IV (DES block size is 8 bytes)
49
+ val ivBytes = keyBytes.copyOf(8)
50
+ ivSpec = IvParameterSpec(ivBytes)
51
+ }
52
+ }
53
+
54
+ /**
55
+ * Encrypt the provided plaintext using DES algorithm.
56
+ * @param text The plaintext to encrypt
57
+ * @return Encrypted string in the configured output format (BASE64 or HEX)
58
+ */
59
+ override fun encrypt(text: String): String {
60
+ val key = secretKey
61
+ ?: throw IllegalStateException("DES not initialized. Call setMachineParams() first.")
62
+
63
+ val transformation = buildTransformation()
64
+ val cipher = Cipher.getInstance(transformation)
65
+
66
+ if (mode == MODE_ECB) {
67
+ cipher.init(Cipher.ENCRYPT_MODE, key)
68
+ } else {
69
+ cipher.init(Cipher.ENCRYPT_MODE, key, ivSpec)
70
+ }
71
+
72
+ val inputBytes = applyPaddingIfNeeded(text.toByteArray(Charsets.UTF_8))
73
+ val encryptedBytes = cipher.doFinal(inputBytes)
74
+
75
+ return formatOutput(encryptedBytes)
76
+ }
77
+
78
+ /**
79
+ * Decrypt the provided ciphertext using DES algorithm.
80
+ * @param text Encrypted string in the configured format (BASE64 or HEX)
81
+ * @return Decrypted plaintext
82
+ */
83
+ override fun decrypt(text: String): String {
84
+ val key = secretKey
85
+ ?: throw IllegalStateException("DES not initialized. Call setMachineParams() first.")
86
+
87
+ val transformation = buildTransformation()
88
+ val cipher = Cipher.getInstance(transformation)
89
+
90
+ if (mode == MODE_ECB) {
91
+ cipher.init(Cipher.DECRYPT_MODE, key)
92
+ } else {
93
+ cipher.init(Cipher.DECRYPT_MODE, key, ivSpec)
94
+ }
95
+
96
+ val encryptedBytes = parseInput(text)
97
+ val decryptedBytes = cipher.doFinal(encryptedBytes)
98
+
99
+ return String(removePaddingIfNeeded(decryptedBytes), Charsets.UTF_8)
100
+ }
101
+
102
+ /**
103
+ * Build the cipher transformation string based on mode and padding.
104
+ */
105
+ private fun buildTransformation(): String {
106
+ val javaPadding = when (padding) {
107
+ PADDING_PKCS7 -> "PKCS5Padding" // PKCS5 is equivalent to PKCS7 for DES
108
+ PADDING_ISO10126 -> "ISO10126Padding"
109
+ PADDING_ZERO, PADDING_NONE -> "NoPadding"
110
+ else -> "PKCS5Padding"
111
+ }
112
+ return "$DES_ALGORITHM/$mode/$javaPadding"
113
+ }
114
+
115
+ /**
116
+ * Apply manual padding for ZERO padding mode.
117
+ */
118
+ private fun applyPaddingIfNeeded(data: ByteArray): ByteArray {
119
+ if (padding != PADDING_ZERO && padding != PADDING_NONE) {
120
+ return data
121
+ }
122
+
123
+ val blockSize = 8 // DES block size
124
+ val paddingLength = blockSize - (data.size % blockSize)
125
+ if (paddingLength == blockSize && padding == PADDING_NONE) {
126
+ return data
127
+ }
128
+
129
+ val paddedData = ByteArray(data.size + paddingLength)
130
+ System.arraycopy(data, 0, paddedData, 0, data.size)
131
+ // Zero padding: remaining bytes are already 0
132
+ return paddedData
133
+ }
134
+
135
+ /**
136
+ * Remove manual padding for ZERO padding mode.
137
+ */
138
+ private fun removePaddingIfNeeded(data: ByteArray): ByteArray {
139
+ if (padding != PADDING_ZERO) {
140
+ return data
141
+ }
142
+
143
+ // Find last non-zero byte
144
+ var lastIndex = data.size - 1
145
+ while (lastIndex >= 0 && data[lastIndex] == 0.toByte()) {
146
+ lastIndex--
147
+ }
148
+ return data.copyOf(lastIndex + 1)
149
+ }
150
+
151
+ /**
152
+ * Format encrypted bytes to the configured output format.
153
+ */
154
+ private fun formatOutput(bytes: ByteArray): String {
155
+ return when (outputFormat) {
156
+ FORMAT_HEX -> bytes.joinToString("") { "%02x".format(it) }
157
+ else -> Base64.encodeToString(bytes, Base64.NO_WRAP)
158
+ }
159
+ }
160
+
161
+ /**
162
+ * Parse input string from the configured format to bytes.
163
+ */
164
+ private fun parseInput(text: String): ByteArray {
165
+ return when (outputFormat) {
166
+ FORMAT_HEX -> text.chunked(2).map { it.toInt(16).toByte() }.toByteArray()
167
+ else -> Base64.decode(text, Base64.NO_WRAP)
168
+ }
169
+ }
170
+
171
+ companion object {
172
+ const val NAME = NativeDesMachineSpec.NAME
173
+
174
+ private const val DES_ALGORITHM = "DES"
175
+
176
+ // Mode constants
177
+ private const val MODE_ECB = "ECB"
178
+ private const val MODE_CBC = "CBC"
179
+ private const val MODE_CFB = "CFB"
180
+ private const val MODE_OFB = "OFB"
181
+ private const val MODE_CTR = "CTR"
182
+
183
+ // Padding constants
184
+ private const val PADDING_PKCS7 = "PKCS7"
185
+ private const val PADDING_ISO10126 = "ISO10126"
186
+ private const val PADDING_ZERO = "ZERO"
187
+ private const val PADDING_NONE = "NONE"
188
+
189
+ // Output format constants
190
+ private const val FORMAT_BASE64 = "BASE64"
191
+ private const val FORMAT_HEX = "HEX"
192
+ }
193
+ }
@@ -0,0 +1,33 @@
1
+ package com.desmachine
2
+
3
+ import com.facebook.react.BaseReactPackage
4
+ import com.facebook.react.bridge.NativeModule
5
+ import com.facebook.react.bridge.ReactApplicationContext
6
+ import com.facebook.react.module.model.ReactModuleInfo
7
+ import com.facebook.react.module.model.ReactModuleInfoProvider
8
+ import java.util.HashMap
9
+
10
+ class DesMachinePackage : BaseReactPackage() {
11
+ override fun getModule(name: String, reactContext: ReactApplicationContext): NativeModule? {
12
+ return if (name == DesMachineModule.NAME) {
13
+ DesMachineModule(reactContext)
14
+ } else {
15
+ null
16
+ }
17
+ }
18
+
19
+ override fun getReactModuleInfoProvider(): ReactModuleInfoProvider {
20
+ return ReactModuleInfoProvider {
21
+ val moduleInfos: MutableMap<String, ReactModuleInfo> = HashMap()
22
+ moduleInfos[DesMachineModule.NAME] = ReactModuleInfo(
23
+ DesMachineModule.NAME,
24
+ DesMachineModule.NAME,
25
+ false, // canOverrideExistingModule
26
+ false, // needsEagerInit
27
+ false, // isCxxModule
28
+ true // isTurboModule
29
+ )
30
+ moduleInfos
31
+ }
32
+ }
33
+ }
@@ -0,0 +1,12 @@
1
+ #import <DesMachineSpec/DesMachineSpec.h>
2
+ #import <CommonCrypto/CommonCryptor.h>
3
+
4
+ @interface DesMachine : NSObject <NativeDesMachineSpec>
5
+
6
+ @property (nonatomic, strong) NSData *secretKey;
7
+ @property (nonatomic, strong) NSData *ivData;
8
+ @property (nonatomic, copy) NSString *mode;
9
+ @property (nonatomic, copy) NSString *padding;
10
+ @property (nonatomic, copy) NSString *outputFormat;
11
+
12
+ @end
@@ -0,0 +1,281 @@
1
+ #import "DesMachine.h"
2
+ #import <CommonCrypto/CommonCryptor.h>
3
+
4
+ // Mode constants
5
+ static NSString *const MODE_ECB = @"ECB";
6
+ static NSString *const MODE_CBC = @"CBC";
7
+ static NSString *const MODE_CFB = @"CFB";
8
+ static NSString *const MODE_OFB = @"OFB";
9
+ static NSString *const MODE_CTR = @"CTR";
10
+
11
+ // Padding constants
12
+ static NSString *const PADDING_PKCS7 = @"PKCS7";
13
+ static NSString *const PADDING_ISO10126 = @"ISO10126";
14
+ static NSString *const PADDING_ZERO = @"ZERO";
15
+ static NSString *const PADDING_NONE = @"NONE";
16
+
17
+ // Output format constants
18
+ static NSString *const FORMAT_BASE64 = @"BASE64";
19
+ static NSString *const FORMAT_HEX = @"HEX";
20
+
21
+ @implementation DesMachine
22
+
23
+ #pragma mark - Initialization
24
+
25
+ - (instancetype)init {
26
+ self = [super init];
27
+ if (self) {
28
+ _mode = MODE_ECB;
29
+ _padding = PADDING_PKCS7;
30
+ _outputFormat = FORMAT_BASE64;
31
+ }
32
+ return self;
33
+ }
34
+
35
+ #pragma mark - TurboModule
36
+
37
+ - (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:
38
+ (const facebook::react::ObjCTurboModule::InitParams &)params
39
+ {
40
+ return std::make_shared<facebook::react::NativeDesMachineSpecJSI>(params);
41
+ }
42
+
43
+ + (NSString *)moduleName
44
+ {
45
+ return @"DesMachine";
46
+ }
47
+
48
+ #pragma mark - NativeDesMachineSpec Methods
49
+
50
+ /**
51
+ * Set the DES machine parameters including key, mode, padding, and output format.
52
+ * @param params NSDictionary containing:
53
+ * - key: NSString (required, minimum 8 characters)
54
+ * - mode: NSString (optional, default: ECB) - ECB, CBC, CFB, OFB, CTR
55
+ * - padding: NSString (optional, default: PKCS7) - PKCS7, ISO10126, ZERO, NONE
56
+ * - outputFormat: NSString (optional, default: BASE64) - BASE64, HEX
57
+ */
58
+ - (void)setMachineParams:(JS::NativeDesMachine::DesMachineParams &)params {
59
+ NSString *key = params.key();
60
+
61
+ if (!key || key.length < 8) {
62
+ @throw [NSException exceptionWithName:@"InvalidKeyException"
63
+ reason:@"DES key must be at least 8 characters long"
64
+ userInfo:nil];
65
+ }
66
+
67
+ // Extract optional parameters with defaults
68
+ // Codegen returns NSString* (nil if not provided) for optional string params
69
+ NSString *modeParam = params.mode();
70
+ NSString *paddingParam = params.padding();
71
+ NSString *outputFormatParam = params.outputFormat();
72
+
73
+ self.mode = (modeParam && modeParam.length > 0) ? modeParam : MODE_ECB;
74
+ self.padding = (paddingParam && paddingParam.length > 0) ? paddingParam : PADDING_PKCS7;
75
+ self.outputFormat = (outputFormatParam && outputFormatParam.length > 0) ? outputFormatParam : FORMAT_BASE64;
76
+
77
+ // Initialize secret key (DES uses 8 bytes)
78
+ NSData *keyData = [key dataUsingEncoding:NSUTF8StringEncoding];
79
+ self.secretKey = [keyData subdataWithRange:NSMakeRange(0, MIN(8, keyData.length))];
80
+
81
+ // Pad key to 8 bytes if needed
82
+ if (self.secretKey.length < 8) {
83
+ NSMutableData *paddedKey = [NSMutableData dataWithData:self.secretKey];
84
+ [paddedKey setLength:8];
85
+ self.secretKey = paddedKey;
86
+ }
87
+
88
+ // Initialize IV for modes that require it (use first 8 bytes of key)
89
+ if (![self.mode isEqualToString:MODE_ECB]) {
90
+ self.ivData = [self.secretKey copy];
91
+ } else {
92
+ self.ivData = nil;
93
+ }
94
+ }
95
+
96
+ /**
97
+ * Encrypt the provided plaintext using DES algorithm.
98
+ * @param text The plaintext to encrypt
99
+ * @return Encrypted string in the configured output format (BASE64 or HEX)
100
+ */
101
+ - (NSString *)encrypt:(NSString *)text {
102
+ if (!self.secretKey) {
103
+ @throw [NSException exceptionWithName:@"NotInitializedException"
104
+ reason:@"DES not initialized. Call setMachineParams() first."
105
+ userInfo:nil];
106
+ }
107
+
108
+ NSData *inputData = [text dataUsingEncoding:NSUTF8StringEncoding];
109
+ NSData *paddedData = [self applyPadding:inputData];
110
+ NSData *encryptedData = [self performDESOperation:kCCEncrypt onData:paddedData];
111
+
112
+ return [self formatOutput:encryptedData];
113
+ }
114
+
115
+ /**
116
+ * Decrypt the provided ciphertext using DES algorithm.
117
+ * @param text Encrypted string in the configured format (BASE64 or HEX)
118
+ * @return Decrypted plaintext
119
+ */
120
+ - (NSString *)decrypt:(NSString *)text {
121
+ if (!self.secretKey) {
122
+ @throw [NSException exceptionWithName:@"NotInitializedException"
123
+ reason:@"DES not initialized. Call setMachineParams() first."
124
+ userInfo:nil];
125
+ }
126
+
127
+ NSData *encryptedData = [self parseInput:text];
128
+ NSData *decryptedData = [self performDESOperation:kCCDecrypt onData:encryptedData];
129
+ NSData *unpaddedData = [self removePadding:decryptedData];
130
+
131
+ return [[NSString alloc] initWithData:unpaddedData encoding:NSUTF8StringEncoding];
132
+ }
133
+
134
+ #pragma mark - DES Operations
135
+
136
+ - (NSData *)performDESOperation:(CCOperation)operation onData:(NSData *)data {
137
+ CCOptions options = [self getCCOptions];
138
+
139
+ size_t bufferSize = data.length + kCCBlockSizeDES;
140
+ void *buffer = malloc(bufferSize);
141
+ size_t numBytesProcessed = 0;
142
+
143
+ CCCryptorStatus status = CCCrypt(
144
+ operation,
145
+ kCCAlgorithmDES,
146
+ options,
147
+ self.secretKey.bytes,
148
+ kCCKeySizeDES,
149
+ self.ivData.bytes,
150
+ data.bytes,
151
+ data.length,
152
+ buffer,
153
+ bufferSize,
154
+ &numBytesProcessed
155
+ );
156
+
157
+ if (status != kCCSuccess) {
158
+ free(buffer);
159
+ @throw [NSException exceptionWithName:@"CryptoException"
160
+ reason:[NSString stringWithFormat:@"DES operation failed with status: %d", status]
161
+ userInfo:nil];
162
+ }
163
+
164
+ NSData *result = [NSData dataWithBytes:buffer length:numBytesProcessed];
165
+ free(buffer);
166
+
167
+ return result;
168
+ }
169
+
170
+ - (CCOptions)getCCOptions {
171
+ CCOptions options = 0;
172
+
173
+ // ECB mode
174
+ if ([self.mode isEqualToString:MODE_ECB]) {
175
+ options |= kCCOptionECBMode;
176
+ }
177
+
178
+ // Padding
179
+ if ([self.padding isEqualToString:PADDING_PKCS7]) {
180
+ options |= kCCOptionPKCS7Padding;
181
+ }
182
+ // For other padding types, we handle manually (no padding flag = NoPadding)
183
+
184
+ return options;
185
+ }
186
+
187
+ #pragma mark - Padding
188
+
189
+ - (NSData *)applyPadding:(NSData *)data {
190
+ if ([self.padding isEqualToString:PADDING_PKCS7]) {
191
+ // PKCS7 is handled by CommonCrypto
192
+ return data;
193
+ }
194
+
195
+ NSUInteger blockSize = kCCBlockSizeDES;
196
+ NSUInteger paddingLength = blockSize - (data.length % blockSize);
197
+
198
+ if (paddingLength == blockSize && [self.padding isEqualToString:PADDING_NONE]) {
199
+ return data;
200
+ }
201
+
202
+ NSMutableData *paddedData = [NSMutableData dataWithData:data];
203
+
204
+ if ([self.padding isEqualToString:PADDING_ZERO] || [self.padding isEqualToString:PADDING_NONE]) {
205
+ // Zero padding
206
+ [paddedData setLength:data.length + paddingLength];
207
+ } else if ([self.padding isEqualToString:PADDING_ISO10126]) {
208
+ // ISO10126: random bytes followed by padding length
209
+ uint8_t randomBytes[paddingLength];
210
+ for (NSUInteger i = 0; i < paddingLength - 1; i++) {
211
+ randomBytes[i] = arc4random_uniform(256);
212
+ }
213
+ randomBytes[paddingLength - 1] = (uint8_t)paddingLength;
214
+ [paddedData appendBytes:randomBytes length:paddingLength];
215
+ }
216
+
217
+ return paddedData;
218
+ }
219
+
220
+ - (NSData *)removePadding:(NSData *)data {
221
+ if ([self.padding isEqualToString:PADDING_PKCS7]) {
222
+ // PKCS7 is handled by CommonCrypto
223
+ return data;
224
+ }
225
+
226
+ if ([self.padding isEqualToString:PADDING_ZERO]) {
227
+ // Find last non-zero byte
228
+ const uint8_t *bytes = (const uint8_t *)data.bytes;
229
+ NSInteger lastIndex = data.length - 1;
230
+ while (lastIndex >= 0 && bytes[lastIndex] == 0) {
231
+ lastIndex--;
232
+ }
233
+ return [data subdataWithRange:NSMakeRange(0, lastIndex + 1)];
234
+ }
235
+
236
+ if ([self.padding isEqualToString:PADDING_ISO10126]) {
237
+ // Last byte indicates padding length
238
+ const uint8_t *bytes = (const uint8_t *)data.bytes;
239
+ uint8_t paddingLength = bytes[data.length - 1];
240
+ if (paddingLength > 0 && paddingLength <= kCCBlockSizeDES) {
241
+ return [data subdataWithRange:NSMakeRange(0, data.length - paddingLength)];
242
+ }
243
+ }
244
+
245
+ return data;
246
+ }
247
+
248
+ #pragma mark - Output Formatting
249
+
250
+ - (NSString *)formatOutput:(NSData *)data {
251
+ if ([self.outputFormat isEqualToString:FORMAT_HEX]) {
252
+ NSMutableString *hexString = [NSMutableString stringWithCapacity:data.length * 2];
253
+ const uint8_t *bytes = (const uint8_t *)data.bytes;
254
+ for (NSUInteger i = 0; i < data.length; i++) {
255
+ [hexString appendFormat:@"%02x", bytes[i]];
256
+ }
257
+ return hexString;
258
+ }
259
+
260
+ // Default: BASE64
261
+ return [data base64EncodedStringWithOptions:0];
262
+ }
263
+
264
+ - (NSData *)parseInput:(NSString *)text {
265
+ if ([self.outputFormat isEqualToString:FORMAT_HEX]) {
266
+ NSMutableData *data = [NSMutableData dataWithCapacity:text.length / 2];
267
+ for (NSUInteger i = 0; i < text.length; i += 2) {
268
+ NSString *hexByte = [text substringWithRange:NSMakeRange(i, 2)];
269
+ unsigned int byteValue;
270
+ [[NSScanner scannerWithString:hexByte] scanHexInt:&byteValue];
271
+ uint8_t byte = (uint8_t)byteValue;
272
+ [data appendBytes:&byte length:1];
273
+ }
274
+ return data;
275
+ }
276
+
277
+ // Default: BASE64
278
+ return [[NSData alloc] initWithBase64EncodedString:text options:0];
279
+ }
280
+
281
+ @end
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+
3
+ import { TurboModuleRegistry } from 'react-native';
4
+ export default TurboModuleRegistry.getEnforcing('DesMachine');
5
+ //# sourceMappingURL=NativeDesMachine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["TurboModuleRegistry","getEnforcing"],"sourceRoot":"../../src","sources":["NativeDesMachine.ts"],"mappings":";;AAAA,SAASA,mBAAmB,QAA0B,cAAc;AAmBpE,eAAeA,mBAAmB,CAACC,YAAY,CAAO,YAAY,CAAC","ignoreList":[]}
@@ -0,0 +1,75 @@
1
+ "use strict";
2
+
3
+ import DesMachine from "./NativeDesMachine.js";
4
+ const Padding = {
5
+ PKCS7: 'PKCS7',
6
+ ISO10126: 'ISO10126',
7
+ ZERO: 'ZERO',
8
+ NONE: 'NONE'
9
+ };
10
+ const Mode = {
11
+ ECB: 'ECB',
12
+ CBC: 'CBC',
13
+ CFB: 'CFB',
14
+ OFB: 'OFB',
15
+ CTR: 'CTR'
16
+ };
17
+ const Format = {
18
+ BASE64: 'BASE64',
19
+ HEX: 'HEX'
20
+ };
21
+ const modeOptions = [{
22
+ label: 'ECB (Electronic Codebook)',
23
+ value: Mode.ECB
24
+ }, {
25
+ label: 'CBC (Cipher Block Chaining)',
26
+ value: Mode.CBC
27
+ }, {
28
+ label: 'CFB (Cipher Feedback)',
29
+ value: Mode.CFB
30
+ }, {
31
+ label: 'OFB (Output Feedback)',
32
+ value: Mode.OFB
33
+ }, {
34
+ label: 'CTR (Counter)',
35
+ value: Mode.CTR
36
+ }];
37
+ const paddingOptions = [{
38
+ label: 'PKCS7',
39
+ value: Padding.PKCS7
40
+ }, {
41
+ label: 'ISO10126',
42
+ value: Padding.ISO10126
43
+ }, {
44
+ label: 'Zero Padding',
45
+ value: Padding.ZERO
46
+ }, {
47
+ label: 'No Padding',
48
+ value: Padding.NONE
49
+ }];
50
+ const formatOptions = [{
51
+ label: 'Base64',
52
+ value: Format.BASE64
53
+ }, {
54
+ label: 'Hexadecimal',
55
+ value: Format.HEX
56
+ }];
57
+ const defaultParams = {
58
+ mode: Mode.ECB,
59
+ padding: Padding.PKCS7,
60
+ outputFormat: Format.BASE64
61
+ };
62
+ export function setMachineParams(params) {
63
+ DesMachine.setMachineParams({
64
+ ...defaultParams,
65
+ ...params
66
+ });
67
+ }
68
+ export function encrypt(text) {
69
+ return DesMachine.encrypt(text);
70
+ }
71
+ export function decrypt(text) {
72
+ return DesMachine.decrypt(text);
73
+ }
74
+ export { Mode, Padding, Format, modeOptions, paddingOptions, formatOptions };
75
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["DesMachine","Padding","PKCS7","ISO10126","ZERO","NONE","Mode","ECB","CBC","CFB","OFB","CTR","Format","BASE64","HEX","modeOptions","label","value","paddingOptions","formatOptions","defaultParams","mode","padding","outputFormat","setMachineParams","params","encrypt","text","decrypt"],"sourceRoot":"../../src","sources":["index.ts"],"mappings":";;AAAA,OAAOA,UAAU,MAAiC,uBAAoB;AAOtE,MAAMC,OAA6D,GAAG;EACpEC,KAAK,EAAE,OAAO;EACdC,QAAQ,EAAE,UAAU;EACpBC,IAAI,EAAE,MAAM;EACZC,IAAI,EAAE;AACR,CAAC;AAED,MAAMC,IAAoD,GAAG;EAC3DC,GAAG,EAAE,KAAK;EACVC,GAAG,EAAE,KAAK;EACVC,GAAG,EAAE,KAAK;EACVC,GAAG,EAAE,KAAK;EACVC,GAAG,EAAE;AACP,CAAC;AAED,MAAMC,MAAkD,GAAG;EACzDC,MAAM,EAAE,QAAQ;EAChBC,GAAG,EAAE;AACP,CAAC;AAOD,MAAMC,WAA8C,GAAG,CACrD;EAAEC,KAAK,EAAE,2BAA2B;EAAEC,KAAK,EAAEX,IAAI,CAACC;AAAI,CAAC,EACvD;EAAES,KAAK,EAAE,6BAA6B;EAAEC,KAAK,EAAEX,IAAI,CAACE;AAAI,CAAC,EACzD;EAAEQ,KAAK,EAAE,uBAAuB;EAAEC,KAAK,EAAEX,IAAI,CAACG;AAAI,CAAC,EACnD;EAAEO,KAAK,EAAE,uBAAuB;EAAEC,KAAK,EAAEX,IAAI,CAACI;AAAI,CAAC,EACnD;EAAEM,KAAK,EAAE,eAAe;EAAEC,KAAK,EAAEX,IAAI,CAACK;AAAI,CAAC,CAC5C;AAED,MAAMO,cAAoD,GAAG,CAC3D;EAAEF,KAAK,EAAE,OAAO;EAAEC,KAAK,EAAEhB,OAAO,CAACC;AAAM,CAAC,EACxC;EAAEc,KAAK,EAAE,UAAU;EAAEC,KAAK,EAAEhB,OAAO,CAACE;AAAS,CAAC,EAC9C;EAAEa,KAAK,EAAE,cAAc;EAAEC,KAAK,EAAEhB,OAAO,CAACG;AAAK,CAAC,EAC9C;EAAEY,KAAK,EAAE,YAAY;EAAEC,KAAK,EAAEhB,OAAO,CAACI;AAAK,CAAC,CAC7C;AAED,MAAMc,aAA8C,GAAG,CACrD;EAAEH,KAAK,EAAE,QAAQ;EAAEC,KAAK,EAAEL,MAAM,CAACC;AAAO,CAAC,EACzC;EAAEG,KAAK,EAAE,aAAa;EAAEC,KAAK,EAAEL,MAAM,CAACE;AAAI,CAAC,CAC5C;AAED,MAAMM,aAAwC,GAAG;EAC/CC,IAAI,EAAEf,IAAI,CAACC,GAAG;EACde,OAAO,EAAErB,OAAO,CAACC,KAAK;EACtBqB,YAAY,EAAEX,MAAM,CAACC;AACvB,CAAC;AAED,OAAO,SAASW,gBAAgBA,CAACC,MAAwB,EAAQ;EAC/DzB,UAAU,CAACwB,gBAAgB,CAAC;IAC1B,GAAGJ,aAAa;IAChB,GAAGK;EACL,CAAC,CAAC;AACJ;AAEA,OAAO,SAASC,OAAOA,CAACC,IAAY,EAAU;EAC5C,OAAO3B,UAAU,CAAC0B,OAAO,CAACC,IAAI,CAAC;AACjC;AAEA,OAAO,SAASC,OAAOA,CAACD,IAAY,EAAU;EAC5C,OAAO3B,UAAU,CAAC4B,OAAO,CAACD,IAAI,CAAC;AACjC;AAEA,SAASrB,IAAI,EAAEL,OAAO,EAAEW,MAAM,EAAEG,WAAW,EAAEG,cAAc,EAAEC,aAAa","ignoreList":[]}
@@ -0,0 +1 @@
1
+ {"type":"module"}
@@ -0,0 +1 @@
1
+ {"type":"module"}
@@ -0,0 +1,18 @@
1
+ import { type TurboModule } from 'react-native';
2
+ export type ModeEncryptionType = 'ECB' | 'CBC' | 'CFB' | 'OFB' | 'CTR';
3
+ export type PaddingEncryptionType = 'PKCS7' | 'ISO10126' | 'ZERO' | 'NONE';
4
+ export type OutputFormatType = 'BASE64' | 'HEX';
5
+ export interface DesMachineParams {
6
+ key: string;
7
+ mode?: ModeEncryptionType;
8
+ padding?: PaddingEncryptionType;
9
+ outputFormat?: OutputFormatType;
10
+ }
11
+ export interface Spec extends TurboModule {
12
+ setMachineParams(params: DesMachineParams): void;
13
+ encrypt(text: string): string;
14
+ decrypt(text: string): string;
15
+ }
16
+ declare const _default: Spec;
17
+ export default _default;
18
+ //# sourceMappingURL=NativeDesMachine.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NativeDesMachine.d.ts","sourceRoot":"","sources":["../../../src/NativeDesMachine.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuB,KAAK,WAAW,EAAE,MAAM,cAAc,CAAC;AAErE,MAAM,MAAM,kBAAkB,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,CAAC;AACvE,MAAM,MAAM,qBAAqB,GAAG,OAAO,GAAG,UAAU,GAAG,MAAM,GAAG,MAAM,CAAC;AAC3E,MAAM,MAAM,gBAAgB,GAAG,QAAQ,GAAG,KAAK,CAAC;AAEhD,MAAM,WAAW,gBAAgB;IAC/B,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,kBAAkB,CAAC;IAC1B,OAAO,CAAC,EAAE,qBAAqB,CAAC;IAChC,YAAY,CAAC,EAAE,gBAAgB,CAAC;CACjC;AAED,MAAM,WAAW,IAAK,SAAQ,WAAW;IACvC,gBAAgB,CAAC,MAAM,EAAE,gBAAgB,GAAG,IAAI,CAAC;IACjD,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;IAC9B,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;CAC/B;;AAED,wBAAoE"}
@@ -0,0 +1,18 @@
1
+ import { type DesMachineParams } from './NativeDesMachine';
2
+ import type { ModeEncryptionType, PaddingEncryptionType, OutputFormatType } from './NativeDesMachine';
3
+ declare const Padding: Record<PaddingEncryptionType, PaddingEncryptionType>;
4
+ declare const Mode: Record<ModeEncryptionType, ModeEncryptionType>;
5
+ declare const Format: Record<OutputFormatType, OutputFormatType>;
6
+ interface OptionsList<T extends string> {
7
+ label: string;
8
+ value: T;
9
+ }
10
+ declare const modeOptions: OptionsList<ModeEncryptionType>[];
11
+ declare const paddingOptions: OptionsList<PaddingEncryptionType>[];
12
+ declare const formatOptions: OptionsList<OutputFormatType>[];
13
+ export declare function setMachineParams(params: DesMachineParams): void;
14
+ export declare function encrypt(text: string): string;
15
+ export declare function decrypt(text: string): string;
16
+ export { Mode, Padding, Format, modeOptions, paddingOptions, formatOptions };
17
+ export type { ModeEncryptionType, PaddingEncryptionType, OutputFormatType };
18
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.ts"],"names":[],"mappings":"AAAA,OAAmB,EAAE,KAAK,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACvE,OAAO,KAAK,EACV,kBAAkB,EAClB,qBAAqB,EACrB,gBAAgB,EACjB,MAAM,oBAAoB,CAAC;AAE5B,QAAA,MAAM,OAAO,EAAE,MAAM,CAAC,qBAAqB,EAAE,qBAAqB,CAKjE,CAAC;AAEF,QAAA,MAAM,IAAI,EAAE,MAAM,CAAC,kBAAkB,EAAE,kBAAkB,CAMxD,CAAC;AAEF,QAAA,MAAM,MAAM,EAAE,MAAM,CAAC,gBAAgB,EAAE,gBAAgB,CAGtD,CAAC;AAEF,UAAU,WAAW,CAAC,CAAC,SAAS,MAAM;IACpC,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,CAAC,CAAC;CACV;AAED,QAAA,MAAM,WAAW,EAAE,WAAW,CAAC,kBAAkB,CAAC,EAMjD,CAAC;AAEF,QAAA,MAAM,cAAc,EAAE,WAAW,CAAC,qBAAqB,CAAC,EAKvD,CAAC;AAEF,QAAA,MAAM,aAAa,EAAE,WAAW,CAAC,gBAAgB,CAAC,EAGjD,CAAC;AAQF,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,gBAAgB,GAAG,IAAI,CAK/D;AAED,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE5C;AAED,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE5C;AAED,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,cAAc,EAAE,aAAa,EAAE,CAAC;AAC7E,YAAY,EAAE,kBAAkB,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,CAAC"}
package/package.json ADDED
@@ -0,0 +1,168 @@
1
+ {
2
+ "name": "react-native-des-machine",
3
+ "version": "0.1.0",
4
+ "description": "React Native module that provides simple text encryption and decryption based on the DES algorithm.",
5
+ "main": "./lib/module/index.js",
6
+ "types": "./lib/typescript/src/index.d.ts",
7
+ "exports": {
8
+ ".": {
9
+ "source": "./src/index.ts",
10
+ "types": "./lib/typescript/src/index.d.ts",
11
+ "default": "./lib/module/index.js"
12
+ },
13
+ "./package.json": "./package.json"
14
+ },
15
+ "files": [
16
+ "src",
17
+ "lib",
18
+ "android",
19
+ "ios",
20
+ "cpp",
21
+ "*.podspec",
22
+ "react-native.config.js",
23
+ "!ios/build",
24
+ "!android/build",
25
+ "!android/gradle",
26
+ "!android/gradlew",
27
+ "!android/gradlew.bat",
28
+ "!android/local.properties",
29
+ "!**/__tests__",
30
+ "!**/__fixtures__",
31
+ "!**/__mocks__",
32
+ "!**/.*"
33
+ ],
34
+ "scripts": {
35
+ "example": "yarn workspace react-native-des-machine-example",
36
+ "clean": "del-cli lib",
37
+ "prepare": "bob build",
38
+ "typecheck": "tsc",
39
+ "test": "jest",
40
+ "release": "release-it --only-version",
41
+ "lint": "eslint \"**/*.{js,ts,tsx}\""
42
+ },
43
+ "keywords": [
44
+ "react-native",
45
+ "ios",
46
+ "android"
47
+ ],
48
+ "repository": {
49
+ "type": "git",
50
+ "url": "git+https://github.com/NeRo8/react-native-des-machine.git"
51
+ },
52
+ "author": "Artur Duchenko <artur.duchenko@gmail.com> (https://github.com/NeRo8)",
53
+ "license": "MIT",
54
+ "bugs": {
55
+ "url": "https://github.com/NeRo8/react-native-des-machine/issues"
56
+ },
57
+ "homepage": "https://github.com/NeRo8/react-native-des-machine#readme",
58
+ "publishConfig": {
59
+ "registry": "https://registry.npmjs.org/"
60
+ },
61
+ "devDependencies": {
62
+ "@commitlint/config-conventional": "^19.8.1",
63
+ "@eslint/compat": "^1.3.2",
64
+ "@eslint/eslintrc": "^3.3.1",
65
+ "@eslint/js": "^9.35.0",
66
+ "@react-native/babel-preset": "0.83.0",
67
+ "@react-native/eslint-config": "0.83.0",
68
+ "@release-it/conventional-changelog": "^10.0.1",
69
+ "@types/jest": "^29.5.14",
70
+ "@types/react": "^19.1.12",
71
+ "commitlint": "^19.8.1",
72
+ "del-cli": "^6.0.0",
73
+ "eslint": "^9.35.0",
74
+ "eslint-config-prettier": "^10.1.8",
75
+ "eslint-plugin-prettier": "^5.5.4",
76
+ "jest": "^29.7.0",
77
+ "lefthook": "^2.0.3",
78
+ "prettier": "^2.8.8",
79
+ "react": "19.1.0",
80
+ "react-native": "0.81.5",
81
+ "react-native-builder-bob": "^0.40.17",
82
+ "release-it": "^19.0.4",
83
+ "typescript": "^5.9.2"
84
+ },
85
+ "peerDependencies": {
86
+ "react": "*",
87
+ "react-native": "*"
88
+ },
89
+ "workspaces": [
90
+ "example"
91
+ ],
92
+ "packageManager": "yarn@4.11.0",
93
+ "react-native-builder-bob": {
94
+ "source": "src",
95
+ "output": "lib",
96
+ "targets": [
97
+ [
98
+ "module",
99
+ {
100
+ "esm": true
101
+ }
102
+ ],
103
+ [
104
+ "typescript",
105
+ {
106
+ "project": "tsconfig.build.json"
107
+ }
108
+ ]
109
+ ]
110
+ },
111
+ "codegenConfig": {
112
+ "name": "DesMachineSpec",
113
+ "type": "modules",
114
+ "jsSrcsDir": "src",
115
+ "android": {
116
+ "javaPackageName": "com.desmachine"
117
+ }
118
+ },
119
+ "jest": {
120
+ "preset": "react-native",
121
+ "modulePathIgnorePatterns": [
122
+ "<rootDir>/example/node_modules",
123
+ "<rootDir>/lib/"
124
+ ]
125
+ },
126
+ "commitlint": {
127
+ "extends": [
128
+ "@commitlint/config-conventional"
129
+ ]
130
+ },
131
+ "release-it": {
132
+ "git": {
133
+ "commitMessage": "chore: release ${version}",
134
+ "tagName": "v${version}"
135
+ },
136
+ "npm": {
137
+ "publish": true
138
+ },
139
+ "github": {
140
+ "release": true
141
+ },
142
+ "plugins": {
143
+ "@release-it/conventional-changelog": {
144
+ "preset": {
145
+ "name": "angular"
146
+ }
147
+ }
148
+ }
149
+ },
150
+ "prettier": {
151
+ "quoteProps": "consistent",
152
+ "singleQuote": true,
153
+ "tabWidth": 2,
154
+ "trailingComma": "es5",
155
+ "useTabs": false
156
+ },
157
+ "create-react-native-library": {
158
+ "type": "turbo-module",
159
+ "languages": "kotlin-objc",
160
+ "tools": [
161
+ "jest",
162
+ "lefthook",
163
+ "release-it",
164
+ "eslint"
165
+ ],
166
+ "version": "0.57.0"
167
+ }
168
+ }
@@ -0,0 +1,20 @@
1
+ import { TurboModuleRegistry, type TurboModule } from 'react-native';
2
+
3
+ export type ModeEncryptionType = 'ECB' | 'CBC' | 'CFB' | 'OFB' | 'CTR';
4
+ export type PaddingEncryptionType = 'PKCS7' | 'ISO10126' | 'ZERO' | 'NONE';
5
+ export type OutputFormatType = 'BASE64' | 'HEX';
6
+
7
+ export interface DesMachineParams {
8
+ key: string;
9
+ mode?: ModeEncryptionType;
10
+ padding?: PaddingEncryptionType;
11
+ outputFormat?: OutputFormatType;
12
+ }
13
+
14
+ export interface Spec extends TurboModule {
15
+ setMachineParams(params: DesMachineParams): void;
16
+ encrypt(text: string): string;
17
+ decrypt(text: string): string;
18
+ }
19
+
20
+ export default TurboModuleRegistry.getEnforcing<Spec>('DesMachine');
package/src/index.ts ADDED
@@ -0,0 +1,75 @@
1
+ import DesMachine, { type DesMachineParams } from './NativeDesMachine';
2
+ import type {
3
+ ModeEncryptionType,
4
+ PaddingEncryptionType,
5
+ OutputFormatType,
6
+ } from './NativeDesMachine';
7
+
8
+ const Padding: Record<PaddingEncryptionType, PaddingEncryptionType> = {
9
+ PKCS7: 'PKCS7',
10
+ ISO10126: 'ISO10126',
11
+ ZERO: 'ZERO',
12
+ NONE: 'NONE',
13
+ };
14
+
15
+ const Mode: Record<ModeEncryptionType, ModeEncryptionType> = {
16
+ ECB: 'ECB',
17
+ CBC: 'CBC',
18
+ CFB: 'CFB',
19
+ OFB: 'OFB',
20
+ CTR: 'CTR',
21
+ };
22
+
23
+ const Format: Record<OutputFormatType, OutputFormatType> = {
24
+ BASE64: 'BASE64',
25
+ HEX: 'HEX',
26
+ };
27
+
28
+ interface OptionsList<T extends string> {
29
+ label: string;
30
+ value: T;
31
+ }
32
+
33
+ const modeOptions: OptionsList<ModeEncryptionType>[] = [
34
+ { label: 'ECB (Electronic Codebook)', value: Mode.ECB },
35
+ { label: 'CBC (Cipher Block Chaining)', value: Mode.CBC },
36
+ { label: 'CFB (Cipher Feedback)', value: Mode.CFB },
37
+ { label: 'OFB (Output Feedback)', value: Mode.OFB },
38
+ { label: 'CTR (Counter)', value: Mode.CTR },
39
+ ];
40
+
41
+ const paddingOptions: OptionsList<PaddingEncryptionType>[] = [
42
+ { label: 'PKCS7', value: Padding.PKCS7 },
43
+ { label: 'ISO10126', value: Padding.ISO10126 },
44
+ { label: 'Zero Padding', value: Padding.ZERO },
45
+ { label: 'No Padding', value: Padding.NONE },
46
+ ];
47
+
48
+ const formatOptions: OptionsList<OutputFormatType>[] = [
49
+ { label: 'Base64', value: Format.BASE64 },
50
+ { label: 'Hexadecimal', value: Format.HEX },
51
+ ];
52
+
53
+ const defaultParams: Partial<DesMachineParams> = {
54
+ mode: Mode.ECB,
55
+ padding: Padding.PKCS7,
56
+ outputFormat: Format.BASE64,
57
+ };
58
+
59
+ export function setMachineParams(params: DesMachineParams): void {
60
+ DesMachine.setMachineParams({
61
+ ...defaultParams,
62
+ ...params,
63
+ });
64
+ }
65
+
66
+ export function encrypt(text: string): string {
67
+ return DesMachine.encrypt(text);
68
+ }
69
+
70
+ export function decrypt(text: string): string {
71
+ return DesMachine.decrypt(text);
72
+ }
73
+
74
+ export { Mode, Padding, Format, modeOptions, paddingOptions, formatOptions };
75
+ export type { ModeEncryptionType, PaddingEncryptionType, OutputFormatType };