use openssl::rsa::Rsa;
use openssl::pkey::PKey;
use std::str;
use base64::Engine;
use base64::engine::general_purpose::URL_SAFE_NO_PAD;
use openssl::hash::MessageDigest;
use openssl::pkey_ctx::PkeyCtx;
use openssl::sign::{Signer, Verifier};
use crate::base64::{decode_u8, encode_file};
pub fn create_pkey_pkcs8() -> (String, String) {
let rsa = Rsa::generate(2048).unwrap();
let pkey = PKey::from_rsa(rsa.clone()).unwrap();
let pub_key: Vec<u8> = pkey.public_key_to_pem().unwrap();
let pri_key: Vec<u8> = pkey.private_key_to_pem_pkcs8().unwrap();
(str::from_utf8(pub_key.as_slice()).unwrap().to_string(), str::from_utf8(pri_key.as_slice()).unwrap().to_string())
}
pub fn pri_key_sign(pri_key: &str, content: &str, types: &str) -> String {
match types {
"RS256"=>{
let key = PKey::private_key_from_pem(pri_key.as_bytes()).unwrap();
let mut signer = Signer::new(MessageDigest::sha256(), &key).unwrap();
signer.update(content.as_bytes()).unwrap();
let signature = signer.sign_to_vec().unwrap();
URL_SAFE_NO_PAD.encode(signature)
}
_ => {
let r = PKey::private_key_from_pem(pri_key.as_bytes()).unwrap();
let mut ctx = PkeyCtx::new(&r).unwrap();
ctx.sign_init().unwrap();
let mut signature = vec![];
ctx.sign_to_vec(content.as_bytes(), &mut signature).unwrap();
encode_file(signature)
}
}
}
pub fn pub_key_verify(pub_key: String, content: &str, signature: String,types:&str) -> bool {
match types {
"RS256" => {
let pkey = PKey::public_key_from_pem(pub_key.as_bytes())
.expect("invalid public key");
let signature_bytes = match URL_SAFE_NO_PAD.decode(signature) {
Ok(sig) => sig,
Err(_) => return false, };
let mut verifier = Verifier::new(MessageDigest::sha256(), &pkey).expect("verifier init failed");
verifier.update(content.as_bytes()).expect("verifier update failed");
verifier.verify(&signature_bytes).unwrap_or(false)
}
_ => {
let pkey = PKey::public_key_from_pem(pub_key.as_bytes()).unwrap();
let mut ctx = PkeyCtx::new(&pkey).unwrap();
ctx.verify_init().unwrap();
let signature = decode_u8(signature);
ctx.verify(content.as_bytes(), signature.as_slice()).unwrap()
}
}
}
pub fn encrypt(pub_key: String, content: &str) -> String {
let r = PKey::public_key_from_pem(pub_key.as_bytes()).unwrap();
let mut ctx = PkeyCtx::new(&r).unwrap();
ctx.encrypt_init().unwrap();
let mut ciphertext = vec![];
ctx.encrypt_to_vec(content.as_bytes(), &mut ciphertext).unwrap();
encode_file(ciphertext)
}
pub fn decrypt(pri_key: String, signature: String) -> String {
let r = PKey::private_key_from_pem(pri_key.as_bytes()).unwrap();
let mut ctx = PkeyCtx::new(&r).unwrap();
ctx.decrypt_init().unwrap();
let from = decode_u8(signature);
let mut data = vec![];
ctx.decrypt_to_vec(from.as_ref(), &mut data).unwrap();
str::from_utf8(data.as_slice()).unwrap().to_string()
}