signature.rs 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  1. use std::process;
  2. use base64; // https://crates.io/crates/base64
  3. use hex::{self, FromHexError}; // https://crates.io/crates/hex
  4. use hmac::{Hmac, Mac, NewMac}; // https://crates.io/crates/hmac
  5. use sha2::Sha256; // https://crates.io/crates/sha2
  6. type HmacSha256 = Hmac<Sha256>;
  7. const KEY: &'static str = "943b421c9eb07c830af81030552c86009268de4e532ba2ee2eab8247c6da0881";
  8. const SALT: &'static str = "520f986b998545b4785e0defbc4f3c1203f22de2374a3d53cb7a7fe9fea309c5";
  9. pub struct Image {
  10. pub src: &'static str,
  11. pub width: usize,
  12. pub height: usize,
  13. pub dpr: u8,
  14. pub ext: &'static str,
  15. }
  16. #[derive(Debug)]
  17. pub enum Error {
  18. InvalidKey(FromHexError),
  19. InvalidSalt(FromHexError),
  20. }
  21. fn main() {
  22. let img = Image {
  23. src: "http://img.example.com/pretty/image.jpg",
  24. width: 100,
  25. height: 80,
  26. dpr: 2,
  27. ext: "webp",
  28. };
  29. match sign_url(img) {
  30. Ok(url) => {
  31. println!("{}", url);
  32. process::exit(0);
  33. }
  34. Err(err) => {
  35. eprintln!("{:#?}", err);
  36. process::exit(1);
  37. }
  38. }
  39. }
  40. pub fn sign_url(img: Image) -> Result<String, Error> {
  41. let url = format!(
  42. "/rs:{resize_type}:{width}:{height}:{enlarge}:{extend}/dpr:{dpr}/{src}.{ext}",
  43. resize_type = "auto",
  44. width = img.width,
  45. height = img.height,
  46. enlarge = 0,
  47. extend = 0,
  48. dpr = img.dpr,
  49. src = base64::encode_config(img.src.as_bytes(), base64::URL_SAFE_NO_PAD),
  50. ext = img.ext,
  51. );
  52. let decoded_key = match hex::decode(KEY) {
  53. Ok(key) => key,
  54. Err(err) => return Err(Error::InvalidKey(err)),
  55. };
  56. let decoded_salt = match hex::decode(SALT) {
  57. Ok(salt) => salt,
  58. Err(err) => return Err(Error::InvalidSalt(err)),
  59. };
  60. let mut hmac = HmacSha256::new_varkey(&decoded_key).unwrap();
  61. hmac.update(&decoded_salt);
  62. hmac.update(url.as_bytes());
  63. let signature = hmac.finalize().into_bytes();
  64. let signature = base64::encode_config(signature.as_slice(), base64::URL_SAFE_NO_PAD);
  65. let signed_url = format!("/{signature}{url}", signature = signature, url = url);
  66. Ok(signed_url)
  67. }