use anyhow::anyhow; use base64::Engine; use rsa::{pkcs8::DecodePublicKey, signature::Verifier}; use sha2::Sha256; pub async fn validate_license_key(license_key: String) -> anyhow::Result { let mut splitted_lk = license_key.split("."); if splitted_lk.clone().count() != 3 { return Err(anyhow!( "license_key can be splitted with 2 . (..)" )); } let id = splitted_lk.next().unwrap(); let expiry = splitted_lk.next().unwrap(); let signature_b64 = splitted_lk.next().unwrap(); const PUBLIC_KEY: &str = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDgVShzcLSPiOi+8ET8fggob1kmi47/cE12JaidPkwfGnScZItghkqtiLsct0U4kJhlp5gO89DYTBmIKadvxwY7kMsLlZzmi2emVH7c27cByGASY8QmWDNdG4Ggy/NDflGGBdAtN6gHawZAg4zHv3qpbPQGHH1/6sXIohcXhOnouwIDAQAB"; let pub_key = rsa::RsaPublicKey::from_public_key_der( &base64::engine::general_purpose::STANDARD.decode(PUBLIC_KEY)?, )?; let signature = base64::engine::general_purpose::STANDARD.decode(signature_b64)?; rsa::pss::VerifyingKey::::new(pub_key) .verify( &format!("{id}{expiry}").as_bytes(), &rsa::pss::Signature::from(signature), ) .map_err(|_| anyhow::anyhow!("Invalid license key".to_string()))?; let expiry_nb = expiry.parse::()?; if expiry_nb < chrono::Utc::now().timestamp() as u64 { tracing::error!( "License key expired: {} < {}", expiry_nb, chrono::Utc::now().timestamp() as u64 ); return Err(anyhow!("License key expired".to_string())); }; Ok(id.to_string()) }