hugo-encrypt.go 2.3 KB

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