@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.
@@ -1,47 +1,60 @@
1
- package land.fx.fula;
2
-
3
- import android.util.Base64;
4
-
5
- import java.io.UnsupportedEncodingException;
6
- import java.security.InvalidAlgorithmParameterException;
7
- import java.security.InvalidKeyException;
8
- import java.security.NoSuchAlgorithmException;
9
- import java.security.spec.InvalidKeySpecException;
10
- import java.security.spec.InvalidParameterSpecException;
11
-
12
- import javax.crypto.BadPaddingException;
13
- import javax.crypto.Cipher;
14
- import javax.crypto.IllegalBlockSizeException;
15
- import javax.crypto.NoSuchPaddingException;
16
- import javax.crypto.SecretKey;
17
- import javax.crypto.SecretKeyFactory;
18
- import javax.crypto.spec.PBEKeySpec;
19
- import javax.crypto.spec.SecretKeySpec;
20
-
21
- public class Cryptography {
22
- public static String encryptMsg(String message, SecretKey secret)
23
- throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidParameterSpecException, IllegalBlockSizeException, BadPaddingException, UnsupportedEncodingException {
24
- Cipher cipher = null;
25
- cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
26
- cipher.init(Cipher.ENCRYPT_MODE, secret);
27
- byte[] cipherText = cipher.doFinal(message.getBytes("UTF-8"));
28
- return Base64.encodeToString(cipherText, Base64.NO_WRAP);
29
- }
30
-
31
- public static String decryptMsg(String cipherText, SecretKey secret)
32
- throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidParameterSpecException, InvalidAlgorithmParameterException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException, UnsupportedEncodingException {
33
- Cipher cipher = null;
34
- cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
35
- cipher.init(Cipher.DECRYPT_MODE, secret);
36
- byte[] decode = Base64.decode(cipherText, Base64.NO_WRAP);
37
- String decryptString = new String(cipher.doFinal(decode), "UTF-8");
38
- return decryptString;
39
- }
40
-
41
- public static SecretKey generateKey(byte[] key)
42
- throws NoSuchAlgorithmException, InvalidKeySpecException {
43
- PBEKeySpec pbeKeySpec = new PBEKeySpec(StaticHelper.bytesToBase64(key).toCharArray(), key, 1000, 128);
44
- SecretKey pbeKey = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256").generateSecret(pbeKeySpec);
45
- return new SecretKeySpec(pbeKey.getEncoded(), "AES");
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 Exception {
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
- if (encryptedKey == null) {
428
- byte[] autoGeneratedIdentity = Fulamobile.generateEd25519Key();
429
- encryptedKey = Cryptography.encryptMsg(StaticHelper.bytesToBase64(autoGeneratedIdentity), secretKey);
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
- } catch (Exception e) {
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 Exception {
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
- byte[] peerIdentity = this.createPeerIdentity(identity);
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
- shutdownInternal();
539
- this.fula = Fulamobile.newClient(fulaConfig);
540
- }
541
- if (this.fula != null) {
542
- this.fula.flush();
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
- return peerIdentity;
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.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",