I'm a beginner in Rust and I'm facing an issue with the RSA crate in Rust.
I'm trying to verify a signature. My code is as simple as :
use rsa::{RsaPublicKey};
use rsa::pkcs8::DecodePublicKey;
fn main() {
let pem = "-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtsQsUV8QpqrygsY+2+JC
Q6Fw8/omM71IM2N/R8pPbzbgOl0p78MZGsgPOQ2HSznjD0FPzsH8oO2B5Uftws04
LHb2HJAYlz25+lN5cqfHAfa3fgmC38FfwBkn7l582UtPWZ/wcBOnyCgb3yLcvJrX
yrt8QxHJgvWO23ITrUVYszImbXQ67YGS0YhMrbixRzmo2tpm3JcIBtnHrEUMsT0N
fFdfsZhTT8YbxBvA8FdODgEwx7u/vf3J9qbi4+Kv8cvqyJuleIRSjVXPsIMnoejI
n04APPKIjpMyQdnWlby7rNyQtE4+CV+jcFjqJbE/Xilcvqxt6DirjFCvYeKYl1uH
LwIDAQAB
-----END PUBLIC KEY-----";
let _public_key = RsaPublicKey::from_public_key_pem(pem).unwrap();
}
However I'm getting an error saying that :
---- tests::add_public_key_verif stdout ----
thread 'tests::add_public_key_verif' panicked at 'called `Result::unwrap()` on an `Err` value: Asn1(Error { kind: Pem(PostEncapsulationBoundary), position: None })', src/lib.rs:136:40
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
In cargo.toml, I have :
[package]
name = "hello_cargo"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
rsa ="0.6.1"
The issue seams to come from the public key generation from the PEM.
Do you know a solution for fix this issue ?
The indentation is the problem here. The whitespace at the beginning of the line is part of the string value, but that's not valid PEM encoding. To fix it, remove the leading whitespace:
fn main() {
let pem = "-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtsQsUV8QpqrygsY+2+JC
Q6Fw8/omM71IM2N/R8pPbzbgOl0p78MZGsgPOQ2HSznjD0FPzsH8oO2B5Uftws04
LHb2HJAYlz25+lN5cqfHAfa3fgmC38FfwBkn7l582UtPWZ/wcBOnyCgb3yLcvJrX
yrt8QxHJgvWO23ITrUVYszImbXQ67YGS0YhMrbixRzmo2tpm3JcIBtnHrEUMsT0N
fFdfsZhTT8YbxBvA8FdODgEwx7u/vf3J9qbi4+Kv8cvqyJuleIRSjVXPsIMnoejI
n04APPKIjpMyQdnWlby7rNyQtE4+CV+jcFjqJbE/Xilcvqxt6DirjFCvYeKYl1uH
LwIDAQAB
-----END PUBLIC KEY-----";
let _public_key = RsaPublicKey::from_public_key_pem(pem).unwrap();
}
Alternatively, consider putting the PEM key data in a separate file and using the include_str! macro to load it into a variable. This keeps the key data separate from the program logic as well as making the indentation issue irrelevant. (Note that this happens at compile time; there is no runtime overhead to this approach.)
Related
I am trying to understand the solana/example-helloworld by re-writing the rust lib myself. I have done this and from the package.json file, to generate the .so file, following is what is run:
cargo build-bpf --manifest-path=./src/program-rust/Cargo.toml --bpf-out-dir=dist/program
I used above since I already have cargo setup locally and run above against my setup, I faced a few issues, from the edition (was using 2021, had to downgrade to 2018) to having to rename main.rs to lib.rs and others I can't remember.
Below is my actual running command from the terminal in the project root directory where the Cargo.toml file is in:
cargo build-bpf --manifest-path=./Cargo.toml --bpf-out-dir=dist/program
But upon running above, in the dist directory, there is nothing
This is actually a multi-tied question:
.so file are signifies solana files, right?
What do we mean by cargo build-bpf?
Is there any reason, why 2021 edition didn't work for the solana example?
Finally, why does the above command not output my .so file?
My Cargo.toml below:
[package]
name = "jjoek-sc"
version = "0.0.1"
description = "My first rust program for solana (hello john)"
authors = ["JJoek <info#jjoek.com>"]
license = "Apache-2.0"
homepage = "https://jjoek.com/"
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
borsh = "0.9.1"
borsh-derive = "0.9.1"
solana-program = "~1.8.14"
Below is my lib.rs
use borsh::{BorshDeserialize, BorshSerialize};
use solana_program::{
account_info::{next_account_info, AccountInfo},
entrypoint,
entrypoint::ProgramResult,
pubkey::Pubkey,
msg,
program_error::ProgramError,
};
/// Define the type of state stored in accounts
#[derive(BorshSerialize, BorshDeserialize, Debug)]
pub struct GreetingAccount {
/// number of greetings
pub counter: u32,
}
// Declare and export the program's entrypoint
entrypoint!(process_instruction);
// Program entrypoint's implementation
pub fn process_instruction(program_id: &Pubkey, accounts: &[AccountInfo], _instruction_data: &[u8]) -> ProgramResult {
msg!("Hello, John everything is gonna be okay");
msg!("Hello World Rust program entrypoint");
// Iterating accounts is safer than indexing
let accounts_iter = &mut accounts.iter();
// Get the account to say hello to
let account = next_account_info(accounts_iter)?;
// The account must be owned by the program in order to modify its data
if account.owner != program_id {
msg!("Greeted account does not have the correct program id");
return Err(ProgramError::IncorrectProgramId);
}
// Increment and store the number of times the account has been greeted
let mut greeting_account = GreetingAccount::try_from_slice(&account.data.borrow())?;
greeting_account.counter += 1;
greeting_account.serialize(&mut &mut account.data.borrow_mut()[..])?;
msg!("Greeted {} time(s)!", greeting_account.counter);
Ok(())
}
.so file are signifies solana files, right?
so stand for shared object, also known as a dynamically relocatable library or dylib in Cargo.toml.
What do we mean by cargo build-bpf?
BPF is a virtual machine inside the kernel, so this should instruct cargo to build for that target.
Is there any reason, why 2021 edition didn't work for the solana example?
I don't know, but I suspect it's a simple fix.
Finally, why does the above command not output my .so file?
Could it be that you are missing the lib section in Cargo.toml:
[lib]
crate-type = ["cdylib", "lib"]
I want to have a static Uuid in my Rust program but I am unable to figure out how to do it.
I tried this but it does not work
fn type_id() -> &'static uuid::Uuid {
let tmp = "9cb4cf49-5c3d-4647-83b0-8f3515da7be1".as_bytes();
let tmp = uuid::Uuid::from_slice(tmp).unwrap();
&tmp
}
error: cannot return reference to local variable `tmp`
returns a reference to data owned by the current function (rustc E0515)
Assuming you're using the uuid crate, several of the "constructor" functions are const. So you can just call them "normally" to initialise your static (which is a const context).
Sadly the playground doesn't have uuid but I figure something along the lines of:
static TYPE_ID: Uuid = Uuid::from_u128(0x9cb4cf49_5c3d_4647_83b0_8f3515da7be1);
or using the hex_literal crate if you prefer something more string-looking:
static TYPE_ID: Uuid = Uuid::from_bytes(hex!("9cb4cf49 5c3d 4647 83b0 8f3515da7be1"));
Thanks #PitaJ. Using once_cell:Lazy works. I am still curious to know if there is a simpler way of doing this so I won't mark the answer as accepted yet.
static TYPE_ID: Lazy<uuid::Uuid> = Lazy::new(|| {
let tmp = "9cb4cf49-5c3d-4647-83b0-8f3515da7be1";
let tmp = uuid::Uuid::from_str(tmp).unwrap();
tmp
});
Do you know how to parse xsd file into Rust structs using https://github.com/lumeohq/xsd-parser-rs?
I do not know how to run the program and how to put files there.
Here's a basic example that parses a file sample.xsd and then prints out the debug representation of the parsed result:
src/main.rs:
use anyhow::{format_err, Result};
use std::fs;
use xsd_parser::parser::parse as xsd_parse;
fn main() -> Result<()> {
let sample = fs::read_to_string("sample.xsd")?;
let parsed = xsd_parse(&sample).map_err(|_| format_err!("failed to parse XSD file"))?;
println!("{:#?}", &parsed);
Ok(())
}
Cargo.toml:
[package]
name = "xsd-demo"
version = "0.1.0"
edition = "2021"
[dependencies]
anyhow = "1"
xsd-parser = { git = "https://github.com/lumeohq/xsd-parser-rs", rev = "7f3d433e4f033b55f057e97c0a30de221dbe3ae1" }
sample.xsd:
I used the sample XSD file from here.
From the project folder, you can invoke rustdoc like cargo doc -p xsd-parser --no-deps --open to generate and open the API docs for the xsd-parser crate, which is what allowed me to figure out how to use the crate.
I'm learning rust, and the best way to learn a programming language is obviously reading and understanding other's code. Now I faced this line I am not able to understand even after reading docs, other source files and googling for it :
In zoxide's main file, there's this line :
if let Err(e) = App::parse().run() { ... }
What does App::parse() mean ? App is a structure and not a variable, so I understand why it's not .parse(), but why ::parse() and what does it do ? (I couldn't find its definition in app's source code (nor in this file))
First, both the files you mentioned are not the App that zoxide is including. zoxide's main.rs file says use crate::app::{App, Run};, so it's including App from src/app/mod.rs, which exports App from src/app/_app.rs
In that file, we can see the declaration of App:
#[derive(Debug, Clap)]
#[clap(
bin_name = env!("CARGO_PKG_NAME"),
about,
author,
after_help = ENV_HELP,
global_setting(AppSettings::ColoredHelp),
global_setting(AppSettings::DisableHelpSubcommand),
global_setting(AppSettings::DisableVersionForSubcommands),
global_setting(AppSettings::PropagateVersion),
version = option_env!("ZOXIDE_VERSION").unwrap_or_default()
)]
pub enum App {
Add(Add),
Import(Import),
Init(Init),
Query(Query),
Remove(Remove),
}
The key in this case is #[derive(Clap)]. If you look at the clap crate you'll see that it's a crate for parsing command line parameters, and deriving from Clap adds a parse method to the structure.
I have this code:
use schnorrkel;
use schnorrkel::{
derive::{ChainCode, Derivation, CHAIN_CODE_LENGTH},
signing_context, Keypair, MiniSecretKey, PublicKey, SecretKey,
};
use substrate_primitives::crypto::Pair as PairT;
use substrate_primitives::sr25519;
use substrate_primitives::sr25519::Pair;
fn main() {
let keypair = sr25519::Pair::generate();
let private_key = keypair.somehow_get_the_private_key_func();
}
I tried to use the SecretKey trait (imported at the beginning), but it says SecretKey is private, so the only way I am thinking of is to modify Substrate's sources to add a function that gives me the private key, but I don't want to do it by source code alteration.
What would be the way to go?
What do you actually need to do? You shouldn't be getting a private key in the runtime at all.
If you want to sign something in your runtime, there are helper functions that will sign a message, if you just pass in the public key, with its corresponding private key.
https://substrate.dev/rustdocs/master/sp_io/crypto/fn.sr25519_sign.html
testing: https://substrate.dev/rustdocs/master/sp_core/testing/struct.KeyStore.html