Skip to content

Commit fe722ef

Browse files
authored
feat: add bytes methods and using embeded TextEncoder and TextDecoder (#113)
* feat: add bytes methods and using embeded TextEncoder and TextDecoder * chore: update readme * chore: removed unused dep * chore: fix types * chore: fix types
1 parent bdde1b3 commit fe722ef

34 files changed

+926
-153
lines changed

README.md

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,12 @@
1010
## JSI
1111

1212

13-
If you want to use with `JSI` instead of `NativeModules` you need to set
13+
If you want to use with `NativeModules` instead of `JSI` you need to set
1414

1515
```typescript
1616
import OpenPGP from "react-native-fast-openpgp";
1717

18-
OpenPGP.useJSI = true;
18+
OpenPGP.useJSI = false;
1919
```
2020
if you need to use generate methods it is a good idea to disable it, because for now JSI will block your UI but it is faster compared to NativeModules
2121

@@ -27,9 +27,11 @@ if you need to use generate methods it is a good idea to disable it, because for
2727
import OpenPGP from "react-native-fast-openpgp";
2828

2929
const encrypted = await OpenPGP.encrypt(message: string, publicKey: string, signedEntity?: Entity, fileHints?: FileHints, options?: KeyOptions ): Promise<string>;
30+
const encrypted = await OpenPGP.encryptBytes(message: Uint8Array, publicKey: string, signedEntity?: Entity, fileHints?: FileHints, options?: KeyOptions ): Promise<Uint8Array>;
3031
const outputFile = await OpenPGP.encryptFile(inputFile: string, outputFile: string, publicKey: string, signedEntity?: Entity, fileHints?: FileHints, options?: KeyOptions): Promise<number>;
3132

3233
const encryptedSymmetric = await OpenPGP.encryptSymmetric(message: string, passphrase: string, fileHints?: FileHints, options?: KeyOptions ): Promise<string>;
34+
const encryptedSymmetric = await OpenPGP.encryptSymmetricBytes(message: Uint8Array, passphrase: string, fileHints?: FileHints, options?: KeyOptions ): Promise<Uint8Array>;
3335
const outputFile = await OpenPGP.encryptSymmetricFile(inputFile: string, outputFile: string, passphrase: string, fileHints?: FileHints, options?: KeyOptions ): Promise<number> ;
3436
```
3537

@@ -38,9 +40,11 @@ const outputFile = await OpenPGP.encryptSymmetricFile(inputFile: string, outputF
3840
import OpenPGP from "react-native-fast-openpgp";
3941

4042
const decrypted = await OpenPGP.decrypt(message: string, privateKey: string, passphrase: string, options?: KeyOptions ): Promise<string>;
43+
const decrypted = await OpenPGP.decryptBytes(message: Uint8Array, privateKey: string, passphrase: string, options?: KeyOptions ): Promise<Uint8Array>;
4144
const outputFile = await OpenPGP.decryptFile(inputFile: string, outputFile: string, privateKey: string, passphrase: string, options?: KeyOptions ): Promise<number>;
4245

4346
const decryptedSymmetric = await OpenPGP.decryptSymmetric(message: string, passphrase: string, options?: KeyOptions ): Promise<string>;
47+
const decryptedSymmetric = await OpenPGP.decryptSymmetricBytes(message: Uint8Array, passphrase: string, options?: KeyOptions ): Promise<Uint8Array>;
4448
const outputFile = await OpenPGP.decryptSymmetricFile(inputFile: string, outputFile: string, passphrase: string, options?: KeyOptions ): Promise<number> ;
4549
```
4650

@@ -49,9 +53,12 @@ const outputFile = await OpenPGP.decryptSymmetricFile(inputFile: string, outputF
4953
import OpenPGP from "react-native-fast-openpgp";
5054

5155
const signed = await OpenPGP.sign(message: string, privateKey: string, passphrase: string, options?: KeyOptions ): Promise<string>;
56+
const signed = await OpenPGP.signBytes(message: Uint8Array, privateKey: string, passphrase: string, options?: KeyOptions ): Promise<Uint8Array>;
57+
const signed = await OpenPGP.signBytesToString(message: Uint8Array, privateKey: string, passphrase: string, options?: KeyOptions ): Promise<string>;
5258
const signed = await OpenPGP.signFile(inputFile: string, privateKey: string, passphrase: string, options?: KeyOptions ): Promise<string>;
5359

5460
const verified = await OpenPGP.verify(signature: string, message: string, publicKey: string ): Promise<boolean>;
61+
const verified = await OpenPGP.verifyBytes(signature: string, message: Uint8Array, publicKey: string ): Promise<boolean>;
5562
const verified = await OpenPGP.verifyFile(signature: string, inputFile: string,publicKey: string): Promise<boolean>;
5663
```
5764

android/fast-openpgp-adapter.cpp

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,3 +92,96 @@ Java_com_fastopenpgp_FastOpenpgpModule_callNative(JNIEnv* env,
9292

9393
return result;
9494
}
95+
96+
extern "C" JNIEXPORT jbyteArray JNICALL
97+
Java_com_fastopenpgp_FastOpenpgpModule_encodeTextNative(JNIEnv* env, jobject thiz, jstring input, jstring encoding) {
98+
if (input == nullptr || encoding == nullptr) {
99+
jclass Exception = env->FindClass("java/lang/NullPointerException");
100+
env->ThrowNew(Exception, "Input parameters 'input' or 'encoding' cannot be null");
101+
return nullptr;
102+
}
103+
104+
// Convert Java Strings to C Strings
105+
const char* inputCStr = env->GetStringUTFChars(input, nullptr);
106+
const char* encodingCStr = env->GetStringUTFChars(encoding, nullptr);
107+
108+
if (inputCStr == nullptr || encodingCStr == nullptr) {
109+
jclass Exception = env->FindClass("java/lang/OutOfMemoryError");
110+
env->ThrowNew(Exception, "Failed to allocate memory for 'input' or 'encoding'");
111+
return nullptr;
112+
}
113+
114+
// Call the shared library function
115+
BytesReturn* response = OpenPGPEncodeText(const_cast<char*>(inputCStr), const_cast<char*>(encodingCStr));
116+
117+
// Release allocated resources
118+
env->ReleaseStringUTFChars(input, inputCStr);
119+
env->ReleaseStringUTFChars(encoding, encodingCStr);
120+
121+
if (response->error != nullptr) {
122+
jclass Exception = env->FindClass("java/lang/Exception");
123+
env->ThrowNew(Exception, response->error);
124+
free(response);
125+
return nullptr;
126+
}
127+
128+
// Create a new byte array to return the encoded data
129+
jbyteArray result = env->NewByteArray(response->size);
130+
if (result == nullptr) {
131+
free(response);
132+
jclass Exception = env->FindClass("java/lang/OutOfMemoryError");
133+
env->ThrowNew(Exception, "Failed to allocate memory for result");
134+
return nullptr;
135+
}
136+
137+
env->SetByteArrayRegion(result, 0, response->size, reinterpret_cast<jbyte*>(response->message));
138+
free(response);
139+
140+
return result;
141+
}
142+
143+
extern "C" JNIEXPORT jstring JNICALL
144+
Java_com_fastopenpgp_FastOpenpgpModule_decodeTextNative(JNIEnv* env, jobject thiz, jbyteArray input, jstring encoding,
145+
jint fatal, jint ignoreBOM, jint stream) {
146+
if (input == nullptr || encoding == nullptr) {
147+
jclass Exception = env->FindClass("java/lang/NullPointerException");
148+
env->ThrowNew(Exception, "Input parameters 'input' or 'encoding' cannot be null");
149+
return nullptr;
150+
}
151+
152+
// Convert Java Strings to C Strings
153+
const char* encodingCStr = env->GetStringUTFChars(encoding, nullptr);
154+
if (encodingCStr == nullptr) {
155+
jclass Exception = env->FindClass("java/lang/OutOfMemoryError");
156+
env->ThrowNew(Exception, "Failed to allocate memory for 'encoding'");
157+
return nullptr;
158+
}
159+
160+
// Convert Java byte array to C byte array
161+
jsize size = env->GetArrayLength(input);
162+
jbyte* inputBytes = env->GetByteArrayElements(input, nullptr);
163+
if (inputBytes == nullptr) {
164+
env->ReleaseStringUTFChars(encoding, encodingCStr);
165+
jclass Exception = env->FindClass("java/lang/OutOfMemoryError");
166+
env->ThrowNew(Exception, "Failed to allocate memory for 'input'");
167+
return nullptr;
168+
}
169+
170+
// Call the shared library function
171+
char* decodedString = OpenPGPDecodeText(inputBytes, size, const_cast<char*>(encodingCStr), fatal, ignoreBOM, stream);
172+
173+
// Release resources
174+
env->ReleaseStringUTFChars(encoding, encodingCStr);
175+
env->ReleaseByteArrayElements(input, inputBytes, JNI_ABORT);
176+
177+
if (decodedString == nullptr) {
178+
jclass Exception = env->FindClass("java/lang/Exception");
179+
env->ThrowNew(Exception, "Decoding failed");
180+
return nullptr;
181+
}
182+
183+
// Convert C string to Java string and return
184+
jstring result = env->NewStringUTF(decodedString);
185+
free(decodedString);
186+
return result;
187+
}

android/src/main/java/com/fastopenpgp/FastOpenpgpModule.kt

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ internal class FastOpenpgpModule(reactContext: ReactApplicationContext) :
1212
external fun initialize(jsContext: Long)
1313
external fun destruct();
1414
external fun callNative(name: String, payload: ByteArray): ByteArray;
15+
external fun encodeTextNative(input: String, encoding: String): ByteArray
16+
external fun decodeTextNative(input: ByteArray, encoding: String, fatal: Int, ignoreBOM: Int, stream: Int): String
1517

1618
companion object {
1719
init {
@@ -38,6 +40,32 @@ internal class FastOpenpgpModule(reactContext: ReactApplicationContext) :
3840
}.start()
3941
}
4042

43+
@ReactMethod(isBlockingSynchronousMethod = true)
44+
fun encodeText(input: String, encoding: String): WritableArray {
45+
return try {
46+
val result = encodeTextNative(input, encoding)
47+
Arguments.createArray().apply {
48+
result.forEach { byteValue: Byte -> pushInt(byteValue.toInt() and 0xFF) }
49+
}
50+
} catch (e: Exception) {
51+
Log.e(TAG, "Encoding error", e)
52+
throw RuntimeException("ENCODE_ERROR: Failed to encode text")
53+
}
54+
}
55+
56+
@ReactMethod(isBlockingSynchronousMethod = true)
57+
fun decodeText(input: ReadableArray, encoding: String, fatal: Boolean, ignoreBOM: Boolean, stream: Boolean): String {
58+
return try {
59+
val bytes = ByteArray(input.size()) { index ->
60+
input.getInt(index).toByte()
61+
}
62+
decodeTextNative(bytes, encoding, if (fatal) 1 else 0, if (ignoreBOM) 1 else 0, if (stream) 1 else 0)
63+
} catch (e: Exception) {
64+
Log.e(TAG, "Decoding error", e)
65+
throw RuntimeException("DECODE_ERROR: Failed to decode text")
66+
}
67+
}
68+
4169
@ReactMethod(isBlockingSynchronousMethod = true)
4270
fun install(): Boolean {
4371
Log.d(TAG, "Attempting to install JSI bindings...")

android/src/main/jniLibs/arm64-v8a/libopenpgp_bridge.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,8 @@ extern "C" {
8181
#endif
8282

8383
extern BytesReturn* OpenPGPBridgeCall(char* name, void* payload, int payloadSize);
84+
extern BytesReturn* OpenPGPEncodeText(char* input, char* encoding);
85+
extern char* OpenPGPDecodeText(void* input, int size, char* encoding, int fatal, int ignoreBOM, int stream);
8486

8587
#ifdef __cplusplus
8688
}
Binary file not shown.

android/src/main/jniLibs/armeabi-v7a/libopenpgp_bridge.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,8 @@ extern "C" {
8181
#endif
8282

8383
extern BytesReturn* OpenPGPBridgeCall(char* name, void* payload, int payloadSize);
84+
extern BytesReturn* OpenPGPEncodeText(char* input, char* encoding);
85+
extern char* OpenPGPDecodeText(void* input, int size, char* encoding, int fatal, int ignoreBOM, int stream);
8486

8587
#ifdef __cplusplus
8688
}
Binary file not shown.

android/src/main/jniLibs/x86/libopenpgp_bridge.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,8 @@ extern "C" {
8181
#endif
8282

8383
extern BytesReturn* OpenPGPBridgeCall(char* name, void* payload, int payloadSize);
84+
extern BytesReturn* OpenPGPEncodeText(char* input, char* encoding);
85+
extern char* OpenPGPDecodeText(void* input, int size, char* encoding, int fatal, int ignoreBOM, int stream);
8486

8587
#ifdef __cplusplus
8688
}
Binary file not shown.

android/src/main/jniLibs/x86_64/libopenpgp_bridge.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,8 @@ extern "C" {
8181
#endif
8282

8383
extern BytesReturn* OpenPGPBridgeCall(char* name, void* payload, int payloadSize);
84+
extern BytesReturn* OpenPGPEncodeText(char* input, char* encoding);
85+
extern char* OpenPGPDecodeText(void* input, int size, char* encoding, int fatal, int ignoreBOM, int stream);
8486

8587
#ifdef __cplusplus
8688
}

0 commit comments

Comments
 (0)