@functionland/react-native-fula 1.2.2 → 1.2.3
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/android/.gradle/7.5.1/checksums/checksums.lock +0 -0
- package/android/.gradle/7.5.1/fileHashes/fileHashes.bin +0 -0
- package/android/.gradle/7.5.1/fileHashes/fileHashes.lock +0 -0
- package/android/.gradle/7.5.1/fileHashes/resourceHashesCache.bin +0 -0
- package/android/.gradle/buildOutputCleanup/buildOutputCleanup.lock +0 -0
- package/android/.gradle/buildOutputCleanup/outputFiles.bin +0 -0
- package/android/src/main/java/land/fx/fula/Cryptography.java +60 -47
- package/android/src/main/java/land/fx/fula/FulaModule.java +39 -16
- package/package.json +1 -1
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -1,47 +1,60 @@
|
|
|
1
|
-
package land.fx.fula;
|
|
2
|
-
|
|
3
|
-
import android.util.Base64;
|
|
4
|
-
|
|
5
|
-
import java.io.UnsupportedEncodingException;
|
|
6
|
-
import java.
|
|
7
|
-
import java.security.
|
|
8
|
-
import java.security.
|
|
9
|
-
import java.security.
|
|
10
|
-
import java.security.spec.
|
|
11
|
-
|
|
12
|
-
import
|
|
13
|
-
import
|
|
14
|
-
|
|
15
|
-
import javax.crypto.
|
|
16
|
-
import javax.crypto.
|
|
17
|
-
import javax.crypto.
|
|
18
|
-
import javax.crypto.
|
|
19
|
-
import javax.crypto.
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
1
|
+
package land.fx.fula;
|
|
2
|
+
|
|
3
|
+
import android.util.Base64;
|
|
4
|
+
|
|
5
|
+
import java.io.UnsupportedEncodingException;
|
|
6
|
+
import java.nio.charset.StandardCharsets;
|
|
7
|
+
import java.security.InvalidAlgorithmParameterException;
|
|
8
|
+
import java.security.InvalidKeyException;
|
|
9
|
+
import java.security.NoSuchAlgorithmException;
|
|
10
|
+
import java.security.spec.InvalidKeySpecException;
|
|
11
|
+
import java.security.SecureRandom;
|
|
12
|
+
import java.nio.ByteBuffer;
|
|
13
|
+
import java.security.spec.InvalidParameterSpecException;
|
|
14
|
+
|
|
15
|
+
import javax.crypto.BadPaddingException;
|
|
16
|
+
import javax.crypto.Cipher;
|
|
17
|
+
import javax.crypto.IllegalBlockSizeException;
|
|
18
|
+
import javax.crypto.NoSuchPaddingException;
|
|
19
|
+
import javax.crypto.SecretKey;
|
|
20
|
+
import javax.crypto.SecretKeyFactory;
|
|
21
|
+
import javax.crypto.spec.PBEKeySpec;
|
|
22
|
+
import javax.crypto.spec.SecretKeySpec;
|
|
23
|
+
import javax.crypto.spec.GCMParameterSpec;
|
|
24
|
+
|
|
25
|
+
public class Cryptography {
|
|
26
|
+
public static String encryptMsg(String message, SecretKey secret)
|
|
27
|
+
throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException, InvalidAlgorithmParameterException {
|
|
28
|
+
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
|
|
29
|
+
byte[] iv = new byte[12]; // Ensure this is randomly generated for each encryption.
|
|
30
|
+
new SecureRandom().nextBytes(iv);
|
|
31
|
+
GCMParameterSpec spec = new GCMParameterSpec(128, iv);
|
|
32
|
+
cipher.init(Cipher.ENCRYPT_MODE, secret, spec);
|
|
33
|
+
byte[] cipherText = cipher.doFinal(message.getBytes(StandardCharsets.UTF_8));
|
|
34
|
+
ByteBuffer byteBuffer = ByteBuffer.allocate(iv.length + cipherText.length);
|
|
35
|
+
byteBuffer.put(iv);
|
|
36
|
+
byteBuffer.put(cipherText);
|
|
37
|
+
return Base64.encodeToString(byteBuffer.array(), Base64.NO_WRAP);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
public static String decryptMsg(String cipherText, SecretKey secret)
|
|
41
|
+
throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
|
|
42
|
+
ByteBuffer byteBuffer = ByteBuffer.wrap(Base64.decode(cipherText, Base64.NO_WRAP));
|
|
43
|
+
byte[] iv = new byte[12];
|
|
44
|
+
byteBuffer.get(iv);
|
|
45
|
+
byte[] cipherBytes = new byte[byteBuffer.remaining()];
|
|
46
|
+
byteBuffer.get(cipherBytes);
|
|
47
|
+
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
|
|
48
|
+
GCMParameterSpec spec = new GCMParameterSpec(128, iv);
|
|
49
|
+
cipher.init(Cipher.DECRYPT_MODE, secret, spec);
|
|
50
|
+
String decryptString = new String(cipher.doFinal(cipherBytes), StandardCharsets.UTF_8);
|
|
51
|
+
return decryptString;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
public static SecretKey generateKey(byte[] key)
|
|
55
|
+
throws NoSuchAlgorithmException, InvalidKeySpecException {
|
|
56
|
+
PBEKeySpec pbeKeySpec = new PBEKeySpec(StaticHelper.bytesToBase64(key).toCharArray(), key, 1000, 128);
|
|
57
|
+
SecretKey pbeKey = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256").generateSecret(pbeKeySpec);
|
|
58
|
+
return new SecretKeySpec(pbeKey.getEncoded(), "AES");
|
|
59
|
+
}
|
|
60
|
+
}
|
|
@@ -16,9 +16,17 @@ import org.apache.commons.io.FileUtils;
|
|
|
16
16
|
import org.jetbrains.annotations.Contract;
|
|
17
17
|
|
|
18
18
|
import java.io.File;
|
|
19
|
+
import java.io.IOException;
|
|
19
20
|
import java.nio.charset.StandardCharsets;
|
|
21
|
+
import java.security.GeneralSecurityException;
|
|
22
|
+
import java.security.InvalidAlgorithmParameterException;
|
|
23
|
+
import java.security.InvalidKeyException;
|
|
24
|
+
import java.security.NoSuchAlgorithmException;
|
|
20
25
|
import java.util.Arrays;
|
|
21
26
|
|
|
27
|
+
import javax.crypto.BadPaddingException;
|
|
28
|
+
import javax.crypto.IllegalBlockSizeException;
|
|
29
|
+
import javax.crypto.NoSuchPaddingException;
|
|
22
30
|
import javax.crypto.SecretKey;
|
|
23
31
|
|
|
24
32
|
import java.util.concurrent.Executors;
|
|
@@ -414,24 +422,32 @@ public class FulaModule extends ReactContextBaseJavaModule {
|
|
|
414
422
|
}
|
|
415
423
|
|
|
416
424
|
@NonNull
|
|
417
|
-
private byte[] createPeerIdentity(byte[] privateKey) throws
|
|
425
|
+
private byte[] createPeerIdentity(byte[] privateKey) throws GeneralSecurityException, IOException {
|
|
418
426
|
try {
|
|
419
427
|
// 1: First: create public key from provided private key
|
|
420
428
|
// 2: Should read the local keychain store (if it is key-value, key is public key above,
|
|
421
429
|
// 3: if found, decrypt using the private key
|
|
422
430
|
// 4: If not found or decryption not successful, generate an identity
|
|
423
431
|
// 5: then encrypt and store in keychain
|
|
424
|
-
|
|
425
432
|
String encryptedKey = sharedPref.getValue(PRIVATE_KEY_STORE_ID);
|
|
426
433
|
SecretKey secretKey = Cryptography.generateKey(privateKey);
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
434
|
+
|
|
435
|
+
if (encryptedKey == null || !encryptedKey.startsWith("FULA_ENC_V2:")) {
|
|
436
|
+
byte[] autoGeneratedIdentity;
|
|
437
|
+
try {
|
|
438
|
+
autoGeneratedIdentity = Fulamobile.generateEd25519Key();
|
|
439
|
+
} catch (Exception e) {
|
|
440
|
+
Log.d("ReactNative", "Failed to generate key: " + e.getMessage());
|
|
441
|
+
throw new GeneralSecurityException("Failed to generate key", e);
|
|
442
|
+
}
|
|
443
|
+
encryptedKey = "FULA_ENC_V2:" + Cryptography.encryptMsg(StaticHelper.bytesToBase64(autoGeneratedIdentity), secretKey);
|
|
430
444
|
sharedPref.add(PRIVATE_KEY_STORE_ID, encryptedKey);
|
|
431
445
|
}
|
|
432
|
-
return StaticHelper.base64ToBytes(Cryptography.decryptMsg(encryptedKey, secretKey));
|
|
433
446
|
|
|
434
|
-
|
|
447
|
+
String decryptedKey = Cryptography.decryptMsg(encryptedKey.replace("FULA_ENC_V2:", ""), secretKey);
|
|
448
|
+
return StaticHelper.base64ToBytes(decryptedKey);
|
|
449
|
+
|
|
450
|
+
} catch (InvalidKeyException | NoSuchAlgorithmException | NoSuchPaddingException | IllegalBlockSizeException | BadPaddingException | InvalidAlgorithmParameterException e) {
|
|
435
451
|
Log.d("ReactNative", "createPeerIdentity failed with Error: " + e.getMessage());
|
|
436
452
|
throw (e);
|
|
437
453
|
}
|
|
@@ -512,7 +528,8 @@ public class FulaModule extends ReactContextBaseJavaModule {
|
|
|
512
528
|
}
|
|
513
529
|
|
|
514
530
|
@NonNull
|
|
515
|
-
private byte[] newClientInternal(byte[] identity, String storePath, String bloxAddr, String exchange, boolean autoFlush, boolean useRelay, boolean refresh) throws
|
|
531
|
+
private byte[] newClientInternal(byte[] identity, String storePath, String bloxAddr, String exchange, boolean autoFlush, boolean useRelay, boolean refresh) throws GeneralSecurityException, IOException {
|
|
532
|
+
byte[] peerIdentity = null;
|
|
516
533
|
try {
|
|
517
534
|
fulaConfig = new Config();
|
|
518
535
|
if (storePath == null || storePath.trim().isEmpty()) {
|
|
@@ -522,7 +539,7 @@ public class FulaModule extends ReactContextBaseJavaModule {
|
|
|
522
539
|
}
|
|
523
540
|
Log.d("ReactNative", "newClientInternal storePath is set: " + fulaConfig.getStorePath());
|
|
524
541
|
|
|
525
|
-
|
|
542
|
+
peerIdentity = this.createPeerIdentity(identity);
|
|
526
543
|
fulaConfig.setIdentity(peerIdentity);
|
|
527
544
|
Log.d("ReactNative", "peerIdentity is set: " + toString(fulaConfig.getIdentity()));
|
|
528
545
|
fulaConfig.setBloxAddr(bloxAddr);
|
|
@@ -535,19 +552,25 @@ public class FulaModule extends ReactContextBaseJavaModule {
|
|
|
535
552
|
}
|
|
536
553
|
if (this.fula == null || refresh) {
|
|
537
554
|
Log.d("ReactNative", "Creating a new Fula instance");
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
555
|
+
try {
|
|
556
|
+
shutdownInternal();
|
|
557
|
+
this.fula = Fulamobile.newClient(fulaConfig);
|
|
558
|
+
if (this.fula != null) {
|
|
559
|
+
this.fula.flush();
|
|
560
|
+
}
|
|
561
|
+
} catch (Exception e) {
|
|
562
|
+
Log.d("ReactNative", "Failed to create new Fula instance: " + e.getMessage());
|
|
563
|
+
throw new IOException("Failed to create new Fula instance", e);
|
|
564
|
+
}
|
|
543
565
|
}
|
|
544
|
-
|
|
545
|
-
} catch (Exception e) {
|
|
566
|
+
} catch (InvalidKeyException | NoSuchAlgorithmException | NoSuchPaddingException | IllegalBlockSizeException | BadPaddingException | InvalidAlgorithmParameterException e) {
|
|
546
567
|
Log.d("ReactNative", "newclientInternal failed with Error: " + e.getMessage());
|
|
547
568
|
throw (e);
|
|
548
569
|
}
|
|
570
|
+
return peerIdentity;
|
|
549
571
|
}
|
|
550
572
|
|
|
573
|
+
|
|
551
574
|
@NonNull
|
|
552
575
|
private String[] initInternal(byte[] identity, String storePath, String bloxAddr, String exchange, boolean autoFlush, String rootCid, boolean useRelay, boolean refresh) throws Exception {
|
|
553
576
|
try {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@functionland/react-native-fula",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.3",
|
|
4
4
|
"description": "This package is a bridge to use the Fula libp2p protocols in the react-native which is using wnfs",
|
|
5
5
|
"main": "lib/commonjs/index",
|
|
6
6
|
"module": "lib/module/index",
|