mirror of
https://github.com/aljazceru/react-native-pubky.git
synced 2025-12-18 23:24:22 +01:00
feat: add create_recovery_file decrypt_recovery_file
Adds create_recovery_file & decrypt_recovery_file functions. Adds examples for create_recovery_file & decrypt_recovery_file. Updates README.md. Updates version to 0.8.0.
This commit is contained in:
33
README.md
33
README.md
@@ -24,6 +24,9 @@ npm install @synonymdev/react-native-pubky
|
|||||||
- [x] [list](#list): Returns a list of Pubky URLs of the files in the path of the `url` provided.
|
- [x] [list](#list): Returns a list of Pubky URLs of the files in the path of the `url` provided.
|
||||||
- [x] [generateSecretKey](#generateSecretKey): Generate a secret key.
|
- [x] [generateSecretKey](#generateSecretKey): Generate a secret key.
|
||||||
- [x] [getPublicKeyFromSecretKey](#getPublicKeyFromSecretKey): Get the public key string and uri from a secret key.
|
- [x] [getPublicKeyFromSecretKey](#getPublicKeyFromSecretKey): Get the public key string and uri from a secret key.
|
||||||
|
- [x] [create_recovery_file](#createRecoveryFile): Create a recovery file.
|
||||||
|
- [x] [decrypt_recovery_file](#decryptRecoveryFile): Decrypt a recovery file.
|
||||||
|
-
|
||||||
### Methods to be Implemented
|
### Methods to be Implemented
|
||||||
- [ ] getProfile: Retrieve the profile of a user.
|
- [ ] getProfile: Retrieve the profile of a user.
|
||||||
- [ ] editProfile: Submit changes to the specified profile.
|
- [ ] editProfile: Submit changes to the specified profile.
|
||||||
@@ -225,6 +228,36 @@ if (signOutRes.isErr()) {
|
|||||||
console.log(signOutRes.value);
|
console.log(signOutRes.value);
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### <a name="createRecoveryFile"></a>createRecoveryFile
|
||||||
|
```js
|
||||||
|
import { createRecoveryFile } from '@synonymdev/react-native-pubky';
|
||||||
|
|
||||||
|
const createRecoveryFileRes = await createRecoveryFile(
|
||||||
|
'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855', // Secret Key
|
||||||
|
'passphrase', // Passphrase
|
||||||
|
);
|
||||||
|
if (createRecoveryFileRes.isErr()) {
|
||||||
|
console.log(createRecoveryFileRes.error.message);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console.log(createRecoveryFileRes.value);
|
||||||
|
```
|
||||||
|
|
||||||
|
### <a name="decryptRecoveryFile"></a>decryptRecoveryFile
|
||||||
|
```js
|
||||||
|
import { decryptRecoveryFile } from '@synonymdev/react-native-pubky';
|
||||||
|
|
||||||
|
const decryptRecoveryFileRes = await decryptRecoveryFile(
|
||||||
|
'cHVia3kub3JnL3JlY292ZXJ5CkZRt1NHIjxyTo0whSSgTgNrH56MPpGrSxvAQSE0x5FeklVJpNJqcNP4zjdwW/OpdBOsEC1qZ5MI/mcEUKFKVAEZwikdclsLZg==', // Recovery File
|
||||||
|
'passphrase', // Passphrase
|
||||||
|
);
|
||||||
|
if (decryptRecoveryFileRes.isErr()) {
|
||||||
|
console.log(decryptRecoveryFileRes.error.message);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console.log(decryptRecoveryFileRes.value);
|
||||||
|
```
|
||||||
|
|
||||||
## Local Installation
|
## Local Installation
|
||||||
|
|
||||||
1. Clone & npm install:
|
1. Clone & npm install:
|
||||||
|
|||||||
@@ -278,6 +278,32 @@ class PubkyModule(reactContext: ReactApplicationContext) :
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ReactMethod
|
||||||
|
fun createRecoveryFile(secretKey: String, passphrase: String, promise: Promise) {
|
||||||
|
try {
|
||||||
|
val result = createRecoveryFile(secretKey, passphrase)
|
||||||
|
val array = Arguments.createArray().apply {
|
||||||
|
result.forEach { pushString(it) }
|
||||||
|
}
|
||||||
|
promise.resolve(array)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
promise.reject("Error", e.message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ReactMethod
|
||||||
|
fun decryptRecoveryFile(recoveryFile: String, passphrase: String, promise: Promise) {
|
||||||
|
try {
|
||||||
|
val result = decryptRecoveryFile(recoveryFile, passphrase)
|
||||||
|
val array = Arguments.createArray().apply {
|
||||||
|
result.forEach { pushString(it) }
|
||||||
|
}
|
||||||
|
promise.resolve(array)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
promise.reject("Error", e.message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val NAME = "Pubky"
|
const val NAME = "Pubky"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1237,7 +1237,7 @@ PODS:
|
|||||||
- ReactCommon/turbomodule/bridging
|
- ReactCommon/turbomodule/bridging
|
||||||
- ReactCommon/turbomodule/core
|
- ReactCommon/turbomodule/core
|
||||||
- Yoga
|
- Yoga
|
||||||
- react-native-pubky (0.7.1):
|
- react-native-pubky (0.8.0):
|
||||||
- DoubleConversion
|
- DoubleConversion
|
||||||
- glog
|
- glog
|
||||||
- hermes-engine
|
- hermes-engine
|
||||||
@@ -1757,7 +1757,7 @@ SPEC CHECKSUMS:
|
|||||||
React-logger: 4072f39df335ca443932e0ccece41fbeb5ca8404
|
React-logger: 4072f39df335ca443932e0ccece41fbeb5ca8404
|
||||||
React-Mapbuffer: 714f2fae68edcabfc332b754e9fbaa8cfc68fdd4
|
React-Mapbuffer: 714f2fae68edcabfc332b754e9fbaa8cfc68fdd4
|
||||||
React-microtasksnativemodule: 4943ad8f99be8ccf5a63329fa7d269816609df9e
|
React-microtasksnativemodule: 4943ad8f99be8ccf5a63329fa7d269816609df9e
|
||||||
react-native-pubky: 1740252f1e510886c4239242d0b731bc4d96b91b
|
react-native-pubky: 1da8f3324a665ecf4495652efe0e67820a22f3a2
|
||||||
React-nativeconfig: 4a9543185905fe41014c06776bf126083795aed9
|
React-nativeconfig: 4a9543185905fe41014c06776bf126083795aed9
|
||||||
React-NativeModulesApple: 0506da59fc40d2e1e6e12a233db5e81c46face27
|
React-NativeModulesApple: 0506da59fc40d2e1e6e12a233db5e81c46face27
|
||||||
React-perflogger: 3bbb82f18e9ac29a1a6931568e99d6305ef4403b
|
React-perflogger: 3bbb82f18e9ac29a1a6931568e99d6305ef4403b
|
||||||
|
|||||||
@@ -14,6 +14,8 @@ import {
|
|||||||
list,
|
list,
|
||||||
generateSecretKey,
|
generateSecretKey,
|
||||||
getPublicKeyFromSecretKey,
|
getPublicKeyFromSecretKey,
|
||||||
|
decryptRecoveryFile,
|
||||||
|
createRecoveryFile,
|
||||||
} from '@synonymdev/react-native-pubky';
|
} from '@synonymdev/react-native-pubky';
|
||||||
|
|
||||||
const HOMESERVER = '8pinxxgqs41n4aididenw5apqp1urfmzdztr8jt4abrkdn435ewo';
|
const HOMESERVER = '8pinxxgqs41n4aididenw5apqp1urfmzdztr8jt4abrkdn435ewo';
|
||||||
@@ -268,6 +270,44 @@ export default function App() {
|
|||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
title={'Create Recovery File'}
|
||||||
|
onPress={async (): Promise<void> => {
|
||||||
|
try {
|
||||||
|
const res = await createRecoveryFile(
|
||||||
|
SECRET_KEY, // Secret Key
|
||||||
|
'passphrase' // Passphrase
|
||||||
|
);
|
||||||
|
if (res.isErr()) {
|
||||||
|
console.log(res.error.message);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console.log(res.value);
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
title={'Decrypt Recovery File'}
|
||||||
|
onPress={async (): Promise<void> => {
|
||||||
|
try {
|
||||||
|
const res = await decryptRecoveryFile(
|
||||||
|
'cHVia3kub3JnL3JlY292ZXJ5CkZRt1NHIjxyTo0whSSgTgNrH56MPpGrSxvAQSE0x5FeklVJpNJqcNP4zjdwW/OpdBOsEC1qZ5MI/mcEUKFKVAEZwikdclsLZg==', // Recovery File (base64 encoded)
|
||||||
|
'passphrase' // Passphrase
|
||||||
|
);
|
||||||
|
if (res.isErr()) {
|
||||||
|
console.log(res.error.message);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console.log(res.value);
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,22 @@
|
|||||||
<dict>
|
<dict>
|
||||||
<key>AvailableLibraries</key>
|
<key>AvailableLibraries</key>
|
||||||
<array>
|
<array>
|
||||||
|
<dict>
|
||||||
|
<key>BinaryPath</key>
|
||||||
|
<string>libpubkymobile.a</string>
|
||||||
|
<key>HeadersPath</key>
|
||||||
|
<string>Headers</string>
|
||||||
|
<key>LibraryIdentifier</key>
|
||||||
|
<string>ios-arm64</string>
|
||||||
|
<key>LibraryPath</key>
|
||||||
|
<string>libpubkymobile.a</string>
|
||||||
|
<key>SupportedArchitectures</key>
|
||||||
|
<array>
|
||||||
|
<string>arm64</string>
|
||||||
|
</array>
|
||||||
|
<key>SupportedPlatform</key>
|
||||||
|
<string>ios</string>
|
||||||
|
</dict>
|
||||||
<dict>
|
<dict>
|
||||||
<key>BinaryPath</key>
|
<key>BinaryPath</key>
|
||||||
<string>libpubkymobile.a</string>
|
<string>libpubkymobile.a</string>
|
||||||
@@ -22,22 +38,6 @@
|
|||||||
<key>SupportedPlatformVariant</key>
|
<key>SupportedPlatformVariant</key>
|
||||||
<string>simulator</string>
|
<string>simulator</string>
|
||||||
</dict>
|
</dict>
|
||||||
<dict>
|
|
||||||
<key>BinaryPath</key>
|
|
||||||
<string>libpubkymobile.a</string>
|
|
||||||
<key>HeadersPath</key>
|
|
||||||
<string>Headers</string>
|
|
||||||
<key>LibraryIdentifier</key>
|
|
||||||
<string>ios-arm64</string>
|
|
||||||
<key>LibraryPath</key>
|
|
||||||
<string>libpubkymobile.a</string>
|
|
||||||
<key>SupportedArchitectures</key>
|
|
||||||
<array>
|
|
||||||
<string>arm64</string>
|
|
||||||
</array>
|
|
||||||
<key>SupportedPlatform</key>
|
|
||||||
<string>ios</string>
|
|
||||||
</dict>
|
|
||||||
</array>
|
</array>
|
||||||
<key>CFBundlePackageType</key>
|
<key>CFBundlePackageType</key>
|
||||||
<string>XFWK</string>
|
<string>XFWK</string>
|
||||||
|
|||||||
@@ -65,6 +65,10 @@ typedef void (*UniFfiRustFutureContinuation)(void * _Nonnull, int8_t);
|
|||||||
// Scaffolding functions
|
// Scaffolding functions
|
||||||
RustBuffer uniffi_pubkymobile_fn_func_auth(RustBuffer url, RustBuffer secret_key, RustCallStatus *_Nonnull out_status
|
RustBuffer uniffi_pubkymobile_fn_func_auth(RustBuffer url, RustBuffer secret_key, RustCallStatus *_Nonnull out_status
|
||||||
);
|
);
|
||||||
|
RustBuffer uniffi_pubkymobile_fn_func_create_recovery_file(RustBuffer secret_key, RustBuffer passphrase, RustCallStatus *_Nonnull out_status
|
||||||
|
);
|
||||||
|
RustBuffer uniffi_pubkymobile_fn_func_decrypt_recovery_file(RustBuffer recovery_file, RustBuffer passphrase, RustCallStatus *_Nonnull out_status
|
||||||
|
);
|
||||||
RustBuffer uniffi_pubkymobile_fn_func_generate_secret_key(RustCallStatus *_Nonnull out_status
|
RustBuffer uniffi_pubkymobile_fn_func_generate_secret_key(RustCallStatus *_Nonnull out_status
|
||||||
|
|
||||||
);
|
);
|
||||||
@@ -208,6 +212,12 @@ void ffi_pubkymobile_rust_future_complete_void(void* _Nonnull handle, RustCallSt
|
|||||||
);
|
);
|
||||||
uint16_t uniffi_pubkymobile_checksum_func_auth(void
|
uint16_t uniffi_pubkymobile_checksum_func_auth(void
|
||||||
|
|
||||||
|
);
|
||||||
|
uint16_t uniffi_pubkymobile_checksum_func_create_recovery_file(void
|
||||||
|
|
||||||
|
);
|
||||||
|
uint16_t uniffi_pubkymobile_checksum_func_decrypt_recovery_file(void
|
||||||
|
|
||||||
);
|
);
|
||||||
uint16_t uniffi_pubkymobile_checksum_func_generate_secret_key(void
|
uint16_t uniffi_pubkymobile_checksum_func_generate_secret_key(void
|
||||||
|
|
||||||
|
|||||||
Binary file not shown.
@@ -65,6 +65,10 @@ typedef void (*UniFfiRustFutureContinuation)(void * _Nonnull, int8_t);
|
|||||||
// Scaffolding functions
|
// Scaffolding functions
|
||||||
RustBuffer uniffi_pubkymobile_fn_func_auth(RustBuffer url, RustBuffer secret_key, RustCallStatus *_Nonnull out_status
|
RustBuffer uniffi_pubkymobile_fn_func_auth(RustBuffer url, RustBuffer secret_key, RustCallStatus *_Nonnull out_status
|
||||||
);
|
);
|
||||||
|
RustBuffer uniffi_pubkymobile_fn_func_create_recovery_file(RustBuffer secret_key, RustBuffer passphrase, RustCallStatus *_Nonnull out_status
|
||||||
|
);
|
||||||
|
RustBuffer uniffi_pubkymobile_fn_func_decrypt_recovery_file(RustBuffer recovery_file, RustBuffer passphrase, RustCallStatus *_Nonnull out_status
|
||||||
|
);
|
||||||
RustBuffer uniffi_pubkymobile_fn_func_generate_secret_key(RustCallStatus *_Nonnull out_status
|
RustBuffer uniffi_pubkymobile_fn_func_generate_secret_key(RustCallStatus *_Nonnull out_status
|
||||||
|
|
||||||
);
|
);
|
||||||
@@ -208,6 +212,12 @@ void ffi_pubkymobile_rust_future_complete_void(void* _Nonnull handle, RustCallSt
|
|||||||
);
|
);
|
||||||
uint16_t uniffi_pubkymobile_checksum_func_auth(void
|
uint16_t uniffi_pubkymobile_checksum_func_auth(void
|
||||||
|
|
||||||
|
);
|
||||||
|
uint16_t uniffi_pubkymobile_checksum_func_create_recovery_file(void
|
||||||
|
|
||||||
|
);
|
||||||
|
uint16_t uniffi_pubkymobile_checksum_func_decrypt_recovery_file(void
|
||||||
|
|
||||||
);
|
);
|
||||||
uint16_t uniffi_pubkymobile_checksum_func_generate_secret_key(void
|
uint16_t uniffi_pubkymobile_checksum_func_generate_secret_key(void
|
||||||
|
|
||||||
|
|||||||
Binary file not shown.
10
ios/Pubky.mm
10
ios/Pubky.mm
@@ -64,6 +64,16 @@ RCT_EXTERN_METHOD(getPublicKeyFromSecretKey:(NSString *)secretKey
|
|||||||
withResolver:(RCTPromiseResolveBlock)resolve
|
withResolver:(RCTPromiseResolveBlock)resolve
|
||||||
withRejecter:(RCTPromiseRejectBlock)reject)
|
withRejecter:(RCTPromiseRejectBlock)reject)
|
||||||
|
|
||||||
|
RCT_EXTERN_METHOD(createRecoveryFile:(NSString *)secretKey
|
||||||
|
passphrase:(NSString *)passphrase
|
||||||
|
withResolver:(RCTPromiseResolveBlock)resolve
|
||||||
|
withRejecter:(RCTPromiseRejectBlock)reject)
|
||||||
|
|
||||||
|
RCT_EXTERN_METHOD(decryptRecoveryFile:(NSString *)recoveryFile
|
||||||
|
passphrase:(NSString *)passphrase
|
||||||
|
withResolver:(RCTPromiseResolveBlock)resolve
|
||||||
|
withRejecter:(RCTPromiseRejectBlock)reject)
|
||||||
|
|
||||||
+ (BOOL)requiresMainQueueSetup
|
+ (BOOL)requiresMainQueueSetup
|
||||||
{
|
{
|
||||||
return NO;
|
return NO;
|
||||||
|
|||||||
@@ -167,4 +167,24 @@ class Pubky: NSObject {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@objc(createRecoveryFile:passphrase:withResolver:withRejecter:)
|
||||||
|
func createRecoveryFile(_ secretKey: String, passphrase: String, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
||||||
|
do {
|
||||||
|
let result = react_native_pubky.createRecoveryFile(secretKey: secretKey, passphrase: passphrase)
|
||||||
|
resolve(result)
|
||||||
|
} catch {
|
||||||
|
reject("createRecoveryFile Error", "Failed to create recovery file", error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc(decryptRecoveryFile:passphrase:withResolver:withRejecter:)
|
||||||
|
func decryptRecoveryFile(_ recoveryFile: String, passphrase: String, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
||||||
|
do {
|
||||||
|
let result = react_native_pubky.decryptRecoveryFile(recoveryFile: recoveryFile, passphrase: passphrase)
|
||||||
|
resolve(result)
|
||||||
|
} catch {
|
||||||
|
reject("decryptRecoveryFile Error", "Failed to decrypt recovery file", error)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -367,6 +367,26 @@ public func auth(url: String, secretKey: String) -> [String] {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public func createRecoveryFile(secretKey: String, passphrase: String) -> [String] {
|
||||||
|
return try! FfiConverterSequenceString.lift(
|
||||||
|
try! rustCall() {
|
||||||
|
uniffi_pubkymobile_fn_func_create_recovery_file(
|
||||||
|
FfiConverterString.lower(secretKey),
|
||||||
|
FfiConverterString.lower(passphrase),$0)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
public func decryptRecoveryFile(recoveryFile: String, passphrase: String) -> [String] {
|
||||||
|
return try! FfiConverterSequenceString.lift(
|
||||||
|
try! rustCall() {
|
||||||
|
uniffi_pubkymobile_fn_func_decrypt_recovery_file(
|
||||||
|
FfiConverterString.lower(recoveryFile),
|
||||||
|
FfiConverterString.lower(passphrase),$0)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
public func generateSecretKey() -> [String] {
|
public func generateSecretKey() -> [String] {
|
||||||
return try! FfiConverterSequenceString.lift(
|
return try! FfiConverterSequenceString.lift(
|
||||||
try! rustCall() {
|
try! rustCall() {
|
||||||
@@ -507,6 +527,12 @@ private var initializationResult: InitializationResult {
|
|||||||
if (uniffi_pubkymobile_checksum_func_auth() != 61378) {
|
if (uniffi_pubkymobile_checksum_func_auth() != 61378) {
|
||||||
return InitializationResult.apiChecksumMismatch
|
return InitializationResult.apiChecksumMismatch
|
||||||
}
|
}
|
||||||
|
if (uniffi_pubkymobile_checksum_func_create_recovery_file() != 55903) {
|
||||||
|
return InitializationResult.apiChecksumMismatch
|
||||||
|
}
|
||||||
|
if (uniffi_pubkymobile_checksum_func_decrypt_recovery_file() != 59688) {
|
||||||
|
return InitializationResult.apiChecksumMismatch
|
||||||
|
}
|
||||||
if (uniffi_pubkymobile_checksum_func_generate_secret_key() != 63116) {
|
if (uniffi_pubkymobile_checksum_func_generate_secret_key() != 63116) {
|
||||||
return InitializationResult.apiChecksumMismatch
|
return InitializationResult.apiChecksumMismatch
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@synonymdev/react-native-pubky",
|
"name": "@synonymdev/react-native-pubky",
|
||||||
"version": "0.7.1",
|
"version": "0.8.0",
|
||||||
"description": "React Native Implementation of Pubky",
|
"description": "React Native Implementation of Pubky",
|
||||||
"source": "./src/index.tsx",
|
"source": "./src/index.tsx",
|
||||||
"main": "./lib/commonjs/index.js",
|
"main": "./lib/commonjs/index.js",
|
||||||
|
|||||||
@@ -478,3 +478,37 @@ pub fn parse_auth_url(url: String) -> Vec<String> {
|
|||||||
Err(error) => create_response_vector(true, error),
|
Err(error) => create_response_vector(true, error),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[uniffi::export]
|
||||||
|
pub fn create_recovery_file(secret_key: String, passphrase: String,) -> Vec<String> {
|
||||||
|
if secret_key.is_empty() || passphrase.is_empty() {
|
||||||
|
return create_response_vector(true, "Secret key and passphrase must not be empty".to_string());
|
||||||
|
}
|
||||||
|
let keypair = match get_keypair_from_secret_key(&secret_key) {
|
||||||
|
Ok(keypair) => keypair,
|
||||||
|
Err(error) => return create_response_vector(true, error),
|
||||||
|
};
|
||||||
|
let recovery_file_bytes = match PubkyClient::create_recovery_file(&keypair, &passphrase) {
|
||||||
|
Ok(bytes) => bytes,
|
||||||
|
Err(_) => return create_response_vector(true, "Failed to create recovery file".to_string()),
|
||||||
|
};
|
||||||
|
let recovery_file = base64::encode(&recovery_file_bytes);
|
||||||
|
create_response_vector(false, recovery_file)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[uniffi::export]
|
||||||
|
pub fn decrypt_recovery_file(recovery_file: String, passphrase: String) -> Vec<String> {
|
||||||
|
if recovery_file.is_empty() || passphrase.is_empty() {
|
||||||
|
return create_response_vector(true, "Recovery file and passphrase must not be empty".to_string());
|
||||||
|
}
|
||||||
|
let recovery_file_bytes = match base64::decode(&recovery_file) {
|
||||||
|
Ok(bytes) => bytes,
|
||||||
|
Err(error) => return create_response_vector(true, format!("Failed to decode recovery file: {}", error)),
|
||||||
|
};
|
||||||
|
let keypair = match PubkyClient::decrypt_recovery_file(&recovery_file_bytes, &passphrase) {
|
||||||
|
Ok(keypair) => keypair,
|
||||||
|
Err(error) => return create_response_vector(true, "Failed to decrypt recovery file".to_string()),
|
||||||
|
};
|
||||||
|
let secret_key = get_secret_key_from_keypair(&keypair);
|
||||||
|
create_response_vector(false, secret_key)
|
||||||
|
}
|
||||||
|
|||||||
@@ -44,41 +44,6 @@ static PUBKY_CLIENT: Lazy<Arc<PubkyClient>> = Lazy::new(|| {
|
|||||||
const HOMESERVER: &str = "pubky://8pinxxgqs41n4aididenw5apqp1urfmzdztr8jt4abrkdn435ewo";
|
const HOMESERVER: &str = "pubky://8pinxxgqs41n4aididenw5apqp1urfmzdztr8jt4abrkdn435ewo";
|
||||||
const SECRET_KEY: &str = "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855";
|
const SECRET_KEY: &str = "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855";
|
||||||
|
|
||||||
fn construct_pubky_url(public_key: &str, domain: &str, path_segments: &[&str]) -> String {
|
|
||||||
// Construct the base URL
|
|
||||||
let mut url = format!("pubky://{}/pub/{}", public_key, domain);
|
|
||||||
|
|
||||||
// Append each path segment, separated by '/'
|
|
||||||
for segment in path_segments {
|
|
||||||
if !segment.is_empty() {
|
|
||||||
url.push('/');
|
|
||||||
url.push_str(segment);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove trailing slash if present
|
|
||||||
if url.ends_with('/') {
|
|
||||||
url.pop();
|
|
||||||
}
|
|
||||||
|
|
||||||
url
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_list_url(full_url: &str) -> Option<String> {
|
|
||||||
if let Some(index) = full_url.find("pub/") {
|
|
||||||
// Add length of "pub/" to include it in the substring
|
|
||||||
let end_index = index + "pub/".len();
|
|
||||||
let substring = &full_url[..end_index];
|
|
||||||
Some(substring.to_string())
|
|
||||||
} else {
|
|
||||||
// "pub/" not found in the string
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
let sign_in_res = signin_or_signup(SECRET_KEY, HOMESERVER).await;
|
let sign_in_res = signin_or_signup(SECRET_KEY, HOMESERVER).await;
|
||||||
@@ -93,8 +58,46 @@ async fn main() {
|
|||||||
println!("Get Response: {:?}", get_res);
|
println!("Get Response: {:?}", get_res);
|
||||||
let list_res = list(url).await;
|
let list_res = list(url).await;
|
||||||
println!("List Response: {:?}", list_res);
|
println!("List Response: {:?}", list_res);
|
||||||
|
let create_response = create_recovery_file(&SECRET_KEY, "password");
|
||||||
|
println!("Create Response: {:?}", create_response);
|
||||||
|
let recovery_file = create_response[1].clone();
|
||||||
|
let decrypt_response = decrypt_recovery_file(&recovery_file, "password");
|
||||||
|
println!("Decrypt Response: {:?}", decrypt_response);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn create_recovery_file(secret_key: &str, passphrase: &str,) -> Vec<String> {
|
||||||
|
if secret_key.is_empty() || passphrase.is_empty() {
|
||||||
|
return create_response_vector(true, "Secret key and passphrase must not be empty".to_string());
|
||||||
|
}
|
||||||
|
let keypair = match get_keypair_from_secret_key(&secret_key) {
|
||||||
|
Ok(keypair) => keypair,
|
||||||
|
Err(error) => return create_response_vector(true, error),
|
||||||
|
};
|
||||||
|
let recovery_file_bytes = match PubkyClient::create_recovery_file(&keypair, &passphrase) {
|
||||||
|
Ok(bytes) => bytes,
|
||||||
|
Err(_) => return create_response_vector(true, "Failed to create recovery file".to_string()),
|
||||||
|
};
|
||||||
|
let recovery_file = base64::encode(&recovery_file_bytes);
|
||||||
|
create_response_vector(false, recovery_file)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn decrypt_recovery_file(recovery_file: &str, passphrase: &str) -> Vec<String> {
|
||||||
|
if recovery_file.is_empty() || passphrase.is_empty() {
|
||||||
|
return create_response_vector(true, "Recovery file and passphrase must not be empty".to_string());
|
||||||
|
}
|
||||||
|
let recovery_file_bytes = match base64::decode(&recovery_file) {
|
||||||
|
Ok(bytes) => bytes,
|
||||||
|
Err(error) => return create_response_vector(true, format!("Failed to decode recovery file: {}", error)),
|
||||||
|
};
|
||||||
|
let keypair = match PubkyClient::decrypt_recovery_file(&recovery_file_bytes, &passphrase) {
|
||||||
|
Ok(keypair) => keypair,
|
||||||
|
Err(error) => return create_response_vector(true, "Failed to decrypt recovery file".to_string()),
|
||||||
|
};
|
||||||
|
let secret_key = get_secret_key_from_keypair(&keypair);
|
||||||
|
create_response_vector(false, secret_key)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
pub async fn signin_or_signup(secret_key: &str, homeserver: &str) -> Vec<String> {
|
pub async fn signin_or_signup(secret_key: &str, homeserver: &str) -> Vec<String> {
|
||||||
let sign_in_res = sign_in(secret_key).await;
|
let sign_in_res = sign_in(secret_key).await;
|
||||||
if sign_in_res[0] == "success" {
|
if sign_in_res[0] == "success" {
|
||||||
@@ -280,3 +283,39 @@ pub async fn list(url: String) -> Vec<String> {
|
|||||||
};
|
};
|
||||||
create_response_vector(false, json_string)
|
create_response_vector(false, json_string)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn construct_pubky_url(public_key: &str, domain: &str, path_segments: &[&str]) -> String {
|
||||||
|
// Construct the base URL
|
||||||
|
let mut url = format!("pubky://{}/pub/{}", public_key, domain);
|
||||||
|
|
||||||
|
// Append each path segment, separated by '/'
|
||||||
|
for segment in path_segments {
|
||||||
|
if !segment.is_empty() {
|
||||||
|
url.push('/');
|
||||||
|
url.push_str(segment);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove trailing slash if present
|
||||||
|
if url.ends_with('/') {
|
||||||
|
url.pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
url
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_list_url(full_url: &str) -> Option<String> {
|
||||||
|
if let Some(index) = full_url.find("pub/") {
|
||||||
|
// Add length of "pub/" to include it in the substring
|
||||||
|
let end_index = index + "pub/".len();
|
||||||
|
let substring = &full_url[..end_index];
|
||||||
|
Some(substring.to_string())
|
||||||
|
} else {
|
||||||
|
// "pub/" not found in the string
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_secret_key_from_keypair(keypair: &Keypair) -> String {
|
||||||
|
hex::encode(keypair.secret_key())
|
||||||
|
}
|
||||||
|
|||||||
@@ -257,3 +257,33 @@ export async function getPublicKeyFromSecretKey(
|
|||||||
return err(JSON.stringify(e));
|
return err(JSON.stringify(e));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function createRecoveryFile(
|
||||||
|
secretKey: string,
|
||||||
|
passphrase: string
|
||||||
|
): Promise<Result<string>> {
|
||||||
|
try {
|
||||||
|
const res = await Pubky.createRecoveryFile(secretKey, passphrase);
|
||||||
|
if (res[0] === 'error') {
|
||||||
|
return err(res[1]);
|
||||||
|
}
|
||||||
|
return ok(res[1]);
|
||||||
|
} catch (e) {
|
||||||
|
return err(JSON.stringify(e));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function decryptRecoveryFile(
|
||||||
|
recoveryFile: string,
|
||||||
|
passphrase: string
|
||||||
|
): Promise<Result<string>> {
|
||||||
|
try {
|
||||||
|
const res = await Pubky.decryptRecoveryFile(recoveryFile, passphrase);
|
||||||
|
if (res[0] === 'error') {
|
||||||
|
return err(res[1]);
|
||||||
|
}
|
||||||
|
return ok(res[1]);
|
||||||
|
} catch (e) {
|
||||||
|
return err(JSON.stringify(e));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user