hugo-encrypt.go 2.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. package main
  2. import (
  3. "flag"
  4. "bytes"
  5. "crypto/aes"
  6. "crypto/cipher"
  7. "crypto/rand"
  8. "crypto/sha256"
  9. "encoding/hex"
  10. "fmt"
  11. "io/ioutil"
  12. "os"
  13. "path/filepath"
  14. "strings"
  15. "github.com/PuerkitoBio/goquery"
  16. "golang.org/x/crypto/pbkdf2"
  17. )
  18. func deriveKey(passphrase string, salt []byte) ([]byte, []byte) {
  19. if salt == nil {
  20. salt = make([]byte, 8)
  21. // http://www.ietf.org/rfc/rfc2898.txt
  22. // Salt.
  23. rand.Read(salt)
  24. }
  25. return pbkdf2.Key([]byte(passphrase), salt, 1000, 32, sha256.New), salt
  26. }
  27. func encrypt(passphrase, plaintext string) string {
  28. key, salt := deriveKey(passphrase, nil)
  29. iv := make([]byte, 12)
  30. // http://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38d.pdf
  31. // Section 8.2
  32. rand.Read(iv)
  33. b, _ := aes.NewCipher(key)
  34. aesgcm, _ := cipher.NewGCM(b)
  35. data := aesgcm.Seal(nil, iv, []byte(plaintext), nil)
  36. return hex.EncodeToString(salt) + "-" + hex.EncodeToString(iv) + "-" + hex.EncodeToString(data)
  37. }
  38. func encryptPage(path string) {
  39. content, err := ioutil.ReadFile(path)
  40. if err != nil {
  41. panic(err)
  42. }
  43. doc, err := goquery.NewDocumentFromReader(bytes.NewBuffer(content))
  44. if err != nil {
  45. panic(err)
  46. }
  47. block := doc.Find("cipher-text")
  48. if len(block.Nodes) == 1 {
  49. fmt.Printf("Processing %s\n", path)
  50. password, _ := block.Attr("data-password")
  51. blockhtml, _ := block.Html()
  52. enchtml := encrypt(password, blockhtml)
  53. block.RemoveAttr("data-password")
  54. block.SetHtml(enchtml)
  55. wholehtml, _ := doc.Html()
  56. ioutil.WriteFile(path, []byte(wholehtml), 0644)
  57. }
  58. }
  59. func main() {
  60. var dir = flag.String("dir", "localhost:8129", "server:port")
  61. flag.Parse()
  62. flagset := make(map[string]bool)
  63. flag.Visit(func(f *flag.Flag) { flagset[f.Name]=true } )
  64. if flagset[dir] {
  65. fmt.Printf("dir set via flags\n")
  66. } else {
  67. fmt.Printf("dir not explicitly set, using default\n")
  68. os.Exit(1)
  69. }
  70. publicPath := os.Args[1]
  71. err := filepath.Walk(publicPath, func(path string, f os.FileInfo, err error) error {
  72. if f == nil {
  73. return err
  74. }
  75. if f.IsDir() {
  76. return nil
  77. }
  78. ok := strings.HasSuffix(f.Name(), ".html")
  79. if ok {
  80. encryptPage(path)
  81. }
  82. return nil
  83. })
  84. if err != nil {
  85. fmt.Printf("filepath.Walk() returned %v\n", err)
  86. }
  87. }