hugo-encrypt.go 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  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. type stringFlag struct {
  60. set bool
  61. value string
  62. }
  63. func (sf *stringFlag) Set(x string) error {
  64. sf.value = x
  65. sf.set = true
  66. return nil
  67. }
  68. func (sf *stringFlag) String() string {
  69. return sf.value
  70. }
  71. var sitepath stringFlag
  72. func init() {
  73. flag.Var(&sitepath, "sitepath", "the sitepath")
  74. }
  75. func main() {
  76. sitePath := os.Args[1]
  77. err := filepath.Walk(sitePath, func(path string, f os.FileInfo, err error) error {
  78. if f == nil {
  79. return err
  80. }
  81. if f.IsDir() {
  82. return nil
  83. }
  84. ok := strings.HasSuffix(f.Name(), ".html")
  85. if ok {
  86. encryptPage(path)
  87. }
  88. return nil
  89. })
  90. if err != nil {
  91. fmt.Printf("filepath.Walk() returned %v\n", err)
  92. }
  93. }