1
0

encrypted_source_url.go 1.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061
  1. package examples
  2. import (
  3. "bytes"
  4. "crypto/aes"
  5. "crypto/cipher"
  6. "crypto/rand"
  7. "encoding/base64"
  8. "encoding/hex"
  9. "fmt"
  10. "io"
  11. "log"
  12. )
  13. func pkcs7pad(data []byte, blockSize int) []byte {
  14. padLen := blockSize - len(data)%blockSize
  15. padding := bytes.Repeat([]byte{byte(padLen)}, padLen)
  16. return append(data, padding...)
  17. }
  18. func ExcryptSourceURL() {
  19. key := "1eb5b0e971ad7f45324c1bb15c947cb207c43152fa5c6c7f35c4f36e0c18e0f1"
  20. var (
  21. keyBin []byte
  22. err error
  23. )
  24. if keyBin, err = hex.DecodeString(key); err != nil {
  25. log.Fatal("Key expected to be hex-encoded string")
  26. }
  27. url := "http://img.example.com/pretty/image.jpg"
  28. c, err := aes.NewCipher(keyBin)
  29. if err != nil {
  30. log.Fatal(err)
  31. }
  32. data := pkcs7pad([]byte(url), aes.BlockSize)
  33. ciphertext := make([]byte, aes.BlockSize+len(data))
  34. iv := ciphertext[:aes.BlockSize]
  35. // We use a random iv generation, but you'll probably want to use some
  36. // deterministic method
  37. if _, err = io.ReadFull(rand.Reader, iv); err != nil {
  38. log.Fatal(err)
  39. }
  40. mode := cipher.NewCBCEncrypter(c, iv)
  41. mode.CryptBlocks(ciphertext[aes.BlockSize:], data)
  42. encryptedURL := base64.RawURLEncoding.EncodeToString(ciphertext)
  43. // We don't sign the URL in this example but it is highly recommended to sign
  44. // imgproxy URLs when imgproxy is being used in production.
  45. // Signing URLs is especially important when using encrypted source URLs to
  46. // prevent a padding oracle attack
  47. fmt.Printf("/unsafe/rs:fit:300:300/enc/%s.jpg", encryptedURL)
  48. }