url_signer.py 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253
  1. import base64
  2. import hashlib
  3. import hmac
  4. import os
  5. import time
  6. from pydantic import BaseModel, Field
  7. from configs import dify_config
  8. class SignedUrlParams(BaseModel):
  9. sign_key: str = Field(..., description="The sign key")
  10. timestamp: str = Field(..., description="Timestamp")
  11. nonce: str = Field(..., description="Nonce")
  12. sign: str = Field(..., description="Signature")
  13. class UrlSigner:
  14. @classmethod
  15. def get_signed_url(cls, url: str, sign_key: str, prefix: str) -> str:
  16. signed_url_params = cls.get_signed_url_params(sign_key, prefix)
  17. return (
  18. f"{url}?timestamp={signed_url_params.timestamp}"
  19. f"&nonce={signed_url_params.nonce}&sign={signed_url_params.sign}"
  20. )
  21. @classmethod
  22. def get_signed_url_params(cls, sign_key: str, prefix: str) -> SignedUrlParams:
  23. timestamp = str(int(time.time()))
  24. nonce = os.urandom(16).hex()
  25. sign = cls._sign(sign_key, timestamp, nonce, prefix)
  26. return SignedUrlParams(sign_key=sign_key, timestamp=timestamp, nonce=nonce, sign=sign)
  27. @classmethod
  28. def verify(cls, sign_key: str, timestamp: str, nonce: str, sign: str, prefix: str) -> bool:
  29. recalculated_sign = cls._sign(sign_key, timestamp, nonce, prefix)
  30. return sign == recalculated_sign
  31. @classmethod
  32. def _sign(cls, sign_key: str, timestamp: str, nonce: str, prefix: str) -> str:
  33. if not dify_config.SECRET_KEY:
  34. raise Exception("SECRET_KEY is not set")
  35. data_to_sign = f"{prefix}|{sign_key}|{timestamp}|{nonce}"
  36. secret_key = dify_config.SECRET_KEY.encode()
  37. sign = hmac.new(secret_key, data_to_sign.encode(), hashlib.sha256).digest()
  38. encoded_sign = base64.urlsafe_b64encode(sign).decode()
  39. return encoded_sign