Skip to content

Commit

Permalink
Merge pull request #61 from functionland/blockchain-blox-commands
Browse files Browse the repository at this point in the history
Added wifiRemoveallMethod
  • Loading branch information
ehsan6sha authored May 28, 2023
2 parents dfff5ed + fd879f4 commit 60738d2
Show file tree
Hide file tree
Showing 9 changed files with 572 additions and 309 deletions.
2 changes: 1 addition & 1 deletion android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ repositories {
dependencies {
//noinspection GradleDynamicVersion
implementation "com.facebook.react:react-native:+" // From node_modules
implementation 'com.github.functionland:fula-build-aar:1.2.1' // From jitpack.io
implementation 'com.github.functionland:fula-build-aar:1.9.0' // From jitpack.io
implementation 'com.github.functionland:wnfs-build-aar:v1.4.1' // From jitpack.io
implementation 'commons-io:commons-io:20030203.000550'
// implementation files('mobile.aar')
Expand Down
106 changes: 85 additions & 21 deletions android/src/main/java/land/fx/fula/FulaModule.java
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ public void initialize() {
SharedPreferenceHelper sharedPref;
SecretKey secretKeyGlobal;
String identityEncryptedGlobal;
static String PRIVATE_KEY_STORE_ID = "PRIVATE_KEY";
static String PRIVATE_KEY_STORE_PEERID = "PRIVATE_KEY";

public static class Client implements land.fx.wnfslib.Datastore {

Expand Down Expand Up @@ -133,6 +133,15 @@ private byte[] toByte(@NonNull String input) {
return input.getBytes(StandardCharsets.UTF_8);
}

private byte[] decToByte(@NonNull String input) {
String[] parts = input.split(",");
byte[] output = new byte[parts.length];
for (int i = 0; i < parts.length; i++) {
output[i] = Byte.parseByte(parts[i]);
}
return output;
}

@NonNull
@Contract("_ -> new")
public String toString(byte[] input) {
Expand Down Expand Up @@ -422,30 +431,48 @@ private boolean retryFailedActionsInternal(int timeout) throws Exception {
}

@NonNull
private byte[] createPeerIdentity(byte[] privateKey) throws GeneralSecurityException, IOException {
private byte[] createPeerIdentity(byte[] identity) throws GeneralSecurityException, IOException {
try {
// 1: First: create public key from provided private key
// 2: Should read the local keychain store (if it is key-value, key is public key above,
// 3: if found, decrypt using the private key
// 4: If not found or decryption not successful, generate an identity
// 5: then encrypt and store in keychain
String encryptedKey = sharedPref.getValue(PRIVATE_KEY_STORE_ID);
SecretKey secretKey = Cryptography.generateKey(privateKey);
byte[] libp2pId;
String encryptedLibp2pId = sharedPref.getValue(PRIVATE_KEY_STORE_PEERID);
byte[] encryptionPair;
SecretKey encryptionSecretKey;
try {
encryptionSecretKey = Cryptography.generateKey(identity);
Log.d("ReactNative", "encryptionSecretKey generated from privateKey");
} catch (Exception e) {
Log.d("ReactNative", "Failed to generate key for encryption: " + e.getMessage());
throw new GeneralSecurityException("Failed to generate key encryption", e);
}

if (encryptedLibp2pId == null || !encryptedLibp2pId.startsWith("FULA_ENC_V3:")) {
Log.d("ReactNative", "encryptedLibp2pId is not correct. creating new one " + encryptedLibp2pId);

if (encryptedKey == null || !encryptedKey.startsWith("FULA_ENC_V2:")) {
byte[] autoGeneratedIdentity;
try {
autoGeneratedIdentity = Fulamobile.generateEd25519Key();
libp2pId = Fulamobile.generateEd25519KeyFromString(toString(identity));
} catch (Exception e) {
Log.d("ReactNative", "Failed to generate key: " + e.getMessage());
throw new GeneralSecurityException("Failed to generate key", e);
Log.d("ReactNative", "Failed to generate libp2pId: " + e.getMessage());
throw new GeneralSecurityException("Failed to generate libp2pId", e);
}
encryptedKey = "FULA_ENC_V2:" + Cryptography.encryptMsg(StaticHelper.bytesToBase64(autoGeneratedIdentity), secretKey);
sharedPref.add(PRIVATE_KEY_STORE_ID, encryptedKey);
encryptedLibp2pId = "FULA_ENC_V3:" + Cryptography.encryptMsg(StaticHelper.bytesToBase64(libp2pId), encryptionSecretKey);
sharedPref.add(PRIVATE_KEY_STORE_PEERID, encryptedLibp2pId);
} else {
Log.d("ReactNative", "encryptedLibp2pId is correct. decrypting " + encryptedLibp2pId);
}

String decryptedKey = Cryptography.decryptMsg(encryptedKey.replace("FULA_ENC_V2:", ""), secretKey);
return StaticHelper.base64ToBytes(decryptedKey);
try {
String decryptedLibp2pId = Cryptography.decryptMsg(encryptedLibp2pId.replace("FULA_ENC_V3:", ""), encryptionSecretKey);

return StaticHelper.base64ToBytes(decryptedLibp2pId);
} catch (InvalidKeyException | NoSuchAlgorithmException | NoSuchPaddingException | IllegalBlockSizeException | BadPaddingException | InvalidAlgorithmParameterException e) {
Log.d("ReactNative", "createPeerIdentity decryptMsg failed with Error: " + e.getMessage());
throw (e);
}

} catch (InvalidKeyException | NoSuchAlgorithmException | NoSuchPaddingException | IllegalBlockSizeException | BadPaddingException | InvalidAlgorithmParameterException e) {
Log.d("ReactNative", "createPeerIdentity failed with Error: " + e.getMessage());
Expand Down Expand Up @@ -478,8 +505,8 @@ private boolean encrypt_and_store_config() throws Exception {
String cid_encrypted = Cryptography.encryptMsg(this.rootConfig.getCid(), this.secretKeyGlobal);
String private_ref_encrypted = Cryptography.encryptMsg(this.rootConfig.getPrivate_ref(), this.secretKeyGlobal);

sharedPref.add("FULA_ENC_V2:cid_encrypted_" + this.identityEncryptedGlobal, cid_encrypted);
sharedPref.add("FULA_ENC_V2:private_ref_encrypted_" + this.identityEncryptedGlobal, private_ref_encrypted);
sharedPref.add("FULA_ENC_V3:cid_encrypted_" + this.identityEncryptedGlobal, cid_encrypted);
sharedPref.add("FULA_ENC_V3:private_ref_encrypted_" + this.identityEncryptedGlobal, private_ref_encrypted);
return true;
} else {
return false;
Expand All @@ -496,14 +523,15 @@ private boolean logoutInternal(byte[] identity, String storePath) throws Excepti
this.fula.flush();
}
SecretKey secretKey = Cryptography.generateKey(identity);

String identity_encrypted = Cryptography.encryptMsg(Arrays.toString(identity), secretKey);
sharedPref.remove("FULA_ENC_V2:cid_encrypted_"+ identity_encrypted);
sharedPref.remove("FULA_ENC_V2:private_ref_encrypted_"+identity_encrypted);
sharedPref.remove("FULA_ENC_V3:cid_encrypted_"+ identity_encrypted);
sharedPref.remove("FULA_ENC_V3:private_ref_encrypted_"+identity_encrypted);

//TODO: Should also remove peerid @Mahdi

sharedPref.remove("FULA_ENC_V2:cid_encrypted_"+ identity_encrypted);
sharedPref.remove("FULA_ENC_V2:private_ref_encrypted_"+ identity_encrypted);
sharedPref.remove("FULA_ENC_V3:cid_encrypted_"+ identity_encrypted);
sharedPref.remove("FULA_ENC_V3:private_ref_encrypted_"+ identity_encrypted);

this.rootConfig = null;
this.secretKeyGlobal = null;
Expand Down Expand Up @@ -591,8 +619,8 @@ private String[] initInternal(byte[] identity, String storePath, String bloxAddr
Log.d("ReactNative", "this.rootCid is empty.");
//Load from keystore

String cid_encrypted_fetched = sharedPref.getValue("FULA_ENC_V2:cid_encrypted_"+ identity_encrypted);
String private_ref_encrypted_fetched = sharedPref.getValue("FULA_ENC_V2:private_ref_encrypted_"+identity_encrypted);
String cid_encrypted_fetched = sharedPref.getValue("FULA_ENC_V3:cid_encrypted_"+ identity_encrypted);
String private_ref_encrypted_fetched = sharedPref.getValue("FULA_ENC_V3:private_ref_encrypted_"+identity_encrypted);
Log.d("ReactNative", "Here1");
String cid = "";
String private_ref = "";
Expand Down Expand Up @@ -1301,6 +1329,10 @@ public void removeStoredReplication(String seedString, String uploader, long poo
});
}

////////////////////////////////////////////////////////////////
///////////////// Blox Hardware Methods ////////////////////////
////////////////////////////////////////////////////////////////

@ReactMethod
public void bloxFreeSpace(Promise promise) {
ThreadUtils.runOnExecutor(() -> {
Expand All @@ -1317,4 +1349,36 @@ public void bloxFreeSpace(Promise promise) {
});
}

@ReactMethod
public void wifiRemoveall(Promise promise) {
ThreadUtils.runOnExecutor(() -> {
Log.d("ReactNative", "wifiRemoveall");
try {
byte[] result = this.fula.wifiRemoveall();
String resultString = toString(result);
Log.d("ReactNative", "result string="+resultString);
promise.resolve(resultString);
} catch (Exception e) {
Log.d("ReactNative", e.getMessage());
promise.reject(e);
}
});
}

@ReactMethod
public void reboot(Promise promise) {
ThreadUtils.runOnExecutor(() -> {
Log.d("ReactNative", "reboot");
try {
byte[] result = this.fula.reboot();
String resultString = toString(result);
Log.d("ReactNative", "result string="+resultString);
promise.resolve(resultString);
} catch (Exception e) {
Log.d("ReactNative", e.getMessage());
promise.reject(e);
}
});
}

}
70 changes: 67 additions & 3 deletions example/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from 'react';
import { StyleSheet, Text, View, Button, TextInput } from 'react-native';

import { fula, blockchain, chainApi } from '@functionland/react-native-fula';
import { fula, blockchain, chainApi, fxblox } from '@functionland/react-native-fula';

const App = () => {
const [key, setKey] = React.useState<string>('');
Expand Down Expand Up @@ -31,15 +31,15 @@ const App = () => {
console.log(err.message, err.code);
});
};
//Key for peerId: 12D3KooWQGQo81K99HfbwuwhvbP4MYfo13fo7U6SAdkAnxoNBdPE
//Key for peerId: 12D3KooWDPZGpr4Jeq144R2KhezH7UHgHqyMXySh8tA5jzUyu2P8
const privateKey = [
183, 7, 117, 9, 159, 132, 170, 235, 215, 34, 145, 181, 60, 207, 4, 27, 27,
17, 17, 167, 100, 89, 157, 218, 73, 200, 183, 145, 104, 151, 204, 142, 241,
94, 225, 7, 153, 168, 239, 94, 7, 187, 123, 158, 149, 149, 227, 170, 32, 54,
203, 243, 211, 78, 120, 114, 199, 1, 197, 134, 6, 91, 87, 152,
];
const privateKeyString = "\\test";
const bloxAddr = '/dns/relay.dev.fx.land/tcp/4001/p2p/12D3KooWDRrBaAfPwsGJivBoUw5fE7ZpDiyfUjqgiURq2DEcL835/p2p-circuit/p2p/12D3KooWD69C5yX91nPe3tz6HRiuw7Pia4xsxE9xv2CghoyK6MPK';
const bloxAddr = '/dns/relay.dev.fx.land/tcp/4001/p2p/12D3KooWDRrBaAfPwsGJivBoUw5fE7ZpDiyfUjqgiURq2DEcL835/p2p-circuit/p2p/12D3KooWQR2XygKM7jhBduhvz2GDJdGEbZL8SZhkeBuXYPn2kRt6';
const newClient = async () => {
try {
return fula.newClient(
Expand Down Expand Up @@ -419,6 +419,70 @@ const App = () => {
}}
color={inprogress ? 'green' : 'blue'}
/>

<Button
title={inprogress ? 'Getting...' : 'Remove all Wifis'}
onPress={async () => {
try {
if (initComplete) {
fula.checkConnection().then((r) => {
console.log('connection check');
console.log(r);
if (r) {
console.log(
'initialization is completed. send remove wifis command'
);
fxblox
.wifiRemoveall()
.then((res) => {
console.log('wifiRemoveall received');
console.log(res);
})
.catch((e) => {
console.log('wifiRemoveall failed');
console.log(e);
});
}
});
} else {
console.log('wait for init to complete');
}
} catch (e) {}
}}
color={inprogress ? 'green' : 'blue'}
/>

<Button
title={inprogress ? 'Getting...' : 'Reboot'}
onPress={async () => {
try {
if (initComplete) {
fula.checkConnection().then((r) => {
console.log('connection check');
console.log(r);
if (r) {
console.log(
'initialization is completed. send reboot command'
);
fxblox
.reboot()
.then((res) => {
console.log('reboot received');
console.log(res);
})
.catch((e) => {
console.log('reboot failed');
console.log(e);
});
}
});
} else {
console.log('wait for init to complete');
}
} catch (e) {}
}}
color={inprogress ? 'green' : 'blue'}
/>
</View>
</View>
);
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@functionland/react-native-fula",
"version": "1.2.4",
"version": "1.9.0",
"description": "This package is a bridge to use the Fula libp2p protocols in the react-native which is using wnfs",
"main": "lib/commonjs/index",
"module": "lib/module/index",
Expand Down
3 changes: 2 additions & 1 deletion src/index.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * as fula from './protocols/fula';
export * as blockchain from './protocols/blockchain';
export * as chainApi from './protocols/chain-api';
export * as chainApi from './protocols/chain-api';
export * as fxblox from './protocols/fxblox';
49 changes: 41 additions & 8 deletions src/interfaces/fulaNativeModule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ interface FulaNativeModule {
autoFlush: boolean, //set to false always unless you know what you are doing. This is to write actions to disk explicitly after each write
useRelay: boolean | null, // if true it forces the use of relay
refresh: boolean // if true it forces to refresh the fula object
) => Promise<string>;
) => Promise<string>;
isReady: (filesystemCheck: boolean) => Promise<boolean>;
logout: (identity: string, storePath: string) => Promise<boolean>;
checkFailedActions: (retry: boolean, timeout: number) => Promise<boolean>;
Expand Down Expand Up @@ -47,7 +47,7 @@ interface FulaNativeModule {

shutdown: () => Promise<void>;

//Blockchain related functions
//Blockchain related functions
createAccount: (seed: string) => Promise<string>;
checkAccountExists: (account: string) => Promise<string>;
createPool: (seed: string, poolName: string) => Promise<string>;
Expand All @@ -56,14 +56,47 @@ interface FulaNativeModule {
leavePool: (seed: string, poolID: number) => Promise<string>;
cancelPoolJoin: (seed: string, poolID: number) => Promise<string>;
listPoolJoinRequests: (poolID: number) => Promise<string>;
votePoolJoinRequest: (seed: string, poolID: number, account: string, accept: boolean) => Promise<string>;
newReplicationRequest: (seed: string, poolID: number, replicationFactor: number, cid: string) => Promise<string>;
newStoreRequest: (seed: string, poolID: number, uploader: string, cid: string) => Promise<string>;
votePoolJoinRequest: (
seed: string,
poolID: number,
account: string,
accept: boolean
) => Promise<string>;
newReplicationRequest: (
seed: string,
poolID: number,
replicationFactor: number,
cid: string
) => Promise<string>;
newStoreRequest: (
seed: string,
poolID: number,
uploader: string,
cid: string
) => Promise<string>;
listAvailableReplicationRequests: (poolID: number) => Promise<string>;
removeReplicationRequest: (seed: string, poolID: number, cid: string) => Promise<string>;
removeStorer: (seed: string, storer: string, poolID: number, cid: string) => Promise<string>;
removeStoredReplication: (seed: string, uploader: string, poolID: number, cid: string) => Promise<string>;
removeReplicationRequest: (
seed: string,
poolID: number,
cid: string
) => Promise<string>;
removeStorer: (
seed: string,
storer: string,
poolID: number,
cid: string
) => Promise<string>;
removeStoredReplication: (
seed: string,
uploader: string,
poolID: number,
cid: string
) => Promise<string>;

//Hardware
bloxFreeSpace: () => Promise<string>;
wifiRemoveall: () => Promise<string>;
reboot: () => Promise<string>;
}

const LINKING_ERROR =
Expand Down
Loading

0 comments on commit 60738d2

Please sign in to comment.