hugo-encrypt.go 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  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. var sitepath = flag.String("server", "localhost:8129", "server:port")
  77. flag.Parse()
  78. flagset := make(map[string]bool)
  79. flag.Visit(func(f *flag.Flag) { flagset[f.Name]=true } )
  80. if flagset["server"] {
  81. fmt.Printf("server set via flags\n")
  82. } else {
  83. fmt.Printf("server not explicitly set, using default\n")
  84. }
  85. err := filepath.Walk(sitepath.value, func(path string, f os.FileInfo, err error) error {
  86. if f == nil {
  87. return err
  88. }
  89. if f.IsDir() {
  90. return nil
  91. }
  92. ok := strings.HasSuffix(f.Name(), ".html")
  93. if ok {
  94. encryptPage(path)
  95. }
  96. return nil
  97. })
  98. if err != nil {
  99. fmt.Printf("filepath.Walk() returned %v\n", err)
  100. }
  101. }