@functionland/react-native-fula 1.2.2 → 1.2.4
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 +47 -24
- 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
|
}
|
|
@@ -462,8 +478,8 @@ public class FulaModule extends ReactContextBaseJavaModule {
|
|
|
462
478
|
String cid_encrypted = Cryptography.encryptMsg(this.rootConfig.getCid(), this.secretKeyGlobal);
|
|
463
479
|
String private_ref_encrypted = Cryptography.encryptMsg(this.rootConfig.getPrivate_ref(), this.secretKeyGlobal);
|
|
464
480
|
|
|
465
|
-
sharedPref.add("cid_encrypted_" + this.identityEncryptedGlobal, cid_encrypted);
|
|
466
|
-
sharedPref.add("private_ref_encrypted_" + this.identityEncryptedGlobal, private_ref_encrypted);
|
|
481
|
+
sharedPref.add("FULA_ENC_V2:cid_encrypted_" + this.identityEncryptedGlobal, cid_encrypted);
|
|
482
|
+
sharedPref.add("FULA_ENC_V2:private_ref_encrypted_" + this.identityEncryptedGlobal, private_ref_encrypted);
|
|
467
483
|
return true;
|
|
468
484
|
} else {
|
|
469
485
|
return false;
|
|
@@ -481,13 +497,13 @@ public class FulaModule extends ReactContextBaseJavaModule {
|
|
|
481
497
|
}
|
|
482
498
|
SecretKey secretKey = Cryptography.generateKey(identity);
|
|
483
499
|
String identity_encrypted = Cryptography.encryptMsg(Arrays.toString(identity), secretKey);
|
|
484
|
-
sharedPref.remove("cid_encrypted_"+ identity_encrypted);
|
|
485
|
-
sharedPref.remove("private_ref_encrypted_"+identity_encrypted);
|
|
500
|
+
sharedPref.remove("FULA_ENC_V2:cid_encrypted_"+ identity_encrypted);
|
|
501
|
+
sharedPref.remove("FULA_ENC_V2:private_ref_encrypted_"+identity_encrypted);
|
|
486
502
|
|
|
487
503
|
//TODO: Should also remove peerid @Mahdi
|
|
488
504
|
|
|
489
|
-
sharedPref.remove("cid_encrypted_"+ identity_encrypted);
|
|
490
|
-
sharedPref.remove("private_ref_encrypted_"+ identity_encrypted);
|
|
505
|
+
sharedPref.remove("FULA_ENC_V2:cid_encrypted_"+ identity_encrypted);
|
|
506
|
+
sharedPref.remove("FULA_ENC_V2:private_ref_encrypted_"+ identity_encrypted);
|
|
491
507
|
|
|
492
508
|
this.rootConfig = null;
|
|
493
509
|
this.secretKeyGlobal = null;
|
|
@@ -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 {
|
|
@@ -568,8 +591,8 @@ public class FulaModule extends ReactContextBaseJavaModule {
|
|
|
568
591
|
Log.d("ReactNative", "this.rootCid is empty.");
|
|
569
592
|
//Load from keystore
|
|
570
593
|
|
|
571
|
-
String cid_encrypted_fetched = sharedPref.getValue("cid_encrypted_"+ identity_encrypted);
|
|
572
|
-
String private_ref_encrypted_fetched = sharedPref.getValue("private_ref_encrypted_"+identity_encrypted);
|
|
594
|
+
String cid_encrypted_fetched = sharedPref.getValue("FULA_ENC_V2:cid_encrypted_"+ identity_encrypted);
|
|
595
|
+
String private_ref_encrypted_fetched = sharedPref.getValue("FULA_ENC_V2:private_ref_encrypted_"+identity_encrypted);
|
|
573
596
|
Log.d("ReactNative", "Here1");
|
|
574
597
|
String cid = "";
|
|
575
598
|
String private_ref = "";
|
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.4",
|
|
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",
|