One of the great shortcomings of using IPFS and many other blockchains is that uploaded files/data are available to everyone worldwide. Privacy on the blockchain is a big deal for the decentralization of personal and corporate data as more people and companies are trying to adopt blockchain. Keeping private RSA keys on a centralized server is giving your data ownership to that centralized entity, but it is also a failure point. Therefore, there is much work on Zero Knowledge Proofs and data encryption on the blockchain. As millions of people have adopted HD wallets, I believe the data encryption keys can be generated using that technology to ease the adoption of data encryption on the blockchain.
HD Wallets
One of the most important aspects of blockchains is the use of keys (public and private) to authenticate actions, resources, and users. Making a small comparison with web2, the public address is similar to your email address or your username that you can share with anyone, and the private key is similar to your password.
To generate these keys, we will use a seed that will be created on the basis of a strong password composed of 12 or 24 words called a “mnemonic phrase”. With this phrase, we can generate as many deterministic keys as we want that we can use on blockchains to be authenticated and to sign transactions: they are called HD keys.
To always get the same keys on a specific blockchain, we use BIP 44 derivation path structure standard: m / purpose’ / coin_type’ / account’ / change / index
For Bitcoin, for example, we use m/44’/0’/0’/0/0/0 and m/60’/0′ for Ethereum. Here is a list of some blockchain derivations paths https://support.atomicwalle t.io/article/146-list-of-derivation-paths.
Deterministic RSA keys
RSA encryption keys are used by many people on the Internet. Still, they are not often used deterministically: for example the use of SSL in the HTTPS protocol and many others protocols like the use of RSA keys to secure SSH communication with servers.
Generation of deterministic keys in RUST
Let’s start by creating a new project
$ cargo new deter-rsa
Let’s add the “rsa” and “bip32” library to the project: the “rsa” library is used to generate encryption keys and asymmetric decryptions and the “bip32” library is used to generate the HD wallet.
$ cargo add rsa bip32
Let’s start with the generation of the mnemonic:
use rand_core::OsRng;
use bip32::{Mnemonic};
fn main() {
println!("The generated mnemonic is \"{}\"", generate_mnemonic());
}
fn generate_mnemonic() -> String {
let mnemonic = Mnemonic::random(&mut OsRng, Default::default());
mnemonic.phrase().to_string()
}

After generating the mnemonic, we can generate the extensible BIP32 private key that will allow us to generate the RSA private key.
use bip32::{Mnemonic, XPrv};
// Other instructions ...
fn generate_bip_private_key(mnemo : Mnemonic) -> XPrv {
let seed = mnemo.to_seed("");
XPrv::new(&seed).unwrap()
}
We will add a function to find the “chain_code” of this private key that we will use to generate a pseudo random number with the “rng_chacha” library that will allow us to have a “seed”.
After generating the seed, we can easily have the RSA key which is based on our mnemonic.
use bip32::{Mnemonic, XPrv, ExtendedPrivateKey, secp256k1::ecdsa::SigningKey};
use rsa::{RsaPrivateKey};
use rand_chacha::ChaCha8Rng;
// Other instructions
fn generate_rsa_private_key(xprv : ExtendedPrivateKey<SigningKey>) -> RsaPrivateKey {
let priv_attrs = xprv.attrs();
let chain_code : [u8; 32] = priv_attrs.chain_code;
let mut seed = ChaCha8Rng::from_seed(chain_code);
RsaPrivateKey::new(&mut seed, 256).unwrap()
}
We will now refactor the main function to use all these functions:
fn main() {
let mnemo = generate_mnemonic();
let bip_xprv = generate_bip_private_key(mnemo);
let rsa_priv_key = generate_rsa_private_key(bip_xprv);
println!("The generated private key is \"{:?}\"", rsa_priv_key);
}
After doing this refactoring, we will enter a mnemonic parameter and try to get the same RSA private key. This is an easy task to do, we will have to add a function named “get_mnemonic” function that accept the mnemonic phrase. Since we can enter a valid or invalid mnemonic, we will return “Result<Mnemonic, String>” in order to handle errors.
To allow visualization of the RSA key, we will use the “pkcs8” library contained in the “rsa” library that I used in one of my previous articles. You can read it by clicking here.
//Other instructions
use rsa::pkcs8::{EncodePrivateKey,LineEnding};
fn main() {
let mnemo = generate_mnemonic();
let bip_xprv = generate_bip_private_key(mnemo);
let rsa_priv_key = generate_rsa_private_key(bip_xprv);
let str_rsa_priv_key = rsa_priv_key.to_pkcs8_pem(LineEnding::default()).unwrap().to_string();
println!("The generated private key is \"{}\"", str_rsa_priv_key);
}

We can now generate a mnemonic that we will test. After running the program, we get the mnemonic « post focus sail learn artwork sketch fade bridge debris doctor labor labor denial verb arm recycle clever attend share bulb vivid clown table lens ». Here Is the RSA the encryption key we get:
-----BEGIN PRIVATE KEY-----
MIHDAgEAMA0GCSqGSIb3DQEBAQUABIGuMIGrAgEAAiEA31nzuW9zjGHR3i8yjfQe
aTrYycVC/+pOMsoJR8QRze0CAwEAAQIhAKDPkS3IUveWTpacgNe4FlPxUz1Wt6/2
qkKqjsv5TCU5AhEA8YmVnQgxPgwSYL8KtWQ1mwIRAOy5mhPpZBh7UvtalmxJRxcC
EACxYFh++YUwC61zXth+XRkCEQDfOgY5UJS7IVAXBk1iv5bxAhAC2ctQKPVWRkMS
x0ZrQ940
-----END PRIVATE KEY-----
After this, I entered the mnemonic generated before using “generate_mnemonic” in the “get_mnemonic” function and I got the same result meaning the RSA key is deterministically generated.
fn main() {
let mnemo = get_mnemonic("post focus sail learn artwork sketch fade bridge debris doctor labor labor denial verb arm recycle clever attend share bulb vivid clown table lens").expect("The mnemonic is invalid");
let bip_xprv = generate_bip_private_key(mnemo);
let rsa_priv_key = generate_rsa_private_key(bip_xprv);
let str_rsa_priv_key = rsa_priv_key.to_pkcs8_pem(LineEnding::default()).unwrap().to_string();
println!("The generated private key is \"{}\"", str_rsa_priv_key);
}
Conclusion :
Thanks to the deterministic encryption keys using the mnemonic of the HD Wallet, it is possible to keep your private files in the same wallet as your cryptocurrencies, the goal of a project I am working on.
The IPFS protocol could benefit from this since many people have now adopted HD wallets in their daily lives.
